Skip to content

Commit

Permalink
only refund if all bundled messages have been delivered (paritytech#2019
Browse files Browse the repository at this point in the history
)
  • Loading branch information
svyatonik authored and serban300 committed Apr 9, 2024
1 parent 03e1684 commit f65fec6
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
17 changes: 12 additions & 5 deletions bridges/bin/runtime-common/src/messages_call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ use sp_runtime::transaction_validity::TransactionValidity;
/// Generic info about a messages delivery/confirmation proof.
#[derive(PartialEq, RuntimeDebug)]
pub struct BaseMessagesProofInfo {
/// Message lane, used by the call.
pub lane_id: LaneId,
/// Nonce of the best message, included in the call.
pub best_bundled_nonce: MessageNonce,
/// Nonce of the best message, stored by this chain before the call is dispatched.
pub best_stored_nonce: MessageNonce,
}

Expand Down Expand Up @@ -58,19 +61,23 @@ pub struct CallHelper<T: Config<I>, I: 'static> {
}

impl<T: Config<I>, I: 'static> CallHelper<T, I> {
/// Check if a call delivered proof/confirmation for at least some of the messages that it
/// contained.
pub fn was_partially_successful(info: &CallInfo) -> bool {
/// Returns true if:
///
/// - call is `receive_messages_proof` and all messages have been delivered;
///
/// - call is `receive_messages_delivery_proof` and all messages confirmations have been
/// received.
pub fn was_successful(info: &CallInfo) -> bool {
match info {
CallInfo::ReceiveMessagesProof(info) => {
let inbound_lane_data =
pallet_bridge_messages::InboundLanes::<T, I>::get(info.0.lane_id);
inbound_lane_data.last_delivered_nonce() > info.0.best_stored_nonce
inbound_lane_data.last_delivered_nonce() == info.0.best_bundled_nonce
},
CallInfo::ReceiveMessagesDeliveryProof(info) => {
let outbound_lane_data =
pallet_bridge_messages::OutboundLanes::<T, I>::get(info.0.lane_id);
outbound_lane_data.latest_received_nonce > info.0.best_stored_nonce
outbound_lane_data.latest_received_nonce == info.0.best_bundled_nonce
},
}
}
Expand Down
59 changes: 56 additions & 3 deletions bridges/bin/runtime-common/src/refund_relayer_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,16 @@ where
finality_proof_info.block_number,
) {
// we only refund relayer if all calls have updated chain state
log::trace!(
target: "runtime::bridge",
"{} from parachain {} via {:?}: failed to refund relayer {:?}, because \
relay chain finality proof has not been accepted",
Self::IDENTIFIER,
Para::Id::get(),
Msgs::Id::get(),
relayer,
);

return Ok(())
}

Expand All @@ -366,15 +376,34 @@ where
para_proof_info,
) {
// we only refund relayer if all calls have updated chain state
log::trace!(
target: "runtime::bridge",
"{} from parachain {} via {:?}: failed to refund relayer {:?}, because \
parachain finality proof has not been accepted",
Self::IDENTIFIER,
Para::Id::get(),
Msgs::Id::get(),
relayer,
);

return Ok(())
}
}

// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that
// Check if the `ReceiveMessagesProof` call delivered all the messages that
// it contained. If this happens, we consider the transaction "helpful" and refund it.
let msgs_call_info = call_info.messages_call_info();
if !MessagesCallHelper::<Runtime, Msgs::Instance>::was_partially_successful(msgs_call_info)
{
if !MessagesCallHelper::<Runtime, Msgs::Instance>::was_successful(msgs_call_info) {
log::trace!(
target: "runtime::bridge",
"{} from parachain {} via {:?}: failed to refund relayer {:?}, because \
some of messages have not been accepted",
Self::IDENTIFIER,
Para::Id::get(),
Msgs::Id::get(),
relayer,
);

return Ok(())
}

Expand Down Expand Up @@ -1032,6 +1061,30 @@ mod tests {
});
}

#[test]
fn post_dispatch_ignores_transaction_that_has_not_delivered_all_messages() {
run_test(|| {
initialize_environment(200, 200, Default::default(), 150);

assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())));
assert_storage_noop!(run_post_dispatch(
Some(parachain_finality_pre_dispatch_data()),
Ok(())
));
assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())));

assert_storage_noop!(run_post_dispatch(
Some(all_finality_confirmation_pre_dispatch_data()),
Ok(())
));
assert_storage_noop!(run_post_dispatch(
Some(parachain_finality_confirmation_pre_dispatch_data()),
Ok(())
));
assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())));
});
}

#[test]
fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() {
run_test(|| {
Expand Down

0 comments on commit f65fec6

Please sign in to comment.