diff --git a/bridges/modules/message-lane/src/benchmarking.rs b/bridges/modules/message-lane/src/benchmarking.rs index 4b0df8213a2aa..c9a27a4d9e2f2 100644 --- a/bridges/modules/message-lane/src/benchmarking.rs +++ b/bridges/modules/message-lane/src/benchmarking.rs @@ -311,8 +311,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: 1, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -349,8 +348,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: 2, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -392,8 +390,7 @@ benchmarks_instance! { (1, 1, relayer1_id.clone()), (2, 2, relayer2_id.clone()), ].into_iter().collect(), - latest_received_nonce: 2, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) @@ -552,8 +549,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: i as MessageNonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -601,8 +597,7 @@ benchmarks_instance! { .enumerate() .map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone())) .collect(), - latest_received_nonce: i as MessageNonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) @@ -637,7 +632,6 @@ fn receive_messages, I: Instance>(nonce: MessageNonce) { let mut inbound_lane_storage = inbound_lane_storage::(bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(), - latest_received_nonce: nonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, }); } diff --git a/bridges/modules/message-lane/src/inbound_lane.rs b/bridges/modules/message-lane/src/inbound_lane.rs index 10ec2f54a20fe..7359aa4ed188a 100644 --- a/bridges/modules/message-lane/src/inbound_lane.rs +++ b/bridges/modules/message-lane/src/inbound_lane.rs @@ -55,20 +55,23 @@ impl InboundLane { /// Receive state of the corresponding outbound lane. pub fn receive_state_update(&mut self, outbound_lane_data: OutboundLaneData) -> Option { let mut data = self.storage.data(); - if outbound_lane_data.latest_received_nonce > data.latest_received_nonce { + let last_delivered_nonce = data.last_delivered_nonce(); + + if outbound_lane_data.latest_received_nonce > last_delivered_nonce { // this is something that should never happen if proofs are correct return None; } - if outbound_lane_data.latest_received_nonce <= data.latest_confirmed_nonce { + if outbound_lane_data.latest_received_nonce <= data.last_confirmed_nonce { return None; } - data.latest_confirmed_nonce = outbound_lane_data.latest_received_nonce; + let new_confirmed_nonce = outbound_lane_data.latest_received_nonce; + data.last_confirmed_nonce = new_confirmed_nonce; // Firstly, remove all of the records where higher nonce <= new confirmed nonce while data .relayers .front() - .map(|(_, nonce_high, _)| *nonce_high <= data.latest_confirmed_nonce) + .map(|(_, nonce_high, _)| *nonce_high <= new_confirmed_nonce) .unwrap_or(false) { data.relayers.pop_front(); @@ -76,8 +79,8 @@ impl InboundLane { // Secondly, update the next record with lower nonce equal to new confirmed nonce if needed. // Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap. match data.relayers.front_mut() { - Some((nonce_low, _, _)) if *nonce_low < data.latest_confirmed_nonce => { - *nonce_low = data.latest_confirmed_nonce + 1; + Some((nonce_low, _, _)) if *nonce_low < new_confirmed_nonce => { + *nonce_low = new_confirmed_nonce + 1; } _ => {} } @@ -94,7 +97,7 @@ impl InboundLane { message_data: DispatchMessageData, ) -> bool { let mut data = self.storage.data(); - let is_correct_message = nonce == data.latest_received_nonce + 1; + let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { return false; } @@ -105,13 +108,11 @@ impl InboundLane { } // if there are more unconfirmed messages than we may accept, reject this message - let unconfirmed_messages_count = nonce.saturating_sub(data.latest_confirmed_nonce); + let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { return false; } - data.latest_received_nonce = nonce; - let push_new = match data.relayers.back_mut() { Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => { *nonce_high = nonce; @@ -173,7 +174,7 @@ mod tests { None, ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + assert_eq!(lane.storage.data().last_confirmed_nonce, 0); }); } @@ -191,7 +192,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!( lane.receive_state_update(OutboundLaneData { @@ -200,7 +201,7 @@ mod tests { }), None, ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); }); } @@ -211,7 +212,7 @@ mod tests { receive_regular_message(&mut lane, 1); receive_regular_message(&mut lane, 2); receive_regular_message(&mut lane, 3); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + assert_eq!(lane.storage.data().last_confirmed_nonce, 0); assert_eq!(lane.storage.data().relayers, vec![(1, 3, TEST_RELAYER_A)]); assert_eq!( @@ -221,7 +222,7 @@ mod tests { }), Some(2), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 2); + assert_eq!(lane.storage.data().last_confirmed_nonce, 2); assert_eq!(lane.storage.data().relayers, vec![(3, 3, TEST_RELAYER_A)]); assert_eq!( @@ -231,7 +232,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!(lane.storage.data().relayers, vec![]); }); } @@ -242,8 +243,7 @@ mod tests { let mut lane = inbound_lane::(TEST_LANE_ID); let mut seed_storage_data = lane.storage.data(); // Prepare data - seed_storage_data.latest_confirmed_nonce = 0; - seed_storage_data.latest_received_nonce = 5; + seed_storage_data.last_confirmed_nonce = 0; seed_storage_data.relayers.push_back((1, 1, TEST_RELAYER_A)); // Simulate messages batch (2, 3, 4) from relayer #2 seed_storage_data.relayers.push_back((2, 4, TEST_RELAYER_B)); @@ -257,7 +257,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!( lane.storage.data().relayers, vec![(4, 4, TEST_RELAYER_B), (5, 5, TEST_RELAYER_C)] @@ -274,7 +274,7 @@ mod tests { 10, message_data(REGULAR_PAYLOAD).into() )); - assert_eq!(lane.storage.data().latest_received_nonce, 0); + assert_eq!(lane.storage.data().last_delivered_nonce(), 0); }); } @@ -391,7 +391,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); receive_regular_message(&mut lane, 1); - assert_eq!(lane.storage.data().latest_received_nonce, 1); + assert_eq!(lane.storage.data().last_delivered_nonce(), 1); }); } } diff --git a/bridges/modules/message-lane/src/lib.rs b/bridges/modules/message-lane/src/lib.rs index 88dd033cbcacb..10b3ec22c226d 100644 --- a/bridges/modules/message-lane/src/lib.rs +++ b/bridges/modules/message-lane/src/lib.rs @@ -464,7 +464,8 @@ decl_module! { // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); + let last_delivered_nonce = lane_data.last_delivered_nonce(); + let received_range = lane.confirm_delivery(last_delivered_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); @@ -499,7 +500,7 @@ decl_module! { frame_support::debug::trace!( "Received messages delivery proof up to (and including) {} at lane {:?}", - lane_data.latest_received_nonce, + last_delivered_nonce, lane_id, ); @@ -526,12 +527,12 @@ impl, I: Instance> Module { /// Get nonce of latest received message at given inbound lane. pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).latest_received_nonce + InboundLanes::::get(&lane).last_delivered_nonce() } /// Get nonce of latest confirmed message at given inbound lane. pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).latest_confirmed_nonce + InboundLanes::::get(&lane).last_confirmed_nonce } /// Get state of unrewarded relayers set. @@ -795,7 +796,7 @@ mod tests { Ok(( TEST_LANE_ID, InboundLaneData { - latest_received_nonce: 1, + last_confirmed_nonce: 1, ..Default::default() }, )), @@ -905,7 +906,7 @@ mod tests { Ok(( TEST_LANE_ID, InboundLaneData { - latest_received_nonce: 1, + last_confirmed_nonce: 1, ..Default::default() }, )), @@ -977,7 +978,7 @@ mod tests { REGULAR_PAYLOAD.1, )); - assert_eq!(InboundLanes::::get(TEST_LANE_ID).latest_received_nonce, 1); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1); }); } @@ -988,8 +989,7 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, InboundLaneData { - latest_confirmed_nonce: 8, - latest_received_nonce: 10, + last_confirmed_nonce: 8, relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)] .into_iter() .collect(), @@ -1022,11 +1022,10 @@ mod tests { assert_eq!( InboundLanes::::get(TEST_LANE_ID), InboundLaneData { + last_confirmed_nonce: 9, relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)] .into_iter() .collect(), - latest_received_nonce: 11, - latest_confirmed_nonce: 9, }, ); assert_eq!( @@ -1108,7 +1107,6 @@ mod tests { TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(), - latest_received_nonce: 1, ..Default::default() } )), @@ -1136,7 +1134,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1180,7 +1177,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1203,7 +1199,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1232,7 +1227,10 @@ mod tests { 0, // weight may be zero in this case (all messages are improperly encoded) ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 1,); + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), + 1, + ); }); } @@ -1255,7 +1253,10 @@ mod tests { REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 3,); + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), + 3, + ); }); } diff --git a/bridges/primitives/message-lane/src/lib.rs b/bridges/primitives/message-lane/src/lib.rs index 4edf936bff3b8..9dba82a71c200 100644 --- a/bridges/primitives/message-lane/src/lib.rs +++ b/bridges/primitives/message-lane/src/lib.rs @@ -74,34 +74,54 @@ pub struct Message { /// Inbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct InboundLaneData { - /// Identifiers of relayers and messages that they have delivered (ordered by message nonce). - /// It is guaranteed to have at most N entries, where N is configured at module level. If - /// there are N entries in this vec, then: + /// Identifiers of relayers and messages that they have delivered to this lane (ordered by message nonce). + /// + /// This serves as a helper storage item, to allow the source chain to easily pay rewards + /// to the relayers who succesfuly delivered messages to the target chain (inbound lane). + /// + /// It is guaranteed to have at most N entries, where N is configured at the module level. + /// If there are N entries in this vec, then: /// 1) all incoming messages are rejected if they're missing corresponding `proof-of(outbound-lane.state)`; - /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).latest_received_nonce` is - /// equal to `this.latest_confirmed_nonce`. - /// Given what is said above, all nonces in this queue are in range (latest_confirmed_nonce; latest_received_nonce]. + /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).last_delivered_nonce` is + /// equal to `self.last_confirmed_nonce`. + /// Given what is said above, all nonces in this queue are in range: + /// `(self.last_confirmed_nonce; self.last_delivered_nonce()]`. /// /// When a relayer sends a single message, both of MessageNonces are the same. /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce. - /// Multiple dispatches from the same relayer one are allowed. + /// Multiple dispatches from the same relayer are allowed. pub relayers: VecDeque<(MessageNonce, MessageNonce, RelayerId)>, - /// Nonce of latest message that we have received from bridged chain. - pub latest_received_nonce: MessageNonce, - /// Nonce of latest message that has been confirmed to the bridged chain. - pub latest_confirmed_nonce: MessageNonce, + + /// Nonce of the last message that + /// a) has been delivered to the target (this) chain and + /// b) the delivery has been confirmed on the source chain + /// + /// that the target chain knows of. + /// + /// This value is updated indirectly when an `OutboundLane` state of the source + /// chain is received alongside with new messages delivery. + pub last_confirmed_nonce: MessageNonce, } impl Default for InboundLaneData { fn default() -> Self { InboundLaneData { relayers: VecDeque::new(), - latest_received_nonce: 0, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } } } +impl InboundLaneData { + /// Nonce of the last message that has been delivered to this (target) chain. + pub fn last_delivered_nonce(&self) -> MessageNonce { + self.relayers + .back() + .map(|(_, last_nonce, _)| *last_nonce) + .unwrap_or(self.last_confirmed_nonce) + } +} + /// Gist of `InboundLaneData::relayers` field used by runtime APIs. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayersState {