Skip to content

Commit 21fdb9a

Browse files
authored
Merge pull request #3356 from autonomys/xdm_max_outgoing
XDM: ensure max outgoing messages per channel is atleast one and ensure to return open channel that can still accept messages
2 parents 37c4242 + 96e9911 commit 21fdb9a

File tree

19 files changed

+160
-80
lines changed

19 files changed

+160
-80
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/subspace-runtime/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use core::num::NonZeroU64;
3434
use domain_runtime_primitives::opaque::Header as DomainHeader;
3535
use domain_runtime_primitives::{
3636
maximum_domain_block_weight, AccountIdConverter, BlockNumber as DomainNumber,
37-
Hash as DomainHash,
37+
Hash as DomainHash, MAX_OUTGOING_MESSAGES,
3838
};
3939
use frame_support::genesis_builder_helper::{build_state, get_preset};
4040
use frame_support::inherent::ProvideInherent;
@@ -650,8 +650,12 @@ parameter_types! {
650650
pub const ChannelInitReservePortion: Perbill = Perbill::from_percent(20);
651651
// TODO update the fee model
652652
pub const ChannelFeeModel: FeeModel<Balance> = FeeModel{relay_fee: SSC};
653+
pub const MaxOutgoingMessages: u32 = MAX_OUTGOING_MESSAGES;
653654
}
654655

656+
// ensure the max outgoing messages is not 0.
657+
const_assert!(MaxOutgoingMessages::get() >= 1);
658+
655659
pub struct DomainRegistration;
656660
impl sp_messenger::DomainRegistration for DomainRegistration {
657661
fn is_domain_registered(domain_id: DomainId) -> bool {
@@ -684,6 +688,7 @@ impl pallet_messenger::Config for Runtime {
684688
type ChannelInitReservePortion = ChannelInitReservePortion;
685689
type DomainRegistration = DomainRegistration;
686690
type ChannelFeeModel = ChannelFeeModel;
691+
type MaxOutgoingMessages = MaxOutgoingMessages;
687692
}
688693

689694
impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime

domains/client/domain-operator/src/tests.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3788,9 +3788,6 @@ async fn test_domain_sudo_calls() {
37883788
.construct_and_send_extrinsic(evm_domain_test_runtime::RuntimeCall::Messenger(
37893789
pallet_messenger::Call::initiate_channel {
37903790
dst_chain_id: ChainId::Consensus,
3791-
params: pallet_messenger::InitiateChannelParams {
3792-
max_outgoing_messages: 100,
3793-
},
37943791
},
37953792
))
37963793
.await
@@ -3931,9 +3928,6 @@ async fn test_xdm_between_consensus_and_domain_should_work() {
39313928
.construct_and_send_extrinsic(evm_domain_test_runtime::RuntimeCall::Messenger(
39323929
pallet_messenger::Call::initiate_channel {
39333930
dst_chain_id: ChainId::Consensus,
3934-
params: pallet_messenger::InitiateChannelParams {
3935-
max_outgoing_messages: 100,
3936-
},
39373931
},
39383932
))
39393933
.await
@@ -4144,9 +4138,6 @@ async fn test_xdm_between_domains_should_work() {
41444138
bob.construct_and_send_extrinsic(auto_id_domain_test_runtime::RuntimeCall::Messenger(
41454139
pallet_messenger::Call::initiate_channel {
41464140
dst_chain_id: ChainId::Domain(EVM_DOMAIN_ID),
4147-
params: pallet_messenger::InitiateChannelParams {
4148-
max_outgoing_messages: 100,
4149-
},
41504141
},
41514142
))
41524143
.await
@@ -4298,9 +4289,6 @@ async fn test_unordered_cross_domains_message_should_work() {
42984289
.construct_and_send_extrinsic(evm_domain_test_runtime::RuntimeCall::Messenger(
42994290
pallet_messenger::Call::initiate_channel {
43004291
dst_chain_id: ChainId::Consensus,
4301-
params: pallet_messenger::InitiateChannelParams {
4302-
max_outgoing_messages: 100,
4303-
},
43044292
},
43054293
))
43064294
.await
@@ -5434,9 +5422,6 @@ async fn test_xdm_false_invalid_fraud_proof() {
54345422
.construct_and_send_extrinsic(evm_domain_test_runtime::RuntimeCall::Messenger(
54355423
pallet_messenger::Call::initiate_channel {
54365424
dst_chain_id: ChainId::Consensus,
5437-
params: pallet_messenger::InitiateChannelParams {
5438-
max_outgoing_messages: 100,
5439-
},
54405425
},
54415426
))
54425427
.await
@@ -5632,9 +5617,6 @@ async fn test_stale_fork_xdm_true_invalid_fraud_proof() {
56325617
.construct_and_send_extrinsic(evm_domain_test_runtime::RuntimeCall::Messenger(
56335618
pallet_messenger::Call::initiate_channel {
56345619
dst_chain_id: ChainId::Consensus,
5635-
params: pallet_messenger::InitiateChannelParams {
5636-
max_outgoing_messages: 100,
5637-
},
56385620
},
56395621
))
56405622
.await

domains/pallets/messenger/src/benchmarking.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ mod benchmarks {
3333
fn initiate_channel() {
3434
let dst_chain_id: ChainId = u32::MAX.into();
3535
assert_ne!(T::SelfChainId::get(), dst_chain_id);
36-
let channel_params = InitiateChannelParams {
37-
max_outgoing_messages: 100,
38-
};
3936
let channel_id = NextChannelId::<T>::get(dst_chain_id);
4037
let account = account("account", 0, 0);
4138
T::Currency::set_balance(
@@ -47,11 +44,7 @@ mod benchmarks {
4744
ChainAllowlist::<T>::put(list);
4845

4946
#[extrinsic_call]
50-
_(
51-
RawOrigin::Signed(account.clone()),
52-
dst_chain_id,
53-
channel_params,
54-
);
47+
_(RawOrigin::Signed(account.clone()), dst_chain_id);
5548

5649
let channel = Channels::<T>::get(dst_chain_id, channel_id).expect("channel should exist");
5750
assert_eq!(channel.state, ChannelState::Initiated);
@@ -203,6 +196,9 @@ mod benchmarks {
203196
last_delivered_message_response_nonce: None,
204197
};
205198
Outbox::<T>::insert((dst_chain_id, channel_id, next_outbox_nonce), req_msg);
199+
OutboxMessageCount::<T>::mutate((dst_chain_id, channel_id), |count| {
200+
*count = count.saturating_add(1u32);
201+
});
206202
// Insert a dummy response message which will be handled during the `relay_message_response` call
207203
let resp_msg: Message<BalanceOf<T>> = Message {
208204
src_chain_id: dst_chain_id,

domains/pallets/messenger/src/lib.rs

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ pub(crate) enum CloseChannelBy<AccountId> {
9898
Sudo,
9999
}
100100

101-
/// Parameters for a new channel between two chains.
102-
#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Copy)]
103-
pub struct InitiateChannelParams {
104-
pub max_outgoing_messages: u32,
105-
}
106-
107101
/// Hold identifier trait for messenger specific balance holds
108102
pub trait HoldIdentifier<T: Config> {
109103
fn messenger_channel() -> FungibleHoldId<T>;
@@ -114,8 +108,8 @@ mod pallet {
114108
use crate::weights::WeightInfo;
115109
use crate::{
116110
BalanceOf, ChainAllowlistUpdate, Channel, ChannelId, ChannelState, CloseChannelBy,
117-
FeeModel, HoldIdentifier, InitiateChannelParams, Nonce, OutboxMessageResult, StateRootOf,
118-
ValidatedRelayMessage, U256,
111+
FeeModel, HoldIdentifier, Nonce, OutboxMessageResult, StateRootOf, ValidatedRelayMessage,
112+
U256,
119113
};
120114
#[cfg(not(feature = "std"))]
121115
use alloc::boxed::Box;
@@ -191,6 +185,8 @@ mod pallet {
191185
type DomainRegistration: DomainRegistration;
192186
/// Channels fee model
193187
type ChannelFeeModel: Get<FeeModel<BalanceOf<Self>>>;
188+
/// Maximum outgoing messages from a given channel
189+
type MaxOutgoingMessages: Get<u32>;
194190
}
195191

196192
/// Pallet messenger used to communicate between chains and other blockchains.
@@ -243,25 +239,21 @@ mod pallet {
243239
/// Used by the dst_chains to verify the message response.
244240
#[pallet::storage]
245241
#[pallet::getter(fn inbox_responses)]
246-
pub(super) type InboxResponses<T: Config> = CountedStorageMap<
247-
_,
248-
Identity,
249-
(ChainId, ChannelId, Nonce),
250-
Message<BalanceOf<T>>,
251-
OptionQuery,
252-
>;
242+
pub(super) type InboxResponses<T: Config> =
243+
StorageMap<_, Identity, (ChainId, ChannelId, Nonce), Message<BalanceOf<T>>, OptionQuery>;
253244

254245
/// Stores the outgoing messages that are awaiting message responses from the dst_chain.
255246
/// Messages are processed in the outbox nonce order of chain's channel.
256247
#[pallet::storage]
257248
#[pallet::getter(fn outbox)]
258-
pub(super) type Outbox<T: Config> = CountedStorageMap<
259-
_,
260-
Identity,
261-
(ChainId, ChannelId, Nonce),
262-
Message<BalanceOf<T>>,
263-
OptionQuery,
264-
>;
249+
pub(super) type Outbox<T: Config> =
250+
StorageMap<_, Identity, (ChainId, ChannelId, Nonce), Message<BalanceOf<T>>, OptionQuery>;
251+
252+
/// Stores the outgoing messages count that are awaiting message responses from the dst_chain.
253+
#[pallet::storage]
254+
#[pallet::getter(fn outbox_message_count)]
255+
pub(super) type OutboxMessageCount<T: Config> =
256+
StorageMap<_, Identity, (ChainId, ChannelId), u32, ValueQuery>;
265257

266258
/// A temporary storage for storing decoded outbox response message between `pre_dispatch_relay_message_response`
267259
/// and `relay_message_response`.
@@ -545,6 +537,15 @@ mod pallet {
545537

546538
/// Invalid channel reserve fee
547539
InvalidChannelReserveFee,
540+
541+
/// Invalid max outgoing messages
542+
InvalidMaxOutgoingMessages,
543+
544+
/// Message count overflow
545+
MessageCountOverflow,
546+
547+
/// Message count underflow
548+
MessageCountUnderflow,
548549
}
549550

550551
#[pallet::call]
@@ -554,11 +555,7 @@ mod pallet {
554555
/// Channel is set to initiated and do not accept or receive any messages.
555556
#[pallet::call_index(0)]
556557
#[pallet::weight(T::WeightInfo::initiate_channel())]
557-
pub fn initiate_channel(
558-
origin: OriginFor<T>,
559-
dst_chain_id: ChainId,
560-
params: InitiateChannelParams,
561-
) -> DispatchResult {
558+
pub fn initiate_channel(origin: OriginFor<T>, dst_chain_id: ChainId) -> DispatchResult {
562559
let owner = ensure_signed(origin)?;
563560

564561
// reserve channel open fees
@@ -575,7 +572,7 @@ mod pallet {
575572

576573
// initiate the channel config
577574
let channel_open_params = ChannelOpenParams {
578-
max_outgoing_messages: params.max_outgoing_messages,
575+
max_outgoing_messages: T::MaxOutgoingMessages::get(),
579576
fee_model: T::ChannelFeeModel::get(),
580577
};
581578
let channel_id = Self::do_init_channel(
@@ -907,8 +904,11 @@ mod pallet {
907904
// loop through channels in descending order until open channel is found.
908905
// we always prefer latest opened channel.
909906
while let Some(channel_id) = next_channel_id.checked_sub(ChannelId::one()) {
907+
let message_count = OutboxMessageCount::<T>::get((dst_chain_id, channel_id));
910908
if let Some(channel) = Channels::<T>::get(dst_chain_id, channel_id) {
911-
if channel.state == ChannelState::Open {
909+
if channel.state == ChannelState::Open
910+
&& message_count < channel.max_outgoing_messages
911+
{
912912
return Some((channel_id, channel.fee));
913913
}
914914
}
@@ -1006,6 +1006,12 @@ mod pallet {
10061006
Error::<T>::InvalidChain,
10071007
);
10081008

1009+
// ensure max outgoing messages is at least 1
1010+
ensure!(
1011+
init_params.max_outgoing_messages >= 1u32,
1012+
Error::<T>::InvalidMaxOutgoingMessages
1013+
);
1014+
10091015
// If the channel owner is in this chain then the channel reserve fee
10101016
// must not be empty
10111017
ensure!(

domains/pallets/messenger/src/messages.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[cfg(not(feature = "std"))]
22
extern crate alloc;
33

4-
use crate::pallet::{ChainAllowlist, UpdatedChannels};
4+
use crate::pallet::{ChainAllowlist, OutboxMessageCount, UpdatedChannels};
55
use crate::{
66
BalanceOf, ChannelId, ChannelState, Channels, CloseChannelBy, Config, Error, Event,
77
InboxResponses, MessageWeightTags as MessageWeightTagStore, Nonce, Outbox, OutboxMessageResult,
@@ -52,7 +52,7 @@ impl<T: Config> Pallet<T> {
5252
|maybe_channel| -> Result<Nonce, DispatchError> {
5353
let channel = maybe_channel.as_mut().ok_or(Error::<T>::MissingChannel)?;
5454
// check if the outbox is full
55-
let count = Outbox::<T>::count();
55+
let count = OutboxMessageCount::<T>::get((dst_chain_id, channel_id));
5656
ensure!(
5757
count < channel.max_outgoing_messages,
5858
Error::<T>::OutboxFull
@@ -72,6 +72,15 @@ impl<T: Config> Pallet<T> {
7272
.latest_response_received_message_nonce,
7373
};
7474
Outbox::<T>::insert((dst_chain_id, channel_id, next_outbox_nonce), msg);
75+
OutboxMessageCount::<T>::try_mutate(
76+
(dst_chain_id, channel_id),
77+
|count| -> Result<(), DispatchError> {
78+
*count = count
79+
.checked_add(1u32)
80+
.ok_or(Error::<T>::MessageCountOverflow)?;
81+
Ok(())
82+
},
83+
)?;
7584

7685
// update channel state
7786
channel.next_outbox_nonce = next_outbox_nonce
@@ -340,6 +349,16 @@ impl<T: Config> Pallet<T> {
340349
let req_msg = Outbox::<T>::take((dst_chain_id, channel_id, nonce))
341350
.ok_or(Error::<T>::MissingMessage)?;
342351

352+
OutboxMessageCount::<T>::try_mutate(
353+
(dst_chain_id, channel_id),
354+
|count| -> Result<(), DispatchError> {
355+
*count = count
356+
.checked_sub(1u32)
357+
.ok_or(Error::<T>::MessageCountUnderflow)?;
358+
Ok(())
359+
},
360+
)?;
361+
343362
// clear out box message weight tag
344363
MessageWeightTagStore::<T>::mutate(|maybe_messages| {
345364
let mut messages = maybe_messages.as_mut().cloned().unwrap_or_default();

domains/pallets/messenger/src/mock.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ macro_rules! impl_runtime {
6060
pub const ChannelReserveFee: Balance = 10;
6161
pub const ChannelInitReservePortion: Perbill = Perbill::from_percent(20);
6262
pub const ChannelFeeModel: FeeModel<Balance> = FeeModel{relay_fee: 1};
63+
pub const MaxOutgoingMessages: u32 = 25;
6364
}
6465

6566
#[derive(
@@ -102,6 +103,7 @@ macro_rules! impl_runtime {
102103
type HoldIdentifier = MockHoldIdentifer;
103104
type DomainRegistration = DomainRegistration;
104105
type ChannelFeeModel = ChannelFeeModel;
106+
type MaxOutgoingMessages = MaxOutgoingMessages;
105107
/// function to fetch endpoint response handler by Endpoint.
106108
fn get_endpoint_handler(
107109
#[allow(unused_variables)] endpoint: &Endpoint,

0 commit comments

Comments
 (0)