Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f9113a4
Fixes for new API
gavofyork May 19, 2023
64946e7
Formatting
gavofyork May 19, 2023
286d7f2
Fixes
gavofyork May 19, 2023
7e2cdb9
Fixes
gavofyork May 19, 2023
99528a9
Further fixes
gavofyork May 19, 2023
9bccddd
XCMP dispatch events mention message ID
gavofyork May 19, 2023
587817c
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 19, 2023
acc04f9
XCMP event includes ID
gavofyork May 19, 2023
cd7beb7
Add DMP message ID functionality
gavofyork May 19, 2023
8b26ce6
Integrate into test parachains
gavofyork May 19, 2023
9862e03
Remove WithUniqueTopic usage
gavofyork May 19, 2023
727c2c3
Use new primitive
gavofyork May 21, 2023
c1f6e61
Formatting
gavofyork May 21, 2023
1450622
undiener
gavofyork May 21, 2023
8f363fc
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 21, 2023
b142f9b
Revert lock
gavofyork May 21, 2023
e3f94df
Fixes
gavofyork May 21, 2023
64300ad
Fixes
gavofyork May 21, 2023
c80c597
Fixes
gavofyork May 21, 2023
5c77d73
Fixes
gavofyork May 21, 2023
23c4cad
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 22, 2023
a2195e6
Formatting
gavofyork May 23, 2023
77a982a
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 24, 2023
f145f0c
message_hash becomes message_id
gavofyork May 24, 2023
9e7dec5
Rename
gavofyork May 24, 2023
174c837
Another Rename
gavofyork May 24, 2023
e7a6ca2
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 24, 2023
9df73c4
Fixes
gavofyork May 24, 2023
d7184f7
Fix
gavofyork May 24, 2023
7fa8116
Merge remote-tracking branch 'origin/master' into gav-unique-topics
gavofyork May 25, 2023
006ebbc
Bump
gavofyork May 25, 2023
422de36
Fixes
gavofyork May 25, 2023
f26e7c6
Grumble.
gavofyork May 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 68 additions & 67 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ opt-level = 3
inherits = "release"
lto = true
codegen-units = 1

168 changes: 81 additions & 87 deletions pallets/dmp-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -250,30 +266,41 @@ 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,
)
.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)
},
}
Expand Down Expand Up @@ -314,15 +341,19 @@ 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.
let remaining_weight = limit.saturating_sub(used);
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 =
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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),]);
});
}

Expand All @@ -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());
});
}
Expand All @@ -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));
Expand Down Expand Up @@ -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));
Expand All @@ -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.
Expand All @@ -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);

Expand All @@ -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);
});
Expand All @@ -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]);
});
Expand All @@ -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!(
Expand All @@ -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() }
Expand Down Expand Up @@ -891,7 +886,6 @@ mod tests {
msg_complete(1002),
msg_complete(1003),
msg_complete(1004),
msg_limit_reached(1005),
]
);
assert_eq!(pages_queued(), 1);
Expand Down
Loading