Skip to content

Commit

Permalink
Add reward field to unrewarded relayers (#2613)
Browse files Browse the repository at this point in the history
* report expected reward from target to source chain in confirmation transaction

* added tests for new code

* fix benchmarks compilation

* clippy + spelling

* remove extra requirements

* RewardAtSource -> RelayerRewardAtSource, delivery_reward_per_message -> relayer_reward_per_message
  • Loading branch information
svyatonik authored and bkontur committed Jun 14, 2024
1 parent 5076e78 commit 19e3687
Show file tree
Hide file tree
Showing 15 changed files with 384 additions and 170 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions bridges/modules/messages/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ fn receive_messages<T: Config<I>, I: 'static>(nonce: MessageNonce) {
state: LaneState::Opened,
relayers: vec![UnrewardedRelayer {
relayer: T::bridged_relayer_id(),
messages: DeliveredMessages::new(nonce),
messages: DeliveredMessages::new(nonce, 1),
}]
.into(),
last_confirmed_nonce: 0,
Expand Down Expand Up @@ -368,7 +368,7 @@ mod benchmarks {
state: LaneState::Opened,
relayers: vec![UnrewardedRelayer {
relayer: relayer_id.clone(),
messages: DeliveredMessages::new(1),
messages: DeliveredMessages::new(1, 1),
}]
.into_iter()
.collect(),
Expand Down Expand Up @@ -412,7 +412,7 @@ mod benchmarks {
total_messages: 2,
last_delivered_nonce: 2,
};
let mut delivered_messages = DeliveredMessages::new(1);
let mut delivered_messages = DeliveredMessages::new(1, 1);
delivered_messages.note_dispatched_message();
let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams {
lane: T::bench_lane_id(),
Expand Down Expand Up @@ -472,11 +472,11 @@ mod benchmarks {
relayers: vec![
UnrewardedRelayer {
relayer: relayer1_id.clone(),
messages: DeliveredMessages::new(1),
messages: DeliveredMessages::new(1, 1),
},
UnrewardedRelayer {
relayer: relayer2_id.clone(),
messages: DeliveredMessages::new(2),
messages: DeliveredMessages::new(2, 1),
},
]
.into_iter()
Expand Down
7 changes: 6 additions & 1 deletion bridges/modules/messages/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,11 @@ mod tests {
for n in 0..BridgedChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX {
inbound_lane_state.relayers.push_back(UnrewardedRelayer {
relayer: Default::default(),
messages: DeliveredMessages { begin: n + 1, end: n + 1 },
messages: DeliveredMessages {
begin: n + 1,
end: n + 1,
relayer_reward_per_message: 0,
},
});
}
InboundLanes::<TestRuntime>::insert(test_lane_id(), inbound_lane_state);
Expand All @@ -273,6 +277,7 @@ mod tests {
messages: DeliveredMessages {
begin: 1,
end: BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
relayer_reward_per_message: 0,
},
});
InboundLanes::<TestRuntime>::insert(test_lane_id(), inbound_lane_state);
Expand Down
98 changes: 81 additions & 17 deletions bridges/modules/messages/src/inbound_lane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{BridgedChainOf, Config};
use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
ChainWithMessages, DeliveredMessages, InboundLaneData, LaneId, LaneState, MessageKey,
MessageNonce, OutboundLaneData, ReceptionResult, UnrewardedRelayer,
MessageNonce, OutboundLaneData, ReceptionResult, RelayerRewardAtSource, UnrewardedRelayer,
};
use bp_runtime::AccountIdOf;
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
Expand Down Expand Up @@ -186,6 +186,7 @@ impl<S: InboundLaneStorage> InboundLane<S> {
relayer_at_bridged_chain: &S::Relayer,
nonce: MessageNonce,
message_data: DispatchMessageData<Dispatch::DispatchPayload>,
relayer_reward_per_message: RelayerRewardAtSource,
) -> ReceptionResult<Dispatch::DispatchLevelResult> {
let mut data = self.storage.data();
if Some(nonce) != data.last_delivered_nonce().checked_add(1) {
Expand All @@ -211,13 +212,16 @@ impl<S: InboundLaneStorage> InboundLane<S> {

// now let's update inbound lane storage
match data.relayers.back_mut() {
Some(entry) if entry.relayer == *relayer_at_bridged_chain => {
Some(entry)
if entry.relayer == *relayer_at_bridged_chain &&
entry.messages.relayer_reward_per_message == relayer_reward_per_message =>
{
entry.messages.note_dispatched_message();
},
_ => {
data.relayers.push_back(UnrewardedRelayer {
relayer: relayer_at_bridged_chain.clone(),
messages: DeliveredMessages::new(nonce),
messages: DeliveredMessages::new(nonce, relayer_reward_per_message),
});
},
};
Expand Down Expand Up @@ -246,7 +250,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
nonce,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
Expand Down Expand Up @@ -373,7 +378,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
10,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::InvalidNonce
);
Expand All @@ -391,7 +397,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&(TEST_RELAYER_A + current_nonce),
current_nonce,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
Expand All @@ -401,7 +408,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&(TEST_RELAYER_A + max_nonce + 1),
max_nonce + 1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::TooManyUnrewardedRelayers,
);
Expand All @@ -410,7 +418,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&(TEST_RELAYER_A + max_nonce),
max_nonce + 1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::TooManyUnrewardedRelayers,
);
Expand All @@ -427,7 +436,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
current_nonce,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
Expand All @@ -437,7 +447,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_B,
max_nonce + 1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::TooManyUnconfirmedMessages,
);
Expand All @@ -446,7 +457,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
max_nonce + 1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::TooManyUnconfirmedMessages,
);
Expand All @@ -461,23 +473,26 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_B,
2,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
3,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
Expand All @@ -492,6 +507,52 @@ mod tests {
});
}

#[test]
fn separate_relayer_entry_is_created_when_same_relayer_wants_different_reward() {
run_test(|| {
let mut lane = active_inbound_lane::<TestRuntime, _>(test_lane_id()).unwrap();
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
1,
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
2,
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE + 1,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
3,
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE + 1,
),
ReceptionResult::Dispatched(dispatch_result(0))
);

let mut unrewarded_relayer_with_larger_reward =
unrewarded_relayer(2, 3, TEST_RELAYER_A);
unrewarded_relayer_with_larger_reward.messages.relayer_reward_per_message =
RELAYER_REWARD_PER_MESSAGE + 1;
assert_eq!(
lane.storage.data().relayers,
vec![
unrewarded_relayer(1, 1, TEST_RELAYER_A),
unrewarded_relayer_with_larger_reward,
]
);
});
}

#[test]
fn rejects_same_message_from_two_different_relayers() {
run_test(|| {
Expand All @@ -500,15 +561,17 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(0))
);
assert_eq!(
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_B,
1,
inbound_message_data(REGULAR_PAYLOAD)
inbound_message_data(REGULAR_PAYLOAD),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::InvalidNonce,
);
Expand All @@ -534,7 +597,8 @@ mod tests {
lane.receive_message::<TestMessageDispatch>(
&TEST_RELAYER_A,
1,
inbound_message_data(payload)
inbound_message_data(payload),
RELAYER_REWARD_PER_MESSAGE,
),
ReceptionResult::Dispatched(dispatch_result(1))
);
Expand Down
25 changes: 17 additions & 8 deletions bridges/modules/messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ use bp_messages::{
DeliveryPayments, DispatchMessage, FromBridgedChainMessagesProof, MessageDispatch,
ProvedLaneMessages, ProvedMessages,
},
ChainWithMessages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId,
MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData,
OutboundMessageDetails, UnrewardedRelayersState, VerificationError,
ChainWithMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce,
MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails,
UnrewardedRelayersState, VerificationError,
};
use bp_runtime::{
AccountIdOf, BasicOperatingMode, HashOf, OwnedBridgeModule, PreComputedSize, RangeInclusiveExt,
Expand Down Expand Up @@ -268,6 +268,11 @@ pub mod pallet {
}
}

// compute the per-message reward that is paid at the bridged (source) chain to relayer
// that has delivered message
let relayer_reward_per_message =
T::DeliveryPayments::relayer_reward_per_message(lane_id, &relayer_id_at_this_chain);

let mut messages_received_status =
ReceivedMessages::new(lane_id, Vec::with_capacity(lane_data.messages.len()));
for mut message in lane_data.messages {
Expand All @@ -294,6 +299,7 @@ pub mod pallet {
&relayer_id_at_bridged_chain,
message.key.nonce,
message.data,
relayer_reward_per_message,
);

// note that we're returning unspent weight to relayer even if message has been
Expand All @@ -320,6 +326,7 @@ pub mod pallet {

// let's now deal with relayer payments
T::DeliveryPayments::pay_reward(
lane_id,
relayer_id_at_this_chain,
total_messages,
valid_messages,
Expand Down Expand Up @@ -381,12 +388,12 @@ pub mod pallet {
)
.map_err(Error::<T, I>::ReceptionConfirmation)?;

if let Some(confirmed_messages) = confirmed_messages {
if let Some(received_range) = confirmed_messages {
// emit 'delivered' event
let received_range = confirmed_messages.begin..=confirmed_messages.end;
Self::deposit_event(Event::MessagesDelivered {
lane_id,
messages: confirmed_messages,
messages_begin: *received_range.start(),
messages_end: *received_range.end(),
});

// if some new messages have been confirmed, reward relayers
Expand Down Expand Up @@ -452,8 +459,10 @@ pub mod pallet {
MessagesDelivered {
/// Lane for which the delivery has been confirmed.
lane_id: LaneId,
/// Delivered messages.
messages: DeliveredMessages,
/// Nonce of the first delivered message.
messages_begin: MessageNonce,
/// Nonce of the last delivered message.
messages_end: MessageNonce,
},
}

Expand Down
Loading

0 comments on commit 19e3687

Please sign in to comment.