mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 04:41:02 +00:00
Companion for polkadot#7234 (XCM: Tools for uniquely referencing messages) (#2601)
* Fixes for new API * Formatting * Fixes * Fixes * Further fixes * XCMP dispatch events mention message ID * XCMP event includes ID * Add DMP message ID functionality * Integrate into test parachains * Remove WithUniqueTopic usage * Use new primitive * Formatting * undiener * Revert lock * Fixes * Fixes * Fixes * Fixes * Formatting * message_hash becomes message_id * Rename * Another Rename * Fixes * Fix * Bump * Fixes * Grumble.
This commit is contained in:
@@ -75,7 +75,7 @@ pub struct PageIndexData {
|
||||
|
||||
/// Simple type used to identify messages for the purpose of reporting events. Secure if and only
|
||||
/// if the message content is unique.
|
||||
pub type MessageId = [u8; 32];
|
||||
pub type MessageId = XcmHash;
|
||||
|
||||
/// Index used to identify overweight messages.
|
||||
pub type OverweightIndex = u64;
|
||||
@@ -174,23 +174,39 @@ pub mod pallet {
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
/// Downward message is invalid XCM.
|
||||
InvalidFormat { message_id: MessageId },
|
||||
InvalidFormat { message_hash: XcmHash },
|
||||
/// Downward message is unsupported version of XCM.
|
||||
UnsupportedVersion { message_id: MessageId },
|
||||
UnsupportedVersion { message_hash: XcmHash },
|
||||
/// Downward message executed with the given outcome.
|
||||
ExecutedDownward { message_id: MessageId, outcome: Outcome },
|
||||
ExecutedDownward { message_hash: XcmHash, message_id: XcmHash, outcome: Outcome },
|
||||
/// The weight limit for handling downward messages was reached.
|
||||
WeightExhausted { message_id: MessageId, remaining_weight: Weight, required_weight: Weight },
|
||||
WeightExhausted {
|
||||
message_hash: XcmHash,
|
||||
message_id: XcmHash,
|
||||
remaining_weight: Weight,
|
||||
required_weight: Weight,
|
||||
},
|
||||
/// Downward message is overweight and was placed in the overweight queue.
|
||||
OverweightEnqueued {
|
||||
message_id: MessageId,
|
||||
message_hash: XcmHash,
|
||||
message_id: XcmHash,
|
||||
overweight_index: OverweightIndex,
|
||||
required_weight: Weight,
|
||||
},
|
||||
/// Downward message from the overweight queue was executed.
|
||||
OverweightServiced { overweight_index: OverweightIndex, weight_used: Weight },
|
||||
/// The maximum number of downward messages was.
|
||||
MaxMessagesExhausted { message_id: MessageId },
|
||||
/// The maximum number of downward messages was reached.
|
||||
MaxMessagesExhausted { message_hash: XcmHash },
|
||||
}
|
||||
|
||||
/// Error type when a message was failed to be serviced.
|
||||
pub(crate) struct ServiceMessageError {
|
||||
/// The message's hash.
|
||||
message_hash: XcmHash,
|
||||
/// The message's ID (which could also be its hash if nothing overrides it).
|
||||
message_id: XcmHash,
|
||||
/// Weight required for the message to be executed.
|
||||
required_weight: Weight,
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
@@ -250,8 +266,9 @@ pub mod pallet {
|
||||
limit: Weight,
|
||||
_sent_at: RelayBlockNumber,
|
||||
mut data: &[u8],
|
||||
) -> Result<Weight, (MessageId, Weight)> {
|
||||
let message_id = sp_io::hashing::blake2_256(data);
|
||||
) -> Result<Weight, ServiceMessageError> {
|
||||
let message_hash = sp_io::hashing::blake2_256(data);
|
||||
let mut message_id = message_hash;
|
||||
let maybe_msg = VersionedXcm::<T::RuntimeCall>::decode_all_with_depth_limit(
|
||||
MAX_XCM_DECODE_DEPTH,
|
||||
&mut data,
|
||||
@@ -259,21 +276,31 @@ pub mod pallet {
|
||||
.map(Xcm::<T::RuntimeCall>::try_from);
|
||||
match maybe_msg {
|
||||
Err(_) => {
|
||||
Self::deposit_event(Event::InvalidFormat { message_id });
|
||||
Self::deposit_event(Event::InvalidFormat { message_hash });
|
||||
Ok(Weight::zero())
|
||||
},
|
||||
Ok(Err(())) => {
|
||||
Self::deposit_event(Event::UnsupportedVersion { message_id });
|
||||
Self::deposit_event(Event::UnsupportedVersion { message_hash });
|
||||
Ok(Weight::zero())
|
||||
},
|
||||
Ok(Ok(x)) => {
|
||||
let outcome = T::XcmExecutor::execute_xcm(Parent, x, message_id, limit);
|
||||
let outcome = T::XcmExecutor::prepare_and_execute(
|
||||
Parent,
|
||||
x,
|
||||
&mut message_id,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
match outcome {
|
||||
Outcome::Error(XcmError::WeightLimitReached(required)) =>
|
||||
Err((message_id, required)),
|
||||
Outcome::Error(XcmError::WeightLimitReached(required_weight)) =>
|
||||
Err(ServiceMessageError { message_hash, message_id, required_weight }),
|
||||
outcome => {
|
||||
let weight_used = outcome.weight_used();
|
||||
Self::deposit_event(Event::ExecutedDownward { message_id, outcome });
|
||||
Self::deposit_event(Event::ExecutedDownward {
|
||||
message_hash,
|
||||
message_id,
|
||||
outcome,
|
||||
});
|
||||
Ok(weight_used)
|
||||
},
|
||||
}
|
||||
@@ -314,7 +341,7 @@ pub mod pallet {
|
||||
maybe_enqueue_page = Some(Vec::with_capacity(item_count_left));
|
||||
|
||||
Self::deposit_event(Event::MaxMessagesExhausted {
|
||||
message_id: sp_io::hashing::blake2_256(&data),
|
||||
message_hash: sp_io::hashing::blake2_256(&data),
|
||||
});
|
||||
} else {
|
||||
// We're not currently enqueuing - try to execute inline.
|
||||
@@ -322,7 +349,11 @@ pub mod pallet {
|
||||
messages_processed += 1;
|
||||
match Self::try_service_message(remaining_weight, sent_at, &data[..]) {
|
||||
Ok(consumed) => used += consumed,
|
||||
Err((message_id, required_weight)) =>
|
||||
Err(ServiceMessageError {
|
||||
message_hash,
|
||||
message_id,
|
||||
required_weight,
|
||||
}) =>
|
||||
// Too much weight required right now.
|
||||
{
|
||||
let is_under_limit =
|
||||
@@ -334,6 +365,7 @@ pub mod pallet {
|
||||
let overweight_index = page_index.overweight_count;
|
||||
Overweight::<T>::insert(overweight_index, (sent_at, data));
|
||||
Self::deposit_event(Event::OverweightEnqueued {
|
||||
message_hash,
|
||||
message_id,
|
||||
overweight_index,
|
||||
required_weight,
|
||||
@@ -348,6 +380,7 @@ pub mod pallet {
|
||||
let item_count_left = item_count.saturating_sub(i);
|
||||
maybe_enqueue_page = Some(Vec::with_capacity(item_count_left));
|
||||
Self::deposit_event(Event::WeightExhausted {
|
||||
message_hash,
|
||||
message_id,
|
||||
remaining_weight,
|
||||
required_weight,
|
||||
@@ -466,50 +499,36 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
pub enum Weightless {}
|
||||
impl PreparedMessage for Weightless {
|
||||
pub struct MockPrepared(Xcm);
|
||||
impl PreparedMessage for MockPrepared {
|
||||
fn weight_of(&self) -> Weight {
|
||||
unreachable!()
|
||||
match ((self.0).0.len(), &(self.0).0.first()) {
|
||||
(1, Some(Transact { require_weight_at_most, .. })) => *require_weight_at_most,
|
||||
_ => Weight::from_parts(1, 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockExec;
|
||||
impl ExecuteXcm<RuntimeCall> for MockExec {
|
||||
type Prepared = Weightless;
|
||||
type Prepared = MockPrepared;
|
||||
|
||||
fn prepare(_message: Xcm) -> Result<Self::Prepared, Xcm> {
|
||||
unreachable!()
|
||||
fn prepare(message: Xcm) -> Result<Self::Prepared, Xcm> {
|
||||
Ok(MockPrepared(message))
|
||||
}
|
||||
|
||||
fn execute(
|
||||
_origin: impl Into<MultiLocation>,
|
||||
_pre: Weightless,
|
||||
_hash: XcmHash,
|
||||
_weight_credit: Weight,
|
||||
) -> Outcome {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn execute_xcm_in_credit(
|
||||
_origin: impl Into<MultiLocation>,
|
||||
message: Xcm,
|
||||
_hash: XcmHash,
|
||||
weight_limit: Weight,
|
||||
prepared: MockPrepared,
|
||||
_id: &mut XcmHash,
|
||||
_weight_credit: Weight,
|
||||
) -> Outcome {
|
||||
let message = prepared.0;
|
||||
let o = match (message.0.len(), &message.0.first()) {
|
||||
(1, Some(Transact { require_weight_at_most, .. })) => {
|
||||
if require_weight_at_most.all_lte(weight_limit) {
|
||||
Outcome::Complete(*require_weight_at_most)
|
||||
} else {
|
||||
Outcome::Error(XcmError::WeightLimitReached(*require_weight_at_most))
|
||||
}
|
||||
},
|
||||
(1, Some(Transact { require_weight_at_most, .. })) =>
|
||||
Outcome::Complete(*require_weight_at_most),
|
||||
// use 1000 to decide that it's not supported.
|
||||
_ => Outcome::Incomplete(
|
||||
Weight::from_parts(1000, 1000).min(weight_limit),
|
||||
XcmError::Unimplemented,
|
||||
),
|
||||
_ => Outcome::Incomplete(Weight::from_parts(1, 1), XcmError::Unimplemented),
|
||||
};
|
||||
TRACE.with(|q| q.borrow_mut().push((message, o.clone())));
|
||||
o
|
||||
@@ -564,13 +583,6 @@ mod tests {
|
||||
(msg(weight), Outcome::Complete(Weight::from_parts(weight, weight)))
|
||||
}
|
||||
|
||||
fn msg_limit_reached(weight: u64) -> (Xcm, Outcome) {
|
||||
(
|
||||
msg(weight),
|
||||
Outcome::Error(XcmError::WeightLimitReached(Weight::from_parts(weight, weight))),
|
||||
)
|
||||
}
|
||||
|
||||
fn pages_queued() -> PageCounter {
|
||||
PageIndex::<Test>::get().end_used - PageIndex::<Test>::get().begin_used
|
||||
}
|
||||
@@ -613,10 +625,7 @@ mod tests {
|
||||
enqueue(&enqueued);
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
|
||||
assert_eq!(
|
||||
take_trace(),
|
||||
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
|
||||
);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001),]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -631,18 +640,15 @@ mod tests {
|
||||
PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0 }
|
||||
);
|
||||
assert_eq!(Pages::<Test>::get(0).len(), 3);
|
||||
assert_eq!(take_trace(), vec![msg_limit_reached(1000)]);
|
||||
assert_eq!(take_trace(), vec![]);
|
||||
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
|
||||
assert_eq!(
|
||||
take_trace(),
|
||||
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
|
||||
);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001)]);
|
||||
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::from_parts(1002, 1002));
|
||||
assert_eq!(take_trace(), vec![msg_complete(1002),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1002)]);
|
||||
assert!(queue_is_empty());
|
||||
});
|
||||
}
|
||||
@@ -655,7 +661,7 @@ mod tests {
|
||||
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
|
||||
assert_eq!(pages_queued(), 1);
|
||||
assert_eq!(Pages::<Test>::get(0).len(), 2);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000)]);
|
||||
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::from_parts(2003, 2003));
|
||||
@@ -693,13 +699,13 @@ mod tests {
|
||||
enqueue(&enqueued);
|
||||
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
|
||||
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(10001),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000)]);
|
||||
assert_eq!(pages_queued(), 2);
|
||||
|
||||
// 5000 is not enough to process the 10001 blocker, so nothing happens.
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(5000, 5000));
|
||||
assert_eq!(weight_used, Weight::zero());
|
||||
assert_eq!(take_trace(), vec![msg_limit_reached(10001),]);
|
||||
assert_eq!(take_trace(), vec![]);
|
||||
|
||||
// 20000 is now enough to process everything.
|
||||
let weight_used = handle_messages(&[], Weight::from_parts(20000, 20000));
|
||||
@@ -720,10 +726,7 @@ mod tests {
|
||||
enqueue(&enqueued);
|
||||
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
|
||||
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
|
||||
assert_eq!(
|
||||
take_trace(),
|
||||
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(10002),]
|
||||
);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001)]);
|
||||
assert_eq!(pages_queued(), 1);
|
||||
|
||||
// 20000 is now enough to process everything.
|
||||
@@ -744,12 +747,7 @@ mod tests {
|
||||
assert_eq!(weight_used, Weight::from_parts(3003, 3003));
|
||||
assert_eq!(
|
||||
take_trace(),
|
||||
vec![
|
||||
msg_complete(1000),
|
||||
msg_complete(1001),
|
||||
msg_complete(1002),
|
||||
msg_limit_reached(10003),
|
||||
]
|
||||
vec![msg_complete(1000), msg_complete(1001), msg_complete(1002),]
|
||||
);
|
||||
assert_eq!(pages_queued(), 1);
|
||||
|
||||
@@ -768,19 +766,19 @@ mod tests {
|
||||
enqueue(&enqueued);
|
||||
let weight_used = handle_messages(&[msg(1002)], Weight::from_parts(1500, 1500));
|
||||
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000)]);
|
||||
assert_eq!(pages_queued(), 2);
|
||||
assert_eq!(PageIndex::<Test>::get().begin_used, 0);
|
||||
|
||||
let weight_used = handle_messages(&[msg(1003)], Weight::from_parts(1500, 1500));
|
||||
assert_eq!(weight_used, Weight::from_parts(1001, 1001));
|
||||
assert_eq!(take_trace(), vec![msg_complete(1001), msg_limit_reached(1002),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1001)]);
|
||||
assert_eq!(pages_queued(), 2);
|
||||
assert_eq!(PageIndex::<Test>::get().begin_used, 1);
|
||||
|
||||
let weight_used = handle_messages(&[msg(1004)], Weight::from_parts(1500, 1500));
|
||||
assert_eq!(weight_used, Weight::from_parts(1002, 1002));
|
||||
assert_eq!(take_trace(), vec![msg_complete(1002), msg_limit_reached(1003),]);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1002)]);
|
||||
assert_eq!(pages_queued(), 2);
|
||||
assert_eq!(PageIndex::<Test>::get().begin_used, 2);
|
||||
});
|
||||
@@ -798,10 +796,7 @@ mod tests {
|
||||
let weight_used = handle_messages(&incoming, Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::from_parts(2002, 2002));
|
||||
assert!(queue_is_empty());
|
||||
assert_eq!(
|
||||
take_trace(),
|
||||
vec![msg_complete(1000), msg_limit_reached(10001), msg_complete(1002),]
|
||||
);
|
||||
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1002),]);
|
||||
|
||||
assert_eq!(overweights(), vec![0]);
|
||||
});
|
||||
@@ -818,7 +813,7 @@ mod tests {
|
||||
let incoming = vec![msg(10000)];
|
||||
let weight_used = handle_messages(&incoming, Weight::from_parts(2500, 2500));
|
||||
assert_eq!(weight_used, Weight::zero());
|
||||
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
|
||||
assert_eq!(take_trace(), vec![]);
|
||||
assert_eq!(overweights(), vec![0]);
|
||||
|
||||
assert_noop!(
|
||||
@@ -845,7 +840,7 @@ mod tests {
|
||||
),
|
||||
Error::<Test>::OverLimit
|
||||
);
|
||||
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
|
||||
assert_eq!(take_trace(), vec![]);
|
||||
|
||||
let base_weight =
|
||||
super::Call::<Test>::service_overweight { index: 0, weight_limit: Weight::zero() }
|
||||
@@ -891,7 +886,6 @@ mod tests {
|
||||
msg_complete(1002),
|
||||
msg_complete(1003),
|
||||
msg_complete(1004),
|
||||
msg_limit_reached(1005),
|
||||
]
|
||||
);
|
||||
assert_eq!(pages_queued(), 1);
|
||||
|
||||
Reference in New Issue
Block a user