Merge branch 'master' into gav-xcm-v3

This commit is contained in:
Keith Yeung
2022-09-22 21:36:30 +08:00
203 changed files with 5861 additions and 3564 deletions
+110 -86
View File
@@ -24,7 +24,8 @@
use codec::{Decode, DecodeLimit, Encode};
use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler};
use frame_support::{
dispatch::Weight, traits::EnsureOrigin, weights::constants::WEIGHT_PER_MILLIS,
traits::EnsureOrigin,
weights::{constants::WEIGHT_PER_MILLIS, Weight},
};
pub use pallet::*;
use scale_info::TypeInfo;
@@ -43,7 +44,7 @@ pub struct ConfigData {
impl Default for ConfigData {
fn default() -> Self {
Self {
max_individual: 10 * WEIGHT_PER_MILLIS, // 10 ms of execution time maximum by default
max_individual: 10u64 * WEIGHT_PER_MILLIS, // 10 ms of execution time maximum by default
}
}
}
@@ -84,12 +85,12 @@ pub mod pallet {
#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type XcmExecutor: ExecuteXcm<Self::Call>;
type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
/// Origin which is allowed to execute overweight messages.
type ExecuteOverweightOrigin: EnsureOrigin<Self::Origin>;
type ExecuteOverweightOrigin: EnsureOrigin<Self::RuntimeOrigin>;
}
/// The configuration.
@@ -140,7 +141,7 @@ pub mod pallet {
///
/// Events:
/// - `OverweightServiced`: On success.
#[pallet::weight(weight_limit.saturating_add(1_000_000))]
#[pallet::weight(weight_limit.saturating_add(Weight::from_ref_time(1_000_000)))]
pub fn service_overweight(
origin: OriginFor<T>,
index: OverweightIndex,
@@ -153,7 +154,7 @@ pub mod pallet {
.map_err(|_| Error::<T>::OverLimit)?;
Overweight::<T>::remove(index);
Self::deposit_event(Event::OverweightServiced { overweight_index: index, weight_used });
Ok(Some(weight_used.saturating_add(1_000_000)).into())
Ok(Some(weight_used.saturating_add(Weight::from_ref_time(1_000_000))).into())
}
}
@@ -189,7 +190,7 @@ pub mod pallet {
/// Exactly equivalent to `service_queue` but expects a mutable `page_index` to be passed
/// in and any changes stored.
fn do_service_queue(limit: Weight, page_index: &mut PageIndexData) -> Weight {
let mut used = 0;
let mut used = Weight::zero();
while page_index.begin_used < page_index.end_used {
let page = Pages::<T>::take(page_index.begin_used);
for (i, &(sent_at, ref data)) in page.iter().enumerate() {
@@ -224,27 +225,27 @@ pub mod pallet {
mut data: &[u8],
) -> Result<Weight, (MessageId, Weight)> {
let message_id = sp_io::hashing::blake2_256(data);
let maybe_msg = VersionedXcm::<T::Call>::decode_all_with_depth_limit(
let maybe_msg = VersionedXcm::<T::RuntimeCall>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut data,
)
.map(Xcm::<T::Call>::try_from);
.map(Xcm::<T::RuntimeCall>::try_from);
match maybe_msg {
Err(_) => {
Self::deposit_event(Event::InvalidFormat { message_id });
Ok(0)
Ok(Weight::zero())
},
Ok(Err(())) => {
Self::deposit_event(Event::UnsupportedVersion { message_id });
Ok(0)
Ok(Weight::zero())
},
Ok(Ok(x)) => {
let outcome = T::XcmExecutor::execute_xcm(Parent, x, message_id, limit);
let outcome = T::XcmExecutor::execute_xcm(Parent, x, message_id, limit.ref_time());
match outcome {
Outcome::Error(XcmError::WeightLimitReached(required)) =>
Err((message_id, required)),
Err((message_id, Weight::from_ref_time(required))),
outcome => {
let weight_used = outcome.weight_used();
let weight_used = Weight::from_ref_time(outcome.weight_used());
Self::deposit_event(Event::ExecutedDownward { message_id, outcome });
Ok(weight_used)
},
@@ -287,7 +288,7 @@ pub mod pallet {
Err((message_id, required_weight)) =>
// Too much weight required right now.
{
if required_weight > config.max_individual {
if required_weight.any_gt(config.max_individual) {
// overweight - add to overweight queue and continue with
// message execution.
let overweight_index = page_index.overweight_count;
@@ -349,11 +350,11 @@ mod tests {
};
use sp_version::RuntimeVersion;
use std::cell::RefCell;
use xcm::latest::{MultiLocation, OriginKind};
use xcm::latest::{MultiLocation, OriginKind, Weight as XCMWeight};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
type Xcm = xcm::latest::Xcm<Call>;
type Xcm = xcm::latest::Xcm<RuntimeCall>;
frame_support::construct_runtime!(
pub enum Test where
@@ -379,15 +380,15 @@ mod tests {
state_version: 1,
};
pub const ParachainId: ParaId = ParaId::new(200);
pub const ReservedXcmpWeight: Weight = 0;
pub const ReservedDmpWeight: Weight = 0;
pub const ReservedXcmpWeight: Weight = Weight::zero();
pub const ReservedDmpWeight: Weight = Weight::zero();
}
type AccountId = u64;
impl frame_system::Config for Test {
type Origin = Origin;
type Call = Call;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
@@ -395,7 +396,7 @@ mod tests {
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type BlockLength = ();
type BlockWeights = ();
@@ -443,7 +444,7 @@ mod tests {
_origin: impl Into<MultiLocation>,
_: Weightless,
_hash: XcmHash,
_weight_limit: Weight,
_weight_limit: XCMWeight,
) -> Outcome {
unreachable!()
}
@@ -454,7 +455,7 @@ mod tests {
}
impl Config for Test {
type Event = Event;
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = MockExec;
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
}
@@ -470,7 +471,7 @@ mod tests {
index.end_used,
enqueued
.iter()
.map(|m| (0, VersionedXcm::<Call>::from(m.clone()).encode()))
.map(|m| (0, VersionedXcm::<RuntimeCall>::from(m.clone()).encode()))
.collect::<Vec<_>>(),
);
index.end_used += 1;
@@ -479,11 +480,13 @@ mod tests {
}
fn handle_messages(incoming: &[Xcm], limit: Weight) -> Weight {
let iter = incoming.iter().map(|m| (0, VersionedXcm::<Call>::from(m.clone()).encode()));
let iter = incoming
.iter()
.map(|m| (0, VersionedXcm::<RuntimeCall>::from(m.clone()).encode()));
DmpQueue::handle_dmp_messages(iter, limit)
}
fn msg(weight: Weight) -> Xcm {
fn msg(weight: XCMWeight) -> Xcm {
Xcm(vec![Transact {
origin_kind: OriginKind::Native,
require_weight_at_most: weight,
@@ -491,11 +494,11 @@ mod tests {
}])
}
fn msg_complete(weight: Weight) -> (Xcm, Outcome) {
fn msg_complete(weight: XCMWeight) -> (Xcm, Outcome) {
(msg(weight), Outcome::Complete(weight))
}
fn msg_limit_reached(weight: Weight) -> (Xcm, Outcome) {
fn msg_limit_reached(weight: XCMWeight) -> (Xcm, Outcome) {
(msg(weight), Outcome::Error(XcmError::WeightLimitReached(weight)))
}
@@ -516,8 +519,8 @@ mod tests {
#[test]
fn basic_setup_works() {
new_test_ext().execute_with(|| {
let weight_used = handle_messages(&[], 1000);
assert_eq!(weight_used, 0);
let weight_used = handle_messages(&[], Weight::from_ref_time(1000));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), Vec::new());
assert!(queue_is_empty());
});
@@ -527,8 +530,8 @@ mod tests {
fn service_inline_complete_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 2001);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001)]);
assert!(queue_is_empty());
});
@@ -539,8 +542,8 @@ mod tests {
new_test_ext().execute_with(|| {
let enqueued = vec![msg(1000), msg(1001), msg(1002)];
enqueue(&enqueued);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2001);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
@@ -552,8 +555,8 @@ mod tests {
fn enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, 999);
assert_eq!(weight_used, 0);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(999));
assert_eq!(weight_used, Weight::zero());
assert_eq!(
PageIndex::<Test>::get(),
PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0 }
@@ -561,15 +564,15 @@ mod tests {
assert_eq!(Pages::<Test>::get(0).len(), 3);
assert_eq!(take_trace(), vec![msg_limit_reached(1000)]);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2001);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 1002);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(1002));
assert_eq!(take_trace(), vec![msg_complete(1002),]);
assert!(queue_is_empty());
});
@@ -579,14 +582,14 @@ mod tests {
fn service_inline_then_enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, 1500);
assert_eq!(weight_used, 1000);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(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),]);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2003);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2003));
assert_eq!(take_trace(), vec![msg_complete(1001), msg_complete(1002),]);
assert!(queue_is_empty());
});
@@ -598,8 +601,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 4006);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(4006));
assert_eq!(
take_trace(),
vec![
@@ -619,19 +622,19 @@ mod tests {
let enqueued = vec![msg(1000), msg(10001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 1000);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(1000));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(10001),]);
assert_eq!(pages_queued(), 2);
// 5000 is not enough to process the 10001 blocker, so nothing happens.
let weight_used = handle_messages(&[], 5000);
assert_eq!(weight_used, 0);
let weight_used = handle_messages(&[], Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), vec![msg_limit_reached(10001),]);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 12006);
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(12006));
assert_eq!(
take_trace(),
vec![msg_complete(10001), msg_complete(1002), msg_complete(1003),]
@@ -646,8 +649,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(10002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 2001);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(10002),]
@@ -655,8 +658,8 @@ mod tests {
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 11005);
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(11005));
assert_eq!(take_trace(), vec![msg_complete(10002), msg_complete(1003),]);
assert!(queue_is_empty());
});
@@ -668,8 +671,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(10003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 3003);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(3003));
assert_eq!(
take_trace(),
vec![
@@ -682,8 +685,8 @@ mod tests {
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 10003);
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(10003));
assert_eq!(take_trace(), vec![msg_complete(10003),]);
assert!(queue_is_empty());
});
@@ -694,20 +697,20 @@ mod tests {
new_test_ext().execute_with(|| {
let enqueued = vec![msg(1000), msg(1001)];
enqueue(&enqueued);
let weight_used = handle_messages(&vec![msg(1002)], 1500);
assert_eq!(weight_used, 1000);
let weight_used = handle_messages(&vec![msg(1002)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1000));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 0);
let weight_used = handle_messages(&vec![msg(1003)], 1500);
assert_eq!(weight_used, 1001);
let weight_used = handle_messages(&vec![msg(1003)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1001));
assert_eq!(take_trace(), vec![msg_complete(1001), msg_limit_reached(1002),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 1);
let weight_used = handle_messages(&vec![msg(1004)], 1500);
assert_eq!(weight_used, 1002);
let weight_used = handle_messages(&vec![msg(1004)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1002));
assert_eq!(take_trace(), vec![msg_complete(1002), msg_limit_reached(1003),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 2);
@@ -718,11 +721,11 @@ mod tests {
fn overweight_should_not_block_queue() {
new_test_ext().execute_with(|| {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: 9999 });
Configuration::<Test>::put(ConfigData { max_individual: Weight::from_ref_time(9999) });
let incoming = vec![msg(1000), msg(10001), msg(1002)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 2002);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2002));
assert!(queue_is_empty());
assert_eq!(
take_trace(),
@@ -737,37 +740,58 @@ mod tests {
fn overweights_should_be_manually_executable() {
new_test_ext().execute_with(|| {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: 9999 });
Configuration::<Test>::put(ConfigData { max_individual: Weight::from_ref_time(9999) });
let incoming = vec![msg(10000)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 0);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
assert_eq!(overweights(), vec![0]);
assert_noop!(DmpQueue::service_overweight(Origin::signed(1), 0, 20000), BadOrigin);
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 1, 20000),
DmpQueue::service_overweight(
RuntimeOrigin::signed(1),
0,
Weight::from_ref_time(20000)
),
BadOrigin
);
assert_noop!(
DmpQueue::service_overweight(
RuntimeOrigin::root(),
1,
Weight::from_ref_time(20000)
),
Error::<Test>::Unknown
);
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 0, 9999),
DmpQueue::service_overweight(RuntimeOrigin::root(), 0, Weight::from_ref_time(9999)),
Error::<Test>::OverLimit
);
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
let base_weight = super::Call::<Test>::service_overweight { index: 0, weight_limit: 0 }
.get_dispatch_info()
.weight;
use frame_support::weights::GetDispatchInfo;
let info = DmpQueue::service_overweight(Origin::root(), 0, 20000).unwrap();
let base_weight =
super::Call::<Test>::service_overweight { index: 0, weight_limit: Weight::zero() }
.get_dispatch_info()
.weight;
use frame_support::dispatch::GetDispatchInfo;
let info = DmpQueue::service_overweight(
RuntimeOrigin::root(),
0,
Weight::from_ref_time(20000),
)
.unwrap();
let actual_weight = info.actual_weight.unwrap();
assert_eq!(actual_weight, base_weight + 10000);
assert_eq!(actual_weight, base_weight + Weight::from_ref_time(10000));
assert_eq!(take_trace(), vec![msg_complete(10000)]);
assert!(overweights().is_empty());
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 0, 20000),
DmpQueue::service_overweight(
RuntimeOrigin::root(),
0,
Weight::from_ref_time(20000)
),
Error::<Test>::Unknown
);
});
@@ -780,8 +804,8 @@ mod tests {
enqueue(&vec![msg(1002), msg(1003)]);
enqueue(&vec![msg(1004), msg(1005)]);
let weight_used = DmpQueue::on_idle(1, 6000);
assert_eq!(weight_used, 5010);
let weight_used = DmpQueue::on_idle(1, Weight::from_ref_time(6000));
assert_eq!(weight_used, Weight::from_ref_time(5010));
assert_eq!(
take_trace(),
vec![