mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 14:31:02 +00:00
Limit max number of unconfirmed messages at inbound lane (#545)
* limit maximal number of unconfirmed messages at inbound lane * unrewarded_relayer_entries API * change relay to support max unrewarded relayer entries * Update modules/message-lane/src/inbound_lane.rs Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Update relays/messages-relay/src/message_lane_loop.rs Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> * removed pub Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
This commit is contained in:
committed by
Bastian Köcher
parent
93b3d49047
commit
2944f997d1
@@ -31,6 +31,8 @@ pub trait InboundLaneStorage {
|
||||
|
||||
/// Lane id.
|
||||
fn id(&self) -> LaneId;
|
||||
/// Return maximal number of unrewarded relayer entries in inbound lane.
|
||||
fn max_unrewarded_relayer_entries(&self) -> MessageNonce;
|
||||
/// Return maximal number of unconfirmed messages in inbound lane.
|
||||
fn max_unconfirmed_messages(&self) -> MessageNonce;
|
||||
/// Get lane data from the storage.
|
||||
@@ -97,8 +99,14 @@ impl<S: InboundLaneStorage> InboundLane<S> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there are more unrewarded relayer entries than we may accept, reject this message
|
||||
if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there are more unconfirmed messages than we may accept, reject this message
|
||||
if self.storage.max_unconfirmed_messages() <= data.relayers.len() as MessageNonce {
|
||||
let unconfirmed_messages_count = nonce.saturating_sub(data.latest_confirmed_nonce);
|
||||
if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -271,10 +279,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_receive_messages_above_max_limit_per_lane() {
|
||||
fn fails_to_receive_messages_above_unrewarded_relayer_entries_limit_per_lane() {
|
||||
run_test(|| {
|
||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
let max_nonce = <TestRuntime as crate::Trait>::MaxUnconfirmedMessagesAtInboundLane::get();
|
||||
let max_nonce = <TestRuntime as crate::Trait>::MaxUnrewardedRelayerEntriesAtInboundLane::get();
|
||||
for current_nonce in 1..max_nonce + 1 {
|
||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
||||
TEST_RELAYER_A + current_nonce,
|
||||
@@ -303,6 +311,39 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() {
|
||||
run_test(|| {
|
||||
let mut lane = inbound_lane::<TestRuntime, _>(TEST_LANE_ID);
|
||||
let max_nonce = <TestRuntime as crate::Trait>::MaxUnconfirmedMessagesAtInboundLane::get();
|
||||
for current_nonce in 1..=max_nonce {
|
||||
assert!(lane.receive_message::<TestMessageDispatch>(
|
||||
TEST_RELAYER_A,
|
||||
current_nonce,
|
||||
message_data(REGULAR_PAYLOAD).into()
|
||||
));
|
||||
}
|
||||
// Fails to dispatch new message from different than latest relayer.
|
||||
assert_eq!(
|
||||
false,
|
||||
lane.receive_message::<TestMessageDispatch>(
|
||||
TEST_RELAYER_B,
|
||||
max_nonce + 1,
|
||||
message_data(REGULAR_PAYLOAD).into()
|
||||
)
|
||||
);
|
||||
// Fails to dispatch new messages from latest relayer.
|
||||
assert_eq!(
|
||||
false,
|
||||
lane.receive_message::<TestMessageDispatch>(
|
||||
TEST_RELAYER_A,
|
||||
max_nonce + 1,
|
||||
message_data(REGULAR_PAYLOAD).into()
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn correctly_receives_following_messages_from_two_relayers_alternately() {
|
||||
run_test(|| {
|
||||
|
||||
@@ -75,16 +75,20 @@ pub trait Trait<I = DefaultInstance>: frame_system::Trait {
|
||||
/// confirmed. The reason is that if you want to use lane, you should be ready to pay
|
||||
/// for it.
|
||||
type MaxMessagesToPruneAtOnce: Get<MessageNonce>;
|
||||
/// Maximal number of "messages" (see note below) in the 'unconfirmed' state at inbound lane.
|
||||
/// Unconfirmed message at inbound lane is the message that has been: sent, delivered and
|
||||
/// dispatched. Its delivery confirmation is still pending. This limit is introduced to bound
|
||||
/// maximal number of relayers-ids in the inbound lane state.
|
||||
/// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the
|
||||
/// relayer has delivered messages, but either confirmations haven't been delivered back to the
|
||||
/// source chain, or we haven't received reward confirmations yet.
|
||||
///
|
||||
/// "Message" in this context does not necessarily mean an individual message, but instead
|
||||
/// continuous range of individual messages, that are delivered by single relayer. So if relayer#1
|
||||
/// has submitted delivery transaction#1 with individual messages [1; 2] and then delivery
|
||||
/// transaction#2 with individual messages [3; 4], this would be treated as single "Message" and
|
||||
/// would occupy single unit of `MaxUnconfirmedMessagesAtInboundLane` limit.
|
||||
/// This constant limits maximal number of entries in the `InboundLaneData::relayers`. Keep
|
||||
/// in mind that the same relayer account may take several (non-consecutive) entries in this
|
||||
/// set.
|
||||
type MaxUnrewardedRelayerEntriesAtInboundLane: Get<MessageNonce>;
|
||||
/// Maximal number of unconfirmed messages at inbound lane. Unconfirmed means that the
|
||||
/// message has been delivered, but either confirmations haven't been delivered back to the
|
||||
/// source chain, or we haven't received reward confirmations for these messages yet.
|
||||
///
|
||||
/// This constant limits difference between last message from last entry of the
|
||||
/// `InboundLaneData::relayers` and first message at the first entry.
|
||||
type MaxUnconfirmedMessagesAtInboundLane: Get<MessageNonce>;
|
||||
/// Maximal number of messages in single delivery transaction. This directly affects the base
|
||||
/// weight of the delivery transaction.
|
||||
@@ -481,6 +485,17 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
|
||||
pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce {
|
||||
InboundLanes::<T, I>::get(&lane).latest_confirmed_nonce
|
||||
}
|
||||
|
||||
/// Get state of unrewarded relayers set.
|
||||
pub fn inbound_unrewarded_relayers_state(
|
||||
lane: bp_message_lane::LaneId,
|
||||
) -> bp_message_lane::UnrewardedRelayersState {
|
||||
let relayers = InboundLanes::<T, I>::get(&lane).relayers;
|
||||
bp_message_lane::UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: relayers.len() as _,
|
||||
messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Getting storage keys for messages and lanes states. These keys are normally used when building
|
||||
@@ -569,6 +584,10 @@ impl<T: Trait<I>, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage<
|
||||
self.lane_id
|
||||
}
|
||||
|
||||
fn max_unrewarded_relayer_entries(&self) -> MessageNonce {
|
||||
T::MaxUnrewardedRelayerEntriesAtInboundLane::get()
|
||||
}
|
||||
|
||||
fn max_unconfirmed_messages(&self) -> MessageNonce {
|
||||
T::MaxUnconfirmedMessagesAtInboundLane::get()
|
||||
}
|
||||
@@ -681,6 +700,7 @@ mod tests {
|
||||
message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestRuntime,
|
||||
PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
|
||||
};
|
||||
use bp_message_lane::UnrewardedRelayersState;
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use frame_system::{EventRecord, Module as System, Phase};
|
||||
use hex_literal::hex;
|
||||
@@ -916,6 +936,13 @@ mod tests {
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
Module::<TestRuntime>::inbound_unrewarded_relayers_state(TEST_LANE_ID),
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 2,
|
||||
messages_in_oldest_entry: 1,
|
||||
},
|
||||
);
|
||||
|
||||
// message proof includes outbound lane state with latest confirmed message updated to 9
|
||||
let mut message_proof: TestMessagesProof = Ok(vec![message(11, REGULAR_PAYLOAD)]).into();
|
||||
@@ -941,6 +968,13 @@ mod tests {
|
||||
latest_confirmed_nonce: 9,
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
Module::<TestRuntime>::inbound_unrewarded_relayers_state(TEST_LANE_ID),
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 2,
|
||||
messages_in_oldest_entry: 1,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -99,13 +99,15 @@ impl frame_system::Trait for TestRuntime {
|
||||
|
||||
parameter_types! {
|
||||
pub const MaxMessagesToPruneAtOnce: u64 = 10;
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 16;
|
||||
pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16;
|
||||
pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32;
|
||||
pub const MaxMessagesInDeliveryTransaction: u64 = 128;
|
||||
}
|
||||
|
||||
impl Trait for TestRuntime {
|
||||
type Event = TestEvent;
|
||||
type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce;
|
||||
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
|
||||
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;
|
||||
type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user