mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Use Message Queue pallet for UMP dispatch (#6271)
* Add ProcessXcmMessage struct * Migrate away from weights in host config * New well-known key to report UMPQ capacity * Add missing file * Fixes * Remove original UMP files * Docs * Update runtime/parachains/src/inclusion/mod.rs Co-authored-by: asynchronous rob <rphmeier@gmail.com> * Add benchmarking * Benchmarks * Mock example of using the QueueChangeHandler to update the WKK * Use master Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Merge remote-tracking branch 'origin/master' into gav-message-queue * Update Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update remove-weight migration The migration got touched on master; just resolving conflicts here. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add message- to dispatch-origin conversion for XCM processing Just using the `impl Into<MultiLocation>` was a bit inflexible. Like this, the Relaychain can convert `UMP(para)` to a MultiLocation `para`. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * DNM: Temporarily comment code since XCMv3 is not merged yet Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use u64 for queue-wide limits on UmpAcceptanceCheckErr Using u32 here was one audit finding for the queue pallet. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Define one sub-queue per *MP queue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Harden check_upward_messages Using safe math and casts. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add type-safe well_known_keys Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add message-queue weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Deploy MessageQueue to Polkadot Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update Cargo.toml Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Migrate to parachain config V5 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update UMP tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert messed up merge 🤦 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update remove-weight migration The migration got touched on master; just resolving conflicts here. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add message- to dispatch-origin conversion for XCM processing Just using the `impl Into<MultiLocation>` was a bit inflexible. Like this, the Relaychain can convert `UMP(para)` to a MultiLocation `para`. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * DNM: Temporarily comment code since XCMv3 is not merged yet Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use u64 for queue-wide limits on UmpAcceptanceCheckErr Using u32 here was one audit finding for the queue pallet. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Define one sub-queue per *MP queue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Harden check_upward_messages Using safe math and casts. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add type-safe well_known_keys Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add message-queue weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Deploy MessageQueue to Polkadot Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update Cargo.toml Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Migrate to parachain config V5 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update UMP tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make stuff compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move DMP and HRMP messages to the MessageQueue It currently does not compile in the CIbecause of some local tweaks to Substrate. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Diener for CI Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * diener update cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert wrong changes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "DNM: Temporarily comment code since XCMv3 is not merged yet" This reverts commit 820aa235cb21dd1d2621843607f7682bf035434e. * Make compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup runtimes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Define benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use master Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Lockfile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add AggregateMessageOrigin This enum currently only holds one value, but having it will make it easier in the future to extend. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Forbid UMP for off-boarding paras - Reject candidates with UMP messages for off-boarding paras - Forbid scheduling off-boarding when a para has unprocess UMPs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Delete stupid test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use BoundedVec for upward messages Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add weights and fix MessageProcessor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bound receive_upward_messages and check bound in configuration pallet Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bound Debug impl Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test runtime Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix xcm-simulator Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Properly fix xcm-simulator and fuzzer Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * cargo update -p sp-io Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Adapt to upstream Substrate changes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix ProcesseMessage impls Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Some tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use master Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * cargo update -p sp-io Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new MQ API Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add UMP while Para offboarding tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use Mocked message processor for benchmarking Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use variables for constants Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add MQ pallet weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use MQ pallet weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Configure QueueChangeHandler Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add config test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix MQ serive weight Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup outgoing UMP dispatch queues Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use Master Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update Cargo.lock Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Weight mul is not const Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove merge marker Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update runtime/parachains/src/inclusion/mod.rs Co-authored-by: Gavin Wood <gavin@parity.io> * Update runtime/kusama/src/lib.rs Co-authored-by: Gavin Wood <gavin@parity.io> * Use lowercase UMP Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clarify comment Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use Weight::from_parts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix doc Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Emit event after the fact Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add defensive_proof to receive_upward_messages Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Reapply "Remove original UMP files" Looks like they came back from the dead. Re-apply commit cf6d316f0 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove old files Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename MaxUmpMessageLen -> MaxUmpMessageLenOf Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test defensive message dropping of receive_upward_messages Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update implementors guide Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove FAIL-CI mark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Delete unused code Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add another test for MQ change hook Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Keep Kusama runtime formatting Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Delete unused code" This reverts commit dd76bca5025b7e1ef846a9539c3607eed185f16a. * Feature gate mock functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Review: Use saturating_add Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test RelayDispatchQueueSize storage key Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move migration to own file to avoid merge conflicts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Migration in own file Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rococo: configure MQ pallet Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Rococo: configure MQ pallet" Going to do this as follow up, since it needs Substrate changes and i dont want to stall this MR any longer. This reverts commit b9c15e8a8339c4e877d654ee3f09903af4210736. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Fixup tests" This reverts commit 88f1cbe20774d20e5e1e554e798960ae39437af1. * Fixup migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix CI Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix other migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bump MAX_CODE_SIZE to 10MiB Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add ForceUpdateUmpLimits migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use defensive instead of defensive_proof 'defensive_proof' also prints the 'self', which spams the console too much when running the tests. Just the length is enough. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename to ScheduleConfigUpdate Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup migration checks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add MAX_CODE_SIZE to ScheduleConfigUpdate Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Set MAX_CODE_SIZE to 4MiB Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix formatting Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Add MAX_CODE_SIZE to ScheduleConfigUpdate" This reverts commit 7caffb09e83083b57affd548215e45b25c3d64dc. * Revert "Set MAX_CODE_SIZE to 4MiB" This reverts commit 103ffbaf686487d2fbe0082a16826af17cacc1a1. * Revert "Bump MAX_CODE_SIZE to 10MiB" This reverts commit 530734b7b0da5b7680054e0242348fcc79a666fe. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove consistency check from migration Re-addig these checks is blocked on https://github.com/paritytech/polkadot/issues/7108 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix constants Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bump MAX_UPWARD_MESSAGE_SIZE_BOUND for Westend Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix migrations Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use old nightly for fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixes * cargo fmt * Fix tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixes * Add MQ pallet to fuzzer Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix XMC simulator example Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove runtime-benchmarks from fuzzers Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Remove runtime-benchmarks from fuzzers" This reverts commit e1f2bb01b6dea2dd465539d3658719895b58b557. * Fix example simulator Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add V6 migration and remove old ones Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Actually make old migrations reusable Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Dont delete old migrations Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Future proof AggregateMessageOrigin and review fixes There are indications that Loopback and Bridged will be needed soon. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fix benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix fuzzer build Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Review Co-authored-by: muharem <ismailov.m.h@gmail.com> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove old migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Set MQ service weight to 20% Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix tabs in Markdown Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: asynchronous rob <rphmeier@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
Generated
+29
@@ -3922,6 +3922,7 @@ dependencies = [
|
||||
"pallet-im-online",
|
||||
"pallet-indices",
|
||||
"pallet-membership",
|
||||
"pallet-message-queue",
|
||||
"pallet-multisig",
|
||||
"pallet-nis",
|
||||
"pallet-nomination-pools",
|
||||
@@ -5963,6 +5964,25 @@ dependencies = [
|
||||
"sp-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallet-message-queue"
|
||||
version = "7.0.0-dev"
|
||||
source = "git+https://github.com/paritytech/substrate?branch=master#b7e0518966b145f22c16137da5c9796fcdb43b73"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"sp-arithmetic",
|
||||
"sp-core",
|
||||
"sp-io",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
"sp-weights",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallet-mmr"
|
||||
version = "4.0.0-dev"
|
||||
@@ -7884,6 +7904,7 @@ dependencies = [
|
||||
"pallet-im-online",
|
||||
"pallet-indices",
|
||||
"pallet-membership",
|
||||
"pallet-message-queue",
|
||||
"pallet-multisig",
|
||||
"pallet-nomination-pools",
|
||||
"pallet-nomination-pools-benchmarking",
|
||||
@@ -8045,6 +8066,7 @@ dependencies = [
|
||||
"pallet-authorship",
|
||||
"pallet-babe",
|
||||
"pallet-balances",
|
||||
"pallet-message-queue",
|
||||
"pallet-session",
|
||||
"pallet-staking",
|
||||
"pallet-timestamp",
|
||||
@@ -9276,6 +9298,7 @@ dependencies = [
|
||||
"pallet-im-online",
|
||||
"pallet-indices",
|
||||
"pallet-membership",
|
||||
"pallet-message-queue",
|
||||
"pallet-mmr",
|
||||
"pallet-multisig",
|
||||
"pallet-nis",
|
||||
@@ -14092,6 +14115,7 @@ dependencies = [
|
||||
"pallet-im-online",
|
||||
"pallet-indices",
|
||||
"pallet-membership",
|
||||
"pallet-message-queue",
|
||||
"pallet-multisig",
|
||||
"pallet-nomination-pools",
|
||||
"pallet-nomination-pools-benchmarking",
|
||||
@@ -14565,12 +14589,14 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain",
|
||||
"polkadot-runtime-parachains",
|
||||
"polkadot-test-runtime",
|
||||
"primitive-types",
|
||||
"scale-info",
|
||||
"sp-arithmetic",
|
||||
"sp-io",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
"sp-weights",
|
||||
"xcm",
|
||||
"xcm-executor",
|
||||
]
|
||||
@@ -14637,6 +14663,7 @@ dependencies = [
|
||||
"sp-io",
|
||||
"sp-std",
|
||||
"xcm",
|
||||
"xcm-builder",
|
||||
"xcm-executor",
|
||||
]
|
||||
|
||||
@@ -14648,6 +14675,7 @@ dependencies = [
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-balances",
|
||||
"pallet-message-queue",
|
||||
"pallet-uniques",
|
||||
"pallet-xcm",
|
||||
"parity-scale-codec",
|
||||
@@ -14675,6 +14703,7 @@ dependencies = [
|
||||
"frame-system",
|
||||
"honggfuzz",
|
||||
"pallet-balances",
|
||||
"pallet-message-queue",
|
||||
"pallet-xcm",
|
||||
"parity-scale-codec",
|
||||
"polkadot-core-primitives",
|
||||
|
||||
@@ -1270,11 +1270,11 @@ impl State {
|
||||
let candidate_entry = match block_entry.candidates.get(index as usize) {
|
||||
None => {
|
||||
gum::debug!(
|
||||
target: LOG_TARGET,
|
||||
?hash,
|
||||
?index,
|
||||
"`get_approval_signatures`: could not find candidate entry for given hash and index!"
|
||||
);
|
||||
target: LOG_TARGET,
|
||||
?hash,
|
||||
?index,
|
||||
"`get_approval_signatures`: could not find candidate entry for given hash and index!"
|
||||
);
|
||||
continue
|
||||
},
|
||||
Some(e) => e,
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
//! Polkadot chain configurations.
|
||||
|
||||
use beefy_primitives::crypto::AuthorityId as BeefyId;
|
||||
use frame_support::weights::Weight;
|
||||
use grandpa::AuthorityId as GrandpaId;
|
||||
#[cfg(feature = "kusama-native")]
|
||||
use kusama_runtime as kusama;
|
||||
@@ -189,7 +188,6 @@ fn default_parachains_host_configuration(
|
||||
max_upward_queue_count: 8,
|
||||
max_upward_queue_size: 1024 * 1024,
|
||||
max_downward_message_size: 1024 * 1024,
|
||||
ump_service_total_weight: Weight::from_parts(100_000_000_000, MAX_POV_SIZE as u64),
|
||||
max_upward_message_size: 50 * 1024,
|
||||
max_upward_message_num_per_candidate: 5,
|
||||
hrmp_sender_deposit: 0,
|
||||
|
||||
@@ -133,7 +133,7 @@ pub type ValidatorSignature = validator_app::Signature;
|
||||
|
||||
/// A declarations of storage keys where an external observer can find some interesting data.
|
||||
pub mod well_known_keys {
|
||||
use super::{HrmpChannelId, Id};
|
||||
use super::{HrmpChannelId, Id, WellKnownKey};
|
||||
use hex_literal::hex;
|
||||
use parity_scale_codec::Encode as _;
|
||||
use sp_io::hashing::twox_64;
|
||||
@@ -210,6 +210,7 @@ pub mod well_known_keys {
|
||||
///
|
||||
/// - `count: u32`, the number of messages currently in the queue for given para,
|
||||
/// - `total_size: u32`, the total size of all messages in the queue.
|
||||
#[deprecated = "Use `relay_dispatch_queue_remaining_capacity` instead"]
|
||||
pub fn relay_dispatch_queue_size(para_id: Id) -> Vec<u8> {
|
||||
let prefix = hex!["f5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e"];
|
||||
|
||||
@@ -224,6 +225,24 @@ pub mod well_known_keys {
|
||||
})
|
||||
}
|
||||
|
||||
/// Type safe version of `relay_dispatch_queue_size`.
|
||||
#[deprecated = "Use `relay_dispatch_queue_remaining_capacity` instead"]
|
||||
pub fn relay_dispatch_queue_size_typed(para: Id) -> WellKnownKey<(u32, u32)> {
|
||||
#[allow(deprecated)]
|
||||
relay_dispatch_queue_size(para).into()
|
||||
}
|
||||
|
||||
/// The upward message dispatch queue remaining capacity for the given para id.
|
||||
///
|
||||
/// The storage entry stores a tuple of two values:
|
||||
///
|
||||
/// - `count: u32`, the number of additional messages which may be enqueued for the given para,
|
||||
/// - `total_size: u32`, the total size of additional messages which may be enqueued for the
|
||||
/// given para.
|
||||
pub fn relay_dispatch_queue_remaining_capacity(para_id: Id) -> WellKnownKey<(u32, u32)> {
|
||||
(b":relay_dispatch_queue_remaining_capacity", para_id).encode().into()
|
||||
}
|
||||
|
||||
/// The HRMP channel for the given identifier.
|
||||
///
|
||||
/// The storage entry should be accessed as an `AbridgedHrmpChannel` encoded value.
|
||||
@@ -1706,6 +1725,42 @@ impl PvfCheckStatement {
|
||||
}
|
||||
}
|
||||
|
||||
/// A well-known and typed storage key.
|
||||
///
|
||||
/// Allows for type-safe access to raw well-known storage keys.
|
||||
pub struct WellKnownKey<T> {
|
||||
/// The raw storage key.
|
||||
pub key: Vec<u8>,
|
||||
_p: sp_std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> From<Vec<u8>> for WellKnownKey<T> {
|
||||
fn from(key: Vec<u8>) -> Self {
|
||||
Self { key, _p: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[u8]> for WellKnownKey<T> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.key.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> WellKnownKey<T> {
|
||||
/// Gets the value or `None` if it does not exist or decoding failed.
|
||||
pub fn get(&self) -> Option<T> {
|
||||
sp_io::storage::get(&self.key)
|
||||
.and_then(|raw| parity_scale_codec::DecodeAll::decode_all(&mut raw.as_ref()).ok())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode> WellKnownKey<T> {
|
||||
/// Sets the value.
|
||||
pub fn set(&self, value: T) {
|
||||
sp_io::storage::set(&self.key, &value.encode());
|
||||
}
|
||||
}
|
||||
|
||||
/// Type discriminator for PVF preparation timeouts
|
||||
#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Inclusion Module
|
||||
|
||||
The inclusion module is responsible for inclusion and availability of scheduled parachains and parathreads.
|
||||
The inclusion module is responsible for inclusion and availability of scheduled parachains and parathreads. It also manages the UMP dispatch queue of each parachain/thread.
|
||||
|
||||
## Storage
|
||||
|
||||
@@ -35,11 +35,27 @@ PendingAvailability: map ParaId => CandidatePendingAvailability;
|
||||
PendingAvailabilityCommitments: map ParaId => CandidateCommitments;
|
||||
```
|
||||
|
||||
## Config Dependencies
|
||||
|
||||
* `MessageQueue`:
|
||||
The message queue provides general queueing and processing functionality. Currently it
|
||||
replaces the old `UMP` dispatch queue. Other use-cases can be implemented as well by
|
||||
adding new variants to `AggregateMessageOrigin`. Normally it should be set to an instance
|
||||
of the `MessageQueue` pallet.
|
||||
|
||||
## Session Change
|
||||
|
||||
1. Clear out all candidates pending availability.
|
||||
1. Clear out all validator bitfields.
|
||||
|
||||
Optional:
|
||||
1. The UMP queue of all outgoing paras can be "swept". This would prevent the dispatch queue from automatically being serviced. It is a consideration for the chain and specific behaviour is not defined.
|
||||
|
||||
## Initialization
|
||||
|
||||
No initialization routine runs for this module. However, the initialization of the `MessageQueue` pallet will attempt to process any pending UMP messages.
|
||||
|
||||
|
||||
## Routines
|
||||
|
||||
All failed checks should lead to an unrecoverable error making the block invalid.
|
||||
@@ -88,7 +104,7 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
||||
1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_cooldown` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID.
|
||||
1. Check the collator's signature on the candidate data.
|
||||
1. check the backing of the candidate using the signatures and the bitfields, comparing against the validators assigned to the groups, fetched with the `group_validators` lookup.
|
||||
1. call `Ump::check_upward_messages(para, commitments.upward_messages)` to check that the upward messages are valid.
|
||||
1. call `check_upward_messages(config, para, commitments.upward_messages)` to check that the upward messages are valid.
|
||||
1. call `Dmp::check_processed_downward_messages(para, commitments.processed_downward_messages)` to check that the DMQ is properly drained.
|
||||
1. call `Hrmp::check_hrmp_watermark(para, commitments.hrmp_watermark)` for each candidate to check rules of processing the HRMP watermark.
|
||||
1. using `Hrmp::check_outbound_hrmp(sender, commitments.horizontal_messages)` ensure that the each candidate sent a valid set of horizontal messages
|
||||
@@ -99,7 +115,7 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
||||
1. If the receipt contains a code upgrade, Call `Paras::schedule_code_upgrade(para_id, code, relay_parent_number, config)`.
|
||||
> TODO: Note that this is safe as long as we never enact candidates where the relay parent is across a session boundary. In that case, which we should be careful to avoid with contextual execution, the configuration might have changed and the para may de-sync from the host's understanding of it.
|
||||
1. Reward all backing validators of each candidate, contained within the `backers` field.
|
||||
1. call `Ump::receive_upward_messages` for each backed candidate, using the [`UpwardMessage`s](../types/messages.md#upward-message) from the [`CandidateCommitments`](../types/candidate.md#candidate-commitments).
|
||||
1. call `receive_upward_messages` for each backed candidate, using the [`UpwardMessage`s](../types/messages.md#upward-message) from the [`CandidateCommitments`](../types/candidate.md#candidate-commitments).
|
||||
1. call `Dmp::prune_dmq` with the para id of the candidate and the candidate's `processed_downward_messages`.
|
||||
1. call `Hrmp::prune_hrmp` with the para id of the candiate and the candidate's `hrmp_watermark`.
|
||||
1. call `Hrmp::queue_outbound_hrmp` with the para id of the candidate and the list of horizontal messages taken from the commitment,
|
||||
@@ -118,3 +134,20 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
||||
* `candidate_pending_availability(ParaId) -> Option<CommittedCandidateReceipt>`: returns the `CommittedCandidateReceipt` pending availability for the para provided, if any.
|
||||
* `pending_availability(ParaId) -> Option<CandidatePendingAvailability>`: returns the metadata around the candidate pending availability for the para, if any.
|
||||
* `collect_disputed(disputed: Vec<CandidateHash>) -> Vec<CoreIndex>`: Sweeps through all paras pending availability. If the candidate hash is one of the disputed candidates, then clean up the corresponding storage for that candidate and the commitments. Return a vector of cleaned-up core IDs.
|
||||
|
||||
These functions were formerly part of the UMP pallet:
|
||||
|
||||
* `check_upward_messages(P: ParaId, Vec<UpwardMessage>)`:
|
||||
1. Checks that the parachain is not currently offboarding and error otherwise.
|
||||
1. Checks that there are at most `config.max_upward_message_num_per_candidate` messages to be enqueued.
|
||||
1. Checks that no message exceeds `config.max_upward_message_size`.
|
||||
1. Checks that the total resulting queue size would not exceed `co`.
|
||||
1. Verify that queuing up the messages could not result in exceeding the queue's footprint
|
||||
according to the config items `config.max_upward_queue_count` and `config.max_upward_queue_size`. The queue's current footprint is provided in `well_known_keys`
|
||||
in order to facilitate oraclisation on to the para.
|
||||
|
||||
Candidate Enactment:
|
||||
|
||||
* `receive_upward_messages(P: ParaId, Vec<UpwardMessage>)`:
|
||||
1. Process each upward message `M` in order:
|
||||
1. Place in the dispatch queue according to its para ID (or handle it immediately).
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# UMP Module
|
||||
|
||||
A module responsible for Upward Message Passing (UMP). See [Messaging Overview](../messaging.md) for more details.
|
||||
|
||||
## Storage
|
||||
|
||||
Storage related to UMP
|
||||
|
||||
```rust
|
||||
/// The messages waiting to be handled by the relay-chain originating from a certain parachain.
|
||||
///
|
||||
/// Note that some upward messages might have been already processed by the inclusion logic. E.g.
|
||||
/// channel management messages.
|
||||
///
|
||||
/// The messages are processed in FIFO order.
|
||||
RelayDispatchQueues: map ParaId => Vec<UpwardMessage>;
|
||||
/// Size of the dispatch queues. Caches sizes of the queues in `RelayDispatchQueue`.
|
||||
///
|
||||
/// First item in the tuple is the count of messages and second
|
||||
/// is the total length (in bytes) of the message payloads.
|
||||
///
|
||||
/// Note that this is an auxilary mapping: it's possible to tell the byte size and the number of
|
||||
/// messages only looking at `RelayDispatchQueues`. This mapping is separate to avoid the cost of
|
||||
/// loading the whole message queue if only the total size and count are required.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - The set of keys should exactly match the set of keys of `RelayDispatchQueues`.
|
||||
RelayDispatchQueueSize: map ParaId => (u32, u32); // (num_messages, total_bytes)
|
||||
/// The ordered list of `ParaId`s that have a `RelayDispatchQueue` entry.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - The set of items from this vector should be exactly the set of the keys in
|
||||
/// `RelayDispatchQueues` and `RelayDispatchQueueSize`.
|
||||
NeedsDispatch: Vec<ParaId>;
|
||||
/// This is the para that gets dispatched first during the next upward dispatchable queue
|
||||
/// execution round.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - If `Some(para)`, then `para` must be present in `NeedsDispatch`.
|
||||
NextDispatchRoundStartWith: Option<ParaId>;
|
||||
```
|
||||
|
||||
|
||||
## Initialization
|
||||
|
||||
No initialization routine runs for this module.
|
||||
|
||||
## Routines
|
||||
|
||||
Candidate Acceptance Function:
|
||||
|
||||
* `check_upward_messages(P: ParaId, Vec<UpwardMessage>`):
|
||||
1. Checks that there are at most `config.max_upward_message_num_per_candidate` messages.
|
||||
1. Checks that no message exceeds `config.max_upward_message_size`.
|
||||
1. Verify that `RelayDispatchQueueSize` for `P` has enough capacity for the messages
|
||||
|
||||
Candidate Enactment:
|
||||
|
||||
* `receive_upward_messages(P: ParaId, Vec<UpwardMessage>)`:
|
||||
1. Process each upward message `M` in order:
|
||||
1. Append the message to `RelayDispatchQueues` for `P`
|
||||
1. Increment the size and the count in `RelayDispatchQueueSize` for `P`.
|
||||
1. Ensure that `P` is present in `NeedsDispatch`.
|
||||
|
||||
The following routine is meant to execute pending entries in upward message queues. This function doesn't fail, even if
|
||||
dispatching any of individual upward messages returns an error.
|
||||
|
||||
`process_pending_upward_messages()`:
|
||||
1. Initialize a cumulative weight counter `T` to 0
|
||||
1. Iterate over items in `NeedsDispatch` cyclically, starting with `NextDispatchRoundStartWith`. If the item specified is `None` start from the beginning. For each `P` encountered:
|
||||
1. Dequeue the first upward message `D` from `RelayDispatchQueues` for `P`
|
||||
1. Decrement the size of the message from `RelayDispatchQueueSize` for `P`
|
||||
1. Delegate processing of the message to the runtime. The weight consumed is added to `T`.
|
||||
1. If `T >= config.ump_service_total_weight`, set `NextDispatchRoundStartWith` to `P` and finish processing.
|
||||
1. If `RelayDispatchQueues` for `P` became empty, remove `P` from `NeedsDispatch`.
|
||||
1. If `NeedsDispatch` became empty then finish processing and set `NextDispatchRoundStartWith` to `None`.
|
||||
> NOTE that in practice we would need to approach the weight calculation more thoroughly, i.e. incorporate all operations
|
||||
> that could take place on the course of handling these upward messages.
|
||||
|
||||
## Session Change
|
||||
|
||||
1. For each `P` in `outgoing_paras` (generated by `Paras::on_new_session`):
|
||||
1. Remove `RelayDispatchQueueSize` of `P`.
|
||||
1. Remove `RelayDispatchQueues` of `P`.
|
||||
1. Remove `P` if it exists in `NeedsDispatch`.
|
||||
1. If `P` is in `NextDispatchRoundStartWith`, then reset it to `None`
|
||||
- Note that if we don't remove the open/close requests since they are going to die out naturally at the end of the session.
|
||||
@@ -63,11 +63,6 @@ struct HostConfiguration {
|
||||
/// no further messages may be added to it. If it exceeds this then the queue may contain only
|
||||
/// a single message.
|
||||
pub max_upward_queue_size: u32,
|
||||
/// The amount of weight we wish to devote to the processing the dispatchable upward messages
|
||||
/// stage.
|
||||
///
|
||||
/// NOTE that this is a soft limit and could be exceeded.
|
||||
pub ump_service_total_weight: Weight,
|
||||
/// The maximum size of an upward message that can be sent by a candidate.
|
||||
///
|
||||
/// This parameter affects the upper bound of size of `CandidateCommitments`.
|
||||
|
||||
@@ -649,6 +649,7 @@ mod tests {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = parachains_paras::TestWeightInfo;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ();
|
||||
type NextSessionRotation = crate::mock::TestNextSessionRotation;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ impl paras::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = paras::TestWeightInfo;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ();
|
||||
type NextSessionRotation = crate::mock::TestNextSessionRotation;
|
||||
}
|
||||
|
||||
|
||||
@@ -773,6 +773,7 @@ mod tests {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = paras::TestWeightInfo;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ();
|
||||
type NextSessionRotation = crate::mock::TestNextSessionRotation;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ use primitives::Id as ParaId;
|
||||
use runtime_parachains::{
|
||||
configuration, dmp, hrmp,
|
||||
paras::{self, ParaGenesisArgs},
|
||||
ump, ParaLifecycle,
|
||||
ParaLifecycle,
|
||||
};
|
||||
use sp_std::boxed::Box;
|
||||
|
||||
@@ -37,10 +37,7 @@ pub mod pallet {
|
||||
|
||||
#[pallet::config]
|
||||
#[pallet::disable_frame_system_supertrait_check]
|
||||
pub trait Config:
|
||||
configuration::Config + paras::Config + dmp::Config + ump::Config + hrmp::Config
|
||||
{
|
||||
}
|
||||
pub trait Config: configuration::Config + paras::Config + dmp::Config + hrmp::Config {}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
|
||||
@@ -59,6 +59,7 @@ pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-offences = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -158,6 +159,7 @@ std = [
|
||||
"pallet-im-online/std",
|
||||
"pallet-indices/std",
|
||||
"pallet-membership/std",
|
||||
"pallet-message-queue/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-nomination-pools/std",
|
||||
"pallet-nomination-pools-runtime-api/std",
|
||||
@@ -225,6 +227,7 @@ runtime-benchmarks = [
|
||||
"pallet-im-online/runtime-benchmarks",
|
||||
"pallet-indices/runtime-benchmarks",
|
||||
"pallet-membership/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-multisig/runtime-benchmarks",
|
||||
"pallet-nomination-pools/runtime-benchmarks",
|
||||
"pallet-nomination-pools-benchmarking/runtime-benchmarks",
|
||||
@@ -276,6 +279,7 @@ try-runtime = [
|
||||
"pallet-im-online/try-runtime",
|
||||
"pallet-indices/try-runtime",
|
||||
"pallet-membership/try-runtime",
|
||||
"pallet-message-queue/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-nomination-pools/try-runtime",
|
||||
"pallet-offences/try-runtime",
|
||||
|
||||
@@ -39,12 +39,14 @@ use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
|
||||
|
||||
use runtime_parachains::{
|
||||
configuration as parachains_configuration, disputes as parachains_disputes,
|
||||
disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp,
|
||||
inclusion as parachains_inclusion, initializer as parachains_initializer,
|
||||
origin as parachains_origin, paras as parachains_paras,
|
||||
disputes::slashing as parachains_slashing,
|
||||
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl, scheduler as parachains_scheduler,
|
||||
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl,
|
||||
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
||||
shared as parachains_shared,
|
||||
};
|
||||
|
||||
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
||||
@@ -56,9 +58,9 @@ use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{
|
||||
ConstU32, Contains, EitherOf, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem,
|
||||
PrivilegeCmp, StorageMapShim, WithdrawReasons,
|
||||
PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim, WithdrawReasons,
|
||||
},
|
||||
weights::ConstantMultiplier,
|
||||
weights::{ConstantMultiplier, WeightMeter},
|
||||
PalletId, RuntimeDebug,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -81,6 +83,7 @@ use sp_staking::SessionIndex;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
use xcm::latest::Junction;
|
||||
|
||||
pub use frame_system::Call as SystemCall;
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
@@ -1088,6 +1091,8 @@ impl parachains_inclusion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = ParasDisputes;
|
||||
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints<Runtime>;
|
||||
type MessageQueue = MessageQueue;
|
||||
type WeightInfo = weights::runtime_parachains_inclusion::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -1098,20 +1103,55 @@ impl parachains_paras::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = weights::runtime_parachains_paras::WeightInfo<Runtime>;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = Babe;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
|
||||
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * BlockWeights::get().max_block;
|
||||
pub const MessageQueueHeapSize: u32 = 65_536;
|
||||
pub const MessageQueueMaxStale: u32 = 16;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink =
|
||||
crate::parachains_ump::XcmSink<xcm_executor::XcmExecutor<xcm_config::XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = weights::runtime_parachains_ump::WeightInfo<Runtime>;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type MessageProcessor = MessageProcessor;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type MessageProcessor =
|
||||
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
||||
type QueueChangeHandler = ParaInclusion;
|
||||
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_dmp::Config for Runtime {}
|
||||
@@ -1411,7 +1451,6 @@ construct_runtime! {
|
||||
Paras: parachains_paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned} = 56,
|
||||
Initializer: parachains_initializer::{Pallet, Call, Storage} = 57,
|
||||
Dmp: parachains_dmp::{Pallet, Storage} = 58,
|
||||
Ump: parachains_ump::{Pallet, Call, Storage, Event} = 59,
|
||||
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>, Config} = 60,
|
||||
ParaSessionInfo: parachains_session_info::{Pallet, Storage} = 61,
|
||||
ParasDisputes: parachains_disputes::{Pallet, Call, Storage, Event<T>} = 62,
|
||||
@@ -1425,6 +1464,9 @@ construct_runtime! {
|
||||
|
||||
// Pallet for sending XCM.
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 99,
|
||||
|
||||
// Generalized message queue
|
||||
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 100,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1485,7 +1527,12 @@ pub mod migrations {
|
||||
);
|
||||
|
||||
/// Unreleased migrations. Add new ones here:
|
||||
pub type Unreleased = SetStorageVersions;
|
||||
pub type Unreleased = (
|
||||
SetStorageVersions,
|
||||
// Remove UMP dispatch queue <https://github.com/paritytech/polkadot/pull/6271>
|
||||
parachains_configuration::migration::v6::MigrateToV6<Runtime>,
|
||||
ump_migrations::UpdateUmpLimits,
|
||||
);
|
||||
|
||||
/// Migrations that set `StorageVersion`s we missed to set.
|
||||
pub struct SetStorageVersions;
|
||||
@@ -1510,6 +1557,24 @@ pub mod migrations {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helpers to configure the ump migrations.
|
||||
pub mod ump_migrations {
|
||||
use runtime_parachains::configuration::migration_ump;
|
||||
|
||||
pub const MAX_UPWARD_QUEUE_SIZE: u32 = 4 * 1024 * 1024;
|
||||
pub const MAX_UPWARD_QUEUE_COUNT: u32 = 699050;
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE: u32 = (1 << 16) - 5; // Checked in test `max_upward_message_size`.
|
||||
pub const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32 = 128;
|
||||
|
||||
pub type UpdateUmpLimits = migration_ump::latest::ScheduleConfigUpdate<
|
||||
super::Runtime,
|
||||
MAX_UPWARD_QUEUE_SIZE,
|
||||
MAX_UPWARD_QUEUE_COUNT,
|
||||
MAX_UPWARD_MESSAGE_SIZE,
|
||||
MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE,
|
||||
>;
|
||||
}
|
||||
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic =
|
||||
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
|
||||
@@ -1525,13 +1590,9 @@ pub type Executive = frame_executive::Executive<
|
||||
/// The payload being signed in the transactions.
|
||||
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
#[macro_use]
|
||||
extern crate frame_benchmarking;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benches {
|
||||
define_benchmarks!(
|
||||
frame_benchmarking::define_benchmarks!(
|
||||
// Polkadot
|
||||
// NOTE: Make sure to prefix these with `runtime_common::` so
|
||||
// that the path resolves correctly in the generated file.
|
||||
@@ -1544,10 +1605,10 @@ mod benches {
|
||||
[runtime_parachains::hrmp, Hrmp]
|
||||
[runtime_parachains::disputes, ParasDisputes]
|
||||
[runtime_parachains::disputes::slashing, ParasSlashing]
|
||||
[runtime_parachains::inclusion, ParaInclusion]
|
||||
[runtime_parachains::initializer, Initializer]
|
||||
[runtime_parachains::paras_inherent, ParaInherent]
|
||||
[runtime_parachains::paras, Paras]
|
||||
[runtime_parachains::ump, Ump]
|
||||
// Substrate
|
||||
[pallet_balances, Balances]
|
||||
[pallet_balances, NisCounterpartBalances]
|
||||
@@ -1563,6 +1624,7 @@ mod benches {
|
||||
[pallet_identity, Identity]
|
||||
[pallet_im_online, ImOnline]
|
||||
[pallet_indices, Indices]
|
||||
[pallet_message_queue, MessageQueue]
|
||||
[pallet_multisig, Multisig]
|
||||
[pallet_nomination_pools, NominationPoolsBench::<Runtime>]
|
||||
[pallet_offences, OffencesBench::<Runtime>]
|
||||
|
||||
@@ -146,3 +146,11 @@ fn nominator_limit() {
|
||||
fn call_size() {
|
||||
RuntimeCall::assert_size_under(230);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_upward_message_size() {
|
||||
assert_eq!(
|
||||
ump_migrations::MAX_UPWARD_MESSAGE_SIZE,
|
||||
pallet_message_queue::MaxMessageLenOf::<Runtime>::get()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ pub mod pallet_identity;
|
||||
pub mod pallet_im_online;
|
||||
pub mod pallet_indices;
|
||||
pub mod pallet_membership;
|
||||
pub mod pallet_message_queue;
|
||||
pub mod pallet_multisig;
|
||||
pub mod pallet_nis;
|
||||
pub mod pallet_nomination_pools;
|
||||
@@ -60,8 +61,8 @@ pub mod runtime_parachains_configuration;
|
||||
pub mod runtime_parachains_disputes;
|
||||
pub mod runtime_parachains_disputes_slashing;
|
||||
pub mod runtime_parachains_hrmp;
|
||||
pub mod runtime_parachains_inclusion;
|
||||
pub mod runtime_parachains_initializer;
|
||||
pub mod runtime_parachains_paras;
|
||||
pub mod runtime_parachains_paras_inherent;
|
||||
pub mod runtime_parachains_ump;
|
||||
pub mod xcm;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `pallet_message_queue`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=kusama-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet-message-queue
|
||||
// --extrinsic=*
|
||||
// --heap-pages=4096
|
||||
// --header=file_header.txt
|
||||
// --output
|
||||
// runtime/kusama/src/weights/pallet_message_queue.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `pallet_message_queue`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> pallet_message_queue::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:0)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn ready_ring_knit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_669 nanoseconds.
|
||||
Weight::from_parts(5_925_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
fn ready_ring_unknit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_604 nanoseconds.
|
||||
Weight::from_parts(5_993_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn service_queue_base() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `576`
|
||||
// Estimated: `2527`
|
||||
// Minimum execution time: 2_104 nanoseconds.
|
||||
Weight::from_parts(2_241_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 2527))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_175 nanoseconds.
|
||||
Weight::from_parts(3_289_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_no_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_198 nanoseconds.
|
||||
Weight::from_parts(3_308_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
fn service_page_item() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `969`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 46_864 nanoseconds.
|
||||
Weight::from_parts(47_073_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
}
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn bump_service_head() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `712`
|
||||
// Estimated: `3027`
|
||||
// Minimum execution time: 3_552 nanoseconds.
|
||||
Weight::from_parts(3_710_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3027))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn reap_page() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66857`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 38_491 nanoseconds.
|
||||
Weight::from_parts(46_983_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_removed() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66857`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 88_529 nanoseconds.
|
||||
Weight::from_parts(144_649_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_updated() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66857`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 79_494 nanoseconds.
|
||||
Weight::from_parts(84_895_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `runtime_parachains::inclusion`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=kusama-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::inclusion
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/kusama/src/weights
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::inclusion`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::inclusion::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:999)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
/// The range of component `i` is `[1, 1000]`.
|
||||
fn receive_upward_messages(i: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `51490`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 47_556 nanoseconds.
|
||||
Weight::from_parts(48_839_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
// Standard Error: 49_019
|
||||
.saturating_add(Weight::from_parts(43_136_059, 0).saturating_mul(i.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into())))
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::ump`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=kusama-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::ump
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/kusama/src/weights/runtime_parachains_ump.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::ump`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::ump::WeightInfo for WeightInfo<T> {
|
||||
/// The range of component `s` is `[0, 51200]`.
|
||||
fn process_upward_message(s: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 5_945_000 picoseconds.
|
||||
Weight::from_parts(6_047_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
// Standard Error: 8
|
||||
.saturating_add(Weight::from_parts(1_364, 0).saturating_mul(s.into()))
|
||||
}
|
||||
/// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
/// Proof Skipped: Ump NeedsDispatch (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
/// Proof Skipped: Ump NextDispatchRoundStartWith (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueues (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueueSize (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueueSize (max_values: None, max_size: None, mode: Measured)
|
||||
fn clean_ump_after_outgoing() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `206`
|
||||
// Estimated: `1691`
|
||||
// Minimum execution time: 9_308_000 picoseconds.
|
||||
Weight::from_parts(9_501_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1691))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: Ump Overweight (r:1 w:1)
|
||||
/// Proof Skipped: Ump Overweight (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump CounterForOverweight (r:1 w:1)
|
||||
/// Proof: Ump CounterForOverweight (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
|
||||
fn service_overweight() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `223`
|
||||
// Estimated: `3688`
|
||||
// Minimum execution time: 23_650_000 picoseconds.
|
||||
Weight::from_parts(23_963_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3688))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ pallet-authority-discovery = { git = "https://github.com/paritytech/substrate",
|
||||
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -80,9 +81,11 @@ std = [
|
||||
"sp-runtime/std",
|
||||
"sp-session/std",
|
||||
"sp-staking/std",
|
||||
"pallet-authority-discovery/std",
|
||||
"pallet-authorship/std",
|
||||
"pallet-babe/std",
|
||||
"pallet-balances/std",
|
||||
"pallet-message-queue/std",
|
||||
"pallet-session/std",
|
||||
"pallet-staking/std",
|
||||
"pallet-timestamp/std",
|
||||
@@ -97,15 +100,23 @@ runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"pallet-babe/runtime-benchmarks",
|
||||
"pallet-balances/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-staking/runtime-benchmarks",
|
||||
"pallet-timestamp/runtime-benchmarks",
|
||||
"pallet-vesting/runtime-benchmarks",
|
||||
"primitives/runtime-benchmarks",
|
||||
"static_assertions",
|
||||
"sp-application-crypto",
|
||||
]
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"pallet-authority-discovery/try-runtime",
|
||||
"pallet-authorship/try-runtime",
|
||||
"pallet-babe/try-runtime",
|
||||
"pallet-balances/try-runtime",
|
||||
"pallet-message-queue/try-runtime",
|
||||
"pallet-session/try-runtime",
|
||||
"pallet-staking/try-runtime",
|
||||
"pallet-timestamp/try-runtime",
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//!
|
||||
//! Configuration can change only at session boundaries and is buffered until then.
|
||||
|
||||
use crate::shared;
|
||||
use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_REF_TIME_PER_MILLIS};
|
||||
use crate::{inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND, shared};
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use polkadot_parachain::primitives::{MAX_HORIZONTAL_MESSAGE_NUM, MAX_UPWARD_MESSAGE_NUM};
|
||||
@@ -36,9 +36,10 @@ mod tests;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
pub mod migration;
|
||||
pub mod migration_ump;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
const LOG_TARGET: &str = "runtime::configuration";
|
||||
|
||||
@@ -132,11 +133,6 @@ pub struct HostConfiguration<BlockNumber> {
|
||||
/// decide to do with its PoV so this value in practice will be picked as a fraction of the PoV
|
||||
/// size.
|
||||
pub max_downward_message_size: u32,
|
||||
/// The amount of weight we wish to devote to the processing the dispatchable upward messages
|
||||
/// stage.
|
||||
///
|
||||
/// NOTE that this is a soft limit and could be exceeded.
|
||||
pub ump_service_total_weight: Weight,
|
||||
/// The maximum number of outbound HRMP channels a parachain is allowed to open.
|
||||
pub hrmp_max_parachain_outbound_channels: u32,
|
||||
/// The maximum number of outbound HRMP channels a parathread is allowed to open.
|
||||
@@ -214,9 +210,6 @@ pub struct HostConfiguration<BlockNumber> {
|
||||
pub needed_approvals: u32,
|
||||
/// The number of samples to do of the `RelayVRFModulo` approval assignment criterion.
|
||||
pub relay_vrf_modulo_samples: u32,
|
||||
/// The maximum amount of weight any individual upward message may consume. Messages above this
|
||||
/// weight go into the overweight queue and may only be serviced explicitly.
|
||||
pub ump_max_individual_weight: Weight,
|
||||
/// This flag controls whether PVF pre-checking is enabled.
|
||||
///
|
||||
/// If the flag is false, the behavior should be exactly the same as prior. Specifically, the
|
||||
@@ -278,7 +271,6 @@ impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber
|
||||
max_upward_queue_count: Default::default(),
|
||||
max_upward_queue_size: Default::default(),
|
||||
max_downward_message_size: Default::default(),
|
||||
ump_service_total_weight: Default::default(),
|
||||
max_upward_message_size: Default::default(),
|
||||
max_upward_message_num_per_candidate: Default::default(),
|
||||
hrmp_sender_deposit: Default::default(),
|
||||
@@ -291,10 +283,6 @@ impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber
|
||||
hrmp_max_parachain_outbound_channels: Default::default(),
|
||||
hrmp_max_parathread_outbound_channels: Default::default(),
|
||||
hrmp_max_message_num_per_candidate: Default::default(),
|
||||
ump_max_individual_weight: Weight::from_parts(
|
||||
20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
MAX_POV_SIZE as u64,
|
||||
),
|
||||
pvf_checking_enabled: false,
|
||||
pvf_voting_ttl: 2u32.into(),
|
||||
minimum_validation_upgrade_delay: 2.into(),
|
||||
@@ -404,7 +392,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
if self.max_upward_message_size > crate::ump::MAX_UPWARD_MESSAGE_SIZE_BOUND {
|
||||
if self.max_upward_message_size > crate::inclusion::MAX_UPWARD_MESSAGE_SIZE_BOUND {
|
||||
return Err(MaxUpwardMessageSizeExceeded {
|
||||
max_message_size: self.max_upward_message_size,
|
||||
})
|
||||
@@ -441,7 +429,7 @@ where
|
||||
/// This function panics if the configuration is inconsistent.
|
||||
pub fn panic_if_not_consistent(&self) {
|
||||
if let Err(err) = self.check_consistency() {
|
||||
panic!("Host configuration is inconsistent: {:?}", err);
|
||||
panic!("Host configuration is inconsistent: {:?}\nCfg:\n{:#?}", err, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -865,6 +853,8 @@ pub mod pallet {
|
||||
))]
|
||||
pub fn set_max_upward_queue_size(origin: OriginFor<T>, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
ensure!(new <= MAX_UPWARD_MESSAGE_SIZE_BOUND, Error::<T>::InvalidNewValue);
|
||||
|
||||
Self::schedule_config_update(|config| {
|
||||
config.max_upward_queue_size = new;
|
||||
})
|
||||
@@ -883,19 +873,6 @@ pub mod pallet {
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the soft limit for the phase of dispatching dispatchable upward messages.
|
||||
#[pallet::call_index(26)]
|
||||
#[pallet::weight((
|
||||
T::WeightInfo::set_config_with_weight(),
|
||||
DispatchClass::Operational,
|
||||
))]
|
||||
pub fn set_ump_service_total_weight(origin: OriginFor<T>, new: Weight) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::schedule_config_update(|config| {
|
||||
config.ump_service_total_weight = new;
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the maximum size of an upward message that can be sent by a candidate.
|
||||
#[pallet::call_index(27)]
|
||||
#[pallet::weight((
|
||||
@@ -1083,19 +1060,6 @@ pub mod pallet {
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the maximum amount of weight any individual upward message may consume.
|
||||
#[pallet::call_index(40)]
|
||||
#[pallet::weight((
|
||||
T::WeightInfo::set_config_with_weight(),
|
||||
DispatchClass::Operational,
|
||||
))]
|
||||
pub fn set_ump_max_individual_weight(origin: OriginFor<T>, new: Weight) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::schedule_config_update(|config| {
|
||||
config.ump_max_individual_weight = new;
|
||||
})
|
||||
}
|
||||
|
||||
/// Enable or disable PVF pre-checking. Consult the field documentation prior executing.
|
||||
#[pallet::call_index(41)]
|
||||
#[pallet::weight((
|
||||
@@ -1283,7 +1247,7 @@ impl<T: Config> Pallet<T> {
|
||||
// duplicated code (making this function to show up in the top of heaviest functions) only for
|
||||
// the sake of essentially avoiding an indirect call. Doesn't worth it.
|
||||
#[inline(never)]
|
||||
fn schedule_config_update(
|
||||
pub(crate) fn schedule_config_update(
|
||||
updater: impl FnOnce(&mut HostConfiguration<T::BlockNumber>),
|
||||
) -> DispatchResult {
|
||||
let mut pending_configs = <PendingConfigs<T>>::get();
|
||||
|
||||
@@ -27,8 +27,6 @@ benchmarks! {
|
||||
|
||||
set_config_with_option_u32 {}: set_max_validators(RawOrigin::Root, Some(10))
|
||||
|
||||
set_config_with_weight {}: set_ump_service_total_weight(RawOrigin::Root, Weight::from_parts(3_000_000, 0))
|
||||
|
||||
set_hrmp_open_request_ttl {}: {
|
||||
Err(BenchmarkError::Override(
|
||||
BenchmarkResult::from_weight(T::BlockWeights::get().max_block)
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
//! A module that is responsible for migration of storage.
|
||||
|
||||
use crate::configuration::{self, ActiveConfig, Config, Pallet, PendingConfigs, MAX_POV_SIZE};
|
||||
use frame_support::{pallet_prelude::*, traits::StorageVersion, weights::Weight};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::vstaging::AsyncBackingParams;
|
||||
use sp_std::vec::Vec;
|
||||
use frame_support::traits::StorageVersion;
|
||||
use primitives::ExecutorParams;
|
||||
|
||||
/// The current storage version.
|
||||
///
|
||||
@@ -29,376 +26,10 @@ use sp_std::vec::Vec;
|
||||
/// v2-v3: <https://github.com/paritytech/polkadot/pull/6091>
|
||||
/// v3-v4: <https://github.com/paritytech/polkadot/pull/6345>
|
||||
/// v4-v5: <https://github.com/paritytech/polkadot/pull/6937>
|
||||
/// + <https://github.com/paritytech/polkadot/pull/6961>
|
||||
/// + <https://github.com/paritytech/polkadot/pull/6934>
|
||||
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(5);
|
||||
/// + <https://github.com/paritytech/polkadot/pull/6961>
|
||||
/// + <https://github.com/paritytech/polkadot/pull/6934>
|
||||
/// v5-v6: <https://github.com/paritytech/polkadot/pull/6271> (remove UMP dispatch queue)
|
||||
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(6);
|
||||
|
||||
pub mod v5 {
|
||||
use super::*;
|
||||
use frame_support::{traits::OnRuntimeUpgrade, weights::constants::WEIGHT_REF_TIME_PER_MILLIS};
|
||||
use primitives::{Balance, SessionIndex};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::prelude::*;
|
||||
|
||||
// Copied over from configuration.rs @ de9e147695b9f1be8bd44e07861a31e483c8343a and removed
|
||||
// all the comments, and changed the Weight struct to OldWeight
|
||||
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, Clone)]
|
||||
pub struct OldHostConfiguration<BlockNumber> {
|
||||
pub max_code_size: u32,
|
||||
pub max_head_data_size: u32,
|
||||
pub max_upward_queue_count: u32,
|
||||
pub max_upward_queue_size: u32,
|
||||
pub max_upward_message_size: u32,
|
||||
pub max_upward_message_num_per_candidate: u32,
|
||||
pub hrmp_max_message_num_per_candidate: u32,
|
||||
pub validation_upgrade_cooldown: BlockNumber,
|
||||
pub validation_upgrade_delay: BlockNumber,
|
||||
pub max_pov_size: u32,
|
||||
pub max_downward_message_size: u32,
|
||||
pub ump_service_total_weight: Weight,
|
||||
pub hrmp_max_parachain_outbound_channels: u32,
|
||||
pub hrmp_max_parathread_outbound_channels: u32,
|
||||
pub hrmp_sender_deposit: Balance,
|
||||
pub hrmp_recipient_deposit: Balance,
|
||||
pub hrmp_channel_max_capacity: u32,
|
||||
pub hrmp_channel_max_total_size: u32,
|
||||
pub hrmp_max_parachain_inbound_channels: u32,
|
||||
pub hrmp_max_parathread_inbound_channels: u32,
|
||||
pub hrmp_channel_max_message_size: u32,
|
||||
pub code_retention_period: BlockNumber,
|
||||
pub parathread_cores: u32,
|
||||
pub parathread_retries: u32,
|
||||
pub group_rotation_frequency: BlockNumber,
|
||||
pub chain_availability_period: BlockNumber,
|
||||
pub thread_availability_period: BlockNumber,
|
||||
pub scheduling_lookahead: u32,
|
||||
pub max_validators_per_core: Option<u32>,
|
||||
pub max_validators: Option<u32>,
|
||||
pub dispute_period: SessionIndex,
|
||||
pub dispute_post_conclusion_acceptance_period: BlockNumber,
|
||||
pub dispute_conclusion_by_time_out_period: BlockNumber,
|
||||
pub no_show_slots: u32,
|
||||
pub n_delay_tranches: u32,
|
||||
pub zeroth_delay_tranche_width: u32,
|
||||
pub needed_approvals: u32,
|
||||
pub relay_vrf_modulo_samples: u32,
|
||||
pub ump_max_individual_weight: Weight,
|
||||
pub pvf_checking_enabled: bool,
|
||||
pub pvf_voting_ttl: SessionIndex,
|
||||
pub minimum_validation_upgrade_delay: BlockNumber,
|
||||
}
|
||||
|
||||
impl<BlockNumber: Default + From<u32>> Default for OldHostConfiguration<BlockNumber> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
group_rotation_frequency: 1u32.into(),
|
||||
chain_availability_period: 1u32.into(),
|
||||
thread_availability_period: 1u32.into(),
|
||||
no_show_slots: 1u32.into(),
|
||||
validation_upgrade_cooldown: Default::default(),
|
||||
validation_upgrade_delay: Default::default(),
|
||||
code_retention_period: Default::default(),
|
||||
max_code_size: Default::default(),
|
||||
max_pov_size: Default::default(),
|
||||
max_head_data_size: Default::default(),
|
||||
parathread_cores: Default::default(),
|
||||
parathread_retries: Default::default(),
|
||||
scheduling_lookahead: Default::default(),
|
||||
max_validators_per_core: Default::default(),
|
||||
max_validators: None,
|
||||
dispute_period: 6,
|
||||
dispute_post_conclusion_acceptance_period: 100.into(),
|
||||
dispute_conclusion_by_time_out_period: 200.into(),
|
||||
n_delay_tranches: Default::default(),
|
||||
zeroth_delay_tranche_width: Default::default(),
|
||||
needed_approvals: Default::default(),
|
||||
relay_vrf_modulo_samples: Default::default(),
|
||||
max_upward_queue_count: Default::default(),
|
||||
max_upward_queue_size: Default::default(),
|
||||
max_downward_message_size: Default::default(),
|
||||
ump_service_total_weight: Default::default(),
|
||||
max_upward_message_size: Default::default(),
|
||||
max_upward_message_num_per_candidate: Default::default(),
|
||||
hrmp_sender_deposit: Default::default(),
|
||||
hrmp_recipient_deposit: Default::default(),
|
||||
hrmp_channel_max_capacity: Default::default(),
|
||||
hrmp_channel_max_total_size: Default::default(),
|
||||
hrmp_max_parachain_inbound_channels: Default::default(),
|
||||
hrmp_max_parathread_inbound_channels: Default::default(),
|
||||
hrmp_channel_max_message_size: Default::default(),
|
||||
hrmp_max_parachain_outbound_channels: Default::default(),
|
||||
hrmp_max_parathread_outbound_channels: Default::default(),
|
||||
hrmp_max_message_num_per_candidate: Default::default(),
|
||||
ump_max_individual_weight: Weight::from_parts(
|
||||
20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
MAX_POV_SIZE as u64,
|
||||
),
|
||||
pvf_checking_enabled: false,
|
||||
pvf_voting_ttl: 2u32.into(),
|
||||
minimum_validation_upgrade_delay: 2.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MigrateToV5<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV5<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade()");
|
||||
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 4, "The migration requires version 4");
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if StorageVersion::get::<Pallet<T>>() == 4 {
|
||||
let weight_consumed = migrate_to_v5::<T>();
|
||||
|
||||
log::info!(target: configuration::LOG_TARGET, "MigrateToV5 executed successfully");
|
||||
STORAGE_VERSION.put::<Pallet<T>>();
|
||||
|
||||
weight_consumed
|
||||
} else {
|
||||
log::warn!(target: configuration::LOG_TARGET, "MigrateToV5 should be removed.");
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running post_upgrade()");
|
||||
ensure!(
|
||||
StorageVersion::get::<Pallet<T>>() == STORAGE_VERSION,
|
||||
"Storage version should be 5 after the migration"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_to_v5<T: Config>() -> Weight {
|
||||
// Unusual formatting is justified:
|
||||
// - make it easier to verify that fields assign what they supposed to assign.
|
||||
// - this code is transient and will be removed after all migrations are done.
|
||||
// - this code is important enough to optimize for legibility sacrificing consistency.
|
||||
#[rustfmt::skip]
|
||||
let translate =
|
||||
|pre: v5::OldHostConfiguration<BlockNumberFor<T>>| ->
|
||||
configuration::HostConfiguration<BlockNumberFor<T>>
|
||||
{
|
||||
super::HostConfiguration {
|
||||
max_code_size : pre.max_code_size,
|
||||
max_head_data_size : pre.max_head_data_size,
|
||||
max_upward_queue_count : pre.max_upward_queue_count,
|
||||
max_upward_queue_size : pre.max_upward_queue_size,
|
||||
max_upward_message_size : pre.max_upward_message_size,
|
||||
max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate,
|
||||
hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate,
|
||||
validation_upgrade_cooldown : pre.validation_upgrade_cooldown,
|
||||
validation_upgrade_delay : pre.validation_upgrade_delay,
|
||||
max_pov_size : pre.max_pov_size,
|
||||
max_downward_message_size : pre.max_downward_message_size,
|
||||
ump_service_total_weight : pre.ump_service_total_weight,
|
||||
hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels,
|
||||
hrmp_max_parathread_outbound_channels : pre.hrmp_max_parathread_outbound_channels,
|
||||
hrmp_sender_deposit : pre.hrmp_sender_deposit,
|
||||
hrmp_recipient_deposit : pre.hrmp_recipient_deposit,
|
||||
hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity,
|
||||
hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size,
|
||||
hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels,
|
||||
hrmp_max_parathread_inbound_channels : pre.hrmp_max_parathread_inbound_channels,
|
||||
hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size,
|
||||
code_retention_period : pre.code_retention_period,
|
||||
parathread_cores : pre.parathread_cores,
|
||||
parathread_retries : pre.parathread_retries,
|
||||
group_rotation_frequency : pre.group_rotation_frequency,
|
||||
chain_availability_period : pre.chain_availability_period,
|
||||
thread_availability_period : pre.thread_availability_period,
|
||||
scheduling_lookahead : pre.scheduling_lookahead,
|
||||
max_validators_per_core : pre.max_validators_per_core,
|
||||
max_validators : pre.max_validators,
|
||||
dispute_period : pre.dispute_period,
|
||||
dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period,
|
||||
no_show_slots : pre.no_show_slots,
|
||||
n_delay_tranches : pre.n_delay_tranches,
|
||||
zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width,
|
||||
needed_approvals : pre.needed_approvals,
|
||||
relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples,
|
||||
ump_max_individual_weight : pre.ump_max_individual_weight,
|
||||
pvf_checking_enabled : pre.pvf_checking_enabled,
|
||||
pvf_voting_ttl : pre.pvf_voting_ttl,
|
||||
minimum_validation_upgrade_delay : pre.minimum_validation_upgrade_delay,
|
||||
|
||||
// Default values are zeroes, thus it's ensured allowed ancestry never crosses the upgrade block.
|
||||
async_backing_params : AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: 0 },
|
||||
|
||||
// Default executor parameters set is empty
|
||||
executor_params : Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(_) = ActiveConfig::<T>::translate(|pre| pre.map(translate)) {
|
||||
// `Err` is returned when the pre-migration type cannot be deserialized. This
|
||||
// cannot happen if the migration runs correctly, i.e. against the expected version.
|
||||
//
|
||||
// This happening almost surely will lead to a panic somewhere else. Corruption seems
|
||||
// to be unlikely to be caused by this. So we just log. Maybe it'll work out still?
|
||||
log::error!(
|
||||
target: configuration::LOG_TARGET,
|
||||
"unexpected error when performing translation of the active configuration during storage upgrade to v5."
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(_) = PendingConfigs::<T>::translate(|pre| {
|
||||
pre.map(
|
||||
|v: Vec<(primitives::SessionIndex, v5::OldHostConfiguration<BlockNumberFor<T>>)>| {
|
||||
v.into_iter()
|
||||
.map(|(session, config)| (session, translate(config)))
|
||||
.collect::<Vec<_>>()
|
||||
},
|
||||
)
|
||||
}) {
|
||||
log::error!(
|
||||
target: configuration::LOG_TARGET,
|
||||
"unexpected error when performing translation of the pending configuration during storage upgrade to v5."
|
||||
);
|
||||
}
|
||||
|
||||
let num_configs = (PendingConfigs::<T>::get().len() + 1) as u64;
|
||||
T::DbWeight::get().reads_writes(num_configs, num_configs)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test};
|
||||
use primitives::ExecutorParams;
|
||||
|
||||
#[test]
|
||||
fn v4_deserialized_from_actual_data() {
|
||||
// Example how to get new `raw_config`:
|
||||
// We'll obtain the raw_config at a specified a block
|
||||
// Steps:
|
||||
// 1. Go to Polkadot.js -> Developer -> Chain state -> Storage: https://polkadot.js.org/apps/#/chainstate
|
||||
// 2. Set these parameters:
|
||||
// 2.1. selected state query: configuration; activeConfig(): PolkadotRuntimeParachainsConfigurationHostConfiguration
|
||||
// 2.2. blockhash to query at: 0xf89d3ab5312c5f70d396dc59612f0aa65806c798346f9db4b35278baed2e0e53 (the hash of the block)
|
||||
// 2.3. Note the value of encoded storage key -> 0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385 for the referenced block.
|
||||
// 2.4. You'll also need the decoded values to update the test.
|
||||
// 3. Go to Polkadot.js -> Developer -> Chain state -> Raw storage
|
||||
// 3.1 Enter the encoded storage key and you get the raw config.
|
||||
|
||||
// This exceeds the maximal line width length, but that's fine, since this is not code and
|
||||
// doesn't need to be read and also leaving it as one line allows to easily copy it.
|
||||
let raw_config = hex_literal::hex!["0000a000005000000a00000000c8000000c800000a0000000a000000100e0000580200000000500000c800000700e8764817020040011e00000000000000005039278c0400000000000000000000005039278c0400000000000000000000e8030000009001001e00000000000000009001008070000000000000000000000a0000000a0000000a00000001000000010500000001c80000000600000058020000580200000200000059000000000000001e000000280000000700c817a80402004001010200000014000000"];
|
||||
|
||||
let v4 = v5::OldHostConfiguration::<primitives::BlockNumber>::decode(&mut &raw_config[..])
|
||||
.unwrap();
|
||||
|
||||
// We check only a sample of the values here. If we missed any fields or messed up data types
|
||||
// that would skew all the fields coming after.
|
||||
assert_eq!(v4.max_code_size, 10_485_760);
|
||||
assert_eq!(v4.validation_upgrade_cooldown, 3600);
|
||||
assert_eq!(v4.max_pov_size, 5_242_880);
|
||||
assert_eq!(v4.hrmp_channel_max_message_size, 102_400);
|
||||
assert_eq!(v4.n_delay_tranches, 89);
|
||||
assert_eq!(v4.ump_max_individual_weight, Weight::from_parts(20_000_000_000, 5_242_880));
|
||||
assert_eq!(v4.minimum_validation_upgrade_delay, 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_migrate_to_v5() {
|
||||
// Host configuration has lots of fields. However, in this migration we only remove one field.
|
||||
// The most important part to check are a couple of the last fields. We also pick
|
||||
// extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and
|
||||
// also their type.
|
||||
//
|
||||
// We specify only the picked fields and the rest should be provided by the `Default`
|
||||
// implementation. That implementation is copied over between the two types and should work
|
||||
// fine.
|
||||
let v4 = v5::OldHostConfiguration::<primitives::BlockNumber> {
|
||||
ump_max_individual_weight: Weight::from_parts(0x71616e6f6e0au64, 0x71616e6f6e0au64),
|
||||
needed_approvals: 69,
|
||||
thread_availability_period: 55,
|
||||
hrmp_recipient_deposit: 1337,
|
||||
max_pov_size: 1111,
|
||||
chain_availability_period: 33,
|
||||
minimum_validation_upgrade_delay: 20,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut pending_configs = Vec::new();
|
||||
pending_configs.push((100, v4.clone()));
|
||||
pending_configs.push((300, v4.clone()));
|
||||
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
// Implant the v4 version in the state.
|
||||
frame_support::storage::unhashed::put_raw(
|
||||
&configuration::ActiveConfig::<Test>::hashed_key(),
|
||||
&v4.encode(),
|
||||
);
|
||||
frame_support::storage::unhashed::put_raw(
|
||||
&configuration::PendingConfigs::<Test>::hashed_key(),
|
||||
&pending_configs.encode(),
|
||||
);
|
||||
|
||||
migrate_to_v5::<Test>();
|
||||
|
||||
let v5 = configuration::ActiveConfig::<Test>::get();
|
||||
let mut configs_to_check = configuration::PendingConfigs::<Test>::get();
|
||||
configs_to_check.push((0, v5.clone()));
|
||||
|
||||
for (_, v4) in configs_to_check {
|
||||
#[rustfmt::skip]
|
||||
{
|
||||
assert_eq!(v4.max_code_size , v5.max_code_size);
|
||||
assert_eq!(v4.max_head_data_size , v5.max_head_data_size);
|
||||
assert_eq!(v4.max_upward_queue_count , v5.max_upward_queue_count);
|
||||
assert_eq!(v4.max_upward_queue_size , v5.max_upward_queue_size);
|
||||
assert_eq!(v4.max_upward_message_size , v5.max_upward_message_size);
|
||||
assert_eq!(v4.max_upward_message_num_per_candidate , v5.max_upward_message_num_per_candidate);
|
||||
assert_eq!(v4.hrmp_max_message_num_per_candidate , v5.hrmp_max_message_num_per_candidate);
|
||||
assert_eq!(v4.validation_upgrade_cooldown , v5.validation_upgrade_cooldown);
|
||||
assert_eq!(v4.validation_upgrade_delay , v5.validation_upgrade_delay);
|
||||
assert_eq!(v4.max_pov_size , v5.max_pov_size);
|
||||
assert_eq!(v4.max_downward_message_size , v5.max_downward_message_size);
|
||||
assert_eq!(v4.ump_service_total_weight , v5.ump_service_total_weight);
|
||||
assert_eq!(v4.hrmp_max_parachain_outbound_channels , v5.hrmp_max_parachain_outbound_channels);
|
||||
assert_eq!(v4.hrmp_max_parathread_outbound_channels , v5.hrmp_max_parathread_outbound_channels);
|
||||
assert_eq!(v4.hrmp_sender_deposit , v5.hrmp_sender_deposit);
|
||||
assert_eq!(v4.hrmp_recipient_deposit , v5.hrmp_recipient_deposit);
|
||||
assert_eq!(v4.hrmp_channel_max_capacity , v5.hrmp_channel_max_capacity);
|
||||
assert_eq!(v4.hrmp_channel_max_total_size , v5.hrmp_channel_max_total_size);
|
||||
assert_eq!(v4.hrmp_max_parachain_inbound_channels , v5.hrmp_max_parachain_inbound_channels);
|
||||
assert_eq!(v4.hrmp_max_parathread_inbound_channels , v5.hrmp_max_parathread_inbound_channels);
|
||||
assert_eq!(v4.hrmp_channel_max_message_size , v5.hrmp_channel_max_message_size);
|
||||
assert_eq!(v4.code_retention_period , v5.code_retention_period);
|
||||
assert_eq!(v4.parathread_cores , v5.parathread_cores);
|
||||
assert_eq!(v4.parathread_retries , v5.parathread_retries);
|
||||
assert_eq!(v4.group_rotation_frequency , v5.group_rotation_frequency);
|
||||
assert_eq!(v4.chain_availability_period , v5.chain_availability_period);
|
||||
assert_eq!(v4.thread_availability_period , v5.thread_availability_period);
|
||||
assert_eq!(v4.scheduling_lookahead , v5.scheduling_lookahead);
|
||||
assert_eq!(v4.max_validators_per_core , v5.max_validators_per_core);
|
||||
assert_eq!(v4.max_validators , v5.max_validators);
|
||||
assert_eq!(v4.dispute_period , v5.dispute_period);
|
||||
assert_eq!(v4.no_show_slots , v5.no_show_slots);
|
||||
assert_eq!(v4.n_delay_tranches , v5.n_delay_tranches);
|
||||
assert_eq!(v4.zeroth_delay_tranche_width , v5.zeroth_delay_tranche_width);
|
||||
assert_eq!(v4.needed_approvals , v5.needed_approvals);
|
||||
assert_eq!(v4.relay_vrf_modulo_samples , v5.relay_vrf_modulo_samples);
|
||||
assert_eq!(v4.ump_max_individual_weight , v5.ump_max_individual_weight);
|
||||
assert_eq!(v4.pvf_checking_enabled , v5.pvf_checking_enabled);
|
||||
assert_eq!(v4.pvf_voting_ttl , v5.pvf_voting_ttl);
|
||||
assert_eq!(v4.minimum_validation_upgrade_delay , v5.minimum_validation_upgrade_delay);
|
||||
}; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression.
|
||||
|
||||
// additional checks for async backing.
|
||||
assert_eq!(v5.async_backing_params.allowed_ancestry_len, 0);
|
||||
assert_eq!(v5.async_backing_params.max_candidate_depth, 0);
|
||||
assert_eq!(v5.executor_params, ExecutorParams::new());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
pub mod v5;
|
||||
pub mod v6;
|
||||
|
||||
@@ -0,0 +1,504 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A module that is responsible for migration of storage.
|
||||
|
||||
use crate::configuration::{self, Config, Pallet, MAX_POV_SIZE};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, StorageVersion},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use primitives::vstaging::AsyncBackingParams;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
use super::*;
|
||||
use frame_support::{traits::OnRuntimeUpgrade, weights::constants::WEIGHT_REF_TIME_PER_MILLIS};
|
||||
use primitives::{Balance, SessionIndex};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::prelude::*;
|
||||
|
||||
// Copied over from configuration.rs @ de9e147695b9f1be8bd44e07861a31e483c8343a and removed
|
||||
// all the comments, and changed the Weight struct to OldWeight
|
||||
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, Clone)]
|
||||
pub struct V4HostConfiguration<BlockNumber> {
|
||||
pub max_code_size: u32,
|
||||
pub max_head_data_size: u32,
|
||||
pub max_upward_queue_count: u32,
|
||||
pub max_upward_queue_size: u32,
|
||||
pub max_upward_message_size: u32,
|
||||
pub max_upward_message_num_per_candidate: u32,
|
||||
pub hrmp_max_message_num_per_candidate: u32,
|
||||
pub validation_upgrade_cooldown: BlockNumber,
|
||||
pub validation_upgrade_delay: BlockNumber,
|
||||
pub max_pov_size: u32,
|
||||
pub max_downward_message_size: u32,
|
||||
pub ump_service_total_weight: Weight,
|
||||
pub hrmp_max_parachain_outbound_channels: u32,
|
||||
pub hrmp_max_parathread_outbound_channels: u32,
|
||||
pub hrmp_sender_deposit: Balance,
|
||||
pub hrmp_recipient_deposit: Balance,
|
||||
pub hrmp_channel_max_capacity: u32,
|
||||
pub hrmp_channel_max_total_size: u32,
|
||||
pub hrmp_max_parachain_inbound_channels: u32,
|
||||
pub hrmp_max_parathread_inbound_channels: u32,
|
||||
pub hrmp_channel_max_message_size: u32,
|
||||
pub code_retention_period: BlockNumber,
|
||||
pub parathread_cores: u32,
|
||||
pub parathread_retries: u32,
|
||||
pub group_rotation_frequency: BlockNumber,
|
||||
pub chain_availability_period: BlockNumber,
|
||||
pub thread_availability_period: BlockNumber,
|
||||
pub scheduling_lookahead: u32,
|
||||
pub max_validators_per_core: Option<u32>,
|
||||
pub max_validators: Option<u32>,
|
||||
pub dispute_period: SessionIndex,
|
||||
pub dispute_post_conclusion_acceptance_period: BlockNumber,
|
||||
pub dispute_conclusion_by_time_out_period: BlockNumber,
|
||||
pub no_show_slots: u32,
|
||||
pub n_delay_tranches: u32,
|
||||
pub zeroth_delay_tranche_width: u32,
|
||||
pub needed_approvals: u32,
|
||||
pub relay_vrf_modulo_samples: u32,
|
||||
pub ump_max_individual_weight: Weight,
|
||||
pub pvf_checking_enabled: bool,
|
||||
pub pvf_voting_ttl: SessionIndex,
|
||||
pub minimum_validation_upgrade_delay: BlockNumber,
|
||||
}
|
||||
|
||||
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, Clone)]
|
||||
pub struct V5HostConfiguration<BlockNumber> {
|
||||
pub max_code_size: u32,
|
||||
pub max_head_data_size: u32,
|
||||
pub max_upward_queue_count: u32,
|
||||
pub max_upward_queue_size: u32,
|
||||
pub max_upward_message_size: u32,
|
||||
pub max_upward_message_num_per_candidate: u32,
|
||||
pub hrmp_max_message_num_per_candidate: u32,
|
||||
pub validation_upgrade_cooldown: BlockNumber,
|
||||
pub validation_upgrade_delay: BlockNumber,
|
||||
pub async_backing_params: AsyncBackingParams,
|
||||
pub max_pov_size: u32,
|
||||
pub max_downward_message_size: u32,
|
||||
pub ump_service_total_weight: Weight,
|
||||
pub hrmp_max_parachain_outbound_channels: u32,
|
||||
pub hrmp_max_parathread_outbound_channels: u32,
|
||||
pub hrmp_sender_deposit: Balance,
|
||||
pub hrmp_recipient_deposit: Balance,
|
||||
pub hrmp_channel_max_capacity: u32,
|
||||
pub hrmp_channel_max_total_size: u32,
|
||||
pub hrmp_max_parachain_inbound_channels: u32,
|
||||
pub hrmp_max_parathread_inbound_channels: u32,
|
||||
pub hrmp_channel_max_message_size: u32,
|
||||
pub executor_params: ExecutorParams,
|
||||
pub code_retention_period: BlockNumber,
|
||||
pub parathread_cores: u32,
|
||||
pub parathread_retries: u32,
|
||||
pub group_rotation_frequency: BlockNumber,
|
||||
pub chain_availability_period: BlockNumber,
|
||||
pub thread_availability_period: BlockNumber,
|
||||
pub scheduling_lookahead: u32,
|
||||
pub max_validators_per_core: Option<u32>,
|
||||
pub max_validators: Option<u32>,
|
||||
pub dispute_period: SessionIndex,
|
||||
pub dispute_post_conclusion_acceptance_period: BlockNumber,
|
||||
pub no_show_slots: u32,
|
||||
pub n_delay_tranches: u32,
|
||||
pub zeroth_delay_tranche_width: u32,
|
||||
pub needed_approvals: u32,
|
||||
pub relay_vrf_modulo_samples: u32,
|
||||
pub ump_max_individual_weight: Weight,
|
||||
pub pvf_checking_enabled: bool,
|
||||
pub pvf_voting_ttl: SessionIndex,
|
||||
pub minimum_validation_upgrade_delay: BlockNumber,
|
||||
}
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V4ActiveConfig<T: Config> =
|
||||
StorageValue<Pallet<T>, V4HostConfiguration<BlockNumberFor<T>>, OptionQuery>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V4PendingConfigs<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
Vec<(SessionIndex, V4HostConfiguration<BlockNumberFor<T>>)>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V5ActiveConfig<T: Config> =
|
||||
StorageValue<Pallet<T>, V5HostConfiguration<BlockNumberFor<T>>, OptionQuery>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V5PendingConfigs<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
Vec<(SessionIndex, V5HostConfiguration<BlockNumberFor<T>>)>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
impl<BlockNumber: Default + From<u32>> Default for V4HostConfiguration<BlockNumber> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
group_rotation_frequency: 1u32.into(),
|
||||
chain_availability_period: 1u32.into(),
|
||||
thread_availability_period: 1u32.into(),
|
||||
no_show_slots: 1u32.into(),
|
||||
validation_upgrade_cooldown: Default::default(),
|
||||
validation_upgrade_delay: Default::default(),
|
||||
code_retention_period: Default::default(),
|
||||
max_code_size: Default::default(),
|
||||
max_pov_size: Default::default(),
|
||||
max_head_data_size: Default::default(),
|
||||
parathread_cores: Default::default(),
|
||||
parathread_retries: Default::default(),
|
||||
scheduling_lookahead: Default::default(),
|
||||
max_validators_per_core: Default::default(),
|
||||
max_validators: None,
|
||||
dispute_period: 6,
|
||||
dispute_post_conclusion_acceptance_period: 100.into(),
|
||||
dispute_conclusion_by_time_out_period: 200.into(),
|
||||
n_delay_tranches: Default::default(),
|
||||
zeroth_delay_tranche_width: Default::default(),
|
||||
needed_approvals: Default::default(),
|
||||
relay_vrf_modulo_samples: Default::default(),
|
||||
max_upward_queue_count: Default::default(),
|
||||
max_upward_queue_size: Default::default(),
|
||||
max_downward_message_size: Default::default(),
|
||||
ump_service_total_weight: Default::default(),
|
||||
max_upward_message_size: Default::default(),
|
||||
max_upward_message_num_per_candidate: Default::default(),
|
||||
hrmp_sender_deposit: Default::default(),
|
||||
hrmp_recipient_deposit: Default::default(),
|
||||
hrmp_channel_max_capacity: Default::default(),
|
||||
hrmp_channel_max_total_size: Default::default(),
|
||||
hrmp_max_parachain_inbound_channels: Default::default(),
|
||||
hrmp_max_parathread_inbound_channels: Default::default(),
|
||||
hrmp_channel_max_message_size: Default::default(),
|
||||
hrmp_max_parachain_outbound_channels: Default::default(),
|
||||
hrmp_max_parathread_outbound_channels: Default::default(),
|
||||
hrmp_max_message_num_per_candidate: Default::default(),
|
||||
ump_max_individual_weight: Weight::from_parts(
|
||||
20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
MAX_POV_SIZE as u64,
|
||||
),
|
||||
pvf_checking_enabled: false,
|
||||
pvf_voting_ttl: 2u32.into(),
|
||||
minimum_validation_upgrade_delay: 2.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BlockNumber: Default + From<u32>> Default for V5HostConfiguration<BlockNumber> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
group_rotation_frequency: 1u32.into(),
|
||||
chain_availability_period: 1u32.into(),
|
||||
thread_availability_period: 1u32.into(),
|
||||
no_show_slots: 1u32.into(),
|
||||
validation_upgrade_cooldown: Default::default(),
|
||||
validation_upgrade_delay: Default::default(),
|
||||
code_retention_period: Default::default(),
|
||||
max_code_size: Default::default(),
|
||||
max_pov_size: Default::default(),
|
||||
max_head_data_size: Default::default(),
|
||||
parathread_cores: Default::default(),
|
||||
parathread_retries: Default::default(),
|
||||
scheduling_lookahead: Default::default(),
|
||||
max_validators_per_core: Default::default(),
|
||||
max_validators: None,
|
||||
dispute_period: 6,
|
||||
dispute_post_conclusion_acceptance_period: 100.into(),
|
||||
n_delay_tranches: Default::default(),
|
||||
zeroth_delay_tranche_width: Default::default(),
|
||||
needed_approvals: Default::default(),
|
||||
relay_vrf_modulo_samples: Default::default(),
|
||||
max_upward_queue_count: Default::default(),
|
||||
max_upward_queue_size: Default::default(),
|
||||
max_downward_message_size: Default::default(),
|
||||
ump_service_total_weight: Default::default(),
|
||||
max_upward_message_size: Default::default(),
|
||||
max_upward_message_num_per_candidate: Default::default(),
|
||||
hrmp_sender_deposit: Default::default(),
|
||||
hrmp_recipient_deposit: Default::default(),
|
||||
hrmp_channel_max_capacity: Default::default(),
|
||||
hrmp_channel_max_total_size: Default::default(),
|
||||
hrmp_max_parachain_inbound_channels: Default::default(),
|
||||
hrmp_max_parathread_inbound_channels: Default::default(),
|
||||
hrmp_channel_max_message_size: Default::default(),
|
||||
hrmp_max_parachain_outbound_channels: Default::default(),
|
||||
hrmp_max_parathread_outbound_channels: Default::default(),
|
||||
hrmp_max_message_num_per_candidate: Default::default(),
|
||||
ump_max_individual_weight: Weight::from_parts(
|
||||
20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
MAX_POV_SIZE as u64,
|
||||
),
|
||||
pvf_checking_enabled: false,
|
||||
pvf_voting_ttl: 2u32.into(),
|
||||
minimum_validation_upgrade_delay: 2.into(),
|
||||
async_backing_params: AsyncBackingParams {
|
||||
max_candidate_depth: 0,
|
||||
allowed_ancestry_len: 0,
|
||||
},
|
||||
executor_params: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MigrateToV5<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV5<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade()");
|
||||
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 4, "The migration requires version 4");
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if StorageVersion::get::<Pallet<T>>() == 4 {
|
||||
let weight_consumed = migrate_to_v5::<T>();
|
||||
|
||||
log::info!(target: configuration::LOG_TARGET, "MigrateToV5 executed successfully");
|
||||
StorageVersion::new(5).put::<Pallet<T>>();
|
||||
|
||||
weight_consumed
|
||||
} else {
|
||||
log::warn!(target: configuration::LOG_TARGET, "MigrateToV5 should be removed.");
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running post_upgrade()");
|
||||
ensure!(
|
||||
StorageVersion::get::<Pallet<T>>() == 5,
|
||||
"Storage version should be 5 after the migration"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_to_v5<T: Config>() -> Weight {
|
||||
// Unusual formatting is justified:
|
||||
// - make it easier to verify that fields assign what they supposed to assign.
|
||||
// - this code is transient and will be removed after all migrations are done.
|
||||
// - this code is important enough to optimize for legibility sacrificing consistency.
|
||||
#[rustfmt::skip]
|
||||
let translate =
|
||||
|pre: V4HostConfiguration<BlockNumberFor<T>>| ->
|
||||
V5HostConfiguration<BlockNumberFor<T>>
|
||||
{
|
||||
V5HostConfiguration {
|
||||
max_code_size : pre.max_code_size,
|
||||
max_head_data_size : pre.max_head_data_size,
|
||||
max_upward_queue_count : pre.max_upward_queue_count,
|
||||
max_upward_queue_size : pre.max_upward_queue_size,
|
||||
max_upward_message_size : pre.max_upward_message_size,
|
||||
max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate,
|
||||
hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate,
|
||||
validation_upgrade_cooldown : pre.validation_upgrade_cooldown,
|
||||
validation_upgrade_delay : pre.validation_upgrade_delay,
|
||||
max_pov_size : pre.max_pov_size,
|
||||
max_downward_message_size : pre.max_downward_message_size,
|
||||
ump_service_total_weight : pre.ump_service_total_weight,
|
||||
hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels,
|
||||
hrmp_max_parathread_outbound_channels : pre.hrmp_max_parathread_outbound_channels,
|
||||
hrmp_sender_deposit : pre.hrmp_sender_deposit,
|
||||
hrmp_recipient_deposit : pre.hrmp_recipient_deposit,
|
||||
hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity,
|
||||
hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size,
|
||||
hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels,
|
||||
hrmp_max_parathread_inbound_channels : pre.hrmp_max_parathread_inbound_channels,
|
||||
hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size,
|
||||
code_retention_period : pre.code_retention_period,
|
||||
parathread_cores : pre.parathread_cores,
|
||||
parathread_retries : pre.parathread_retries,
|
||||
group_rotation_frequency : pre.group_rotation_frequency,
|
||||
chain_availability_period : pre.chain_availability_period,
|
||||
thread_availability_period : pre.thread_availability_period,
|
||||
scheduling_lookahead : pre.scheduling_lookahead,
|
||||
max_validators_per_core : pre.max_validators_per_core,
|
||||
max_validators : pre.max_validators,
|
||||
dispute_period : pre.dispute_period,
|
||||
dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period,
|
||||
no_show_slots : pre.no_show_slots,
|
||||
n_delay_tranches : pre.n_delay_tranches,
|
||||
zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width,
|
||||
needed_approvals : pre.needed_approvals,
|
||||
relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples,
|
||||
ump_max_individual_weight : pre.ump_max_individual_weight,
|
||||
pvf_checking_enabled : pre.pvf_checking_enabled,
|
||||
pvf_voting_ttl : pre.pvf_voting_ttl,
|
||||
minimum_validation_upgrade_delay : pre.minimum_validation_upgrade_delay,
|
||||
|
||||
// Default values are zeroes, thus it's ensured allowed ancestry never crosses the upgrade block.
|
||||
async_backing_params : AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: 0 },
|
||||
|
||||
// Default executor parameters set is empty
|
||||
executor_params : Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
let v4 = V4ActiveConfig::<T>::get()
|
||||
.defensive_proof("Could not decode old config")
|
||||
.unwrap_or_default();
|
||||
let v5 = translate(v4);
|
||||
V5ActiveConfig::<T>::set(Some(v5));
|
||||
|
||||
let pending_v4 = V4PendingConfigs::<T>::get()
|
||||
.defensive_proof("Could not decode old pending")
|
||||
.unwrap_or_default();
|
||||
let mut pending_v5 = Vec::new();
|
||||
|
||||
for (session, v4) in pending_v4.into_iter() {
|
||||
let v5 = translate(v4);
|
||||
pending_v5.push((session, v5));
|
||||
}
|
||||
V5PendingConfigs::<T>::set(Some(pending_v5.clone()));
|
||||
|
||||
let num_configs = (pending_v5.len() + 1) as u64;
|
||||
T::DbWeight::get().reads_writes(num_configs, num_configs)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test};
|
||||
use primitives::ExecutorParams;
|
||||
|
||||
#[test]
|
||||
fn v4_deserialized_from_actual_data() {
|
||||
// Example how to get new `raw_config`:
|
||||
// We'll obtain the raw_config at a specified a block
|
||||
// Steps:
|
||||
// 1. Go to Polkadot.js -> Developer -> Chain state -> Storage: https://polkadot.js.org/apps/#/chainstate
|
||||
// 2. Set these parameters:
|
||||
// 2.1. selected state query: configuration; activeConfig(): PolkadotRuntimeParachainsConfigurationHostConfiguration
|
||||
// 2.2. blockhash to query at: 0xf89d3ab5312c5f70d396dc59612f0aa65806c798346f9db4b35278baed2e0e53 (the hash of the block)
|
||||
// 2.3. Note the value of encoded storage key -> 0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385 for the referenced block.
|
||||
// 2.4. You'll also need the decoded values to update the test.
|
||||
// 3. Go to Polkadot.js -> Developer -> Chain state -> Raw storage
|
||||
// 3.1 Enter the encoded storage key and you get the raw config.
|
||||
|
||||
// This exceeds the maximal line width length, but that's fine, since this is not code and
|
||||
// doesn't need to be read and also leaving it as one line allows to easily copy it.
|
||||
let raw_config = hex_literal::hex!["0000a000005000000a00000000c8000000c800000a0000000a000000100e0000580200000000500000c800000700e8764817020040011e00000000000000005039278c0400000000000000000000005039278c0400000000000000000000e8030000009001001e00000000000000009001008070000000000000000000000a0000000a0000000a00000001000000010500000001c80000000600000058020000580200000200000059000000000000001e000000280000000700c817a80402004001010200000014000000"];
|
||||
|
||||
let v4 = v5::V4HostConfiguration::<primitives::BlockNumber>::decode(&mut &raw_config[..])
|
||||
.unwrap();
|
||||
|
||||
// We check only a sample of the values here. If we missed any fields or messed up data types
|
||||
// that would skew all the fields coming after.
|
||||
assert_eq!(v4.max_code_size, 10_485_760);
|
||||
assert_eq!(v4.validation_upgrade_cooldown, 3600);
|
||||
assert_eq!(v4.max_pov_size, 5_242_880);
|
||||
assert_eq!(v4.hrmp_channel_max_message_size, 102_400);
|
||||
assert_eq!(v4.n_delay_tranches, 89);
|
||||
assert_eq!(v4.ump_max_individual_weight, Weight::from_parts(20_000_000_000, 5_242_880));
|
||||
assert_eq!(v4.minimum_validation_upgrade_delay, 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_migrate_to_v5() {
|
||||
// Host configuration has lots of fields. However, in this migration we only remove one field.
|
||||
// The most important part to check are a couple of the last fields. We also pick
|
||||
// extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and
|
||||
// also their type.
|
||||
//
|
||||
// We specify only the picked fields and the rest should be provided by the `Default`
|
||||
// implementation. That implementation is copied over between the two types and should work
|
||||
// fine.
|
||||
let v4 = v5::V4HostConfiguration::<primitives::BlockNumber> {
|
||||
ump_max_individual_weight: Weight::from_parts(0x71616e6f6e0au64, 0x71616e6f6e0au64),
|
||||
needed_approvals: 69,
|
||||
thread_availability_period: 55,
|
||||
hrmp_recipient_deposit: 1337,
|
||||
max_pov_size: 1111,
|
||||
chain_availability_period: 33,
|
||||
minimum_validation_upgrade_delay: 20,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut pending_configs = Vec::new();
|
||||
pending_configs.push((100, v4.clone()));
|
||||
pending_configs.push((300, v4.clone()));
|
||||
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
// Implant the v4 version in the state.
|
||||
V4ActiveConfig::<Test>::set(Some(v4));
|
||||
V4PendingConfigs::<Test>::set(Some(pending_configs));
|
||||
|
||||
migrate_to_v5::<Test>();
|
||||
|
||||
let v5 = V5ActiveConfig::<Test>::get().unwrap();
|
||||
let mut configs_to_check = V5PendingConfigs::<Test>::get().unwrap();
|
||||
configs_to_check.push((0, v5.clone()));
|
||||
|
||||
for (_, v4) in configs_to_check {
|
||||
#[rustfmt::skip]
|
||||
{
|
||||
assert_eq!(v4.max_code_size , v5.max_code_size);
|
||||
assert_eq!(v4.max_head_data_size , v5.max_head_data_size);
|
||||
assert_eq!(v4.max_upward_queue_count , v5.max_upward_queue_count);
|
||||
assert_eq!(v4.max_upward_queue_size , v5.max_upward_queue_size);
|
||||
assert_eq!(v4.max_upward_message_size , v5.max_upward_message_size);
|
||||
assert_eq!(v4.max_upward_message_num_per_candidate , v5.max_upward_message_num_per_candidate);
|
||||
assert_eq!(v4.hrmp_max_message_num_per_candidate , v5.hrmp_max_message_num_per_candidate);
|
||||
assert_eq!(v4.validation_upgrade_cooldown , v5.validation_upgrade_cooldown);
|
||||
assert_eq!(v4.validation_upgrade_delay , v5.validation_upgrade_delay);
|
||||
assert_eq!(v4.max_pov_size , v5.max_pov_size);
|
||||
assert_eq!(v4.max_downward_message_size , v5.max_downward_message_size);
|
||||
assert_eq!(v4.ump_service_total_weight , v5.ump_service_total_weight);
|
||||
assert_eq!(v4.hrmp_max_parachain_outbound_channels , v5.hrmp_max_parachain_outbound_channels);
|
||||
assert_eq!(v4.hrmp_max_parathread_outbound_channels , v5.hrmp_max_parathread_outbound_channels);
|
||||
assert_eq!(v4.hrmp_sender_deposit , v5.hrmp_sender_deposit);
|
||||
assert_eq!(v4.hrmp_recipient_deposit , v5.hrmp_recipient_deposit);
|
||||
assert_eq!(v4.hrmp_channel_max_capacity , v5.hrmp_channel_max_capacity);
|
||||
assert_eq!(v4.hrmp_channel_max_total_size , v5.hrmp_channel_max_total_size);
|
||||
assert_eq!(v4.hrmp_max_parachain_inbound_channels , v5.hrmp_max_parachain_inbound_channels);
|
||||
assert_eq!(v4.hrmp_max_parathread_inbound_channels , v5.hrmp_max_parathread_inbound_channels);
|
||||
assert_eq!(v4.hrmp_channel_max_message_size , v5.hrmp_channel_max_message_size);
|
||||
assert_eq!(v4.code_retention_period , v5.code_retention_period);
|
||||
assert_eq!(v4.parathread_cores , v5.parathread_cores);
|
||||
assert_eq!(v4.parathread_retries , v5.parathread_retries);
|
||||
assert_eq!(v4.group_rotation_frequency , v5.group_rotation_frequency);
|
||||
assert_eq!(v4.chain_availability_period , v5.chain_availability_period);
|
||||
assert_eq!(v4.thread_availability_period , v5.thread_availability_period);
|
||||
assert_eq!(v4.scheduling_lookahead , v5.scheduling_lookahead);
|
||||
assert_eq!(v4.max_validators_per_core , v5.max_validators_per_core);
|
||||
assert_eq!(v4.max_validators , v5.max_validators);
|
||||
assert_eq!(v4.dispute_period , v5.dispute_period);
|
||||
assert_eq!(v4.no_show_slots , v5.no_show_slots);
|
||||
assert_eq!(v4.n_delay_tranches , v5.n_delay_tranches);
|
||||
assert_eq!(v4.zeroth_delay_tranche_width , v5.zeroth_delay_tranche_width);
|
||||
assert_eq!(v4.needed_approvals , v5.needed_approvals);
|
||||
assert_eq!(v4.relay_vrf_modulo_samples , v5.relay_vrf_modulo_samples);
|
||||
assert_eq!(v4.ump_max_individual_weight , v5.ump_max_individual_weight);
|
||||
assert_eq!(v4.pvf_checking_enabled , v5.pvf_checking_enabled);
|
||||
assert_eq!(v4.pvf_voting_ttl , v5.pvf_voting_ttl);
|
||||
assert_eq!(v4.minimum_validation_upgrade_delay , v5.minimum_validation_upgrade_delay);
|
||||
}; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression.
|
||||
|
||||
// additional checks for async backing.
|
||||
assert_eq!(v5.async_backing_params.allowed_ancestry_len, 0);
|
||||
assert_eq!(v5.async_backing_params.max_candidate_depth, 0);
|
||||
assert_eq!(v5.executor_params, ExecutorParams::new());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A module that is responsible for migration of storage.
|
||||
|
||||
use crate::configuration::{self, Config, Pallet};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, StorageVersion},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
use primitives::SessionIndex;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::prelude::*;
|
||||
|
||||
use super::v5::V5HostConfiguration;
|
||||
// Change this once there is V7.
|
||||
type V6HostConfiguration<BlockNumber> = configuration::HostConfiguration<BlockNumber>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V5ActiveConfig<T: Config> =
|
||||
StorageValue<Pallet<T>, V5HostConfiguration<BlockNumberFor<T>>, OptionQuery>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V5PendingConfigs<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
Vec<(SessionIndex, V5HostConfiguration<BlockNumberFor<T>>)>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V6ActiveConfig<T: Config> =
|
||||
StorageValue<Pallet<T>, V6HostConfiguration<BlockNumberFor<T>>, OptionQuery>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type V6PendingConfigs<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
Vec<(SessionIndex, V6HostConfiguration<BlockNumberFor<T>>)>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
pub struct MigrateToV6<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV6<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade()");
|
||||
|
||||
ensure!(StorageVersion::get::<Pallet<T>>() == 5, "The migration requires version 4");
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if StorageVersion::get::<Pallet<T>>() == 5 {
|
||||
let weight_consumed = migrate_to_v6::<T>();
|
||||
|
||||
log::info!(target: configuration::LOG_TARGET, "MigrateToV6 executed successfully");
|
||||
StorageVersion::new(6).put::<Pallet<T>>();
|
||||
|
||||
weight_consumed
|
||||
} else {
|
||||
log::warn!(target: configuration::LOG_TARGET, "MigrateToV6 should be removed.");
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
log::trace!(target: crate::configuration::LOG_TARGET, "Running post_upgrade()");
|
||||
ensure!(
|
||||
StorageVersion::get::<Pallet<T>>() == 6,
|
||||
"Storage version should be 6 after the migration"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_to_v6<T: Config>() -> Weight {
|
||||
// Unusual formatting is justified:
|
||||
// - make it easier to verify that fields assign what they supposed to assign.
|
||||
// - this code is transient and will be removed after all migrations are done.
|
||||
// - this code is important enough to optimize for legibility sacrificing consistency.
|
||||
#[rustfmt::skip]
|
||||
let translate =
|
||||
|pre: V5HostConfiguration<BlockNumberFor<T>>| ->
|
||||
V6HostConfiguration<BlockNumberFor<T>>
|
||||
{
|
||||
V6HostConfiguration {
|
||||
max_code_size : pre.max_code_size,
|
||||
max_head_data_size : pre.max_head_data_size,
|
||||
max_upward_queue_count : pre.max_upward_queue_count,
|
||||
max_upward_queue_size : pre.max_upward_queue_size,
|
||||
max_upward_message_size : pre.max_upward_message_size,
|
||||
max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate,
|
||||
hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate,
|
||||
validation_upgrade_cooldown : pre.validation_upgrade_cooldown,
|
||||
validation_upgrade_delay : pre.validation_upgrade_delay,
|
||||
max_pov_size : pre.max_pov_size,
|
||||
max_downward_message_size : pre.max_downward_message_size,
|
||||
hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels,
|
||||
hrmp_max_parathread_outbound_channels : pre.hrmp_max_parathread_outbound_channels,
|
||||
hrmp_sender_deposit : pre.hrmp_sender_deposit,
|
||||
hrmp_recipient_deposit : pre.hrmp_recipient_deposit,
|
||||
hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity,
|
||||
hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size,
|
||||
hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels,
|
||||
hrmp_max_parathread_inbound_channels : pre.hrmp_max_parathread_inbound_channels,
|
||||
hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size,
|
||||
code_retention_period : pre.code_retention_period,
|
||||
parathread_cores : pre.parathread_cores,
|
||||
parathread_retries : pre.parathread_retries,
|
||||
group_rotation_frequency : pre.group_rotation_frequency,
|
||||
chain_availability_period : pre.chain_availability_period,
|
||||
thread_availability_period : pre.thread_availability_period,
|
||||
scheduling_lookahead : pre.scheduling_lookahead,
|
||||
max_validators_per_core : pre.max_validators_per_core,
|
||||
max_validators : pre.max_validators,
|
||||
dispute_period : pre.dispute_period,
|
||||
dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period,
|
||||
no_show_slots : pre.no_show_slots,
|
||||
n_delay_tranches : pre.n_delay_tranches,
|
||||
zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width,
|
||||
needed_approvals : pre.needed_approvals,
|
||||
relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples,
|
||||
pvf_checking_enabled : pre.pvf_checking_enabled,
|
||||
pvf_voting_ttl : pre.pvf_voting_ttl,
|
||||
minimum_validation_upgrade_delay : pre.minimum_validation_upgrade_delay,
|
||||
async_backing_params : pre.async_backing_params,
|
||||
executor_params : pre.executor_params,
|
||||
}
|
||||
};
|
||||
|
||||
let v5 = V5ActiveConfig::<T>::get()
|
||||
.defensive_proof("Could not decode old config")
|
||||
.unwrap_or_default();
|
||||
let v6 = translate(v5);
|
||||
V6ActiveConfig::<T>::set(Some(v6));
|
||||
|
||||
let pending_v4 = V5PendingConfigs::<T>::get()
|
||||
.defensive_proof("Could not decode old pending")
|
||||
.unwrap_or_default();
|
||||
let mut pending_v5 = Vec::new();
|
||||
|
||||
for (session, v5) in pending_v4.into_iter() {
|
||||
let v6 = translate(v5);
|
||||
pending_v5.push((session, v6));
|
||||
}
|
||||
V6PendingConfigs::<T>::set(Some(pending_v5.clone()));
|
||||
|
||||
let num_configs = (pending_v5.len() + 1) as u64;
|
||||
T::DbWeight::get().reads_writes(num_configs, num_configs)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test};
|
||||
|
||||
#[test]
|
||||
fn v5_deserialized_from_actual_data() {
|
||||
// Example how to get new `raw_config`:
|
||||
// We'll obtain the raw_config at a specified a block
|
||||
// Steps:
|
||||
// 1. Go to Polkadot.js -> Developer -> Chain state -> Storage: https://polkadot.js.org/apps/#/chainstate
|
||||
// 2. Set these parameters:
|
||||
// 2.1. selected state query: configuration; activeConfig(): PolkadotRuntimeParachainsConfigurationHostConfiguration
|
||||
// 2.2. blockhash to query at: 0xf89d3ab5312c5f70d396dc59612f0aa65806c798346f9db4b35278baed2e0e53 (the hash of the block)
|
||||
// 2.3. Note the value of encoded storage key -> 0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385 for the referenced block.
|
||||
// 2.4. You'll also need the decoded values to update the test.
|
||||
// 3. Go to Polkadot.js -> Developer -> Chain state -> Raw storage
|
||||
// 3.1 Enter the encoded storage key and you get the raw config.
|
||||
|
||||
// This exceeds the maximal line width length, but that's fine, since this is not code and
|
||||
// doesn't need to be read and also leaving it as one line allows to easily copy it.
|
||||
let raw_config = hex_literal::hex!["00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000"];
|
||||
|
||||
let v5 =
|
||||
V5HostConfiguration::<primitives::BlockNumber>::decode(&mut &raw_config[..]).unwrap();
|
||||
|
||||
// We check only a sample of the values here. If we missed any fields or messed up data types
|
||||
// that would skew all the fields coming after.
|
||||
assert_eq!(v5.max_code_size, 5242880);
|
||||
assert_eq!(v5.validation_upgrade_cooldown, 200);
|
||||
assert_eq!(v5.max_pov_size, 5_242_880);
|
||||
assert_eq!(v5.hrmp_channel_max_message_size, 102_400);
|
||||
assert_eq!(v5.n_delay_tranches, 40);
|
||||
assert_eq!(v5.ump_max_individual_weight, Weight::from_parts(20_000_000_000, 5_242_880));
|
||||
assert_eq!(v5.minimum_validation_upgrade_delay, 15); // This is the last field in the struct.
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_migrate_to_v6() {
|
||||
// Host configuration has lots of fields. However, in this migration we only remove one field.
|
||||
// The most important part to check are a couple of the last fields. We also pick
|
||||
// extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and
|
||||
// also their type.
|
||||
//
|
||||
// We specify only the picked fields and the rest should be provided by the `Default`
|
||||
// implementation. That implementation is copied over between the two types and should work
|
||||
// fine.
|
||||
let v5 = V5HostConfiguration::<primitives::BlockNumber> {
|
||||
ump_max_individual_weight: Weight::from_parts(0x71616e6f6e0au64, 0x71616e6f6e0au64),
|
||||
needed_approvals: 69,
|
||||
thread_availability_period: 55,
|
||||
hrmp_recipient_deposit: 1337,
|
||||
max_pov_size: 1111,
|
||||
chain_availability_period: 33,
|
||||
minimum_validation_upgrade_delay: 20,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut pending_configs = Vec::new();
|
||||
pending_configs.push((100, v5.clone()));
|
||||
pending_configs.push((300, v5.clone()));
|
||||
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
// Implant the v5 version in the state.
|
||||
V5ActiveConfig::<Test>::set(Some(v5));
|
||||
V5PendingConfigs::<Test>::set(Some(pending_configs));
|
||||
|
||||
migrate_to_v6::<Test>();
|
||||
|
||||
let v6 = V6ActiveConfig::<Test>::get().unwrap();
|
||||
let mut configs_to_check = V6PendingConfigs::<Test>::get().unwrap();
|
||||
configs_to_check.push((0, v6.clone()));
|
||||
|
||||
for (_, v5) in configs_to_check {
|
||||
#[rustfmt::skip]
|
||||
{
|
||||
assert_eq!(v5.max_code_size , v6.max_code_size);
|
||||
assert_eq!(v5.max_head_data_size , v6.max_head_data_size);
|
||||
assert_eq!(v5.max_upward_queue_count , v6.max_upward_queue_count);
|
||||
assert_eq!(v5.max_upward_queue_size , v6.max_upward_queue_size);
|
||||
assert_eq!(v5.max_upward_message_size , v6.max_upward_message_size);
|
||||
assert_eq!(v5.max_upward_message_num_per_candidate , v6.max_upward_message_num_per_candidate);
|
||||
assert_eq!(v5.hrmp_max_message_num_per_candidate , v6.hrmp_max_message_num_per_candidate);
|
||||
assert_eq!(v5.validation_upgrade_cooldown , v6.validation_upgrade_cooldown);
|
||||
assert_eq!(v5.validation_upgrade_delay , v6.validation_upgrade_delay);
|
||||
assert_eq!(v5.max_pov_size , v6.max_pov_size);
|
||||
assert_eq!(v5.max_downward_message_size , v6.max_downward_message_size);
|
||||
assert_eq!(v5.hrmp_max_parachain_outbound_channels , v6.hrmp_max_parachain_outbound_channels);
|
||||
assert_eq!(v5.hrmp_max_parathread_outbound_channels , v6.hrmp_max_parathread_outbound_channels);
|
||||
assert_eq!(v5.hrmp_sender_deposit , v6.hrmp_sender_deposit);
|
||||
assert_eq!(v5.hrmp_recipient_deposit , v6.hrmp_recipient_deposit);
|
||||
assert_eq!(v5.hrmp_channel_max_capacity , v6.hrmp_channel_max_capacity);
|
||||
assert_eq!(v5.hrmp_channel_max_total_size , v6.hrmp_channel_max_total_size);
|
||||
assert_eq!(v5.hrmp_max_parachain_inbound_channels , v6.hrmp_max_parachain_inbound_channels);
|
||||
assert_eq!(v5.hrmp_max_parathread_inbound_channels , v6.hrmp_max_parathread_inbound_channels);
|
||||
assert_eq!(v5.hrmp_channel_max_message_size , v6.hrmp_channel_max_message_size);
|
||||
assert_eq!(v5.code_retention_period , v6.code_retention_period);
|
||||
assert_eq!(v5.parathread_cores , v6.parathread_cores);
|
||||
assert_eq!(v5.parathread_retries , v6.parathread_retries);
|
||||
assert_eq!(v5.group_rotation_frequency , v6.group_rotation_frequency);
|
||||
assert_eq!(v5.chain_availability_period , v6.chain_availability_period);
|
||||
assert_eq!(v5.thread_availability_period , v6.thread_availability_period);
|
||||
assert_eq!(v5.scheduling_lookahead , v6.scheduling_lookahead);
|
||||
assert_eq!(v5.max_validators_per_core , v6.max_validators_per_core);
|
||||
assert_eq!(v5.max_validators , v6.max_validators);
|
||||
assert_eq!(v5.dispute_period , v6.dispute_period);
|
||||
assert_eq!(v5.no_show_slots , v6.no_show_slots);
|
||||
assert_eq!(v5.n_delay_tranches , v6.n_delay_tranches);
|
||||
assert_eq!(v5.zeroth_delay_tranche_width , v6.zeroth_delay_tranche_width);
|
||||
assert_eq!(v5.needed_approvals , v6.needed_approvals);
|
||||
assert_eq!(v5.relay_vrf_modulo_samples , v6.relay_vrf_modulo_samples);
|
||||
assert_eq!(v5.pvf_checking_enabled , v6.pvf_checking_enabled);
|
||||
assert_eq!(v5.pvf_voting_ttl , v6.pvf_voting_ttl);
|
||||
assert_eq!(v5.minimum_validation_upgrade_delay , v6.minimum_validation_upgrade_delay);
|
||||
assert_eq!(v5.async_backing_params.allowed_ancestry_len, v6.async_backing_params.allowed_ancestry_len);
|
||||
assert_eq!(v5.async_backing_params.max_candidate_depth , v6.async_backing_params.max_candidate_depth);
|
||||
assert_eq!(v5.executor_params , v6.executor_params);
|
||||
}; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression.
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A module that is responsible for migration of UMP storage.
|
||||
|
||||
#![allow(unused_imports)] // Since we use features.
|
||||
|
||||
use crate::configuration::{self, ActiveConfig, Config, PendingConfigs, WeightInfo, LOG_TARGET};
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
|
||||
pub mod latest {
|
||||
use super::*;
|
||||
use frame_support::{pallet_prelude::Weight, traits::OnRuntimeUpgrade};
|
||||
|
||||
/// Force update the UMP limits in the parachain host config.
|
||||
// NOTE: `OnRuntimeUpgrade` does not have a `self`, so everything must be compile time.
|
||||
pub struct ScheduleConfigUpdate<
|
||||
T,
|
||||
const MAX_UPWARD_QUEUE_SIZE: u32,
|
||||
const MAX_UPWARD_QUEUE_COUNT: u32,
|
||||
const MAX_UPWARD_MESSAGE_SIZE: u32,
|
||||
const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32,
|
||||
>(core::marker::PhantomData<T>);
|
||||
|
||||
impl<
|
||||
T: Config,
|
||||
const MAX_UPWARD_QUEUE_SIZE: u32,
|
||||
const MAX_UPWARD_QUEUE_COUNT: u32,
|
||||
const MAX_UPWARD_MESSAGE_SIZE: u32,
|
||||
const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32,
|
||||
> OnRuntimeUpgrade
|
||||
for ScheduleConfigUpdate<
|
||||
T,
|
||||
MAX_UPWARD_QUEUE_SIZE,
|
||||
MAX_UPWARD_QUEUE_COUNT,
|
||||
MAX_UPWARD_MESSAGE_SIZE,
|
||||
MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE,
|
||||
>
|
||||
{
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, &'static str> {
|
||||
log::info!(target: LOG_TARGET, "pre_upgrade");
|
||||
let mut pending = PendingConfigs::<T>::get();
|
||||
pending.sort_by_key(|(s, _)| *s);
|
||||
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Active HostConfig:\n\n{:#?}\n",
|
||||
ActiveConfig::<T>::get()
|
||||
);
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Last pending HostConfig upgrade:\n\n{:#?}\n",
|
||||
pending.last()
|
||||
);
|
||||
|
||||
Ok((pending.len() as u32).encode())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if let Err(e) = configuration::Pallet::<T>::schedule_config_update(|cfg| {
|
||||
cfg.max_upward_queue_size = MAX_UPWARD_QUEUE_SIZE;
|
||||
cfg.max_upward_queue_count = MAX_UPWARD_QUEUE_COUNT;
|
||||
cfg.max_upward_message_size = MAX_UPWARD_MESSAGE_SIZE;
|
||||
cfg.max_upward_message_num_per_candidate = MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE;
|
||||
}) {
|
||||
log::error!(
|
||||
target: LOG_TARGET,
|
||||
"\n!!!!!!!!!!!!!!!!!!!!!!!!\nFailed to schedule HostConfig upgrade: {:?}\n!!!!!!!!!!!!!!!!!!!!!!!!\n",
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
T::WeightInfo::set_config_with_block_number()
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
||||
log::info!(target: LOG_TARGET, "post_upgrade");
|
||||
let old_pending: u32 = Decode::decode(&mut &state[..]).expect("Known good");
|
||||
let mut pending = PendingConfigs::<T>::get();
|
||||
pending.sort_by_key(|(s, _)| *s);
|
||||
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Last pending HostConfig upgrade:\n\n{:#?}\n",
|
||||
pending.last()
|
||||
);
|
||||
assert_eq!(
|
||||
pending.len(),
|
||||
old_pending as usize + 1,
|
||||
"There must be a new pending upgrade enqueued"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Configuration, ParasShared, RuntimeOrigin, Test};
|
||||
use frame_support::{assert_err, assert_ok};
|
||||
use frame_support::{assert_err, assert_noop, assert_ok};
|
||||
|
||||
fn on_new_session(session_index: SessionIndex) -> (HostConfiguration<u32>, HostConfiguration<u32>) {
|
||||
ParasShared::set_session_index(session_index);
|
||||
@@ -309,7 +309,6 @@ fn setting_pending_config_members() {
|
||||
max_upward_queue_count: 1337,
|
||||
max_upward_queue_size: 228,
|
||||
max_downward_message_size: 2048,
|
||||
ump_service_total_weight: Weight::from_parts(20000, 20000),
|
||||
max_upward_message_size: 448,
|
||||
max_upward_message_num_per_candidate: 5,
|
||||
hrmp_sender_deposit: 22,
|
||||
@@ -322,7 +321,6 @@ fn setting_pending_config_members() {
|
||||
hrmp_max_parachain_outbound_channels: 10,
|
||||
hrmp_max_parathread_outbound_channels: 20,
|
||||
hrmp_max_message_num_per_candidate: 20,
|
||||
ump_max_individual_weight: Weight::from_parts(909, 909),
|
||||
pvf_checking_enabled: true,
|
||||
pvf_voting_ttl: 3,
|
||||
minimum_validation_upgrade_delay: 20,
|
||||
@@ -418,16 +416,18 @@ fn setting_pending_config_members() {
|
||||
new_config.max_upward_queue_size,
|
||||
)
|
||||
.unwrap();
|
||||
assert_noop!(
|
||||
Configuration::set_max_upward_queue_size(
|
||||
RuntimeOrigin::root(),
|
||||
MAX_UPWARD_MESSAGE_SIZE_BOUND + 1,
|
||||
),
|
||||
Error::<Test>::InvalidNewValue
|
||||
);
|
||||
Configuration::set_max_downward_message_size(
|
||||
RuntimeOrigin::root(),
|
||||
new_config.max_downward_message_size,
|
||||
)
|
||||
.unwrap();
|
||||
Configuration::set_ump_service_total_weight(
|
||||
RuntimeOrigin::root(),
|
||||
new_config.ump_service_total_weight,
|
||||
)
|
||||
.unwrap();
|
||||
Configuration::set_max_upward_message_size(
|
||||
RuntimeOrigin::root(),
|
||||
new_config.max_upward_message_size,
|
||||
@@ -488,11 +488,6 @@ fn setting_pending_config_members() {
|
||||
new_config.hrmp_max_message_num_per_candidate,
|
||||
)
|
||||
.unwrap();
|
||||
Configuration::set_ump_max_individual_weight(
|
||||
RuntimeOrigin::root(),
|
||||
new_config.ump_max_individual_weight,
|
||||
)
|
||||
.unwrap();
|
||||
Configuration::set_pvf_checking_enabled(
|
||||
RuntimeOrigin::root(),
|
||||
new_config.pvf_checking_enabled,
|
||||
|
||||
@@ -15,18 +15,16 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
mock::{
|
||||
new_test_ext, Configuration, Hrmp, MockGenesisConfig, Paras, ParasShared,
|
||||
RuntimeEvent as MockEvent, RuntimeOrigin, System, Test,
|
||||
},
|
||||
paras::ParaKind,
|
||||
use crate::mock::{
|
||||
deregister_parachain, new_test_ext, register_parachain, register_parachain_with_balance,
|
||||
Configuration, Hrmp, MockGenesisConfig, Paras, ParasShared, RuntimeEvent as MockEvent,
|
||||
RuntimeOrigin, System, Test,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok, traits::Currency as _};
|
||||
use primitives::{BlockNumber, ValidationCode};
|
||||
use frame_support::assert_noop;
|
||||
use primitives::BlockNumber;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
|
||||
pub(crate) fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
|
||||
let config = Configuration::config();
|
||||
while System::block_number() < to {
|
||||
let b = System::block_number();
|
||||
@@ -129,29 +127,6 @@ fn default_genesis_config() -> MockGenesisConfig {
|
||||
}
|
||||
}
|
||||
|
||||
fn register_parachain_with_balance(id: ParaId, balance: Balance) {
|
||||
let validation_code: ValidationCode = vec![1].into();
|
||||
assert_ok!(Paras::schedule_para_initialize(
|
||||
id,
|
||||
crate::paras::ParaGenesisArgs {
|
||||
para_kind: ParaKind::Parachain,
|
||||
genesis_head: vec![1].into(),
|
||||
validation_code: validation_code.clone(),
|
||||
},
|
||||
));
|
||||
|
||||
assert_ok!(Paras::add_trusted_validation_code(RuntimeOrigin::root(), validation_code));
|
||||
<Test as Config>::Currency::make_free_balance_be(&id.into_account_truncating(), balance);
|
||||
}
|
||||
|
||||
fn register_parachain(id: ParaId) {
|
||||
register_parachain_with_balance(id, 1000);
|
||||
}
|
||||
|
||||
fn deregister_parachain(id: ParaId) {
|
||||
assert_ok!(Paras::schedule_para_cleanup(id));
|
||||
}
|
||||
|
||||
fn channel_exists(sender: ParaId, recipient: ParaId) -> bool {
|
||||
HrmpChannels::<Test>::get(&HrmpChannelId { sender, recipient }).is_some()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use frame_benchmarking::benchmarks;
|
||||
use pallet_message_queue as mq;
|
||||
|
||||
benchmarks! {
|
||||
where_clause {
|
||||
where
|
||||
T: mq::Config,
|
||||
}
|
||||
|
||||
receive_upward_messages {
|
||||
let i in 1 .. 1000;
|
||||
|
||||
let max_len = mq::MaxMessageLenOf::<T>::get() as usize;
|
||||
let para = 42u32.into(); // not especially important.
|
||||
let upward_messages = vec![vec![0; max_len]; i as usize];
|
||||
Pallet::<T>::receive_upward_messages(para, vec![vec![0; max_len]; 1].as_slice());
|
||||
}: { Pallet::<T>::receive_upward_messages(para, upward_messages.as_slice()) }
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
Pallet,
|
||||
crate::mock::new_test_ext(Default::default()),
|
||||
crate::mock::Test
|
||||
);
|
||||
}
|
||||
@@ -21,20 +21,32 @@
|
||||
//! to included.
|
||||
|
||||
use crate::{
|
||||
configuration, disputes, dmp, hrmp, paras, paras_inherent::DisputedBitfield,
|
||||
scheduler::CoreAssignment, shared, ump,
|
||||
configuration::{self, HostConfiguration},
|
||||
disputes, dmp, hrmp, paras,
|
||||
paras_inherent::DisputedBitfield,
|
||||
scheduler::CoreAssignment,
|
||||
shared,
|
||||
};
|
||||
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_support::{
|
||||
defensive,
|
||||
pallet_prelude::*,
|
||||
traits::{Defensive, EnqueueMessage},
|
||||
BoundedSlice,
|
||||
};
|
||||
use pallet_message_queue::OnQueueChanged;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
supermajority_threshold, AvailabilityBitfield, BackedCandidate, CandidateCommitments,
|
||||
CandidateDescriptor, CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex,
|
||||
GroupIndex, Hash, HeadData, Id as ParaId, SigningContext, UncheckedSignedAvailabilityBitfields,
|
||||
ValidatorId, ValidatorIndex, ValidityAttestation,
|
||||
supermajority_threshold, well_known_keys, AvailabilityBitfield, BackedCandidate,
|
||||
CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateReceipt,
|
||||
CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash, HeadData, Id as ParaId, SigningContext,
|
||||
UncheckedSignedAvailabilityBitfields, UpwardMessage, ValidatorId, ValidatorIndex,
|
||||
ValidityAttestation,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::One, DispatchError};
|
||||
use sp_runtime::{traits::One, DispatchError, SaturatedConversion, Saturating};
|
||||
#[cfg(feature = "std")]
|
||||
use sp_std::fmt;
|
||||
use sp_std::{collections::btree_set::BTreeSet, prelude::*};
|
||||
|
||||
pub use pallet::*;
|
||||
@@ -42,6 +54,32 @@ pub use pallet::*;
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn receive_upward_messages(i: u32) -> Weight;
|
||||
}
|
||||
|
||||
pub struct TestWeightInfo;
|
||||
impl WeightInfo for TestWeightInfo {
|
||||
fn receive_upward_messages(_: u32) -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
}
|
||||
|
||||
impl WeightInfo for () {
|
||||
fn receive_upward_messages(_: u32) -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maximum value that `config.max_upward_message_size` can be set to.
|
||||
///
|
||||
/// This is used for benchmarking sanely bounding relevant storage items. It is expected from the `configuration`
|
||||
/// pallet to check these values before setting.
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 128 * 1024;
|
||||
|
||||
/// A bitfield signed by a validator indicating that it is keeping its piece of the erasure-coding
|
||||
/// for any backed candidates referred to by a `1` bit available.
|
||||
///
|
||||
@@ -179,6 +217,55 @@ pub fn minimum_backing_votes(n_validators: usize) -> usize {
|
||||
sp_std::cmp::min(n_validators, 2)
|
||||
}
|
||||
|
||||
/// Reads the footprint of queues for a specific origin type.
|
||||
pub trait QueueFootprinter {
|
||||
type Origin;
|
||||
|
||||
fn message_count(origin: Self::Origin) -> u64;
|
||||
}
|
||||
|
||||
impl QueueFootprinter for () {
|
||||
type Origin = UmpQueueId;
|
||||
|
||||
fn message_count(_: Self::Origin) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregate message origin for the `MessageQueue` pallet.
|
||||
///
|
||||
/// Can be extended to serve further use-cases besides just UMP. Is stored in storage, so any change
|
||||
/// to existing values will require a migration.
|
||||
#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub enum AggregateMessageOrigin {
|
||||
/// Inbound upward message.
|
||||
#[codec(index = 0)]
|
||||
Ump(UmpQueueId),
|
||||
}
|
||||
|
||||
/// Identifies a UMP queue inside the `MessageQueue` pallet.
|
||||
///
|
||||
/// It is written in verbose form since future variants like `Loopback` and `Bridged` are already
|
||||
/// forseeable.
|
||||
#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub enum UmpQueueId {
|
||||
/// The message originated from this parachain.
|
||||
#[codec(index = 0)]
|
||||
Para(ParaId),
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl From<u32> for AggregateMessageOrigin {
|
||||
fn from(n: u32) -> Self {
|
||||
// Some dummy for the benchmarks.
|
||||
Self::Ump(UmpQueueId::Para(n.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// The maximal length of a UMP message.
|
||||
pub type MaxUmpMessageLenOf<T> =
|
||||
<<T as Config>::MessageQueue as EnqueueMessage<AggregateMessageOrigin>>::MaxMessageLen;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
@@ -193,13 +280,22 @@ pub mod pallet {
|
||||
+ shared::Config
|
||||
+ paras::Config
|
||||
+ dmp::Config
|
||||
+ ump::Config
|
||||
+ hrmp::Config
|
||||
+ configuration::Config
|
||||
{
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
type DisputesHandler: disputes::DisputesHandler<Self::BlockNumber>;
|
||||
type RewardValidators: RewardValidators;
|
||||
|
||||
/// The system message queue.
|
||||
///
|
||||
/// The message queue provides general queueing and processing functionality. Currently it
|
||||
/// replaces the old `UMP` dispatch queue. Other use-cases can be implemented as well by
|
||||
/// adding new variants to `AggregateMessageOrigin`.
|
||||
type MessageQueue: EnqueueMessage<AggregateMessageOrigin>;
|
||||
|
||||
/// Weight info for the calls of this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
@@ -211,6 +307,8 @@ pub mod pallet {
|
||||
CandidateIncluded(CandidateReceipt<T::Hash>, HeadData, CoreIndex, GroupIndex),
|
||||
/// A candidate timed out. `[candidate, head_data]`
|
||||
CandidateTimedOut(CandidateReceipt<T::Hash>, HeadData, CoreIndex),
|
||||
/// Some upward messages have been received and will be processed.
|
||||
UpwardMessagesReceived { from: ParaId, count: u32 },
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
@@ -299,6 +397,71 @@ pub mod pallet {
|
||||
|
||||
const LOG_TARGET: &str = "runtime::inclusion";
|
||||
|
||||
/// The reason that a candidate's outputs were rejected for.
|
||||
#[derive(derive_more::From)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
enum AcceptanceCheckErr<BlockNumber> {
|
||||
HeadDataTooLarge,
|
||||
/// Code upgrades are not permitted at the current time.
|
||||
PrematureCodeUpgrade,
|
||||
/// The new runtime blob is too large.
|
||||
NewCodeTooLarge,
|
||||
/// The candidate violated this DMP acceptance criteria.
|
||||
ProcessedDownwardMessages(dmp::ProcessedDownwardMessagesAcceptanceErr),
|
||||
/// The candidate violated this UMP acceptance criteria.
|
||||
UpwardMessages(UmpAcceptanceCheckErr),
|
||||
/// The candidate violated this HRMP watermark acceptance criteria.
|
||||
HrmpWatermark(hrmp::HrmpWatermarkAcceptanceErr<BlockNumber>),
|
||||
/// The candidate violated this outbound HRMP acceptance criteria.
|
||||
OutboundHrmp(hrmp::OutboundHrmpAcceptanceErr),
|
||||
}
|
||||
|
||||
/// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance
|
||||
/// criteria rules.
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum UmpAcceptanceCheckErr {
|
||||
/// The maximal number of messages that can be submitted in one batch was exceeded.
|
||||
MoreMessagesThanPermitted { sent: u32, permitted: u32 },
|
||||
/// The maximal size of a single message was exceeded.
|
||||
MessageSize { idx: u32, msg_size: u32, max_size: u32 },
|
||||
/// The allowed number of messages in the queue was exceeded.
|
||||
CapacityExceeded { count: u64, limit: u64 },
|
||||
/// The allowed combined message size in the queue was exceeded.
|
||||
TotalSizeExceeded { total_size: u64, limit: u64 },
|
||||
/// A para-chain cannot send UMP messages while it is offboarding.
|
||||
IsOffboarding,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl fmt::Debug for UmpAcceptanceCheckErr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
UmpAcceptanceCheckErr::MoreMessagesThanPermitted { sent, permitted } => write!(
|
||||
fmt,
|
||||
"more upward messages than permitted by config ({} > {})",
|
||||
sent, permitted,
|
||||
),
|
||||
UmpAcceptanceCheckErr::MessageSize { idx, msg_size, max_size } => write!(
|
||||
fmt,
|
||||
"upward message idx {} larger than permitted by config ({} > {})",
|
||||
idx, msg_size, max_size,
|
||||
),
|
||||
UmpAcceptanceCheckErr::CapacityExceeded { count, limit } => write!(
|
||||
fmt,
|
||||
"the ump queue would have more items than permitted by config ({} > {})",
|
||||
count, limit,
|
||||
),
|
||||
UmpAcceptanceCheckErr::TotalSizeExceeded { total_size, limit } => write!(
|
||||
fmt,
|
||||
"the ump queue would have grown past the max size permitted by config ({} > {})",
|
||||
total_size, limit,
|
||||
),
|
||||
UmpAcceptanceCheckErr::IsOffboarding =>
|
||||
write!(fmt, "upward message rejected because the para is off-boarding",),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Block initialization logic, called by initializer.
|
||||
pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight {
|
||||
@@ -311,12 +474,25 @@ impl<T: Config> Pallet<T> {
|
||||
/// Handle an incoming session change.
|
||||
pub(crate) fn initializer_on_new_session(
|
||||
_notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>,
|
||||
outgoing_paras: &[ParaId],
|
||||
) {
|
||||
// unlike most drain methods, drained elements are not cleared on `Drop` of the iterator
|
||||
// and require consumption.
|
||||
for _ in <PendingAvailabilityCommitments<T>>::drain() {}
|
||||
for _ in <PendingAvailability<T>>::drain() {}
|
||||
for _ in <AvailabilityBitfields<T>>::drain() {}
|
||||
|
||||
Self::cleanup_outgoing_ump_dispatch_queues(outgoing_paras);
|
||||
}
|
||||
|
||||
pub(crate) fn cleanup_outgoing_ump_dispatch_queues(outgoing: &[ParaId]) {
|
||||
for outgoing_para in outgoing {
|
||||
Self::cleanup_outgoing_ump_dispatch_queue(*outgoing_para);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cleanup_outgoing_ump_dispatch_queue(para: ParaId) {
|
||||
T::MessageQueue::sweep_queue(AggregateMessageOrigin::Ump(UmpQueueId::Para(para)));
|
||||
}
|
||||
|
||||
/// Extract the freed cores based on cores that became available.
|
||||
@@ -698,20 +874,22 @@ impl<T: Config> Pallet<T> {
|
||||
let relay_parent_number = now;
|
||||
let check_ctx = CandidateCheckContext::<T>::new(now, relay_parent_number);
|
||||
|
||||
if let Err(err) = check_ctx.check_validation_outputs(
|
||||
para_id,
|
||||
&validation_outputs.head_data,
|
||||
&validation_outputs.new_validation_code,
|
||||
validation_outputs.processed_downward_messages,
|
||||
&validation_outputs.upward_messages,
|
||||
T::BlockNumber::from(validation_outputs.hrmp_watermark),
|
||||
&validation_outputs.horizontal_messages,
|
||||
) {
|
||||
if check_ctx
|
||||
.check_validation_outputs(
|
||||
para_id,
|
||||
&validation_outputs.head_data,
|
||||
&validation_outputs.new_validation_code,
|
||||
validation_outputs.processed_downward_messages,
|
||||
&validation_outputs.upward_messages,
|
||||
T::BlockNumber::from(validation_outputs.hrmp_watermark),
|
||||
&validation_outputs.horizontal_messages,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Validation outputs checking for parachain `{}` failed: {:?}",
|
||||
"Validation outputs checking for parachain `{}` failed",
|
||||
u32::from(para_id),
|
||||
err,
|
||||
);
|
||||
false
|
||||
} else {
|
||||
@@ -750,31 +928,31 @@ impl<T: Config> Pallet<T> {
|
||||
// initial weight is config read.
|
||||
let mut weight = T::DbWeight::get().reads_writes(1, 0);
|
||||
if let Some(new_code) = commitments.new_validation_code {
|
||||
weight += <paras::Pallet<T>>::schedule_code_upgrade(
|
||||
weight.saturating_add(<paras::Pallet<T>>::schedule_code_upgrade(
|
||||
receipt.descriptor.para_id,
|
||||
new_code,
|
||||
relay_parent_number,
|
||||
&config,
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
// enact the messaging facet of the candidate.
|
||||
weight += <dmp::Pallet<T>>::prune_dmq(
|
||||
weight.saturating_accrue(<dmp::Pallet<T>>::prune_dmq(
|
||||
receipt.descriptor.para_id,
|
||||
commitments.processed_downward_messages,
|
||||
);
|
||||
weight += <ump::Pallet<T>>::receive_upward_messages(
|
||||
));
|
||||
weight.saturating_accrue(Self::receive_upward_messages(
|
||||
receipt.descriptor.para_id,
|
||||
commitments.upward_messages,
|
||||
);
|
||||
weight += <hrmp::Pallet<T>>::prune_hrmp(
|
||||
commitments.upward_messages.as_slice(),
|
||||
));
|
||||
weight.saturating_accrue(<hrmp::Pallet<T>>::prune_hrmp(
|
||||
receipt.descriptor.para_id,
|
||||
T::BlockNumber::from(commitments.hrmp_watermark),
|
||||
);
|
||||
weight += <hrmp::Pallet<T>>::queue_outbound_hrmp(
|
||||
));
|
||||
weight.saturating_accrue(<hrmp::Pallet<T>>::queue_outbound_hrmp(
|
||||
receipt.descriptor.para_id,
|
||||
commitments.horizontal_messages,
|
||||
);
|
||||
));
|
||||
|
||||
Self::deposit_event(Event::<T>::CandidateIncluded(
|
||||
plain,
|
||||
@@ -783,12 +961,105 @@ impl<T: Config> Pallet<T> {
|
||||
backing_group,
|
||||
));
|
||||
|
||||
weight +
|
||||
<paras::Pallet<T>>::note_new_head(
|
||||
receipt.descriptor.para_id,
|
||||
commitments.head_data,
|
||||
relay_parent_number,
|
||||
)
|
||||
weight.saturating_add(<paras::Pallet<T>>::note_new_head(
|
||||
receipt.descriptor.para_id,
|
||||
commitments.head_data,
|
||||
relay_parent_number,
|
||||
))
|
||||
}
|
||||
|
||||
/// Check that all the upward messages sent by a candidate pass the acceptance criteria.
|
||||
pub(crate) fn check_upward_messages(
|
||||
config: &HostConfiguration<T::BlockNumber>,
|
||||
para: ParaId,
|
||||
upward_messages: &[UpwardMessage],
|
||||
) -> Result<(), UmpAcceptanceCheckErr> {
|
||||
// Cannot send UMP messages while off-boarding.
|
||||
if <paras::Pallet<T>>::is_offboarding(para) {
|
||||
ensure!(upward_messages.is_empty(), UmpAcceptanceCheckErr::IsOffboarding);
|
||||
}
|
||||
|
||||
let additional_msgs = upward_messages.len();
|
||||
if additional_msgs > config.max_upward_message_num_per_candidate as usize {
|
||||
return Err(UmpAcceptanceCheckErr::MoreMessagesThanPermitted {
|
||||
sent: additional_msgs as u32,
|
||||
permitted: config.max_upward_message_num_per_candidate,
|
||||
})
|
||||
}
|
||||
|
||||
let fp = T::MessageQueue::footprint(AggregateMessageOrigin::Ump(UmpQueueId::Para(para)));
|
||||
let (para_queue_count, mut para_queue_size) = (fp.count, fp.size);
|
||||
|
||||
if para_queue_count.saturating_add(additional_msgs as u64) >
|
||||
config.max_upward_queue_count as u64
|
||||
{
|
||||
return Err(UmpAcceptanceCheckErr::CapacityExceeded {
|
||||
count: para_queue_count.saturating_add(additional_msgs as u64),
|
||||
limit: config.max_upward_queue_count as u64,
|
||||
})
|
||||
}
|
||||
|
||||
for (idx, msg) in upward_messages.into_iter().enumerate() {
|
||||
let msg_size = msg.len();
|
||||
if msg_size > config.max_upward_message_size as usize {
|
||||
return Err(UmpAcceptanceCheckErr::MessageSize {
|
||||
idx: idx as u32,
|
||||
msg_size: msg_size as u32,
|
||||
max_size: config.max_upward_message_size,
|
||||
})
|
||||
}
|
||||
// make sure that the queue is not overfilled.
|
||||
// we do it here only once since returning false invalidates the whole relay-chain block.
|
||||
if para_queue_size.saturating_add(msg_size as u64) > config.max_upward_queue_size as u64
|
||||
{
|
||||
return Err(UmpAcceptanceCheckErr::TotalSizeExceeded {
|
||||
total_size: para_queue_size.saturating_add(msg_size as u64),
|
||||
limit: config.max_upward_queue_size as u64,
|
||||
})
|
||||
}
|
||||
para_queue_size.saturating_accrue(msg_size as u64);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Enqueues `upward_messages` from a `para`'s accepted candidate block.
|
||||
///
|
||||
/// This function is infallible since the candidate was already accepted and we therefore need
|
||||
/// to deal with the messages as given. Messages that are too long will be ignored since such
|
||||
/// candidates should have already been rejected in [`Self::check_upward_messages`].
|
||||
pub(crate) fn receive_upward_messages(para: ParaId, upward_messages: &[Vec<u8>]) -> Weight {
|
||||
let bounded = upward_messages
|
||||
.iter()
|
||||
.filter_map(|d| {
|
||||
BoundedSlice::try_from(&d[..])
|
||||
.map_err(|e| {
|
||||
defensive!("Accepted candidate contains too long msg, len=", d.len());
|
||||
e
|
||||
})
|
||||
.ok()
|
||||
})
|
||||
.collect();
|
||||
Self::receive_bounded_upward_messages(para, bounded)
|
||||
}
|
||||
|
||||
/// Enqueues storage-bounded `upward_messages` from a `para`'s accepted candidate block.
|
||||
pub(crate) fn receive_bounded_upward_messages(
|
||||
para: ParaId,
|
||||
messages: Vec<BoundedSlice<'_, u8, MaxUmpMessageLenOf<T>>>,
|
||||
) -> Weight {
|
||||
let count = messages.len() as u32;
|
||||
if count == 0 {
|
||||
return Weight::zero()
|
||||
}
|
||||
|
||||
T::MessageQueue::enqueue_messages(
|
||||
messages.into_iter(),
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)),
|
||||
);
|
||||
let weight = <T as Config>::WeightInfo::receive_upward_messages(count);
|
||||
Self::deposit_event(Event::UpwardMessagesReceived { from: para, count });
|
||||
weight
|
||||
}
|
||||
|
||||
/// Cleans up all paras pending availability that the predicate returns true for.
|
||||
@@ -902,17 +1173,6 @@ const fn availability_threshold(n_validators: usize) -> usize {
|
||||
supermajority_threshold(n_validators)
|
||||
}
|
||||
|
||||
#[derive(derive_more::From, Debug)]
|
||||
enum AcceptanceCheckErr<BlockNumber> {
|
||||
HeadDataTooLarge,
|
||||
PrematureCodeUpgrade,
|
||||
NewCodeTooLarge,
|
||||
ProcessedDownwardMessages(dmp::ProcessedDownwardMessagesAcceptanceErr),
|
||||
UpwardMessages(ump::AcceptanceCheckErr),
|
||||
HrmpWatermark(hrmp::HrmpWatermarkAcceptanceErr<BlockNumber>),
|
||||
OutboundHrmp(hrmp::OutboundHrmpAcceptanceErr),
|
||||
}
|
||||
|
||||
impl<BlockNumber> AcceptanceCheckErr<BlockNumber> {
|
||||
/// Returns the same error so that it can be threaded through a needle of `DispatchError` and
|
||||
/// ultimately returned from a `Dispatchable`.
|
||||
@@ -930,6 +1190,26 @@ impl<BlockNumber> AcceptanceCheckErr<BlockNumber> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> OnQueueChanged<AggregateMessageOrigin> for Pallet<T> {
|
||||
// Write back the remaining queue capacity into `relay_dispatch_queue_remaining_capacity`.
|
||||
fn on_queue_changed(origin: AggregateMessageOrigin, count: u64, size: u64) {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(p)) => p,
|
||||
};
|
||||
// TODO maybe migrate this to u64
|
||||
let (count, size) = (count.saturated_into(), size.saturated_into());
|
||||
// TODO paritytech/polkadot#6283: Remove all usages of `relay_dispatch_queue_size`
|
||||
#[allow(deprecated)]
|
||||
well_known_keys::relay_dispatch_queue_size_typed(para).set((count, size));
|
||||
|
||||
let config = <configuration::Pallet<T>>::config();
|
||||
let remaining_count = config.max_upward_queue_count.saturating_sub(count);
|
||||
let remaining_size = config.max_upward_queue_size.saturating_sub(size);
|
||||
well_known_keys::relay_dispatch_queue_remaining_capacity(para)
|
||||
.set((remaining_count, remaining_size));
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of data required for checking a candidate.
|
||||
pub(crate) struct CandidateCheckContext<T: Config> {
|
||||
config: configuration::HostConfiguration<T::BlockNumber>,
|
||||
@@ -965,12 +1245,13 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
let relay_parent_number = now - One::one();
|
||||
|
||||
{
|
||||
// this should never fail because the para is registered
|
||||
let persisted_validation_data = match crate::util::make_persisted_validation_data::<T>(
|
||||
para_id,
|
||||
relay_parent_number,
|
||||
parent_storage_root,
|
||||
) {
|
||||
)
|
||||
.defensive_proof("the para is registered")
|
||||
{
|
||||
Some(l) => l,
|
||||
None => return Ok(Err(FailedToCreatePVD)),
|
||||
};
|
||||
@@ -1018,10 +1299,9 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
) {
|
||||
log::debug!(
|
||||
target: LOG_TARGET,
|
||||
"Validation outputs checking during inclusion of a candidate {} for parachain `{}` failed: {:?}",
|
||||
"Validation outputs checking during inclusion of a candidate {} for parachain `{}` failed",
|
||||
candidate_idx,
|
||||
u32::from(para_id),
|
||||
err,
|
||||
);
|
||||
Err(err.strip_into_dispatch_err::<T>())?;
|
||||
};
|
||||
@@ -1059,10 +1339,18 @@ impl<T: Config> CandidateCheckContext<T> {
|
||||
|
||||
// check if the candidate passes the messaging acceptance criteria
|
||||
<dmp::Pallet<T>>::check_processed_downward_messages(para_id, processed_downward_messages)?;
|
||||
<ump::Pallet<T>>::check_upward_messages(&self.config, para_id, upward_messages)?;
|
||||
Pallet::<T>::check_upward_messages(&self.config, para_id, upward_messages)?;
|
||||
<hrmp::Pallet<T>>::check_hrmp_watermark(para_id, self.relay_parent_number, hrmp_watermark)?;
|
||||
<hrmp::Pallet<T>>::check_outbound_hrmp(&self.config, para_id, horizontal_messages)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> QueueFootprinter for Pallet<T> {
|
||||
type Origin = UmpQueueId;
|
||||
|
||||
fn message_count(origin: Self::Origin) -> u64 {
|
||||
T::MessageQueue::footprint(AggregateMessageOrigin::Ump(origin)).count
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use crate::{
|
||||
use assert_matches::assert_matches;
|
||||
use frame_support::assert_noop;
|
||||
use keyring::Sr25519Keyring;
|
||||
use parity_scale_codec::DecodeAll;
|
||||
use primitives::{
|
||||
BlockNumber, CandidateCommitments, CandidateDescriptor, CollatorId,
|
||||
CompactStatement as Statement, Hash, SignedAvailabilityBitfield, SignedStatement,
|
||||
@@ -159,6 +160,17 @@ pub(crate) fn back_candidate(
|
||||
backed
|
||||
}
|
||||
|
||||
pub(crate) fn run_to_block_default_notifications(to: BlockNumber, new_session: Vec<BlockNumber>) {
|
||||
run_to_block(to, |b| {
|
||||
new_session.contains(&b).then_some(SessionChangeNotification {
|
||||
prev_config: Configuration::config(),
|
||||
new_config: Configuration::config(),
|
||||
session_index: ParasShared::session_index() + 1,
|
||||
..Default::default()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn run_to_block(
|
||||
to: BlockNumber,
|
||||
new_session: impl Fn(BlockNumber) -> Option<SessionChangeNotification<BlockNumber>>,
|
||||
@@ -177,8 +189,8 @@ pub(crate) fn run_to_block(
|
||||
¬ification.new_config,
|
||||
notification.validators.clone(),
|
||||
);
|
||||
Paras::initializer_on_new_session(¬ification);
|
||||
ParaInclusion::initializer_on_new_session(¬ification);
|
||||
let outgoing = Paras::initializer_on_new_session(¬ification);
|
||||
ParaInclusion::initializer_on_new_session(¬ification, &outgoing);
|
||||
}
|
||||
|
||||
System::on_finalize(b);
|
||||
@@ -1972,3 +1984,12 @@ fn session_change_wipes() {
|
||||
assert!(<PendingAvailabilityCommitments<Test>>::iter().collect::<Vec<_>>().is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
/// Assert that the encoding of a known `AggregateMessageOrigin` did not change.
|
||||
#[test]
|
||||
fn aggregate_origin_decode_regression_check() {
|
||||
let ump = AggregateMessageOrigin::Ump(UmpQueueId::Para(u32::MAX.into()));
|
||||
let raw = (0u8, 0u8, u32::MAX).encode();
|
||||
let decoded = AggregateMessageOrigin::decode_all(&mut &raw[..]);
|
||||
assert_eq!(decoded, Ok(ump), "Migration needed for AggregateMessageOrigin");
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
use crate::{
|
||||
configuration::{self, HostConfiguration},
|
||||
disputes::{self, DisputesHandler as _, SlashingHandler as _},
|
||||
dmp, hrmp, inclusion, paras, scheduler, session_info, shared, ump,
|
||||
dmp, hrmp, inclusion, paras, scheduler, session_info, shared,
|
||||
};
|
||||
use frame_support::{
|
||||
traits::{OneSessionHandler, Randomness},
|
||||
@@ -113,7 +113,6 @@ pub mod pallet {
|
||||
+ session_info::Config
|
||||
+ disputes::Config
|
||||
+ dmp::Config
|
||||
+ ump::Config
|
||||
+ hrmp::Config
|
||||
{
|
||||
/// A randomness beacon.
|
||||
@@ -168,7 +167,6 @@ pub mod pallet {
|
||||
T::DisputesHandler::initializer_initialize(now) +
|
||||
T::SlashingHandler::initializer_initialize(now) +
|
||||
dmp::Pallet::<T>::initializer_initialize(now) +
|
||||
ump::Pallet::<T>::initializer_initialize(now) +
|
||||
hrmp::Pallet::<T>::initializer_initialize(now);
|
||||
|
||||
HasInitialized::<T>::set(Some(()));
|
||||
@@ -179,7 +177,6 @@ pub mod pallet {
|
||||
fn on_finalize(now: T::BlockNumber) {
|
||||
// reverse initialization order.
|
||||
hrmp::Pallet::<T>::initializer_finalize();
|
||||
ump::Pallet::<T>::initializer_finalize();
|
||||
dmp::Pallet::<T>::initializer_finalize();
|
||||
T::SlashingHandler::initializer_finalize();
|
||||
T::DisputesHandler::initializer_finalize();
|
||||
@@ -263,12 +260,11 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
let outgoing_paras = paras::Pallet::<T>::initializer_on_new_session(¬ification);
|
||||
scheduler::Pallet::<T>::initializer_on_new_session(¬ification);
|
||||
inclusion::Pallet::<T>::initializer_on_new_session(¬ification);
|
||||
inclusion::Pallet::<T>::initializer_on_new_session(¬ification, &outgoing_paras);
|
||||
session_info::Pallet::<T>::initializer_on_new_session(¬ification);
|
||||
T::DisputesHandler::initializer_on_new_session(¬ification);
|
||||
T::SlashingHandler::initializer_on_new_session(session_index);
|
||||
dmp::Pallet::<T>::initializer_on_new_session(¬ification, &outgoing_paras);
|
||||
ump::Pallet::<T>::initializer_on_new_session(¬ification, &outgoing_paras);
|
||||
hrmp::Pallet::<T>::initializer_on_new_session(¬ification, &outgoing_paras);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ pub mod reward_points;
|
||||
pub mod scheduler;
|
||||
pub mod session_info;
|
||||
pub mod shared;
|
||||
pub mod ump;
|
||||
|
||||
pub mod runtime_api_impl;
|
||||
|
||||
@@ -47,6 +46,8 @@ mod util;
|
||||
mod builder;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
mod ump_tests;
|
||||
|
||||
pub use origin::{ensure_parachain, Origin};
|
||||
pub use paras::ParaLifecycle;
|
||||
|
||||
@@ -17,27 +17,31 @@
|
||||
//! Mocks for all the traits.
|
||||
|
||||
use crate::{
|
||||
configuration, disputes, dmp, hrmp, inclusion, initializer, origin, paras, paras_inherent,
|
||||
scheduler, session_info, shared,
|
||||
ump::{self, MessageId, UmpSink},
|
||||
ParaId,
|
||||
configuration, disputes, dmp, hrmp,
|
||||
inclusion::{self, AggregateMessageOrigin, UmpQueueId},
|
||||
initializer, origin, paras,
|
||||
paras::ParaKind,
|
||||
paras_inherent, scheduler, session_info, shared, ParaId,
|
||||
};
|
||||
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
traits::{ConstU32, GenesisBuild, ValidatorSet, ValidatorSetWithIdentification},
|
||||
weights::Weight,
|
||||
assert_ok, parameter_types,
|
||||
traits::{
|
||||
Currency, GenesisBuild, ProcessMessage, ProcessMessageError, ValidatorSet,
|
||||
ValidatorSetWithIdentification,
|
||||
},
|
||||
weights::{Weight, WeightMeter},
|
||||
};
|
||||
use frame_support_test::TestRandomness;
|
||||
use parity_scale_codec::Decode;
|
||||
use primitives::{
|
||||
AuthorityDiscoveryId, Balance, BlockNumber, CandidateHash, Header, Moment, SessionIndex,
|
||||
UpwardMessage, ValidatorIndex,
|
||||
UpwardMessage, ValidationCode, ValidatorIndex,
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_core::{ConstU32, H256};
|
||||
use sp_io::TestExternalities;
|
||||
use sp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup},
|
||||
transaction_validity::TransactionPriority,
|
||||
Permill,
|
||||
};
|
||||
@@ -54,6 +58,7 @@ frame_support::construct_runtime!(
|
||||
{
|
||||
System: frame_system,
|
||||
Balances: pallet_balances,
|
||||
MessageQueue: pallet_message_queue,
|
||||
Paras: paras,
|
||||
Configuration: configuration,
|
||||
ParasShared: shared,
|
||||
@@ -62,7 +67,6 @@ frame_support::construct_runtime!(
|
||||
Scheduler: scheduler,
|
||||
Initializer: initializer,
|
||||
Dmp: dmp,
|
||||
Ump: ump,
|
||||
Hrmp: hrmp,
|
||||
ParachainsOrigin: origin,
|
||||
SessionInfo: session_info,
|
||||
@@ -149,15 +153,10 @@ impl pallet_babe::Config for Test {
|
||||
|
||||
// session module is the trigger
|
||||
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
||||
|
||||
type DisabledValidators = ();
|
||||
|
||||
type WeightInfo = ();
|
||||
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
|
||||
type KeyOwnerProof = sp_core::Void;
|
||||
|
||||
type EquivocationReportSystem = ();
|
||||
}
|
||||
|
||||
@@ -212,6 +211,7 @@ impl crate::paras::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = crate::paras::TestWeightInfo;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = TestNextSessionRotation;
|
||||
}
|
||||
|
||||
@@ -221,14 +221,6 @@ parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
}
|
||||
|
||||
impl crate::ump::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink = TestUmpSink;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
|
||||
type WeightInfo = crate::ump::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl crate::hrmp::Config for Test {
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
@@ -292,10 +284,62 @@ impl crate::disputes::SlashingHandler<BlockNumber> for Test {
|
||||
|
||||
impl crate::scheduler::Config for Test {}
|
||||
|
||||
pub struct TestMessageQueueWeight;
|
||||
impl pallet_message_queue::WeightInfo for TestMessageQueueWeight {
|
||||
fn ready_ring_knit() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn ready_ring_unknit() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn service_queue_base() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn service_page_base_completion() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn service_page_base_no_completion() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn service_page_item() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn bump_service_head() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn reap_page() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn execute_overweight_page_removed() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
fn execute_overweight_page_updated() -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
}
|
||||
parameter_types! {
|
||||
pub const MessageQueueServiceWeight: Weight = Weight::from_all(500);
|
||||
}
|
||||
|
||||
pub type MessageQueueSize = u32;
|
||||
|
||||
impl pallet_message_queue::Config for Test {
|
||||
type Size = MessageQueueSize;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = TestMessageQueueWeight;
|
||||
type MessageProcessor = TestProcessMessage;
|
||||
type QueueChangeHandler = ParaInclusion;
|
||||
type HeapSize = ConstU32<65536>;
|
||||
type MaxStale = ConstU32<8>;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
}
|
||||
|
||||
impl crate::inclusion::Config for Test {
|
||||
type WeightInfo = ();
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = Disputes;
|
||||
type RewardValidators = TestRewardValidators;
|
||||
type MessageQueue = MessageQueue;
|
||||
}
|
||||
|
||||
impl crate::paras_inherent::Config for Test {
|
||||
@@ -372,39 +416,39 @@ pub fn availability_rewards() -> HashMap<ValidatorIndex, usize> {
|
||||
AVAILABILITY_REWARDS.with(|r| r.borrow().clone())
|
||||
}
|
||||
|
||||
std::thread_local! {
|
||||
static PROCESSED: RefCell<Vec<(ParaId, UpwardMessage)>> = RefCell::new(vec![]);
|
||||
}
|
||||
|
||||
/// Return which messages have been processed by `process_upward_message` and clear the buffer.
|
||||
pub fn take_processed() -> Vec<(ParaId, UpwardMessage)> {
|
||||
PROCESSED.with(|opt_hook| std::mem::take(&mut *opt_hook.borrow_mut()))
|
||||
parameter_types! {
|
||||
pub static Processed: Vec<(ParaId, UpwardMessage)> = vec![];
|
||||
}
|
||||
|
||||
/// An implementation of a UMP sink that just records which messages were processed.
|
||||
///
|
||||
/// A message's weight is defined by the first 4 bytes of its data, which we decode into a
|
||||
/// `u32`.
|
||||
pub struct TestUmpSink;
|
||||
impl UmpSink for TestUmpSink {
|
||||
fn process_upward_message(
|
||||
actual_origin: ParaId,
|
||||
actual_msg: &[u8],
|
||||
max_weight: Weight,
|
||||
) -> Result<Weight, (MessageId, Weight)> {
|
||||
let weight = match u32::decode(&mut &actual_msg[..]) {
|
||||
Ok(w) => Weight::from_parts(w as u64, w as u64),
|
||||
Err(_) => return Ok(Weight::zero()), // same as the real `UmpSink`
|
||||
pub struct TestProcessMessage;
|
||||
impl ProcessMessage for TestProcessMessage {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: AggregateMessageOrigin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(p)) => p,
|
||||
};
|
||||
if weight.any_gt(max_weight) {
|
||||
let id = sp_io::hashing::blake2_256(actual_msg);
|
||||
return Err((id, weight))
|
||||
|
||||
let required = match u32::decode(&mut &message[..]) {
|
||||
Ok(w) => Weight::from_parts(w as u64, w as u64),
|
||||
Err(_) => return Err(ProcessMessageError::Corrupt), // same as the real `ProcessMessage`
|
||||
};
|
||||
if !meter.check_accrue(required) {
|
||||
return Err(ProcessMessageError::Overweight(required))
|
||||
}
|
||||
|
||||
PROCESSED.with(|opt_hook| {
|
||||
opt_hook.borrow_mut().push((actual_origin, actual_msg.to_owned()));
|
||||
});
|
||||
Ok(weight)
|
||||
let mut processed = Processed::get();
|
||||
processed.push((para, message.to_vec()));
|
||||
Processed::set(processed);
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,3 +507,50 @@ pub fn assert_last_event(generic_event: RuntimeEvent) {
|
||||
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
|
||||
assert_eq!(event, &system_event);
|
||||
}
|
||||
|
||||
pub fn assert_last_events<E>(generic_events: E)
|
||||
where
|
||||
E: DoubleEndedIterator<Item = RuntimeEvent> + ExactSizeIterator,
|
||||
{
|
||||
for (i, (got, want)) in frame_system::Pallet::<Test>::events()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.map(|e| e.event)
|
||||
.zip(generic_events.rev().map(<Test as frame_system::Config>::RuntimeEvent::from))
|
||||
.rev()
|
||||
.enumerate()
|
||||
{
|
||||
assert_eq!((i, got), (i, want));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn register_parachain_with_balance(id: ParaId, balance: Balance) {
|
||||
let validation_code: ValidationCode = vec![1].into();
|
||||
assert_ok!(Paras::schedule_para_initialize(
|
||||
id,
|
||||
crate::paras::ParaGenesisArgs {
|
||||
para_kind: ParaKind::Parachain,
|
||||
genesis_head: vec![1].into(),
|
||||
validation_code: validation_code.clone(),
|
||||
},
|
||||
));
|
||||
|
||||
assert_ok!(Paras::add_trusted_validation_code(RuntimeOrigin::root(), validation_code));
|
||||
<Test as crate::hrmp::Config>::Currency::make_free_balance_be(
|
||||
&id.into_account_truncating(),
|
||||
balance,
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn register_parachain(id: ParaId) {
|
||||
register_parachain_with_balance(id, 1000);
|
||||
}
|
||||
|
||||
pub(crate) fn deregister_parachain(id: ParaId) {
|
||||
assert_ok!(Paras::schedule_para_cleanup(id));
|
||||
}
|
||||
|
||||
/// Calls `schedule_para_cleanup` in a new storage transactions, since it assumes rollback on error.
|
||||
pub(crate) fn try_deregister_parachain(id: ParaId) -> crate::DispatchResult {
|
||||
frame_support::storage::transactional::with_storage_layer(|| Paras::schedule_para_cleanup(id))
|
||||
}
|
||||
|
||||
@@ -107,7 +107,12 @@
|
||||
//! ```
|
||||
//!
|
||||
|
||||
use crate::{configuration, initializer::SessionChangeNotification, shared};
|
||||
use crate::{
|
||||
configuration,
|
||||
inclusion::{QueueFootprinter, UmpQueueId},
|
||||
initializer::SessionChangeNotification,
|
||||
shared,
|
||||
};
|
||||
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
||||
use frame_support::{pallet_prelude::*, traits::EstimateNextSessionRotation};
|
||||
use frame_system::pallet_prelude::*;
|
||||
@@ -551,6 +556,12 @@ pub mod pallet {
|
||||
|
||||
type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;
|
||||
|
||||
/// Retrieve how many UMP messages are enqueued for this para-chain.
|
||||
///
|
||||
/// This is used to judge whether or not a para-chain can offboard. Per default this should
|
||||
/// be set to the `ParaInclusion` pallet.
|
||||
type QueueFootprinter: QueueFootprinter<Origin = UmpQueueId>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
@@ -1653,12 +1664,13 @@ impl<T: Config> Pallet<T> {
|
||||
///
|
||||
/// - para is not a stable parachain or parathread (i.e. [`ParaLifecycle::is_stable`] is `false`)
|
||||
/// - para has a pending upgrade.
|
||||
/// - para has unprocessed messages in its UMP queue.
|
||||
///
|
||||
/// No-op if para is not registered at all.
|
||||
pub(crate) fn schedule_para_cleanup(id: ParaId) -> DispatchResult {
|
||||
// Disallow offboarding in case there is a PVF pre-checking in progress.
|
||||
//
|
||||
// This is not a fundamential limitation but rather simplification: it allows us to get
|
||||
// This is not a fundamental limitation but rather simplification: it allows us to get
|
||||
// away without introducing additional logic for pruning and, more importantly, enacting
|
||||
// ongoing PVF pre-checking votes. It also removes some nasty edge cases.
|
||||
//
|
||||
@@ -1683,7 +1695,7 @@ impl<T: Config> Pallet<T> {
|
||||
Some(ParaLifecycle::Parachain) => {
|
||||
ParaLifecycles::<T>::insert(&id, ParaLifecycle::OffboardingParachain);
|
||||
},
|
||||
_ => return Err(Error::<T>::CannotOffboard)?,
|
||||
_ => return Err(Error::<T>::CannotOffboard.into()),
|
||||
}
|
||||
|
||||
let scheduled_session = Self::scheduled_session();
|
||||
@@ -1693,6 +1705,10 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
});
|
||||
|
||||
if <T as Config>::QueueFootprinter::message_count(UmpQueueId::Para(id)) != 0 {
|
||||
return Err(Error::<T>::CannotOffboard.into())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1986,6 +2002,13 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the given ID refers to a para that is offboarding.
|
||||
///
|
||||
/// An invalid or non-offboarding para ID will return `false`.
|
||||
pub fn is_offboarding(id: ParaId) -> bool {
|
||||
ParaLifecycles::<T>::get(&id).map_or(false, |state| state.is_offboarding())
|
||||
}
|
||||
|
||||
/// Whether a para ID corresponds to any live parachain.
|
||||
///
|
||||
/// Includes parachains which will downgrade to a parathread in the future.
|
||||
|
||||
@@ -29,7 +29,7 @@ use crate::{
|
||||
initializer,
|
||||
metrics::METRICS,
|
||||
scheduler::{self, CoreAssignment, FreedReason},
|
||||
shared, ump, ParaId,
|
||||
shared, ParaId,
|
||||
};
|
||||
use bitvec::prelude::BitVec;
|
||||
use frame_support::{
|
||||
@@ -531,10 +531,6 @@ impl<T: Config> Pallet<T> {
|
||||
// Note which of the scheduled cores were actually occupied by a backed candidate.
|
||||
<scheduler::Pallet<T>>::occupied(&occupied);
|
||||
|
||||
// Give some time slice to dispatch pending upward messages.
|
||||
// this is max config.ump_service_total_weight
|
||||
let _ump_weight = <ump::Pallet<T>>::process_pending_upward_messages();
|
||||
|
||||
METRICS.on_after_filter(total_consumed_weight.ref_time());
|
||||
|
||||
Ok(Some(total_consumed_weight).into())
|
||||
|
||||
@@ -331,14 +331,18 @@ where
|
||||
<frame_system::Pallet<T>>::read_events_no_consensus()
|
||||
.into_iter()
|
||||
.filter_map(|record| extract_event(record.event))
|
||||
.map(|event| match event {
|
||||
RawEvent::<T>::CandidateBacked(c, h, core, group) =>
|
||||
CandidateEvent::CandidateBacked(c, h, core, group),
|
||||
RawEvent::<T>::CandidateIncluded(c, h, core, group) =>
|
||||
CandidateEvent::CandidateIncluded(c, h, core, group),
|
||||
RawEvent::<T>::CandidateTimedOut(c, h, core) =>
|
||||
CandidateEvent::CandidateTimedOut(c, h, core),
|
||||
RawEvent::<T>::__Ignore(_, _) => unreachable!("__Ignore cannot be used"),
|
||||
.filter_map(|event| {
|
||||
Some(match event {
|
||||
RawEvent::<T>::CandidateBacked(c, h, core, group) =>
|
||||
CandidateEvent::CandidateBacked(c, h, core, group),
|
||||
RawEvent::<T>::CandidateIncluded(c, h, core, group) =>
|
||||
CandidateEvent::CandidateIncluded(c, h, core, group),
|
||||
RawEvent::<T>::CandidateTimedOut(c, h, core) =>
|
||||
CandidateEvent::CandidateTimedOut(c, h, core),
|
||||
// Not needed for candidate events.
|
||||
RawEvent::<T>::UpwardMessagesReceived { .. } => return None,
|
||||
RawEvent::<T>::__Ignore(_, _) => unreachable!("__Ignore cannot be used"),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -1,765 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
configuration::{self, HostConfiguration},
|
||||
initializer,
|
||||
};
|
||||
use frame_support::{pallet_prelude::*, traits::EnsureOrigin};
|
||||
use frame_system::pallet_prelude::*;
|
||||
use polkadot_parachain::primitives::UpwardMessages;
|
||||
use primitives::{Id as ParaId, UpwardMessage};
|
||||
use sp_std::{collections::btree_map::BTreeMap, fmt, marker::PhantomData, mem, prelude::*};
|
||||
use xcm::latest::Outcome;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
/// Maximum value that `config.max_upward_message_size` can be set to
|
||||
///
|
||||
/// This is used for benchmarking sanely bounding relevant storage items. It is expected from the `configurations`
|
||||
/// pallet to check these values before setting.
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 50 * 1024;
|
||||
/// Maximum amount of overweight messages that can exist in the queue at any given time.
|
||||
pub const MAX_OVERWEIGHT_MESSAGES: u32 = 1000;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
pub mod migration;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests;
|
||||
|
||||
/// All upward messages coming from parachains will be funneled into an implementation of this trait.
|
||||
///
|
||||
/// The message is opaque from the perspective of UMP. The message size can range from 0 to
|
||||
/// `config.max_upward_message_size`.
|
||||
///
|
||||
/// It's up to the implementation of this trait to decide what to do with a message as long as it
|
||||
/// returns the amount of weight consumed in the process of handling. Ignoring a message is a valid
|
||||
/// strategy.
|
||||
///
|
||||
/// There are no guarantees on how much time it takes for the message sent by a candidate to end up
|
||||
/// in the sink after the candidate was enacted. That typically depends on the UMP traffic, the sizes
|
||||
/// of upward messages and the configuration of UMP.
|
||||
///
|
||||
/// It is possible that by the time the message is sank the origin parachain was offboarded. It is
|
||||
/// up to the implementer to check that if it cares.
|
||||
pub trait UmpSink {
|
||||
/// Process an incoming upward message and return the amount of weight it consumed, or `None` if
|
||||
/// it did not begin processing a message since it would otherwise exceed `max_weight`.
|
||||
///
|
||||
/// See the trait docs for more details.
|
||||
fn process_upward_message(
|
||||
origin: ParaId,
|
||||
msg: &[u8],
|
||||
max_weight: Weight,
|
||||
) -> Result<Weight, (MessageId, Weight)>;
|
||||
}
|
||||
|
||||
/// An implementation of a sink that just swallows the message without consuming any weight. Returns
|
||||
/// `Some(0)` indicating that no messages existed for it to process.
|
||||
impl UmpSink for () {
|
||||
fn process_upward_message(
|
||||
_: ParaId,
|
||||
_: &[u8],
|
||||
_: Weight,
|
||||
) -> Result<Weight, (MessageId, Weight)> {
|
||||
Ok(Weight::zero())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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];
|
||||
|
||||
/// Index used to identify overweight messages.
|
||||
pub type OverweightIndex = u64;
|
||||
|
||||
/// A specific implementation of a `UmpSink` where messages are in the XCM format
|
||||
/// and will be forwarded to the XCM Executor.
|
||||
pub struct XcmSink<XcmExecutor, Config>(PhantomData<(XcmExecutor, Config)>);
|
||||
|
||||
/// Returns a [`MessageId`] for the given upward message payload.
|
||||
fn upward_message_id(data: &[u8]) -> MessageId {
|
||||
sp_io::hashing::blake2_256(data)
|
||||
}
|
||||
|
||||
impl<XcmExecutor: xcm::latest::ExecuteXcm<C::RuntimeCall>, C: Config> UmpSink
|
||||
for XcmSink<XcmExecutor, C>
|
||||
{
|
||||
fn process_upward_message(
|
||||
origin: ParaId,
|
||||
mut data: &[u8],
|
||||
max_weight: Weight,
|
||||
) -> Result<Weight, (MessageId, Weight)> {
|
||||
use parity_scale_codec::DecodeLimit;
|
||||
use xcm::{
|
||||
latest::{Error as XcmError, Junction, Xcm},
|
||||
VersionedXcm,
|
||||
};
|
||||
|
||||
let id = upward_message_id(data);
|
||||
let maybe_msg_and_weight = VersionedXcm::<C::RuntimeCall>::decode_all_with_depth_limit(
|
||||
xcm::MAX_XCM_DECODE_DEPTH,
|
||||
&mut data,
|
||||
)
|
||||
.map(|xcm| {
|
||||
(
|
||||
Xcm::<C::RuntimeCall>::try_from(xcm),
|
||||
// NOTE: We are overestimating slightly here.
|
||||
// The benchmark is timing this whole function with different message sizes and a NOOP extrinsic to
|
||||
// measure the size-dependent weight. But as we use the weight funtion **in** the benchmarked funtion we
|
||||
// are taking call and control-flow overhead into account twice.
|
||||
<C as Config>::WeightInfo::process_upward_message(data.len() as u32),
|
||||
)
|
||||
});
|
||||
match maybe_msg_and_weight {
|
||||
Err(_) => {
|
||||
Pallet::<C>::deposit_event(Event::InvalidFormat(id));
|
||||
Ok(Weight::zero())
|
||||
},
|
||||
Ok((Err(()), weight_used)) => {
|
||||
Pallet::<C>::deposit_event(Event::UnsupportedVersion(id));
|
||||
Ok(weight_used)
|
||||
},
|
||||
Ok((Ok(xcm_message), weight_used)) => {
|
||||
let xcm_junction = Junction::Parachain(origin.into());
|
||||
let outcome = XcmExecutor::execute_xcm(xcm_junction, xcm_message, id, max_weight);
|
||||
match outcome {
|
||||
Outcome::Error(XcmError::WeightLimitReached(required)) => Err((id, required)),
|
||||
outcome => {
|
||||
let outcome_weight = outcome.weight_used();
|
||||
Pallet::<C>::deposit_event(Event::ExecutedUpward(id, outcome));
|
||||
Ok(weight_used.saturating_add(outcome_weight))
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance
|
||||
/// criteria rules.
|
||||
pub enum AcceptanceCheckErr {
|
||||
MoreMessagesThanPermitted { sent: u32, permitted: u32 },
|
||||
MessageSize { idx: u32, msg_size: u32, max_size: u32 },
|
||||
CapacityExceeded { count: u32, limit: u32 },
|
||||
TotalSizeExceeded { total_size: u32, limit: u32 },
|
||||
}
|
||||
|
||||
impl fmt::Debug for AcceptanceCheckErr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
AcceptanceCheckErr::MoreMessagesThanPermitted { sent, permitted } => write!(
|
||||
fmt,
|
||||
"more upward messages than permitted by config ({} > {})",
|
||||
sent, permitted,
|
||||
),
|
||||
AcceptanceCheckErr::MessageSize { idx, msg_size, max_size } => write!(
|
||||
fmt,
|
||||
"upward message idx {} larger than permitted by config ({} > {})",
|
||||
idx, msg_size, max_size,
|
||||
),
|
||||
AcceptanceCheckErr::CapacityExceeded { count, limit } => write!(
|
||||
fmt,
|
||||
"the ump queue would have more items than permitted by config ({} > {})",
|
||||
count, limit,
|
||||
),
|
||||
AcceptanceCheckErr::TotalSizeExceeded { total_size, limit } => write!(
|
||||
fmt,
|
||||
"the ump queue would have grown past the max size permitted by config ({} > {})",
|
||||
total_size, limit,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Weight information of this pallet.
|
||||
pub trait WeightInfo {
|
||||
fn service_overweight() -> Weight;
|
||||
fn process_upward_message(s: u32) -> Weight;
|
||||
fn clean_ump_after_outgoing() -> Weight;
|
||||
}
|
||||
|
||||
/// fallback implementation
|
||||
pub struct TestWeightInfo;
|
||||
impl WeightInfo for TestWeightInfo {
|
||||
fn service_overweight() -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
|
||||
fn process_upward_message(_msg_size: u32) -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
|
||||
fn clean_ump_after_outgoing() -> Weight {
|
||||
Weight::MAX
|
||||
}
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::without_storage_info]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config + configuration::Config {
|
||||
/// The aggregate event.
|
||||
type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// A place where all received upward messages are funneled.
|
||||
type UmpSink: UmpSink;
|
||||
|
||||
/// The factor by which the weight limit it multiplied for the first UMP message to execute with.
|
||||
///
|
||||
/// An amount less than 100 keeps more available weight in the queue for messages after the first, and potentially
|
||||
/// stalls the queue in doing so. More than 100 will provide additional weight for the first message only.
|
||||
///
|
||||
/// Generally you'll want this to be a bit more - 150 or 200 would be good values.
|
||||
type FirstMessageFactorPercent: Get<u64>;
|
||||
|
||||
/// Origin which is allowed to execute overweight messages.
|
||||
type ExecuteOverweightOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event {
|
||||
/// Upward message is invalid XCM.
|
||||
/// \[ id \]
|
||||
InvalidFormat(MessageId),
|
||||
/// Upward message is unsupported version of XCM.
|
||||
/// \[ id \]
|
||||
UnsupportedVersion(MessageId),
|
||||
/// Upward message executed with the given outcome.
|
||||
/// \[ id, outcome \]
|
||||
ExecutedUpward(MessageId, Outcome),
|
||||
/// The weight limit for handling upward messages was reached.
|
||||
/// \[ id, remaining, required \]
|
||||
WeightExhausted(MessageId, Weight, Weight),
|
||||
/// Some upward messages have been received and will be processed.
|
||||
/// \[ para, count, size \]
|
||||
UpwardMessagesReceived(ParaId, u32, u32),
|
||||
/// The weight budget was exceeded for an individual upward message.
|
||||
///
|
||||
/// This message can be later dispatched manually using `service_overweight` dispatchable
|
||||
/// using the assigned `overweight_index`.
|
||||
///
|
||||
/// \[ para, id, overweight_index, required \]
|
||||
OverweightEnqueued(ParaId, MessageId, OverweightIndex, Weight),
|
||||
/// Upward message from the overweight queue was executed with the given actual weight
|
||||
/// used.
|
||||
///
|
||||
/// \[ overweight_index, used \]
|
||||
OverweightServiced(OverweightIndex, Weight),
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// The message index given is unknown.
|
||||
UnknownMessageIndex,
|
||||
/// The amount of weight given is possibly not enough for executing the message.
|
||||
WeightOverLimit,
|
||||
}
|
||||
|
||||
/// The messages waiting to be handled by the relay-chain originating from a certain parachain.
|
||||
///
|
||||
/// Note that some upward messages might have been already processed by the inclusion logic. E.g.
|
||||
/// channel management messages.
|
||||
///
|
||||
/// The messages are processed in FIFO order.
|
||||
#[pallet::storage]
|
||||
pub type RelayDispatchQueues<T: Config> =
|
||||
StorageMap<_, Twox64Concat, ParaId, Vec<UpwardMessage>, ValueQuery>;
|
||||
|
||||
/// Size of the dispatch queues. Caches sizes of the queues in `RelayDispatchQueue`.
|
||||
///
|
||||
/// First item in the tuple is the count of messages and second
|
||||
/// is the total length (in bytes) of the message payloads.
|
||||
///
|
||||
/// Note that this is an auxiliary mapping: it's possible to tell the byte size and the number of
|
||||
/// messages only looking at `RelayDispatchQueues`. This mapping is separate to avoid the cost of
|
||||
/// loading the whole message queue if only the total size and count are required.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - The set of keys should exactly match the set of keys of `RelayDispatchQueues`.
|
||||
// NOTE that this field is used by parachains via merkle storage proofs, therefore changing
|
||||
// the format will require migration of parachains.
|
||||
#[pallet::storage]
|
||||
pub type RelayDispatchQueueSize<T: Config> =
|
||||
StorageMap<_, Twox64Concat, ParaId, (u32, u32), ValueQuery>;
|
||||
|
||||
/// The ordered list of `ParaId`s that have a `RelayDispatchQueue` entry.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - The set of items from this vector should be exactly the set of the keys in
|
||||
/// `RelayDispatchQueues` and `RelayDispatchQueueSize`.
|
||||
#[pallet::storage]
|
||||
pub type NeedsDispatch<T: Config> = StorageValue<_, Vec<ParaId>, ValueQuery>;
|
||||
|
||||
/// This is the para that gets will get dispatched first during the next upward dispatchable queue
|
||||
/// execution round.
|
||||
///
|
||||
/// Invariant:
|
||||
/// - If `Some(para)`, then `para` must be present in `NeedsDispatch`.
|
||||
#[pallet::storage]
|
||||
pub type NextDispatchRoundStartWith<T: Config> = StorageValue<_, ParaId>;
|
||||
|
||||
/// The messages that exceeded max individual message weight budget.
|
||||
///
|
||||
/// These messages stay there until manually dispatched.
|
||||
#[pallet::storage]
|
||||
pub type Overweight<T: Config> =
|
||||
CountedStorageMap<_, Twox64Concat, OverweightIndex, (ParaId, Vec<u8>), OptionQuery>;
|
||||
|
||||
/// The number of overweight messages ever recorded in `Overweight` (and thus the lowest free
|
||||
/// index).
|
||||
#[pallet::storage]
|
||||
pub type OverweightCount<T: Config> = StorageValue<_, OverweightIndex, ValueQuery>;
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Service a single overweight upward message.
|
||||
///
|
||||
/// - `origin`: Must pass `ExecuteOverweightOrigin`.
|
||||
/// - `index`: The index of the overweight message to service.
|
||||
/// - `weight_limit`: The amount of weight that message execution may take.
|
||||
///
|
||||
/// Errors:
|
||||
/// - `UnknownMessageIndex`: Message of `index` is unknown.
|
||||
/// - `WeightOverLimit`: Message execution may use greater than `weight_limit`.
|
||||
///
|
||||
/// Events:
|
||||
/// - `OverweightServiced`: On success.
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(weight_limit.saturating_add(<T as Config>::WeightInfo::service_overweight()))]
|
||||
pub fn service_overweight(
|
||||
origin: OriginFor<T>,
|
||||
index: OverweightIndex,
|
||||
weight_limit: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
T::ExecuteOverweightOrigin::ensure_origin(origin)?;
|
||||
|
||||
let (sender, data) =
|
||||
Overweight::<T>::get(index).ok_or(Error::<T>::UnknownMessageIndex)?;
|
||||
let used = T::UmpSink::process_upward_message(sender, &data[..], weight_limit)
|
||||
.map_err(|_| Error::<T>::WeightOverLimit)?;
|
||||
Overweight::<T>::remove(index);
|
||||
Self::deposit_event(Event::OverweightServiced(index, used));
|
||||
Ok(Some(used.saturating_add(<T as Config>::WeightInfo::service_overweight())).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Routines related to the upward message passing.
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Block initialization logic, called by initializer.
|
||||
pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
|
||||
/// Block finalization logic, called by initializer.
|
||||
pub(crate) fn initializer_finalize() {}
|
||||
|
||||
/// Called by the initializer to note that a new session has started.
|
||||
pub(crate) fn initializer_on_new_session(
|
||||
_notification: &initializer::SessionChangeNotification<T::BlockNumber>,
|
||||
outgoing_paras: &[ParaId],
|
||||
) -> Weight {
|
||||
Self::perform_outgoing_para_cleanup(outgoing_paras)
|
||||
}
|
||||
|
||||
/// Iterate over all paras that were noted for offboarding and remove all the data
|
||||
/// associated with them.
|
||||
fn perform_outgoing_para_cleanup(outgoing: &[ParaId]) -> Weight {
|
||||
let mut weight: Weight = Weight::zero();
|
||||
for outgoing_para in outgoing {
|
||||
weight = weight.saturating_add(Self::clean_ump_after_outgoing(outgoing_para));
|
||||
}
|
||||
weight
|
||||
}
|
||||
|
||||
/// Remove all relevant storage items for an outgoing parachain.
|
||||
pub(crate) fn clean_ump_after_outgoing(outgoing_para: &ParaId) -> Weight {
|
||||
RelayDispatchQueueSize::<T>::remove(outgoing_para);
|
||||
RelayDispatchQueues::<T>::remove(outgoing_para);
|
||||
|
||||
// Remove the outgoing para from the `NeedsDispatch` list and from
|
||||
// `NextDispatchRoundStartWith`.
|
||||
//
|
||||
// That's needed for maintaining invariant that `NextDispatchRoundStartWith` points to an
|
||||
// existing item in `NeedsDispatch`.
|
||||
NeedsDispatch::<T>::mutate(|v| {
|
||||
if let Ok(i) = v.binary_search(outgoing_para) {
|
||||
v.remove(i);
|
||||
}
|
||||
});
|
||||
NextDispatchRoundStartWith::<T>::mutate(|v| *v = v.filter(|p| p == outgoing_para));
|
||||
|
||||
<T as Config>::WeightInfo::clean_ump_after_outgoing()
|
||||
}
|
||||
|
||||
/// Check that all the upward messages sent by a candidate pass the acceptance criteria. Returns
|
||||
/// false, if any of the messages doesn't pass.
|
||||
pub(crate) fn check_upward_messages(
|
||||
config: &HostConfiguration<T::BlockNumber>,
|
||||
para: ParaId,
|
||||
upward_messages: &[UpwardMessage],
|
||||
) -> Result<(), AcceptanceCheckErr> {
|
||||
if upward_messages.len() as u32 > config.max_upward_message_num_per_candidate {
|
||||
return Err(AcceptanceCheckErr::MoreMessagesThanPermitted {
|
||||
sent: upward_messages.len() as u32,
|
||||
permitted: config.max_upward_message_num_per_candidate,
|
||||
})
|
||||
}
|
||||
|
||||
let (mut para_queue_count, mut para_queue_size) = RelayDispatchQueueSize::<T>::get(¶);
|
||||
|
||||
for (idx, msg) in upward_messages.into_iter().enumerate() {
|
||||
let msg_size = msg.len() as u32;
|
||||
if msg_size > config.max_upward_message_size {
|
||||
return Err(AcceptanceCheckErr::MessageSize {
|
||||
idx: idx as u32,
|
||||
msg_size,
|
||||
max_size: config.max_upward_message_size,
|
||||
})
|
||||
}
|
||||
para_queue_count += 1;
|
||||
para_queue_size += msg_size;
|
||||
}
|
||||
|
||||
// make sure that the queue is not overfilled.
|
||||
// we do it here only once since returning false invalidates the whole relay-chain block.
|
||||
if para_queue_count > config.max_upward_queue_count {
|
||||
return Err(AcceptanceCheckErr::CapacityExceeded {
|
||||
count: para_queue_count,
|
||||
limit: config.max_upward_queue_count,
|
||||
})
|
||||
}
|
||||
if para_queue_size > config.max_upward_queue_size {
|
||||
return Err(AcceptanceCheckErr::TotalSizeExceeded {
|
||||
total_size: para_queue_size,
|
||||
limit: config.max_upward_queue_size,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Enqueues `upward_messages` from a `para`'s accepted candidate block.
|
||||
pub(crate) fn receive_upward_messages(para: ParaId, upward_messages: UpwardMessages) -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
if !upward_messages.is_empty() {
|
||||
let (extra_count, extra_size) = upward_messages
|
||||
.iter()
|
||||
.fold((0, 0), |(cnt, size), d| (cnt + 1, size + d.len() as u32));
|
||||
|
||||
RelayDispatchQueues::<T>::mutate(¶, |v| v.extend(upward_messages.into_iter()));
|
||||
|
||||
RelayDispatchQueueSize::<T>::mutate(¶, |(ref mut cnt, ref mut size)| {
|
||||
*cnt += extra_count;
|
||||
*size += extra_size;
|
||||
});
|
||||
|
||||
NeedsDispatch::<T>::mutate(|v| {
|
||||
if let Err(i) = v.binary_search(¶) {
|
||||
v.insert(i, para);
|
||||
}
|
||||
});
|
||||
|
||||
// NOTE: The actual computation is not accounted for. It should be benchmarked.
|
||||
weight += T::DbWeight::get().reads_writes(3, 3);
|
||||
|
||||
Self::deposit_event(Event::UpwardMessagesReceived(para, extra_count, extra_size));
|
||||
}
|
||||
|
||||
weight
|
||||
}
|
||||
|
||||
/// Devote some time into dispatching pending upward messages.
|
||||
pub(crate) fn process_pending_upward_messages() -> Weight {
|
||||
const MAX_MESSAGES_PER_BLOCK: u8 = 10;
|
||||
let mut messages_processed = 0;
|
||||
let mut weight_used = Weight::zero();
|
||||
|
||||
let config = <configuration::Pallet<T>>::config();
|
||||
let mut cursor = NeedsDispatchCursor::new::<T>();
|
||||
let mut queue_cache = QueueCache::new();
|
||||
|
||||
while let Some(dispatchee) = cursor.peek() {
|
||||
if weight_used.any_gte(config.ump_service_total_weight) ||
|
||||
messages_processed >= MAX_MESSAGES_PER_BLOCK
|
||||
{
|
||||
// Temporarily allow for processing of a max of 10 messages per block, until we
|
||||
// properly account for proof size weights.
|
||||
//
|
||||
// Then check whether we've reached or overshoot the
|
||||
// preferred weight for the dispatching stage.
|
||||
//
|
||||
// if so - bail.
|
||||
break
|
||||
}
|
||||
let max_weight = if weight_used == Weight::zero() {
|
||||
// we increase the amount of weight that we're allowed to use on the first message to try to prevent
|
||||
// the possibility of blockage of the queue.
|
||||
config
|
||||
.ump_service_total_weight
|
||||
.saturating_mul(T::FirstMessageFactorPercent::get()) /
|
||||
100
|
||||
} else {
|
||||
config.ump_service_total_weight - weight_used
|
||||
};
|
||||
|
||||
// attempt to process the next message from the queue of the dispatchee; if not beyond
|
||||
// our remaining weight limit, then consume it.
|
||||
let maybe_next = queue_cache.peek_front::<T>(dispatchee);
|
||||
if let Some(upward_message) = maybe_next {
|
||||
messages_processed += 1;
|
||||
match T::UmpSink::process_upward_message(dispatchee, upward_message, max_weight) {
|
||||
Ok(used) => {
|
||||
weight_used += used;
|
||||
let _ = queue_cache.consume_front::<T>(dispatchee);
|
||||
},
|
||||
Err((id, required)) => {
|
||||
let is_under_limit = Overweight::<T>::count() < MAX_OVERWEIGHT_MESSAGES;
|
||||
weight_used.saturating_accrue(T::DbWeight::get().reads(1));
|
||||
if required.any_gt(config.ump_max_individual_weight) && is_under_limit {
|
||||
// overweight - add to overweight queue and continue with message
|
||||
// execution consuming the message.
|
||||
let upward_message = queue_cache.consume_front::<T>(dispatchee).expect(
|
||||
"`consume_front` should return the same msg as `peek_front`;\
|
||||
if we get into this branch then `peek_front` returned `Some`;\
|
||||
thus `upward_message` cannot be `None`; qed",
|
||||
);
|
||||
let index = Self::stash_overweight(dispatchee, upward_message);
|
||||
Self::deposit_event(Event::OverweightEnqueued(
|
||||
dispatchee, id, index, required,
|
||||
));
|
||||
} else {
|
||||
// we process messages in order and don't drop them if we run out of weight,
|
||||
// so need to break here without calling `consume_front`.
|
||||
Self::deposit_event(Event::WeightExhausted(id, max_weight, required));
|
||||
break
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if queue_cache.is_empty::<T>(dispatchee) {
|
||||
// the queue is empty now - this para doesn't need attention anymore.
|
||||
cursor.remove();
|
||||
} else {
|
||||
cursor.advance();
|
||||
}
|
||||
}
|
||||
|
||||
cursor.flush::<T>();
|
||||
queue_cache.flush::<T>();
|
||||
|
||||
weight_used
|
||||
}
|
||||
|
||||
/// Puts a given upward message into the list of overweight messages allowing it to be executed
|
||||
/// later.
|
||||
fn stash_overweight(sender: ParaId, upward_message: Vec<u8>) -> OverweightIndex {
|
||||
let index = OverweightCount::<T>::mutate(|count| {
|
||||
let index = *count;
|
||||
*count += 1;
|
||||
index
|
||||
});
|
||||
|
||||
Overweight::<T>::insert(index, (sender, upward_message));
|
||||
index
|
||||
}
|
||||
}
|
||||
|
||||
/// To avoid constant fetching, deserializing and serialization the queues are cached.
|
||||
///
|
||||
/// After an item dequeued from a queue for the first time, the queue is stored in this struct
|
||||
/// rather than being serialized and persisted.
|
||||
///
|
||||
/// This implementation works best when:
|
||||
///
|
||||
/// 1. when the queues are shallow
|
||||
/// 2. the dispatcher makes more than one cycle
|
||||
///
|
||||
/// if the queues are deep and there are many we would load and keep the queues for a long time,
|
||||
/// thus increasing the peak memory consumption of the wasm runtime. Under such conditions persisting
|
||||
/// queues might play better since it's unlikely that they are going to be requested once more.
|
||||
///
|
||||
/// On the other hand, the situation when deep queues exist and it takes more than one dispatcher
|
||||
/// cycle to traverse the queues is already sub-optimal and better be avoided.
|
||||
///
|
||||
/// This struct is not supposed to be dropped but rather to be consumed by [`flush`].
|
||||
struct QueueCache(BTreeMap<ParaId, QueueCacheEntry>);
|
||||
|
||||
struct QueueCacheEntry {
|
||||
queue: Vec<UpwardMessage>,
|
||||
total_size: u32,
|
||||
consumed_count: usize,
|
||||
consumed_size: usize,
|
||||
}
|
||||
|
||||
impl QueueCache {
|
||||
fn new() -> Self {
|
||||
Self(BTreeMap::new())
|
||||
}
|
||||
|
||||
fn ensure_cached<T: Config>(&mut self, para: ParaId) -> &mut QueueCacheEntry {
|
||||
self.0.entry(para).or_insert_with(|| {
|
||||
let queue = RelayDispatchQueues::<T>::get(¶);
|
||||
let (_, total_size) = RelayDispatchQueueSize::<T>::get(¶);
|
||||
QueueCacheEntry { queue, total_size, consumed_count: 0, consumed_size: 0 }
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the message at the front of `para`'s queue, or `None` if the queue is empty.
|
||||
///
|
||||
/// Does not mutate the queue.
|
||||
fn peek_front<T: Config>(&mut self, para: ParaId) -> Option<&UpwardMessage> {
|
||||
let entry = self.ensure_cached::<T>(para);
|
||||
entry.queue.get(entry.consumed_count)
|
||||
}
|
||||
|
||||
/// Attempts to remove one message from the front of `para`'s queue. If the queue is empty, then
|
||||
/// does nothing.
|
||||
fn consume_front<T: Config>(&mut self, para: ParaId) -> Option<UpwardMessage> {
|
||||
let cache_entry = self.ensure_cached::<T>(para);
|
||||
|
||||
match cache_entry.queue.get_mut(cache_entry.consumed_count) {
|
||||
Some(msg) => {
|
||||
cache_entry.consumed_count += 1;
|
||||
cache_entry.consumed_size += msg.len();
|
||||
|
||||
Some(mem::take(msg))
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns if the queue for the given para is empty.
|
||||
///
|
||||
/// That is, if this returns `true` then the next call to [`peek_front`] will return `None`.
|
||||
///
|
||||
/// Does not mutate the queue.
|
||||
fn is_empty<T: Config>(&mut self, para: ParaId) -> bool {
|
||||
let cache_entry = self.ensure_cached::<T>(para);
|
||||
cache_entry.consumed_count >= cache_entry.queue.len()
|
||||
}
|
||||
|
||||
/// Flushes the updated queues into the storage.
|
||||
fn flush<T: Config>(self) {
|
||||
// NOTE we use an explicit method here instead of Drop impl because it has unwanted semantics
|
||||
// within runtime. It is dangerous to use because of double-panics and flushing on a panic
|
||||
// is not necessary as well.
|
||||
for (para, entry) in self.0 {
|
||||
if entry.consumed_count >= entry.queue.len() {
|
||||
// remove the entries altogether.
|
||||
RelayDispatchQueues::<T>::remove(¶);
|
||||
RelayDispatchQueueSize::<T>::remove(¶);
|
||||
} else if entry.consumed_count > 0 {
|
||||
RelayDispatchQueues::<T>::insert(¶, &entry.queue[entry.consumed_count..]);
|
||||
let count = (entry.queue.len() - entry.consumed_count) as u32;
|
||||
let size = entry.total_size.saturating_sub(entry.consumed_size as u32);
|
||||
RelayDispatchQueueSize::<T>::insert(¶, (count, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A cursor that iterates over all entries in `NeedsDispatch`.
|
||||
///
|
||||
/// This cursor will start with the para indicated by `NextDispatchRoundStartWith` storage entry.
|
||||
/// This cursor is cyclic meaning that after reaching the end it will jump to the beginning. Unlike
|
||||
/// an iterator, this cursor allows removing items during the iteration.
|
||||
///
|
||||
/// Each iteration cycle *must be* concluded with a call to either `advance` or `remove`.
|
||||
///
|
||||
/// This struct is not supposed to be dropped but rather to be consumed by [`flush`].
|
||||
#[derive(Debug)]
|
||||
struct NeedsDispatchCursor {
|
||||
needs_dispatch: Vec<ParaId>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl NeedsDispatchCursor {
|
||||
fn new<T: Config>() -> Self {
|
||||
let needs_dispatch: Vec<ParaId> = NeedsDispatch::<T>::get();
|
||||
let start_with = NextDispatchRoundStartWith::<T>::get();
|
||||
|
||||
let initial_index = match start_with {
|
||||
Some(para) => match needs_dispatch.binary_search(¶) {
|
||||
Ok(found_index) => found_index,
|
||||
Err(_supposed_index) => {
|
||||
// well that's weird because we maintain an invariant that
|
||||
// `NextDispatchRoundStartWith` must point into one of the items in
|
||||
// `NeedsDispatch`.
|
||||
//
|
||||
// let's select 0 as the starting index as a safe bet.
|
||||
debug_assert!(false);
|
||||
0
|
||||
},
|
||||
},
|
||||
None => 0,
|
||||
};
|
||||
|
||||
Self { needs_dispatch, index: initial_index }
|
||||
}
|
||||
|
||||
/// Returns the item the cursor points to.
|
||||
fn peek(&self) -> Option<ParaId> {
|
||||
self.needs_dispatch.get(self.index).cloned()
|
||||
}
|
||||
|
||||
/// Moves the cursor to the next item.
|
||||
fn advance(&mut self) {
|
||||
if self.needs_dispatch.is_empty() {
|
||||
return
|
||||
}
|
||||
self.index = (self.index + 1) % self.needs_dispatch.len();
|
||||
}
|
||||
|
||||
/// Removes the item under the cursor.
|
||||
fn remove(&mut self) {
|
||||
if self.needs_dispatch.is_empty() {
|
||||
return
|
||||
}
|
||||
let _ = self.needs_dispatch.remove(self.index);
|
||||
|
||||
// we might've removed the last element and that doesn't necessarily mean that `needs_dispatch`
|
||||
// became empty. Reposition the cursor in this case to the beginning.
|
||||
if self.needs_dispatch.get(self.index).is_none() {
|
||||
self.index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Flushes the dispatcher state into the persistent storage.
|
||||
fn flush<T: Config>(self) {
|
||||
let next_one = self.peek();
|
||||
NextDispatchRoundStartWith::<T>::set(next_one);
|
||||
NeedsDispatch::<T>::put(self.needs_dispatch);
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{Pallet as Ump, *};
|
||||
use frame_system::RawOrigin;
|
||||
use xcm::prelude::*;
|
||||
|
||||
fn assert_last_event_type<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
let events = frame_system::Pallet::<T>::events();
|
||||
let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
|
||||
// compare to the last event record
|
||||
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
|
||||
assert_eq!(sp_std::mem::discriminant(event), sp_std::mem::discriminant(&system_event));
|
||||
}
|
||||
|
||||
fn queue_upward_msg<T: Config>(
|
||||
host_conf: &HostConfiguration<T::BlockNumber>,
|
||||
para: ParaId,
|
||||
msg: UpwardMessage,
|
||||
) {
|
||||
let len = msg.len() as u32;
|
||||
let msgs: UpwardMessages = vec![msg].try_into().unwrap();
|
||||
Ump::<T>::check_upward_messages(host_conf, para, &msgs).unwrap();
|
||||
let _ = Ump::<T>::receive_upward_messages(para, msgs);
|
||||
assert_last_event_type::<T>(Event::UpwardMessagesReceived(para, 1, len).into());
|
||||
}
|
||||
|
||||
// Create a message with at least `size` bytes encoded length
|
||||
fn create_message_min_size<T: Config>(size: u32) -> Vec<u8> {
|
||||
// Create a message with an empty remark call to determine the encoding overhead
|
||||
let msg_size_empty_transact = VersionedXcm::<T>::from(Xcm::<T>(vec![Transact {
|
||||
origin_kind: OriginKind::SovereignAccount,
|
||||
require_weight_at_most: Weight::MAX,
|
||||
call: frame_system::Call::<T>::remark_with_event { remark: vec![] }.encode().into(),
|
||||
}]))
|
||||
.encode()
|
||||
.len();
|
||||
|
||||
// Create a message with a remark call of just the size required to make the whole encoded message the requested size
|
||||
let size = size.saturating_sub(msg_size_empty_transact as u32) as usize;
|
||||
let mut remark = Vec::new();
|
||||
remark.resize(size, 0u8);
|
||||
let msg = VersionedXcm::<T>::from(Xcm::<T>(vec![Transact {
|
||||
origin_kind: OriginKind::SovereignAccount,
|
||||
require_weight_at_most: Weight::MAX,
|
||||
call: frame_system::Call::<T>::remark_with_event { remark }.encode().into(),
|
||||
}]))
|
||||
.encode();
|
||||
|
||||
assert!(msg.len() >= size);
|
||||
msg
|
||||
}
|
||||
|
||||
fn create_message_overweight<T: Config>() -> Vec<u8> {
|
||||
// We use a `set_code` Call because it
|
||||
let call = frame_system::Call::<T>::set_code { code: vec![] };
|
||||
VersionedXcm::<T>::from(Xcm::<T>(vec![Transact {
|
||||
origin_kind: OriginKind::Superuser,
|
||||
require_weight_at_most: Weight::MAX / 2,
|
||||
call: call.encode().into(),
|
||||
}]))
|
||||
.encode()
|
||||
}
|
||||
|
||||
frame_benchmarking::benchmarks! {
|
||||
// NOTE: We are overestimating slightly here.
|
||||
// The benchmark is timing this whole function with different message sizes and a NOOP extrinsic to
|
||||
// measure the size-dependent weight. But as we use the weight function **in** the benchmarked function we
|
||||
// are taking call and control-flow overhead into account twice.
|
||||
process_upward_message {
|
||||
let s in 0..MAX_UPWARD_MESSAGE_SIZE_BOUND;
|
||||
let para = ParaId::from(1978);
|
||||
let data = create_message_min_size::<T>(s);
|
||||
}: {
|
||||
assert!(T::UmpSink::process_upward_message(para, &data[..], Weight::MAX).is_ok());
|
||||
}
|
||||
|
||||
clean_ump_after_outgoing {
|
||||
// max number of queued messages.
|
||||
let count = configuration::ActiveConfig::<T>::get().max_upward_queue_count;
|
||||
let host_conf = configuration::ActiveConfig::<T>::get();
|
||||
let msg = create_message_min_size::<T>(0);
|
||||
// Start with the block number 1. This is needed because should an event be
|
||||
// emitted during the genesis block they will be implicitly wiped.
|
||||
frame_system::Pallet::<T>::set_block_number(1u32.into());
|
||||
// fill the queue, each message has it's own para-id.
|
||||
for id in 0..count {
|
||||
queue_upward_msg::<T>(&host_conf, ParaId::from(id), msg.clone());
|
||||
}
|
||||
}: {
|
||||
Ump::<T>::clean_ump_after_outgoing(&ParaId::from(0));
|
||||
}
|
||||
|
||||
service_overweight {
|
||||
let host_conf = configuration::ActiveConfig::<T>::get();
|
||||
let para = ParaId::from(1978);
|
||||
// The message's weight does not really matter here, as we add service_overweight's
|
||||
// max_weight parameter to the extrinsic's weight in the weight calculation.
|
||||
// The size of the message influences decoding time, so we create a min-sized message here
|
||||
// and take the decoding weight into account by adding it to the extrinsic execution weight
|
||||
// in the process_upward_message function.
|
||||
let msg = create_message_overweight::<T>();
|
||||
|
||||
// This just makes sure that 0 is not a valid index and we can use it later on.
|
||||
let _ = Ump::<T>::service_overweight(RawOrigin::Root.into(), 0, Weight::from_parts(1000, 1000));
|
||||
// Start with the block number 1. This is needed because should an event be
|
||||
// emitted during the genesis block they will be implicitly wiped.
|
||||
frame_system::Pallet::<T>::set_block_number(1u32.into());
|
||||
queue_upward_msg::<T>(&host_conf, para, msg.clone());
|
||||
Ump::<T>::process_pending_upward_messages();
|
||||
assert_last_event_type::<T>(
|
||||
Event::OverweightEnqueued(para, upward_message_id(&msg), 0, Weight::zero()).into()
|
||||
);
|
||||
}: _(RawOrigin::Root, 0, Weight::MAX)
|
||||
verify {
|
||||
assert_last_event_type::<T>(Event::OverweightServiced(0, Weight::zero()).into());
|
||||
}
|
||||
}
|
||||
|
||||
frame_benchmarking::impl_benchmark_test_suite!(
|
||||
Ump,
|
||||
crate::mock::new_test_ext(crate::ump::tests::GenesisConfigBuilder::default().build()),
|
||||
crate::mock::Test
|
||||
);
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::ump::{Config, Overweight, Pallet};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
traits::{OnRuntimeUpgrade, StorageVersion},
|
||||
weights::Weight,
|
||||
};
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
if StorageVersion::get::<Pallet<T>>() == 0 {
|
||||
let mut weight = T::DbWeight::get().reads(1);
|
||||
|
||||
let overweight_messages = Overweight::<T>::initialize_counter() as u64;
|
||||
log::info!("Initialized Overweight to {}", overweight_messages);
|
||||
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(overweight_messages, 1));
|
||||
|
||||
StorageVersion::new(1).put::<Pallet<T>>();
|
||||
|
||||
weight.saturating_add(T::DbWeight::get().writes(1))
|
||||
} else {
|
||||
log::warn!("skipping v1, should be removed");
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::mock::{
|
||||
assert_last_event, new_test_ext, take_processed, Configuration, MockGenesisConfig,
|
||||
RuntimeOrigin, System, Test, Ump,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok, weights::Weight};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub(super) struct GenesisConfigBuilder {
|
||||
max_upward_message_size: u32,
|
||||
max_upward_message_num_per_candidate: u32,
|
||||
max_upward_queue_count: u32,
|
||||
max_upward_queue_size: u32,
|
||||
ump_service_total_weight: Weight,
|
||||
ump_max_individual_weight: Weight,
|
||||
}
|
||||
|
||||
impl Default for GenesisConfigBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_upward_message_size: 32,
|
||||
max_upward_message_num_per_candidate: 2,
|
||||
max_upward_queue_count: 4,
|
||||
max_upward_queue_size: 64,
|
||||
ump_service_total_weight: Weight::from_parts(1000, 1000),
|
||||
ump_max_individual_weight: Weight::from_parts(100, 100),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenesisConfigBuilder {
|
||||
pub(super) fn build(self) -> crate::mock::MockGenesisConfig {
|
||||
let mut genesis = default_genesis_config();
|
||||
let config = &mut genesis.configuration.config;
|
||||
|
||||
config.max_upward_message_size = self.max_upward_message_size;
|
||||
config.max_upward_message_num_per_candidate = self.max_upward_message_num_per_candidate;
|
||||
config.max_upward_queue_count = self.max_upward_queue_count;
|
||||
config.max_upward_queue_size = self.max_upward_queue_size;
|
||||
config.ump_service_total_weight = self.ump_service_total_weight;
|
||||
config.ump_max_individual_weight = self.ump_max_individual_weight;
|
||||
genesis
|
||||
}
|
||||
}
|
||||
|
||||
fn default_genesis_config() -> MockGenesisConfig {
|
||||
MockGenesisConfig {
|
||||
configuration: crate::configuration::GenesisConfig {
|
||||
config: crate::configuration::HostConfiguration {
|
||||
max_downward_message_size: 1024,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_upward_msg(para: ParaId, msg: UpwardMessage) {
|
||||
let msgs: UpwardMessages = vec![msg].try_into().unwrap();
|
||||
assert!(Ump::check_upward_messages(&Configuration::config(), para, &msgs).is_ok());
|
||||
let _ = Ump::receive_upward_messages(para, msgs);
|
||||
}
|
||||
|
||||
fn assert_storage_consistency_exhaustive() {
|
||||
// check that empty queues don't clutter the storage.
|
||||
for (_para, queue) in RelayDispatchQueues::<Test>::iter() {
|
||||
assert!(!queue.is_empty());
|
||||
}
|
||||
|
||||
// actually count the counts and sizes in queues and compare them to the bookkept version.
|
||||
for (para, queue) in RelayDispatchQueues::<Test>::iter() {
|
||||
let (expected_count, expected_size) = RelayDispatchQueueSize::<Test>::get(para);
|
||||
let (actual_count, actual_size) = queue
|
||||
.into_iter()
|
||||
.fold((0, 0), |(acc_count, acc_size), x| (acc_count + 1, acc_size + x.len() as u32));
|
||||
|
||||
assert_eq!(expected_count, actual_count);
|
||||
assert_eq!(expected_size, actual_size);
|
||||
}
|
||||
|
||||
// since we wipe the empty queues the sets of paras in queue contents, queue sizes and
|
||||
// need dispatch set should all be equal.
|
||||
let queue_contents_set =
|
||||
RelayDispatchQueues::<Test>::iter().map(|(k, _)| k).collect::<HashSet<ParaId>>();
|
||||
let queue_sizes_set = RelayDispatchQueueSize::<Test>::iter()
|
||||
.map(|(k, _)| k)
|
||||
.collect::<HashSet<ParaId>>();
|
||||
let needs_dispatch_set = NeedsDispatch::<Test>::get().into_iter().collect::<HashSet<ParaId>>();
|
||||
assert_eq!(queue_contents_set, queue_sizes_set);
|
||||
assert_eq!(queue_contents_set, needs_dispatch_set);
|
||||
|
||||
// `NextDispatchRoundStartWith` should point into a para that is tracked.
|
||||
if let Some(para) = NextDispatchRoundStartWith::<Test>::get() {
|
||||
assert!(queue_contents_set.contains(¶));
|
||||
}
|
||||
|
||||
// `NeedsDispatch` is always sorted.
|
||||
assert!(NeedsDispatch::<Test>::get().windows(2).all(|xs| xs[0] <= xs[1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_empty() {
|
||||
new_test_ext(default_genesis_config()).execute_with(|| {
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// make sure that the case with empty queues is handled properly
|
||||
Ump::process_pending_upward_messages();
|
||||
|
||||
assert_storage_consistency_exhaustive();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_single_message() {
|
||||
let a = ParaId::from(228);
|
||||
let msg = 1000u32.encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
queue_upward_msg(a, msg.clone());
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, msg)]);
|
||||
|
||||
assert_storage_consistency_exhaustive();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_resume_after_exceeding_dispatch_stage_weight() {
|
||||
let a = ParaId::from(128);
|
||||
let c = ParaId::from(228);
|
||||
let q = ParaId::from(911);
|
||||
|
||||
let a_msg_1 = (200u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (100u32, "a_msg_2").encode();
|
||||
let c_msg_1 = (300u32, "c_msg_1").encode();
|
||||
let c_msg_2 = (100u32, "c_msg_2").encode();
|
||||
let q_msg = (500u32, "q_msg").encode();
|
||||
|
||||
new_test_ext(
|
||||
GenesisConfigBuilder {
|
||||
ump_service_total_weight: Weight::from_parts(500, 500),
|
||||
..Default::default()
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
.execute_with(|| {
|
||||
queue_upward_msg(q, q_msg.clone());
|
||||
queue_upward_msg(c, c_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// we expect only two first messages to fit in the first iteration.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, a_msg_1), (c, c_msg_1)]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
queue_upward_msg(c, c_msg_2.clone());
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// second iteration should process the second message.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(q, q_msg)]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// 3rd iteration.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, a_msg_2), (c, c_msg_2)]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// finally, make sure that the queue is empty.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_keeps_message_after_weight_exhausted() {
|
||||
let a = ParaId::from(128);
|
||||
|
||||
let a_msg_1 = (300u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (300u32, "a_msg_2").encode();
|
||||
|
||||
new_test_ext(
|
||||
GenesisConfigBuilder {
|
||||
ump_service_total_weight: Weight::from_parts(500, 500),
|
||||
ump_max_individual_weight: Weight::from_parts(300, 300),
|
||||
..Default::default()
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
.execute_with(|| {
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// we expect only one message to fit in the first iteration.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, a_msg_1)]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// second iteration should process the remaining message.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, a_msg_2)]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
|
||||
// finally, make sure that the queue is empty.
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![]);
|
||||
assert_storage_consistency_exhaustive();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_correctly_handle_remove_of_latest() {
|
||||
let a = ParaId::from(1991);
|
||||
let b = ParaId::from(1999);
|
||||
|
||||
let a_msg_1 = (300u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (300u32, "a_msg_2").encode();
|
||||
let b_msg_1 = (300u32, "b_msg_1").encode();
|
||||
|
||||
new_test_ext(
|
||||
GenesisConfigBuilder {
|
||||
ump_service_total_weight: Weight::from_parts(900, 900),
|
||||
..Default::default()
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
.execute_with(|| {
|
||||
// We want to test here an edge case, where we remove the queue with the highest
|
||||
// para id (i.e. last in the `needs_dispatch` order).
|
||||
//
|
||||
// If the last entry was removed we should proceed execution, assuming we still have
|
||||
// weight available.
|
||||
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
queue_upward_msg(b, b_msg_1.clone());
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(a, a_msg_1), (b, b_msg_1), (a, a_msg_2)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_relay_dispatch_queue_size_is_externally_accessible() {
|
||||
// Make sure that the relay dispatch queue size storage entry is accessible via well known
|
||||
// keys and is decodable into a (u32, u32).
|
||||
|
||||
use parity_scale_codec::Decode as _;
|
||||
use primitives::well_known_keys;
|
||||
|
||||
let a = ParaId::from(228);
|
||||
let msg = vec![1, 2, 3];
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
queue_upward_msg(a, msg);
|
||||
|
||||
let raw_queue_size = sp_io::storage::get(&well_known_keys::relay_dispatch_queue_size(a))
|
||||
.expect(
|
||||
"enqueing a message should create the dispatch queue\
|
||||
and it should be accessible via the well known keys",
|
||||
);
|
||||
let (cnt, size) = <(u32, u32)>::decode(&mut &raw_queue_size[..])
|
||||
.expect("the dispatch queue size should be decodable into (u32, u32)");
|
||||
|
||||
assert_eq!(cnt, 1);
|
||||
assert_eq!(size, 3);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn service_overweight_unknown() {
|
||||
// This test just makes sure that 0 is not a valid index and we can use it not worrying in
|
||||
// the next test.
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
assert_noop!(
|
||||
Ump::service_overweight(RuntimeOrigin::root(), 0, Weight::from_parts(1000, 1000)),
|
||||
Error::<Test>::UnknownMessageIndex
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overweight_queue_works() {
|
||||
let para_a = ParaId::from(2021);
|
||||
|
||||
let a_msg_1 = (301u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (500u32, "a_msg_2").encode();
|
||||
let a_msg_3 = (500u32, "a_msg_3").encode();
|
||||
|
||||
new_test_ext(
|
||||
GenesisConfigBuilder {
|
||||
ump_service_total_weight: Weight::from_parts(900, 900),
|
||||
ump_max_individual_weight: Weight::from_parts(300, 300),
|
||||
..Default::default()
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
.execute_with(|| {
|
||||
// HACK: Start with the block number 1. This is needed because should an event be
|
||||
// emitted during the genesis block they will be implicitly wiped.
|
||||
System::set_block_number(1);
|
||||
|
||||
// This one is overweight. However, the weight is plenty and we can afford to execute
|
||||
// this message, thus expect it.
|
||||
queue_upward_msg(para_a, a_msg_1.clone());
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_eq!(take_processed(), vec![(para_a, a_msg_1)]);
|
||||
|
||||
// This is overweight and this message cannot fit into the total weight budget.
|
||||
queue_upward_msg(para_a, a_msg_2.clone());
|
||||
queue_upward_msg(para_a, a_msg_3.clone());
|
||||
Ump::process_pending_upward_messages();
|
||||
assert_last_event(
|
||||
Event::OverweightEnqueued(
|
||||
para_a,
|
||||
upward_message_id(&a_msg_3[..]),
|
||||
0,
|
||||
Weight::from_parts(500, 500),
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
||||
// Now verify that if we wanted to service this overweight message with less than enough
|
||||
// weight it will fail.
|
||||
assert_noop!(
|
||||
Ump::service_overweight(RuntimeOrigin::root(), 0, Weight::from_parts(499, 499)),
|
||||
Error::<Test>::WeightOverLimit
|
||||
);
|
||||
|
||||
// ... and if we try to service it with just enough weight it will succeed as well.
|
||||
assert_ok!(Ump::service_overweight(RuntimeOrigin::root(), 0, Weight::from_parts(500, 500)));
|
||||
assert_last_event(Event::OverweightServiced(0, Weight::from_parts(500, 500)).into());
|
||||
|
||||
// ... and if we try to service a message with index that doesn't exist it will error
|
||||
// out.
|
||||
assert_noop!(
|
||||
Ump::service_overweight(RuntimeOrigin::root(), 1, Weight::from_parts(1000, 1000)),
|
||||
Error::<Test>::UnknownMessageIndex
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
inclusion::{
|
||||
tests::run_to_block_default_notifications as run_to_block, AggregateMessageOrigin,
|
||||
AggregateMessageOrigin::Ump, UmpAcceptanceCheckErr, UmpQueueId,
|
||||
},
|
||||
mock::{
|
||||
assert_last_event, assert_last_events, new_test_ext, Configuration, MessageQueue,
|
||||
MessageQueueSize, MockGenesisConfig, ParaInclusion, Processed, System, Test, *,
|
||||
},
|
||||
};
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
pallet_prelude::*,
|
||||
traits::{EnqueueMessage, ExecuteOverweightError, ServiceQueues},
|
||||
weights::Weight,
|
||||
};
|
||||
use primitives::v4::{well_known_keys, Id as ParaId, UpwardMessage};
|
||||
use sp_core::twox_64;
|
||||
use sp_runtime::traits::{Bounded, Hash};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
pub(super) struct GenesisConfigBuilder {
|
||||
max_upward_message_size: u32,
|
||||
max_upward_message_num_per_candidate: u32,
|
||||
max_upward_queue_count: u32,
|
||||
max_upward_queue_size: u32,
|
||||
}
|
||||
|
||||
impl Default for GenesisConfigBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_upward_message_size: 16,
|
||||
max_upward_message_num_per_candidate: 2,
|
||||
max_upward_queue_count: 4,
|
||||
max_upward_queue_size: 64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenesisConfigBuilder {
|
||||
pub(super) fn large_queue_count() -> Self {
|
||||
Self { max_upward_queue_count: 128, ..Default::default() }
|
||||
}
|
||||
|
||||
pub(super) fn build(self) -> crate::mock::MockGenesisConfig {
|
||||
let mut genesis = default_genesis_config();
|
||||
let config = &mut genesis.configuration.config;
|
||||
|
||||
config.max_upward_message_size = self.max_upward_message_size;
|
||||
config.max_upward_message_num_per_candidate = self.max_upward_message_num_per_candidate;
|
||||
config.max_upward_queue_count = self.max_upward_queue_count;
|
||||
config.max_upward_queue_size = self.max_upward_queue_size;
|
||||
genesis
|
||||
}
|
||||
}
|
||||
|
||||
fn default_genesis_config() -> MockGenesisConfig {
|
||||
MockGenesisConfig {
|
||||
configuration: crate::configuration::GenesisConfig {
|
||||
config: crate::configuration::HostConfiguration {
|
||||
max_downward_message_size: 1024,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_upward_msg(para: ParaId, msg: UpwardMessage) {
|
||||
try_queue_upward_msg(para, msg).unwrap();
|
||||
}
|
||||
|
||||
fn try_queue_upward_msg(para: ParaId, msg: UpwardMessage) -> Result<(), UmpAcceptanceCheckErr> {
|
||||
let msgs = vec![msg];
|
||||
ParaInclusion::check_upward_messages(&Configuration::config(), para, &msgs)?;
|
||||
ParaInclusion::receive_upward_messages(para, msgs.as_slice());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod check_upward_messages {
|
||||
use super::*;
|
||||
|
||||
const P_0: ParaId = ParaId::new(0u32);
|
||||
const P_1: ParaId = ParaId::new(1u32);
|
||||
|
||||
// Currently its trivial since unbounded, but this function will be handy when we bound it.
|
||||
fn msg(data: &str) -> UpwardMessage {
|
||||
data.as_bytes().to_vec()
|
||||
}
|
||||
|
||||
/// Check that these messages *could* be queued.
|
||||
fn check(para: ParaId, msgs: Vec<UpwardMessage>, err: Option<UmpAcceptanceCheckErr>) {
|
||||
assert_eq!(
|
||||
ParaInclusion::check_upward_messages(&Configuration::config(), para, &msgs[..]).err(),
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
/// Enqueue these upward messages.
|
||||
fn queue(para: ParaId, msgs: Vec<UpwardMessage>) {
|
||||
msgs.into_iter().for_each(|msg| super::queue_upward_msg(para, msg));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_works() {
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let _g = frame_support::StorageNoopGuard::default();
|
||||
check(P_0, vec![msg("p0m0")], None);
|
||||
check(P_1, vec![msg("p1m0")], None);
|
||||
check(P_0, vec![msg("p0m1")], None);
|
||||
check(P_1, vec![msg("p1m1")], None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn num_per_candidate_exceeded_error() {
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let _g = frame_support::StorageNoopGuard::default();
|
||||
let permitted = Configuration::config().max_upward_message_num_per_candidate;
|
||||
|
||||
for sent in 0..permitted + 1 {
|
||||
check(P_0, vec![msg(""); sent as usize], None);
|
||||
}
|
||||
for sent in permitted + 1..permitted + 10 {
|
||||
check(
|
||||
P_0,
|
||||
vec![msg(""); sent as usize],
|
||||
Some(UmpAcceptanceCheckErr::MoreMessagesThanPermitted { sent, permitted }),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn size_per_message_exceeded_error() {
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let _g = frame_support::StorageNoopGuard::default();
|
||||
let max_size = Configuration::config().max_upward_message_size;
|
||||
let max_per_candidate = Configuration::config().max_upward_message_num_per_candidate;
|
||||
|
||||
for msg_size in 0..=max_size {
|
||||
check(P_0, vec![vec![0; msg_size as usize]], None);
|
||||
}
|
||||
for msg_size in max_size + 1..max_size + 10 {
|
||||
for goods in 0..max_per_candidate {
|
||||
let mut msgs = vec![vec![0; max_size as usize]; goods as usize];
|
||||
msgs.push(vec![0; msg_size as usize]);
|
||||
|
||||
check(
|
||||
P_0,
|
||||
msgs,
|
||||
Some(UmpAcceptanceCheckErr::MessageSize { idx: goods, msg_size, max_size }),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queue_count_exceeded_error() {
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let limit = Configuration::config().max_upward_queue_count as u64;
|
||||
|
||||
for _ in 0..limit {
|
||||
check(P_0, vec![msg("")], None);
|
||||
queue(P_0, vec![msg("")]);
|
||||
}
|
||||
|
||||
check(
|
||||
P_0,
|
||||
vec![msg("")],
|
||||
Some(UmpAcceptanceCheckErr::CapacityExceeded { count: limit + 1, limit }),
|
||||
);
|
||||
check(
|
||||
P_0,
|
||||
vec![msg(""); 2],
|
||||
Some(UmpAcceptanceCheckErr::CapacityExceeded { count: limit + 2, limit }),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queue_size_exceeded_error() {
|
||||
new_test_ext(GenesisConfigBuilder::large_queue_count().build()).execute_with(|| {
|
||||
let limit = Configuration::config().max_upward_queue_size as u64;
|
||||
assert_eq!(pallet_message_queue::ItemHeader::<MessageQueueSize>::max_encoded_len(), 5);
|
||||
assert!(
|
||||
Configuration::config().max_upward_queue_size <
|
||||
crate::inclusion::MaxUmpMessageLenOf::<Test>::get(),
|
||||
"Test will not work"
|
||||
);
|
||||
|
||||
for _ in 0..limit {
|
||||
check(P_0, vec![msg("1")], None);
|
||||
queue(P_0, vec![msg("1")]);
|
||||
}
|
||||
|
||||
check(
|
||||
P_0,
|
||||
vec![msg("1")],
|
||||
Some(UmpAcceptanceCheckErr::TotalSizeExceeded { total_size: limit + 1, limit }),
|
||||
);
|
||||
check(
|
||||
P_0,
|
||||
vec![msg("123456")],
|
||||
Some(UmpAcceptanceCheckErr::TotalSizeExceeded { total_size: limit + 6, limit }),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_empty() {
|
||||
new_test_ext(default_genesis_config()).execute_with(|| {
|
||||
// make sure that the case with empty queues is handled properly
|
||||
MessageQueue::service_queues(Weight::max_value());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_single_message() {
|
||||
let a = ParaId::from(228);
|
||||
let msg = 1000u32.encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
queue_upward_msg(a, msg.clone());
|
||||
MessageQueue::service_queues(Weight::max_value());
|
||||
assert_eq!(Processed::take(), vec![(a, msg)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_resume_after_exceeding_dispatch_stage_weight() {
|
||||
let a = ParaId::from(128);
|
||||
let c = ParaId::from(228);
|
||||
let q = ParaId::from(911);
|
||||
|
||||
let a_msg_1 = (200u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (100u32, "a_msg_2").encode();
|
||||
let c_msg_1 = (300u32, "c_msg_1").encode();
|
||||
let c_msg_2 = (100u32, "c_msg_2").encode();
|
||||
let q_msg = (500u32, "q_msg").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
queue_upward_msg(q, q_msg.clone());
|
||||
queue_upward_msg(c, c_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
|
||||
// we expect only two first messages to fit in the first iteration.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![(q, q_msg)]);
|
||||
queue_upward_msg(c, c_msg_2.clone());
|
||||
// second iteration should process the second message.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![(c, c_msg_1), (c, c_msg_2)]);
|
||||
// 3rd iteration.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![(a, a_msg_1), (a, a_msg_2)]);
|
||||
// finally, make sure that the queue is empty.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_keeps_message_after_weight_exhausted() {
|
||||
let a = ParaId::from(128);
|
||||
|
||||
let a_msg_1 = (300u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (300u32, "a_msg_2").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
|
||||
// we expect only one message to fit in the first iteration.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![(a, a_msg_1)]);
|
||||
// second iteration should process the remaining message.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![(a, a_msg_2)]);
|
||||
// finally, make sure that the queue is empty.
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
assert_eq!(Processed::take(), vec![]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_correctly_handle_remove_of_latest() {
|
||||
let a = ParaId::from(1991);
|
||||
let b = ParaId::from(1999);
|
||||
|
||||
let a_msg_1 = (300u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (300u32, "a_msg_2").encode();
|
||||
let b_msg_1 = (300u32, "b_msg_1").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
// We want to test here an edge case, where we remove the queue with the highest
|
||||
// para id (i.e. last in the `needs_dispatch` order).
|
||||
//
|
||||
// If the last entry was removed we should proceed execution, assuming we still have
|
||||
// weight available.
|
||||
|
||||
queue_upward_msg(a, a_msg_1.clone());
|
||||
queue_upward_msg(a, a_msg_2.clone());
|
||||
queue_upward_msg(b, b_msg_1.clone());
|
||||
MessageQueue::service_queues(Weight::from_parts(900, 900));
|
||||
assert_eq!(Processed::take(), vec![(a, a_msg_1), (a, a_msg_2), (b, b_msg_1)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(debug_assertions, should_panic = "Defensive failure has been triggered")]
|
||||
fn queue_enact_too_long_ignored() {
|
||||
const P_0: ParaId = ParaId::new(0u32);
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let max_enact = crate::inclusion::MaxUmpMessageLenOf::<Test>::get() as usize;
|
||||
let m1 = (300u32, "a_msg_1").encode();
|
||||
let m2 = vec![0u8; max_enact + 1];
|
||||
let m3 = (300u32, "a_msg_3").encode();
|
||||
|
||||
// .. but the enact defensively ignores.
|
||||
ParaInclusion::receive_upward_messages(P_0, &[m1.clone(), m2.clone(), m3.clone()]);
|
||||
// There is one message in the queue now:
|
||||
MessageQueue::service_queues(Weight::from_parts(900, 900));
|
||||
assert_eq!(Processed::take(), vec![(P_0, m1), (P_0, m3)]);
|
||||
});
|
||||
}
|
||||
|
||||
/// Check that the Inclusion pallet correctly updates the well known keys in the MQ handler.
|
||||
///
|
||||
/// Also checks that it works in the presence of overweight messages.
|
||||
#[test]
|
||||
fn relay_dispatch_queue_size_is_updated() {
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let cfg = Configuration::config();
|
||||
|
||||
for p in 0..100 {
|
||||
let para = p.into();
|
||||
// Do some tricks with the weight such that the MQ pallet will process in order:
|
||||
// Q0:0, Q1:0 … Q0:1, Q1:1 …
|
||||
let m1 = (300u32 * (100 - p), "m1").encode();
|
||||
let m2 = (300u32 * (100 - p), "m11").encode();
|
||||
|
||||
queue_upward_msg(para, m1);
|
||||
queue_upward_msg(para, m2);
|
||||
|
||||
assert_queue_size(para, 2, 15);
|
||||
assert_queue_remaining(
|
||||
para,
|
||||
cfg.max_upward_queue_count - 2,
|
||||
cfg.max_upward_queue_size - 15,
|
||||
);
|
||||
|
||||
// Now processing one message should also update the queue size.
|
||||
MessageQueue::service_queues(Weight::from_all(300u64 * (100 - p) as u64));
|
||||
assert_queue_remaining(
|
||||
para,
|
||||
cfg.max_upward_queue_count - 1,
|
||||
cfg.max_upward_queue_size - 8,
|
||||
);
|
||||
}
|
||||
|
||||
// The messages of Q0…Q98 are overweight, so `service_queues` wont help.
|
||||
for p in 0..98 {
|
||||
let para = UmpQueueId::Para(p.into());
|
||||
MessageQueue::service_queues(Weight::from_all(u64::MAX));
|
||||
|
||||
let fp = MessageQueue::footprint(AggregateMessageOrigin::Ump(para));
|
||||
let (para_queue_count, para_queue_size) = (fp.count, fp.size);
|
||||
assert_eq!(para_queue_count, 1, "count wrong for para: {}", p);
|
||||
assert_eq!(para_queue_size, 8, "size wrong for para: {}", p);
|
||||
}
|
||||
// All queues are empty after processing overweight messages.
|
||||
for p in 0..100 {
|
||||
let para = UmpQueueId::Para(p.into());
|
||||
let _ = <MessageQueue as ServiceQueues>::execute_overweight(
|
||||
Weight::from_all(u64::MAX),
|
||||
(AggregateMessageOrigin::Ump(para.clone()), 0, 1),
|
||||
);
|
||||
|
||||
assert_queue_remaining(p.into(), cfg.max_upward_queue_count, cfg.max_upward_queue_size);
|
||||
let fp = MessageQueue::footprint(AggregateMessageOrigin::Ump(para));
|
||||
let (para_queue_count, para_queue_size) = (fp.count, fp.size);
|
||||
assert_eq!(para_queue_count, 0, "count wrong for para: {}", p);
|
||||
assert_eq!(para_queue_size, 0, "size wrong for para: {}", p);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Assert that the old and the new way of accessing `relay_dispatch_queue_size` is the same.
|
||||
#[test]
|
||||
fn relay_dispatch_queue_size_key_is_correct() {
|
||||
#![allow(deprecated)]
|
||||
// Storage alias to the old way of accessing the queue size.
|
||||
#[frame_support::storage_alias]
|
||||
type RelayDispatchQueueSize = StorageMap<Ump, Twox64Concat, ParaId, (u32, u32), ValueQuery>;
|
||||
|
||||
for i in 0..1024 {
|
||||
// A "random" para id.
|
||||
let para: ParaId = u32::from_ne_bytes(twox_64(&i.encode())[..4].try_into().unwrap()).into();
|
||||
|
||||
let well_known = primitives::well_known_keys::relay_dispatch_queue_size(para);
|
||||
let aliased = RelayDispatchQueueSize::hashed_key_for(para);
|
||||
|
||||
assert_eq!(well_known, aliased, "Old and new key must match");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_relay_dispatch_queue_size_is_externally_accessible() {
|
||||
// Make sure that the relay dispatch queue size storage entry is accessible via well known
|
||||
// keys and is decodable into a (u32, u32).
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
let cfg = Configuration::config();
|
||||
|
||||
for para in 0..10 {
|
||||
let para = para.into();
|
||||
queue_upward_msg(para, vec![0u8; 3]);
|
||||
assert_queue_size(para, 1, 3);
|
||||
assert_queue_remaining(
|
||||
para,
|
||||
cfg.max_upward_queue_count - 1,
|
||||
cfg.max_upward_queue_size - 3,
|
||||
);
|
||||
|
||||
queue_upward_msg(para, vec![0u8; 3]);
|
||||
assert_queue_size(para, 2, 6);
|
||||
assert_queue_remaining(
|
||||
para,
|
||||
cfg.max_upward_queue_count - 2,
|
||||
cfg.max_upward_queue_size - 6,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn assert_queue_size(para: ParaId, count: u32, size: u32) {
|
||||
#[allow(deprecated)]
|
||||
let raw_queue_size = sp_io::storage::get(&well_known_keys::relay_dispatch_queue_size(para)).expect(
|
||||
"enqueing a message should create the dispatch queue\
|
||||
and it should be accessible via the well known keys",
|
||||
);
|
||||
let (c, s) = <(u32, u32)>::decode(&mut &raw_queue_size[..])
|
||||
.expect("the dispatch queue size should be decodable into (u32, u32)");
|
||||
assert_eq!((c, s), (count, size));
|
||||
|
||||
// Test the deprecated but at least type-safe `relay_dispatch_queue_size_typed`:
|
||||
#[allow(deprecated)]
|
||||
let (c, s) = well_known_keys::relay_dispatch_queue_size_typed(para).get().expect(
|
||||
"enqueing a message should create the dispatch queue\
|
||||
and it should be accessible via the well known keys",
|
||||
);
|
||||
assert_eq!((c, s), (count, size));
|
||||
}
|
||||
|
||||
fn assert_queue_remaining(para: ParaId, count: u32, size: u32) {
|
||||
let (remaining_cnt, remaining_size) =
|
||||
well_known_keys::relay_dispatch_queue_remaining_capacity(para)
|
||||
.get()
|
||||
.expect("No storage value");
|
||||
assert_eq!(remaining_cnt, count, "Wrong number of remaining messages in Q{}", para);
|
||||
assert_eq!(remaining_size, size, "Wrong remaining size in Q{}", para);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn service_overweight_unknown() {
|
||||
// This test just makes sure that 0 is not a valid index and we can use it not worrying in
|
||||
// the next test.
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
assert_noop!(
|
||||
<MessageQueue as ServiceQueues>::execute_overweight(
|
||||
Weight::MAX,
|
||||
(Ump(UmpQueueId::Para(0u32.into())), 0, 0)
|
||||
),
|
||||
ExecuteOverweightError::NotFound,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overweight_queue_works() {
|
||||
let para_a = ParaId::from(2021);
|
||||
|
||||
let a_msg_1 = (301u32, "a_msg_1").encode();
|
||||
let a_msg_2 = (501u32, "a_msg_2").encode();
|
||||
let a_msg_3 = (501u32, "a_msg_3").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
// HACK: Start with the block number 1. This is needed because should an event be
|
||||
// emitted during the genesis block they will be implicitly wiped.
|
||||
System::set_block_number(1);
|
||||
|
||||
// This one is overweight. However, the weight is plenty and we can afford to execute
|
||||
// this message, thus expect it.
|
||||
queue_upward_msg(para_a, a_msg_1.clone());
|
||||
queue_upward_msg(para_a, a_msg_2.clone());
|
||||
queue_upward_msg(para_a, a_msg_3.clone());
|
||||
|
||||
MessageQueue::service_queues(Weight::from_parts(500, 500));
|
||||
let hash_1 = <<Test as frame_system::Config>::Hashing as Hash>::hash(&a_msg_1[..]);
|
||||
let hash_2 = <<Test as frame_system::Config>::Hashing as Hash>::hash(&a_msg_2[..]);
|
||||
let hash_3 = <<Test as frame_system::Config>::Hashing as Hash>::hash(&a_msg_3[..]);
|
||||
assert_last_events(
|
||||
[
|
||||
pallet_message_queue::Event::<Test>::Processed {
|
||||
hash: hash_1.clone(),
|
||||
origin: Ump(UmpQueueId::Para(para_a)),
|
||||
weight_used: Weight::from_parts(301, 301),
|
||||
success: true,
|
||||
}
|
||||
.into(),
|
||||
pallet_message_queue::Event::<Test>::OverweightEnqueued {
|
||||
hash: hash_2.clone(),
|
||||
origin: Ump(UmpQueueId::Para(para_a)),
|
||||
page_index: 0,
|
||||
message_index: 1,
|
||||
}
|
||||
.into(),
|
||||
pallet_message_queue::Event::<Test>::OverweightEnqueued {
|
||||
hash: hash_3.clone(),
|
||||
origin: Ump(UmpQueueId::Para(para_a)),
|
||||
page_index: 0,
|
||||
message_index: 2,
|
||||
}
|
||||
.into(),
|
||||
]
|
||||
.into_iter(),
|
||||
);
|
||||
assert_eq!(Processed::take(), vec![(para_a, a_msg_1)]);
|
||||
|
||||
// Now verify that if we wanted to service this overweight message with less than enough
|
||||
// weight it will fail.
|
||||
assert_noop!(
|
||||
<MessageQueue as ServiceQueues>::execute_overweight(
|
||||
Weight::from_parts(500, 500),
|
||||
(Ump(UmpQueueId::Para(para_a)), 0, 2)
|
||||
),
|
||||
ExecuteOverweightError::InsufficientWeight,
|
||||
);
|
||||
|
||||
// ... and if we try to service it with just enough weight it will succeed as well.
|
||||
assert_ok!(<MessageQueue as ServiceQueues>::execute_overweight(
|
||||
Weight::from_parts(501, 501),
|
||||
(Ump(UmpQueueId::Para(para_a)), 0, 2)
|
||||
));
|
||||
assert_last_event(
|
||||
pallet_message_queue::Event::<Test>::Processed {
|
||||
hash: hash_3,
|
||||
origin: Ump(UmpQueueId::Para(para_a)),
|
||||
weight_used: Weight::from_parts(501, 501),
|
||||
success: true,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
|
||||
// ... and if we try to service a message with index that doesn't exist it will error
|
||||
// out.
|
||||
assert_noop!(
|
||||
<MessageQueue as ServiceQueues>::execute_overweight(
|
||||
Weight::from_parts(501, 501),
|
||||
(Ump(UmpQueueId::Para(para_a)), 0, 2)
|
||||
),
|
||||
ExecuteOverweightError::NotFound,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Tests that UMP messages in the dispatch queue of the relay prevents the parachain from being
|
||||
/// scheduled for offboarding.
|
||||
#[test]
|
||||
fn cannot_offboard_while_ump_dispatch_queued() {
|
||||
let para = 32.into();
|
||||
let msg = (300u32, "something").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
register_parachain(para);
|
||||
run_to_block(5, vec![4, 5]);
|
||||
|
||||
queue_upward_msg(para, msg.clone());
|
||||
queue_upward_msg(para, msg.clone());
|
||||
// Cannot offboard since there are two UMP messages in the queue.
|
||||
for i in 6..10 {
|
||||
assert!(try_deregister_parachain(para).is_err());
|
||||
run_to_block(i, vec![i]);
|
||||
assert!(Paras::is_valid_para(para));
|
||||
}
|
||||
|
||||
// Now let's process the first message.
|
||||
MessageQueue::on_initialize(System::block_number());
|
||||
assert_eq!(Processed::take().len(), 1);
|
||||
// Cannot offboard since there is another one in the queue.
|
||||
assert!(try_deregister_parachain(para).is_err());
|
||||
// Now also process the second message ...
|
||||
MessageQueue::on_initialize(System::block_number());
|
||||
assert_eq!(Processed::take().len(), 1);
|
||||
|
||||
// ... and offboard.
|
||||
run_to_block(10, vec![10]);
|
||||
assert!(Paras::is_valid_para(para));
|
||||
assert_ok!(try_deregister_parachain(para));
|
||||
assert!(Paras::is_offboarding(para));
|
||||
|
||||
// Offboarding completed.
|
||||
run_to_block(11, vec![11]);
|
||||
assert!(!Paras::is_valid_para(para));
|
||||
});
|
||||
}
|
||||
|
||||
/// A para-chain cannot send an UMP to the relay chain while it is offboarding.
|
||||
#[test]
|
||||
fn cannot_enqueue_ump_while_offboarding() {
|
||||
let para = 32.into();
|
||||
let msg = (300u32, "something").encode();
|
||||
|
||||
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
|
||||
register_parachain(para);
|
||||
run_to_block(5, vec![4, 5]);
|
||||
|
||||
// Start with an offboarding para.
|
||||
assert_ok!(try_deregister_parachain(para));
|
||||
assert!(Paras::is_offboarding(para));
|
||||
|
||||
// Cannot enqueue a message.
|
||||
assert!(try_queue_upward_msg(para, msg.clone()).is_err());
|
||||
run_to_block(6, vec![6]);
|
||||
// Para is still there and still cannot enqueue a message.
|
||||
assert!(Paras::is_offboarding(para));
|
||||
assert!(try_queue_upward_msg(para, msg.clone()).is_err());
|
||||
// Now offboarding is completed.
|
||||
run_to_block(7, vec![7]);
|
||||
assert!(!Paras::is_valid_para(para));
|
||||
});
|
||||
}
|
||||
@@ -56,6 +56,7 @@ pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -154,6 +155,7 @@ std = [
|
||||
"pallet-im-online/std",
|
||||
"pallet-indices/std",
|
||||
"pallet-membership/std",
|
||||
"pallet-message-queue/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-nomination-pools/std",
|
||||
"pallet-nomination-pools-runtime-api/std",
|
||||
@@ -214,6 +216,7 @@ runtime-benchmarks = [
|
||||
"pallet-im-online/runtime-benchmarks",
|
||||
"pallet-indices/runtime-benchmarks",
|
||||
"pallet-membership/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-multisig/runtime-benchmarks",
|
||||
"pallet-nomination-pools/runtime-benchmarks",
|
||||
"pallet-nomination-pools-benchmarking/runtime-benchmarks",
|
||||
@@ -262,6 +265,7 @@ try-runtime = [
|
||||
"pallet-im-online/try-runtime",
|
||||
"pallet-indices/try-runtime",
|
||||
"pallet-membership/try-runtime",
|
||||
"pallet-message-queue/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-nomination-pools/try-runtime",
|
||||
"pallet-offences/try-runtime",
|
||||
|
||||
@@ -28,12 +28,14 @@ use runtime_common::{
|
||||
|
||||
use runtime_parachains::{
|
||||
configuration as parachains_configuration, disputes as parachains_disputes,
|
||||
disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp,
|
||||
inclusion as parachains_inclusion, initializer as parachains_initializer,
|
||||
origin as parachains_origin, paras as parachains_paras,
|
||||
disputes::slashing as parachains_slashing,
|
||||
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl, scheduler as parachains_scheduler,
|
||||
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl,
|
||||
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
||||
shared as parachains_shared,
|
||||
};
|
||||
|
||||
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
||||
@@ -43,9 +45,9 @@ use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{
|
||||
ConstU32, EitherOf, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, LockIdentifier,
|
||||
PrivilegeCmp, WithdrawReasons,
|
||||
PrivilegeCmp, ProcessMessage, ProcessMessageError, WithdrawReasons,
|
||||
},
|
||||
weights::ConstantMultiplier,
|
||||
weights::{ConstantMultiplier, WeightMeter},
|
||||
PalletId, RuntimeDebug,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -80,6 +82,7 @@ use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
use static_assertions::const_assert;
|
||||
use xcm::latest::Junction;
|
||||
|
||||
pub use frame_system::Call as SystemCall;
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
@@ -1098,6 +1101,8 @@ impl parachains_inclusion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = ParasDisputes;
|
||||
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints<Runtime>;
|
||||
type MessageQueue = MessageQueue;
|
||||
type WeightInfo = weights::runtime_parachains_inclusion::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -1108,20 +1113,55 @@ impl parachains_paras::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = weights::runtime_parachains_paras::WeightInfo<Runtime>;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = Babe;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
|
||||
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * BlockWeights::get().max_block;
|
||||
pub const MessageQueueHeapSize: u32 = 65_536;
|
||||
pub const MessageQueueMaxStale: u32 = 8;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink =
|
||||
crate::parachains_ump::XcmSink<xcm_executor::XcmExecutor<xcm_config::XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = weights::runtime_parachains_ump::WeightInfo<Self>;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type MessageProcessor = MessageProcessor;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type MessageProcessor =
|
||||
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
||||
type QueueChangeHandler = ParaInclusion;
|
||||
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_dmp::Config for Runtime {}
|
||||
@@ -1386,7 +1426,7 @@ construct_runtime! {
|
||||
Paras: parachains_paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned} = 56,
|
||||
Initializer: parachains_initializer::{Pallet, Call, Storage} = 57,
|
||||
Dmp: parachains_dmp::{Pallet, Storage} = 58,
|
||||
Ump: parachains_ump::{Pallet, Call, Storage, Event} = 59,
|
||||
// Ump 59
|
||||
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>, Config} = 60,
|
||||
ParaSessionInfo: parachains_session_info::{Pallet, Storage} = 61,
|
||||
ParasDisputes: parachains_disputes::{Pallet, Call, Storage, Event<T>} = 62,
|
||||
@@ -1400,6 +1440,9 @@ construct_runtime! {
|
||||
|
||||
// Pallet for sending XCM.
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 99,
|
||||
|
||||
// Generalized message queue
|
||||
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 100,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,7 +1496,8 @@ pub mod migrations {
|
||||
|
||||
pub type V0938 = (
|
||||
pallet_xcm::migration::v1::MigrateToV1<Runtime>,
|
||||
parachains_ump::migration::v1::MigrateToV1<Runtime>,
|
||||
// The UMP pallet got deleted in <https://github.com/paritytech/polkadot/pull/6271>
|
||||
// parachains_ump::migration::v1::MigrateToV1<Runtime>,
|
||||
);
|
||||
|
||||
pub type V0940 = (
|
||||
@@ -1471,7 +1515,12 @@ pub mod migrations {
|
||||
);
|
||||
|
||||
/// Unreleased migrations. Add new ones here:
|
||||
pub type Unreleased = SetStorageVersions;
|
||||
pub type Unreleased = (
|
||||
SetStorageVersions,
|
||||
// Remove UMP dispatch queue <https://github.com/paritytech/polkadot/pull/6271>
|
||||
parachains_configuration::migration::v6::MigrateToV6<Runtime>,
|
||||
ump_migrations::UpdateUmpLimits,
|
||||
);
|
||||
|
||||
/// Migrations that set `StorageVersion`s we missed to set.
|
||||
pub struct SetStorageVersions;
|
||||
@@ -1496,6 +1545,24 @@ pub mod migrations {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helpers to configure all migrations.
|
||||
pub mod ump_migrations {
|
||||
use runtime_parachains::configuration::migration_ump;
|
||||
|
||||
pub const MAX_UPWARD_QUEUE_SIZE: u32 = 1 * 1024 * 1024;
|
||||
pub const MAX_UPWARD_QUEUE_COUNT: u32 = 174762;
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE: u32 = (1 << 16) - 5; // Checked in test `max_upward_message_size`.
|
||||
pub const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32 = 16;
|
||||
|
||||
pub type UpdateUmpLimits = migration_ump::latest::ScheduleConfigUpdate<
|
||||
super::Runtime,
|
||||
MAX_UPWARD_QUEUE_SIZE,
|
||||
MAX_UPWARD_QUEUE_COUNT,
|
||||
MAX_UPWARD_MESSAGE_SIZE,
|
||||
MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE,
|
||||
>;
|
||||
}
|
||||
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic =
|
||||
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
|
||||
@@ -1512,13 +1579,9 @@ pub type Executive = frame_executive::Executive<
|
||||
/// The payload being signed in transactions.
|
||||
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
#[macro_use]
|
||||
extern crate frame_benchmarking;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benches {
|
||||
define_benchmarks!(
|
||||
frame_benchmarking::define_benchmarks!(
|
||||
// Polkadot
|
||||
// NOTE: Make sure to prefix these with `runtime_common::` so
|
||||
// the that path resolves correctly in the generated file.
|
||||
@@ -1531,10 +1594,10 @@ mod benches {
|
||||
[runtime_parachains::disputes, ParasDisputes]
|
||||
[runtime_parachains::disputes::slashing, ParasSlashing]
|
||||
[runtime_parachains::hrmp, Hrmp]
|
||||
[runtime_parachains::inclusion, ParaInclusion]
|
||||
[runtime_parachains::initializer, Initializer]
|
||||
[runtime_parachains::paras, Paras]
|
||||
[runtime_parachains::paras_inherent, ParaInherent]
|
||||
[runtime_parachains::ump, Ump]
|
||||
// Substrate
|
||||
[pallet_bags_list, VoterList]
|
||||
[pallet_balances, Balances]
|
||||
@@ -1552,6 +1615,7 @@ mod benches {
|
||||
[pallet_im_online, ImOnline]
|
||||
[pallet_indices, Indices]
|
||||
[pallet_membership, TechnicalMembership]
|
||||
[pallet_message_queue, MessageQueue]
|
||||
[pallet_multisig, Multisig]
|
||||
[pallet_nomination_pools, NominationPoolsBench::<Runtime>]
|
||||
[pallet_offences, OffencesBench::<Runtime>]
|
||||
@@ -2258,6 +2322,14 @@ mod test {
|
||||
If the limit is too strong, maybe consider increase the limit",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_upward_message_size() {
|
||||
assert_eq!(
|
||||
ump_migrations::MAX_UPWARD_MESSAGE_SIZE,
|
||||
pallet_message_queue::MaxMessageLenOf::<Runtime>::get()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -32,6 +32,7 @@ pub mod pallet_identity;
|
||||
pub mod pallet_im_online;
|
||||
pub mod pallet_indices;
|
||||
pub mod pallet_membership;
|
||||
pub mod pallet_message_queue;
|
||||
pub mod pallet_multisig;
|
||||
pub mod pallet_nomination_pools;
|
||||
pub mod pallet_preimage;
|
||||
@@ -56,7 +57,7 @@ pub mod runtime_parachains_configuration;
|
||||
pub mod runtime_parachains_disputes;
|
||||
pub mod runtime_parachains_disputes_slashing;
|
||||
pub mod runtime_parachains_hrmp;
|
||||
pub mod runtime_parachains_inclusion;
|
||||
pub mod runtime_parachains_initializer;
|
||||
pub mod runtime_parachains_paras;
|
||||
pub mod runtime_parachains_paras_inherent;
|
||||
pub mod runtime_parachains_ump;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `pallet_message_queue`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet-message-queue
|
||||
// --extrinsic=*
|
||||
// --heap-pages=4096
|
||||
// --header=file_header.txt
|
||||
// --output
|
||||
// runtime/polkadot/src/weights/pallet_message_queue.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `pallet_message_queue`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> pallet_message_queue::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:0)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn ready_ring_knit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_631 nanoseconds.
|
||||
Weight::from_parts(6_182_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
fn ready_ring_unknit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_515 nanoseconds.
|
||||
Weight::from_parts(5_775_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn service_queue_base() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `576`
|
||||
// Estimated: `2527`
|
||||
// Minimum execution time: 2_098 nanoseconds.
|
||||
Weight::from_parts(2_265_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 2527))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_194 nanoseconds.
|
||||
Weight::from_parts(3_436_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_no_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_409 nanoseconds.
|
||||
Weight::from_parts(3_673_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
fn service_page_item() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `971`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 49_243 nanoseconds.
|
||||
Weight::from_parts(50_380_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
}
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn bump_service_head() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `712`
|
||||
// Estimated: `3027`
|
||||
// Minimum execution time: 3_744 nanoseconds.
|
||||
Weight::from_parts(3_922_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3027))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn reap_page() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66859`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 28_995 nanoseconds.
|
||||
Weight::from_parts(30_370_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_removed() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66859`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 76_268 nanoseconds.
|
||||
Weight::from_parts(77_933_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_updated() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66859`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 78_029 nanoseconds.
|
||||
Weight::from_parts(80_632_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `runtime_parachains::inclusion`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=polkadot-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::inclusion
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/polkadot/src/weights
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::inclusion`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::inclusion::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:999)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
/// The range of component `i` is `[1, 1000]`.
|
||||
fn receive_upward_messages(i: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `51490`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 50_423 nanoseconds.
|
||||
Weight::from_parts(160_584_092, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
// Standard Error: 75_127
|
||||
.saturating_add(Weight::from_parts(41_929_458, 0).saturating_mul(i.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into())))
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::ump`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=polkadot-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::ump
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/polkadot/src/weights/runtime_parachains_ump.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::ump`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::ump::WeightInfo for WeightInfo<T> {
|
||||
/// The range of component `s` is `[0, 51200]`.
|
||||
fn process_upward_message(s: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 5_941_000 picoseconds.
|
||||
Weight::from_parts(6_024_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
// Standard Error: 8
|
||||
.saturating_add(Weight::from_parts(1_365, 0).saturating_mul(s.into()))
|
||||
}
|
||||
/// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
/// Proof Skipped: Ump NeedsDispatch (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
/// Proof Skipped: Ump NextDispatchRoundStartWith (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueues (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueueSize (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueueSize (max_values: None, max_size: None, mode: Measured)
|
||||
fn clean_ump_after_outgoing() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `240`
|
||||
// Estimated: `1725`
|
||||
// Minimum execution time: 9_387_000 picoseconds.
|
||||
Weight::from_parts(9_538_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1725))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: Ump Overweight (r:1 w:1)
|
||||
/// Proof Skipped: Ump Overweight (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump CounterForOverweight (r:1 w:1)
|
||||
/// Proof: Ump CounterForOverweight (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
|
||||
fn service_overweight() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `257`
|
||||
// Estimated: `3722`
|
||||
// Minimum execution time: 23_382_000 picoseconds.
|
||||
Weight::from_parts(23_808_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3722))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-nis = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -140,6 +141,7 @@ std = [
|
||||
"pallet-im-online/std",
|
||||
"pallet-indices/std",
|
||||
"pallet-membership/std",
|
||||
"pallet-message-queue/std",
|
||||
"pallet-mmr/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-offences/std",
|
||||
@@ -199,6 +201,7 @@ runtime-benchmarks = [
|
||||
"pallet-im-online/runtime-benchmarks",
|
||||
"pallet-indices/runtime-benchmarks",
|
||||
"pallet-membership/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-multisig/runtime-benchmarks",
|
||||
"pallet-preimage/runtime-benchmarks",
|
||||
"pallet-proxy/runtime-benchmarks",
|
||||
@@ -239,6 +242,7 @@ try-runtime = [
|
||||
"pallet-im-online/try-runtime",
|
||||
"pallet-indices/try-runtime",
|
||||
"pallet-membership/try-runtime",
|
||||
"pallet-message-queue/try-runtime",
|
||||
"pallet-mmr/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-nis/try-runtime",
|
||||
|
||||
@@ -39,12 +39,14 @@ use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
|
||||
|
||||
use runtime_parachains::{
|
||||
configuration as parachains_configuration, disputes as parachains_disputes,
|
||||
disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp,
|
||||
inclusion as parachains_inclusion, initializer as parachains_initializer,
|
||||
origin as parachains_origin, paras as parachains_paras,
|
||||
disputes::slashing as parachains_slashing,
|
||||
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl, scheduler as parachains_scheduler,
|
||||
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl,
|
||||
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
||||
shared as parachains_shared,
|
||||
};
|
||||
|
||||
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
||||
@@ -57,9 +59,9 @@ use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{
|
||||
Contains, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, LockIdentifier,
|
||||
PrivilegeCmp, StorageMapShim, WithdrawReasons,
|
||||
PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim, WithdrawReasons,
|
||||
},
|
||||
weights::ConstantMultiplier,
|
||||
weights::{ConstantMultiplier, WeightMeter},
|
||||
PalletId, RuntimeDebug,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -83,6 +85,7 @@ use sp_staking::SessionIndex;
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
use static_assertions::const_assert;
|
||||
use xcm::latest::Junction;
|
||||
|
||||
pub use frame_system::Call as SystemCall;
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
@@ -1025,6 +1028,8 @@ impl parachains_inclusion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = ParasDisputes;
|
||||
type RewardValidators = RewardValidators;
|
||||
type MessageQueue = MessageQueue;
|
||||
type WeightInfo = weights::runtime_parachains_inclusion::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -1035,20 +1040,55 @@ impl parachains_paras::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = weights::runtime_parachains_paras::WeightInfo<Runtime>;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = Babe;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
|
||||
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * BlockWeights::get().max_block;
|
||||
pub const MessageQueueHeapSize: u32 = 32 * 1024;
|
||||
pub const MessageQueueMaxStale: u32 = 96;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink =
|
||||
crate::parachains_ump::XcmSink<xcm_executor::XcmExecutor<xcm_config::XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = weights::runtime_parachains_ump::WeightInfo<Runtime>;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type MessageProcessor = MessageProcessor;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type MessageProcessor =
|
||||
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
||||
type QueueChangeHandler = ParaInclusion;
|
||||
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_dmp::Config for Runtime {}
|
||||
@@ -1414,11 +1454,11 @@ construct_runtime! {
|
||||
Paras: parachains_paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned} = 56,
|
||||
Initializer: parachains_initializer::{Pallet, Call, Storage} = 57,
|
||||
Dmp: parachains_dmp::{Pallet, Storage} = 58,
|
||||
Ump: parachains_ump::{Pallet, Call, Storage, Event} = 59,
|
||||
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>, Config} = 60,
|
||||
ParaSessionInfo: parachains_session_info::{Pallet, Storage} = 61,
|
||||
ParasDisputes: parachains_disputes::{Pallet, Call, Storage, Event<T>} = 62,
|
||||
ParasSlashing: parachains_slashing::{Pallet, Call, Storage, ValidateUnsigned} = 63,
|
||||
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 64,
|
||||
|
||||
// Parachain Onboarding Pallets. Start indices at 70 to leave room.
|
||||
Registrar: paras_registrar::{Pallet, Call, Storage, Event<T>, Config} = 70,
|
||||
@@ -1495,7 +1535,29 @@ pub mod migrations {
|
||||
);
|
||||
|
||||
/// Unreleased migrations. Add new ones here:
|
||||
pub type Unreleased = ();
|
||||
pub type Unreleased = (
|
||||
// Remove UMP dispatch queue <https://github.com/paritytech/polkadot/pull/6271>
|
||||
parachains_configuration::migration::v6::MigrateToV6<Runtime>,
|
||||
ump_migrations::UpdateUmpLimits,
|
||||
);
|
||||
}
|
||||
|
||||
/// Helpers to configure all migrations.
|
||||
pub mod ump_migrations {
|
||||
use runtime_parachains::configuration::migration_ump;
|
||||
|
||||
pub const MAX_UPWARD_QUEUE_SIZE: u32 = 8 * 1024 * 1024;
|
||||
pub const MAX_UPWARD_QUEUE_COUNT: u32 = 1398101;
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE: u32 = (1 << 15) - 5; // Checked in test `max_upward_message_size`.
|
||||
pub const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32 = 1024;
|
||||
|
||||
pub type UpdateUmpLimits = migration_ump::latest::ScheduleConfigUpdate<
|
||||
super::Runtime,
|
||||
MAX_UPWARD_QUEUE_SIZE,
|
||||
MAX_UPWARD_QUEUE_COUNT,
|
||||
MAX_UPWARD_MESSAGE_SIZE,
|
||||
MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE,
|
||||
>;
|
||||
}
|
||||
|
||||
/// Executive: handles dispatch to the various modules.
|
||||
@@ -1535,13 +1597,9 @@ frame_support::ord_parameter_types! {
|
||||
pub const MigController: AccountId = AccountId::from(hex_literal::hex!("52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
#[macro_use]
|
||||
extern crate frame_benchmarking;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benches {
|
||||
define_benchmarks!(
|
||||
frame_benchmarking::define_benchmarks!(
|
||||
// Polkadot
|
||||
// NOTE: Make sure to prefix these with `runtime_common::` so
|
||||
// the that path resolves correctly in the generated file.
|
||||
@@ -1553,10 +1611,10 @@ mod benches {
|
||||
[runtime_parachains::configuration, Configuration]
|
||||
[runtime_parachains::hrmp, Hrmp]
|
||||
[runtime_parachains::disputes, ParasDisputes]
|
||||
[runtime_parachains::inclusion, ParaInclusion]
|
||||
[runtime_parachains::initializer, Initializer]
|
||||
[runtime_parachains::paras_inherent, ParaInherent]
|
||||
[runtime_parachains::paras, Paras]
|
||||
[runtime_parachains::ump, Ump]
|
||||
// Substrate
|
||||
[pallet_balances, Balances]
|
||||
[pallet_balances, NisCounterpartBalances]
|
||||
@@ -1572,6 +1630,7 @@ mod benches {
|
||||
[pallet_im_online, ImOnline]
|
||||
[pallet_indices, Indices]
|
||||
[pallet_membership, TechnicalMembership]
|
||||
[pallet_message_queue, MessageQueue]
|
||||
[pallet_multisig, Multisig]
|
||||
[pallet_preimage, Preimage]
|
||||
[pallet_proxy, Proxy]
|
||||
@@ -2164,6 +2223,20 @@ mod encoding_tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn max_upward_message_size() {
|
||||
use sp_core::Get;
|
||||
assert_eq!(
|
||||
ump_migrations::MAX_UPWARD_MESSAGE_SIZE,
|
||||
pallet_message_queue::MaxMessageLenOf::<Runtime>::get()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "try-runtime"))]
|
||||
mod remote_tests {
|
||||
use super::*;
|
||||
|
||||
@@ -28,6 +28,7 @@ pub mod pallet_identity;
|
||||
pub mod pallet_im_online;
|
||||
pub mod pallet_indices;
|
||||
pub mod pallet_membership;
|
||||
pub mod pallet_message_queue;
|
||||
pub mod pallet_multisig;
|
||||
pub mod pallet_nis;
|
||||
pub mod pallet_preimage;
|
||||
@@ -49,8 +50,8 @@ pub mod runtime_common_slots;
|
||||
pub mod runtime_parachains_configuration;
|
||||
pub mod runtime_parachains_disputes;
|
||||
pub mod runtime_parachains_hrmp;
|
||||
pub mod runtime_parachains_inclusion;
|
||||
pub mod runtime_parachains_initializer;
|
||||
pub mod runtime_parachains_paras;
|
||||
pub mod runtime_parachains_paras_inherent;
|
||||
pub mod runtime_parachains_ump;
|
||||
pub mod xcm;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `pallet_message_queue`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=rococo-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet-message-queue
|
||||
// --extrinsic=*
|
||||
// --heap-pages=4096
|
||||
// --header=file_header.txt
|
||||
// --output
|
||||
// runtime/rococo/src/weights/pallet_message_queue.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `pallet_message_queue`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> pallet_message_queue::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:0)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn ready_ring_knit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 9_427 nanoseconds.
|
||||
Weight::from_parts(9_806_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
fn ready_ring_unknit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `837`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 20_178 nanoseconds.
|
||||
Weight::from_parts(20_550_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn service_queue_base() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `576`
|
||||
// Estimated: `2527`
|
||||
// Minimum execution time: 3_746 nanoseconds.
|
||||
Weight::from_parts(3_885_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 2527))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 4_906 nanoseconds.
|
||||
Weight::from_parts(5_060_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_no_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `648`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 5_194 nanoseconds.
|
||||
Weight::from_parts(5_361_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
fn service_page_item() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `936`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 62_021 nanoseconds.
|
||||
Weight::from_parts(62_487_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
}
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn bump_service_head() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `712`
|
||||
// Estimated: `3027`
|
||||
// Minimum execution time: 6_989 nanoseconds.
|
||||
Weight::from_parts(8_098_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3027))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn reap_page() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66846`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 38_177 nanoseconds.
|
||||
Weight::from_parts(44_704_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_removed() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66846`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 48_404 nanoseconds.
|
||||
Weight::from_parts(55_066_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_updated() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66846`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 66_523 nanoseconds.
|
||||
Weight::from_parts(73_063_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `runtime_parachains::inclusion`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=rococo-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::inclusion
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/rococo/src/weights
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::inclusion`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::inclusion::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:999)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
/// The range of component `i` is `[1, 1000]`.
|
||||
fn receive_upward_messages(i: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `51490`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 48_782 nanoseconds.
|
||||
Weight::from_parts(49_384_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
// Standard Error: 32_635
|
||||
.saturating_add(Weight::from_parts(43_384_796, 0).saturating_mul(i.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into())))
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::ump`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=rococo-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::ump
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/rococo/src/weights/runtime_parachains_ump.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::ump`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::ump::WeightInfo for WeightInfo<T> {
|
||||
/// The range of component `s` is `[0, 51200]`.
|
||||
fn process_upward_message(s: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 6_036_000 picoseconds.
|
||||
Weight::from_parts(6_133_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
// Standard Error: 8
|
||||
.saturating_add(Weight::from_parts(1_360, 0).saturating_mul(s.into()))
|
||||
}
|
||||
/// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
/// Proof Skipped: Ump NeedsDispatch (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
/// Proof Skipped: Ump NextDispatchRoundStartWith (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueues (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueueSize (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueueSize (max_values: None, max_size: None, mode: Measured)
|
||||
fn clean_ump_after_outgoing() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `202`
|
||||
// Estimated: `1687`
|
||||
// Minimum execution time: 8_630_000 picoseconds.
|
||||
Weight::from_parts(8_883_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1687))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: Ump Overweight (r:1 w:1)
|
||||
/// Proof Skipped: Ump Overweight (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump CounterForOverweight (r:1 w:1)
|
||||
/// Proof: Ump CounterForOverweight (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
|
||||
fn service_overweight() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `219`
|
||||
// Estimated: `3684`
|
||||
// Minimum execution time: 22_583_000 picoseconds.
|
||||
Weight::from_parts(22_844_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3684))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ use polkadot_runtime_parachains::{
|
||||
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent, runtime_api_impl::v4 as runtime_impl,
|
||||
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
||||
shared as parachains_shared, ump as parachains_ump,
|
||||
shared as parachains_shared,
|
||||
};
|
||||
|
||||
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
||||
@@ -477,6 +477,8 @@ impl parachains_inclusion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = ParasDisputes;
|
||||
type RewardValidators = RewardValidatorsWithEraPoints<Runtime>;
|
||||
type MessageQueue = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl parachains_disputes::Config for Runtime {
|
||||
@@ -508,6 +510,7 @@ impl parachains_paras::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = parachains_paras::TestWeightInfo;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = Babe;
|
||||
}
|
||||
|
||||
@@ -517,14 +520,6 @@ parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink = ();
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
|
||||
type WeightInfo = parachains_ump::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl parachains_hrmp::Config for Runtime {
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
@@ -672,7 +667,6 @@ construct_runtime! {
|
||||
ParasOrigin: parachains_origin::{Pallet, Origin},
|
||||
ParaSessionInfo: parachains_session_info::{Pallet, Storage},
|
||||
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>},
|
||||
Ump: parachains_ump::{Pallet, Call, Storage, Event},
|
||||
Dmp: parachains_dmp::{Pallet, Storage},
|
||||
Xcm: pallet_xcm::{Pallet, Call, Event<T>, Origin},
|
||||
ParasDisputes: parachains_disputes::{Pallet, Storage, Event<T>},
|
||||
|
||||
@@ -54,6 +54,7 @@ pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-offences = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -144,6 +145,7 @@ std = [
|
||||
"pallet-im-online/std",
|
||||
"pallet-indices/std",
|
||||
"pallet-membership/std",
|
||||
"pallet-message-queue/std",
|
||||
"beefy-primitives/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-nomination-pools/std",
|
||||
@@ -206,6 +208,8 @@ runtime-benchmarks = [
|
||||
"pallet-identity/runtime-benchmarks",
|
||||
"pallet-im-online/runtime-benchmarks",
|
||||
"pallet-indices/runtime-benchmarks",
|
||||
"pallet-membership/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-multisig/runtime-benchmarks",
|
||||
"pallet-nomination-pools-benchmarking/runtime-benchmarks",
|
||||
"pallet-preimage/runtime-benchmarks",
|
||||
@@ -249,6 +253,7 @@ try-runtime = [
|
||||
"pallet-im-online/try-runtime",
|
||||
"pallet-indices/try-runtime",
|
||||
"pallet-membership/try-runtime",
|
||||
"pallet-message-queue/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-nomination-pools/try-runtime",
|
||||
"pallet-offences/try-runtime",
|
||||
|
||||
@@ -25,8 +25,11 @@ use beefy_primitives::crypto::{AuthorityId as BeefyId, Signature as BeefySignatu
|
||||
use frame_election_provider_support::{onchain, SequentialPhragmen};
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{ConstU32, InstanceFilter, KeyOwnerProofSystem, WithdrawReasons},
|
||||
weights::ConstantMultiplier,
|
||||
traits::{
|
||||
ConstU32, InstanceFilter, KeyOwnerProofSystem, ProcessMessage, ProcessMessageError,
|
||||
WithdrawReasons,
|
||||
},
|
||||
weights::{ConstantMultiplier, WeightMeter},
|
||||
PalletId,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -50,12 +53,14 @@ use runtime_common::{
|
||||
};
|
||||
use runtime_parachains::{
|
||||
configuration as parachains_configuration, disputes as parachains_disputes,
|
||||
disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp,
|
||||
inclusion as parachains_inclusion, initializer as parachains_initializer,
|
||||
origin as parachains_origin, paras as parachains_paras,
|
||||
disputes::slashing as parachains_slashing,
|
||||
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
|
||||
paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl, scheduler as parachains_scheduler,
|
||||
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
|
||||
runtime_api_impl::v4 as parachains_runtime_api_impl,
|
||||
scheduler as parachains_scheduler, session_info as parachains_session_info,
|
||||
shared as parachains_shared,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_core::{OpaqueMetadata, RuntimeDebug};
|
||||
@@ -76,6 +81,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*};
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
use xcm::latest::Junction;
|
||||
|
||||
pub use frame_system::Call as SystemCall;
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
@@ -895,6 +901,8 @@ impl parachains_inclusion::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DisputesHandler = ParasDisputes;
|
||||
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints<Runtime>;
|
||||
type MessageQueue = MessageQueue;
|
||||
type WeightInfo = weights::runtime_parachains_inclusion::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -905,20 +913,55 @@ impl parachains_paras::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = weights::runtime_parachains_paras::WeightInfo<Runtime>;
|
||||
type UnsignedPriority = ParasUnsignedPriority;
|
||||
type QueueFootprinter = ParaInclusion;
|
||||
type NextSessionRotation = Babe;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
|
||||
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * BlockWeights::get().max_block;
|
||||
pub const MessageQueueHeapSize: u32 = 128 * 1024;
|
||||
pub const MessageQueueMaxStale: u32 = 48;
|
||||
}
|
||||
|
||||
impl parachains_ump::Config for Runtime {
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink =
|
||||
crate::parachains_ump::XcmSink<xcm_executor::XcmExecutor<xcm_config::XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = weights::runtime_parachains_ump::WeightInfo<Runtime>;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type MessageProcessor = MessageProcessor;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type MessageProcessor =
|
||||
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
||||
type QueueChangeHandler = ParaInclusion;
|
||||
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_dmp::Config for Runtime {}
|
||||
@@ -1162,7 +1205,7 @@ construct_runtime! {
|
||||
Paras: parachains_paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned} = 47,
|
||||
Initializer: parachains_initializer::{Pallet, Call, Storage} = 48,
|
||||
Dmp: parachains_dmp::{Pallet, Storage} = 49,
|
||||
Ump: parachains_ump::{Pallet, Call, Storage, Event} = 50,
|
||||
// RIP Ump 50
|
||||
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>, Config} = 51,
|
||||
ParaSessionInfo: parachains_session_info::{Pallet, Storage} = 52,
|
||||
ParasDisputes: parachains_disputes::{Pallet, Call, Storage, Event<T>} = 53,
|
||||
@@ -1178,6 +1221,9 @@ construct_runtime! {
|
||||
|
||||
// Pallet for sending XCM.
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 99,
|
||||
|
||||
// Generalized message queue
|
||||
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 100,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,7 +1283,29 @@ pub mod migrations {
|
||||
);
|
||||
|
||||
/// Unreleased migrations. Add new ones here:
|
||||
pub type Unreleased = ();
|
||||
pub type Unreleased = (
|
||||
// Remove UMP dispatch queue <https://github.com/paritytech/polkadot/pull/6271>
|
||||
parachains_configuration::migration::v6::MigrateToV6<Runtime>,
|
||||
ump_migrations::UpdateUmpLimits,
|
||||
);
|
||||
}
|
||||
|
||||
/// Helpers to configure all migrations.
|
||||
pub mod ump_migrations {
|
||||
use runtime_parachains::configuration::migration_ump;
|
||||
|
||||
pub const MAX_UPWARD_QUEUE_SIZE: u32 = 8 * 1024 * 1024;
|
||||
pub const MAX_UPWARD_QUEUE_COUNT: u32 = 1398101;
|
||||
pub const MAX_UPWARD_MESSAGE_SIZE: u32 = (1 << 17) - 5; // Checked in test `max_upward_message_size`.
|
||||
pub const MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE: u32 = 512;
|
||||
|
||||
pub type UpdateUmpLimits = migration_ump::latest::ScheduleConfigUpdate<
|
||||
super::Runtime,
|
||||
MAX_UPWARD_QUEUE_SIZE,
|
||||
MAX_UPWARD_QUEUE_COUNT,
|
||||
MAX_UPWARD_MESSAGE_SIZE,
|
||||
MAX_UPWARD_MESSAGE_NUM_PER_CANDIDATE,
|
||||
>;
|
||||
}
|
||||
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
@@ -1255,13 +1323,9 @@ pub type Executive = frame_executive::Executive<
|
||||
/// The payload being signed in transactions.
|
||||
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
#[macro_use]
|
||||
extern crate frame_benchmarking;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benches {
|
||||
define_benchmarks!(
|
||||
frame_benchmarking::define_benchmarks!(
|
||||
// Polkadot
|
||||
// NOTE: Make sure to prefix these with `runtime_common::` so
|
||||
// the that path resolves correctly in the generated file.
|
||||
@@ -1273,10 +1337,10 @@ mod benches {
|
||||
[runtime_parachains::disputes, ParasDisputes]
|
||||
[runtime_parachains::disputes::slashing, ParasSlashing]
|
||||
[runtime_parachains::hrmp, Hrmp]
|
||||
[runtime_parachains::inclusion, ParaInclusion]
|
||||
[runtime_parachains::initializer, Initializer]
|
||||
[runtime_parachains::paras, Paras]
|
||||
[runtime_parachains::paras_inherent, ParaInherent]
|
||||
[runtime_parachains::ump, Ump]
|
||||
// Substrate
|
||||
[pallet_bags_list, VoterList]
|
||||
[pallet_balances, Balances]
|
||||
@@ -1286,6 +1350,7 @@ mod benches {
|
||||
[pallet_identity, Identity]
|
||||
[pallet_im_online, ImOnline]
|
||||
[pallet_indices, Indices]
|
||||
[pallet_message_queue, MessageQueue]
|
||||
[pallet_multisig, Multisig]
|
||||
[pallet_nomination_pools, NominationPoolsBench::<Runtime>]
|
||||
[pallet_offences, OffencesBench::<Runtime>]
|
||||
@@ -1902,6 +1967,19 @@ sp_api::impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn max_upward_message_size() {
|
||||
assert_eq!(
|
||||
ump_migrations::MAX_UPWARD_MESSAGE_SIZE,
|
||||
pallet_message_queue::MaxMessageLenOf::<Runtime>::get()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "try-runtime"))]
|
||||
mod remote_tests {
|
||||
use super::*;
|
||||
|
||||
@@ -50,6 +50,14 @@ fn call_size() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_upward_message_size() {
|
||||
assert_eq!(
|
||||
ump_migrations::MAX_UPWARD_MESSAGE_SIZE,
|
||||
pallet_message_queue::MaxMessageLenOf::<Runtime>::get()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check_teleport_assets_weight() {
|
||||
// This test sanity checks that at least 50 teleports can exist in a block.
|
||||
|
||||
@@ -24,6 +24,7 @@ pub mod pallet_fast_unstake;
|
||||
pub mod pallet_identity;
|
||||
pub mod pallet_im_online;
|
||||
pub mod pallet_indices;
|
||||
pub mod pallet_message_queue;
|
||||
pub mod pallet_multisig;
|
||||
pub mod pallet_nomination_pools;
|
||||
pub mod pallet_preimage;
|
||||
@@ -44,8 +45,8 @@ pub mod runtime_parachains_configuration;
|
||||
pub mod runtime_parachains_disputes;
|
||||
pub mod runtime_parachains_disputes_slashing;
|
||||
pub mod runtime_parachains_hrmp;
|
||||
pub mod runtime_parachains_inclusion;
|
||||
pub mod runtime_parachains_initializer;
|
||||
pub mod runtime_parachains_paras;
|
||||
pub mod runtime_parachains_paras_inherent;
|
||||
pub mod runtime_parachains_ump;
|
||||
pub mod xcm;
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `pallet_message_queue`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=westend-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet-message-queue
|
||||
// --extrinsic=*
|
||||
// --heap-pages=4096
|
||||
// --header=file_header.txt
|
||||
// --output
|
||||
// runtime/westend/src/weights/pallet_message_queue.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `pallet_message_queue`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> pallet_message_queue::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:0)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn ready_ring_knit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `804`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_813 nanoseconds.
|
||||
Weight::from_parts(5_980_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:2 w:2)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
fn ready_ring_unknit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `804`
|
||||
// Estimated: `5554`
|
||||
// Minimum execution time: 5_742 nanoseconds.
|
||||
Weight::from_parts(5_986_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5554))
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn service_queue_base() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `543`
|
||||
// Estimated: `2527`
|
||||
// Minimum execution time: 2_118 nanoseconds.
|
||||
Weight::from_parts(2_206_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 2527))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `615`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_153 nanoseconds.
|
||||
Weight::from_parts(3_240_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn service_page_base_no_completion() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `615`
|
||||
// Estimated: `68060`
|
||||
// Minimum execution time: 3_191 nanoseconds.
|
||||
Weight::from_parts(3_289_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 68060))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
fn service_page_item() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `904`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 47_975 nanoseconds.
|
||||
Weight::from_parts(49_334_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
}
|
||||
/// Storage: MessageQueue ServiceHead (r:1 w:1)
|
||||
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:0)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
fn bump_service_head() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `679`
|
||||
// Estimated: `3027`
|
||||
// Minimum execution time: 3_725 nanoseconds.
|
||||
Weight::from_parts(4_074_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3027))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn reap_page() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66814`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 28_769 nanoseconds.
|
||||
Weight::from_parts(29_450_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_removed() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66814`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 74_422 nanoseconds.
|
||||
Weight::from_parts(78_637_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:1)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
fn execute_overweight_page_updated() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `66814`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 75_542 nanoseconds.
|
||||
Weight::from_parts(80_545_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
//! Autogenerated weights for `runtime_parachains::inclusion`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-02-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=westend-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::inclusion
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/westend/src/weights
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::inclusion`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::inclusion::WeightInfo for WeightInfo<T> {
|
||||
/// Storage: MessageQueue BookStateFor (r:1 w:1)
|
||||
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
|
||||
/// Storage: MessageQueue Pages (r:1 w:999)
|
||||
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
|
||||
/// The range of component `i` is `[1, 1000]`.
|
||||
fn receive_upward_messages(i: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `51490`
|
||||
// Estimated: `70587`
|
||||
// Minimum execution time: 49_053 nanoseconds.
|
||||
Weight::from_parts(49_506_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 70587))
|
||||
// Standard Error: 62_734
|
||||
.saturating_add(Weight::from_parts(43_511_974, 0).saturating_mul(i.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into())))
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `runtime_parachains::ump`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/polkadot
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=westend-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=runtime_parachains::ump
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/westend/src/weights/runtime_parachains_ump.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions for `runtime_parachains::ump`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_parachains::ump::WeightInfo for WeightInfo<T> {
|
||||
/// The range of component `s` is `[0, 51200]`.
|
||||
fn process_upward_message(s: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 6_172_000 picoseconds.
|
||||
Weight::from_parts(6_259_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 0))
|
||||
// Standard Error: 8
|
||||
.saturating_add(Weight::from_parts(1_359, 0).saturating_mul(s.into()))
|
||||
}
|
||||
/// Storage: Ump NeedsDispatch (r:1 w:1)
|
||||
/// Proof Skipped: Ump NeedsDispatch (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump NextDispatchRoundStartWith (r:1 w:1)
|
||||
/// Proof Skipped: Ump NextDispatchRoundStartWith (max_values: Some(1), max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueues (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueues (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump RelayDispatchQueueSize (r:0 w:1)
|
||||
/// Proof Skipped: Ump RelayDispatchQueueSize (max_values: None, max_size: None, mode: Measured)
|
||||
fn clean_ump_after_outgoing() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `206`
|
||||
// Estimated: `1691`
|
||||
// Minimum execution time: 9_533_000 picoseconds.
|
||||
Weight::from_parts(9_765_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1691))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: Ump Overweight (r:1 w:1)
|
||||
/// Proof Skipped: Ump Overweight (max_values: None, max_size: None, mode: Measured)
|
||||
/// Storage: Ump CounterForOverweight (r:1 w:1)
|
||||
/// Proof: Ump CounterForOverweight (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
|
||||
fn service_overweight() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `223`
|
||||
// Estimated: `3688`
|
||||
// Minimum execution time: 23_648_000 picoseconds.
|
||||
Weight::from_parts(23_848_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3688))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(2))
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage,
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::{AllowUnpaidExecutionFrom, MintLocation};
|
||||
@@ -206,7 +205,9 @@ impl xcm_balances_benchmark::Config for Test {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
use sp_runtime::BuildStorage;
|
||||
let t = GenesisConfig { ..Default::default() }.build_storage().unwrap();
|
||||
sp_tracing::try_init_simple();
|
||||
t.into()
|
||||
|
||||
@@ -27,7 +27,6 @@ use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
traits::{BlakeTwo256, IdentityLookup, TrailingZeroInput},
|
||||
BuildStorage,
|
||||
};
|
||||
use xcm_builder::{
|
||||
test_utils::{
|
||||
@@ -194,7 +193,9 @@ impl generic::Config for Test {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
use sp_runtime::BuildStorage;
|
||||
let t = GenesisConfig { ..Default::default() }.build_storage().unwrap();
|
||||
sp_tracing::try_init_simple();
|
||||
t.into()
|
||||
|
||||
@@ -15,6 +15,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d
|
||||
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -29,6 +30,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-xcm = { path = "../pallet-xcm" }
|
||||
polkadot-runtime-parachains = { path = "../../runtime/parachains" }
|
||||
assert_matches = "1.5.0"
|
||||
polkadot-test-runtime = { path = "../../runtime/test-runtime" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -46,6 +48,7 @@ std = [
|
||||
"sp-arithmetic/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-weights/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"polkadot-parachain/std",
|
||||
|
||||
@@ -54,6 +54,9 @@ pub use barriers::{
|
||||
RespectSuspension, TakeWeightCredit, WithComputedOrigin,
|
||||
};
|
||||
|
||||
mod process_xcm_message;
|
||||
pub use process_xcm_message::ProcessXcmMessage;
|
||||
|
||||
mod currency_adapter;
|
||||
pub use currency_adapter::CurrencyAdapter;
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Implementation of `ProcessMessage` for an `ExecuteXcm` implementation.
|
||||
|
||||
use frame_support::{
|
||||
ensure,
|
||||
traits::{ProcessMessage, ProcessMessageError},
|
||||
};
|
||||
use parity_scale_codec::{Decode, FullCodec, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_std::{fmt::Debug, marker::PhantomData};
|
||||
use sp_weights::{Weight, WeightMeter};
|
||||
use xcm::prelude::*;
|
||||
|
||||
/// A message processor that delegates execution to an [XcmExecutor].
|
||||
pub struct ProcessXcmMessage<MessageOrigin, XcmExecutor, Call>(
|
||||
PhantomData<(MessageOrigin, XcmExecutor, Call)>,
|
||||
);
|
||||
impl<
|
||||
MessageOrigin: Into<MultiLocation> + FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug,
|
||||
XcmExecutor: ExecuteXcm<Call>,
|
||||
Call,
|
||||
> ProcessMessage for ProcessXcmMessage<MessageOrigin, XcmExecutor, Call>
|
||||
{
|
||||
type Origin = MessageOrigin;
|
||||
|
||||
/// Process the given message, using no more than the remaining `weight` to do so.
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let hash = blake2_256(message);
|
||||
let versioned_message = VersionedXcm::<Call>::decode(&mut &message[..])
|
||||
.map_err(|_| ProcessMessageError::Corrupt)?;
|
||||
let message = Xcm::<Call>::try_from(versioned_message)
|
||||
.map_err(|_| ProcessMessageError::Unsupported)?;
|
||||
let pre = XcmExecutor::prepare(message).map_err(|_| ProcessMessageError::Unsupported)?;
|
||||
let required = pre.weight_of();
|
||||
ensure!(meter.can_accrue(required), ProcessMessageError::Overweight(required));
|
||||
|
||||
let (consumed, result) =
|
||||
match XcmExecutor::execute(origin.into(), pre, hash, Weight::zero()) {
|
||||
Outcome::Complete(w) => (w, Ok(true)),
|
||||
Outcome::Incomplete(w, _) => (w, Ok(false)),
|
||||
// In the error-case we assume the worst case and consume all possible weight.
|
||||
Outcome::Error(_) => (required, Err(ProcessMessageError::Unsupported)),
|
||||
};
|
||||
meter.defensive_saturating_accrue(consumed);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
assert_err, assert_ok,
|
||||
traits::{ProcessMessageError, ProcessMessageError::*},
|
||||
};
|
||||
use parity_scale_codec::Encode;
|
||||
use polkadot_test_runtime::*;
|
||||
use xcm::{v2, v3, VersionedXcm};
|
||||
|
||||
const ORIGIN: Junction = Junction::OnlyChild;
|
||||
/// The processor to use for tests.
|
||||
type Processor =
|
||||
ProcessXcmMessage<Junction, xcm_executor::XcmExecutor<xcm_config::XcmConfig>, RuntimeCall>;
|
||||
|
||||
#[test]
|
||||
fn process_message_trivial_works() {
|
||||
// ClearOrigin works.
|
||||
assert!(process(v2_xcm(true)).unwrap());
|
||||
assert!(process(v3_xcm(true)).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_message_trivial_fails() {
|
||||
// Trap makes it fail.
|
||||
assert!(!process(v3_xcm(false)).unwrap());
|
||||
assert!(!process(v3_xcm(false)).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_message_corrupted_fails() {
|
||||
let msgs: &[&[u8]] = &[&[], &[55, 66], &[123, 222, 233]];
|
||||
for msg in msgs {
|
||||
assert_err!(process_raw(msg), Corrupt);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_message_overweight_fails() {
|
||||
for msg in [v3_xcm(true), v3_xcm(false), v3_xcm(false), v2_xcm(false)] {
|
||||
let msg = &msg.encode()[..];
|
||||
|
||||
// Errors if we stay below a weight limit of 1000.
|
||||
for i in 0..10 {
|
||||
let meter = &mut WeightMeter::from_limit((i * 10).into());
|
||||
assert_err!(
|
||||
Processor::process_message(msg, ORIGIN, meter),
|
||||
Overweight(1000.into())
|
||||
);
|
||||
assert_eq!(meter.consumed, 0.into());
|
||||
}
|
||||
|
||||
// Works with a limit of 1000.
|
||||
let meter = &mut WeightMeter::from_limit(1000.into());
|
||||
assert_ok!(Processor::process_message(msg, ORIGIN, meter));
|
||||
assert_eq!(meter.consumed, 1000.into());
|
||||
}
|
||||
}
|
||||
|
||||
fn v2_xcm(success: bool) -> VersionedXcm<RuntimeCall> {
|
||||
let instr = if success {
|
||||
v3::Instruction::<RuntimeCall>::ClearOrigin
|
||||
} else {
|
||||
v3::Instruction::<RuntimeCall>::Trap(1)
|
||||
};
|
||||
VersionedXcm::V3(v3::Xcm::<RuntimeCall>(vec![instr]))
|
||||
}
|
||||
|
||||
fn v3_xcm(success: bool) -> VersionedXcm<RuntimeCall> {
|
||||
let instr = if success {
|
||||
v2::Instruction::<RuntimeCall>::ClearOrigin
|
||||
} else {
|
||||
v2::Instruction::<RuntimeCall>::Trap(1)
|
||||
};
|
||||
VersionedXcm::V2(v2::Xcm::<RuntimeCall>(vec![instr]))
|
||||
}
|
||||
|
||||
fn process(msg: VersionedXcm<RuntimeCall>) -> Result<bool, ProcessMessageError> {
|
||||
process_raw(msg.encode().as_slice())
|
||||
}
|
||||
|
||||
fn process_raw(raw: &[u8]) -> Result<bool, ProcessMessageError> {
|
||||
Processor::process_message(raw, ORIGIN, &mut WeightMeter::max_limit())
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
xcm = { path = "../" }
|
||||
xcm-executor = { path = "../xcm-executor" }
|
||||
xcm-builder = { path = "../xcm-builder" }
|
||||
polkadot-core-primitives = { path = "../../core-primitives"}
|
||||
polkadot-parachain = { path = "../../parachain" }
|
||||
polkadot-runtime-parachains = { path = "../../runtime/parachains" }
|
||||
|
||||
@@ -13,6 +13,7 @@ log = { version = "0.4.14", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-uniques = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
@@ -35,6 +36,7 @@ runtime-benchmarks = [
|
||||
"frame-system/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"pallet-balances/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"pallet-uniques/runtime-benchmarks",
|
||||
"pallet-xcm/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
|
||||
@@ -20,7 +20,7 @@ mod relay_chain;
|
||||
use frame_support::sp_tracing;
|
||||
use xcm::prelude::*;
|
||||
use xcm_executor::traits::Convert;
|
||||
use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain};
|
||||
use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt};
|
||||
|
||||
pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]);
|
||||
pub const INITIAL_BALANCE: u128 = 1_000_000_000;
|
||||
@@ -46,7 +46,11 @@ decl_test_parachain! {
|
||||
decl_test_relay_chain! {
|
||||
pub struct Relay {
|
||||
Runtime = relay_chain::Runtime,
|
||||
RuntimeCall = relay_chain::RuntimeCall,
|
||||
RuntimeEvent = relay_chain::RuntimeEvent,
|
||||
XcmConfig = relay_chain::XcmConfig,
|
||||
MessageQueue = relay_chain::MessageQueue,
|
||||
System = relay_chain::System,
|
||||
new_ext = relay_ext(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{AsEnsureOriginWithArg, Everything, Nothing},
|
||||
weights::Weight,
|
||||
traits::{AsEnsureOriginWithArg, Everything, Nothing, ProcessMessage, ProcessMessageError},
|
||||
weights::{Weight, WeightMeter},
|
||||
};
|
||||
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -27,7 +27,11 @@ use sp_core::{ConstU32, H256};
|
||||
use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32};
|
||||
|
||||
use polkadot_parachain::primitives::Id as ParaId;
|
||||
use polkadot_runtime_parachains::{configuration, origin, shared, ump};
|
||||
use polkadot_runtime_parachains::{
|
||||
configuration,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
origin, shared,
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::{
|
||||
Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex,
|
||||
@@ -232,19 +236,50 @@ parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
}
|
||||
|
||||
impl ump::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink = ump::XcmSink<XcmExecutor<XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
|
||||
type WeightInfo = ump::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl origin::Config for Runtime {}
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
|
||||
type Block = frame_system::mocking::MockBlock<Runtime>;
|
||||
|
||||
parameter_types! {
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000);
|
||||
pub const MessageQueueHeapSize: u32 = 65_536;
|
||||
pub const MessageQueueMaxStale: u32 = 16;
|
||||
}
|
||||
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
type MessageProcessor = MessageProcessor;
|
||||
type QueueChangeHandler = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
@@ -254,8 +289,8 @@ construct_runtime!(
|
||||
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
ParasOrigin: origin::{Pallet, Origin},
|
||||
ParasUmp: ump::{Pallet, Call, Storage, Event},
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin},
|
||||
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>},
|
||||
MessageQueue: pallet_message_queue::{Pallet, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@ scale-info = { version = "2.5.0", features = ["derive"] }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
@@ -31,6 +32,7 @@ polkadot-parachain = { path = "../../../parachain" }
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"pallet-xcm/runtime-benchmarks",
|
||||
"pallet-message-queue/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
]
|
||||
|
||||
@@ -60,7 +60,11 @@ decl_test_parachain! {
|
||||
decl_test_relay_chain! {
|
||||
pub struct Relay {
|
||||
Runtime = relay_chain::Runtime,
|
||||
RuntimeCall = relay_chain::RuntimeCall,
|
||||
RuntimeEvent = relay_chain::RuntimeEvent,
|
||||
XcmConfig = relay_chain::XcmConfig,
|
||||
MessageQueue = relay_chain::MessageQueue,
|
||||
System = relay_chain::System,
|
||||
new_ext = relay_ext(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{Everything, Nothing},
|
||||
weights::Weight,
|
||||
traits::{Everything, Nothing, ProcessMessage, ProcessMessageError},
|
||||
weights::{Weight, WeightMeter},
|
||||
};
|
||||
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -27,7 +27,11 @@ use sp_core::{ConstU32, H256};
|
||||
use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32};
|
||||
|
||||
use polkadot_parachain::primitives::Id as ParaId;
|
||||
use polkadot_runtime_parachains::{configuration, origin, shared, ump};
|
||||
use polkadot_runtime_parachains::{
|
||||
configuration,
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
origin, shared,
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::{
|
||||
AccountId32Aliases, AllowUnpaidExecutionFrom, ChildParachainAsNative,
|
||||
@@ -122,7 +126,7 @@ type LocalOriginConverter = (
|
||||
parameter_types! {
|
||||
pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000);
|
||||
pub KsmPerSecondPerByte: (AssetId, u128, u128) = (Concrete(TokenLocation::get()), 1, 1);
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
pub const MaxInstructions: u32 = u32::MAX;
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
}
|
||||
|
||||
@@ -196,19 +200,54 @@ parameter_types! {
|
||||
pub const FirstMessageFactorPercent: u64 = 100;
|
||||
}
|
||||
|
||||
impl ump::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UmpSink = ump::XcmSink<XcmExecutor<XcmConfig>, Runtime>;
|
||||
type FirstMessageFactorPercent = FirstMessageFactorPercent;
|
||||
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
|
||||
type WeightInfo = ump::TestWeightInfo;
|
||||
}
|
||||
|
||||
impl origin::Config for Runtime {}
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
|
||||
type Block = frame_system::mocking::MockBlock<Runtime>;
|
||||
|
||||
parameter_types! {
|
||||
/// Amount of weight that can be spent per block to service messages.
|
||||
pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000);
|
||||
pub const MessageQueueHeapSize: u32 = 65_536;
|
||||
pub const MessageQueueMaxStale: u32 = 16;
|
||||
}
|
||||
|
||||
/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet.
|
||||
pub struct MessageProcessor;
|
||||
impl ProcessMessage for MessageProcessor {
|
||||
type Origin = AggregateMessageOrigin;
|
||||
|
||||
fn process_message(
|
||||
message: &[u8],
|
||||
origin: Self::Origin,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<bool, ProcessMessageError> {
|
||||
let para = match origin {
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para,
|
||||
};
|
||||
xcm_builder::ProcessXcmMessage::<
|
||||
Junction,
|
||||
xcm_executor::XcmExecutor<XcmConfig>,
|
||||
RuntimeCall,
|
||||
>::process_message(message, Junction::Parachain(para.into()), meter)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_message_queue::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Size = u32;
|
||||
type HeapSize = MessageQueueHeapSize;
|
||||
type MaxStale = MessageQueueMaxStale;
|
||||
type ServiceWeight = MessageQueueServiceWeight;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type MessageProcessor = MessageProcessor;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type MessageProcessor =
|
||||
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
|
||||
type QueueChangeHandler = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
@@ -218,7 +257,7 @@ construct_runtime!(
|
||||
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
ParasOrigin: origin::{Pallet, Origin},
|
||||
ParasUmp: ump::{Pallet, Call, Storage, Event},
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin},
|
||||
MessageQueue: pallet_message_queue::{Pallet, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
pub use codec::Encode;
|
||||
pub use paste;
|
||||
|
||||
pub use frame_support::{traits::Get, weights::Weight};
|
||||
pub use frame_support::{
|
||||
traits::{EnqueueMessage, Get, ProcessMessage, ProcessMessageError, ServiceQueues},
|
||||
weights::{Weight, WeightMeter},
|
||||
};
|
||||
pub use sp_io::{hashing::blake2_256, TestExternalities};
|
||||
pub use sp_std::{cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData};
|
||||
|
||||
@@ -30,9 +33,10 @@ pub use polkadot_parachain::primitives::{
|
||||
};
|
||||
pub use polkadot_runtime_parachains::{
|
||||
dmp,
|
||||
ump::{self, MessageId, UmpSink, XcmSink},
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
};
|
||||
pub use xcm::{latest::prelude::*, VersionedXcm};
|
||||
pub use xcm_builder::ProcessXcmMessage;
|
||||
pub use xcm_executor::XcmExecutor;
|
||||
|
||||
pub trait TestExt {
|
||||
@@ -100,7 +104,11 @@ macro_rules! decl_test_relay_chain {
|
||||
(
|
||||
pub struct $name:ident {
|
||||
Runtime = $runtime:path,
|
||||
RuntimeCall = $runtime_call:path,
|
||||
RuntimeEvent = $runtime_event:path,
|
||||
XcmConfig = $xcm_config:path,
|
||||
MessageQueue = $mq:path,
|
||||
System = $system:path,
|
||||
new_ext = $new_ext:expr,
|
||||
}
|
||||
) => {
|
||||
@@ -108,18 +116,37 @@ macro_rules! decl_test_relay_chain {
|
||||
|
||||
$crate::__impl_ext!($name, $new_ext);
|
||||
|
||||
impl $crate::UmpSink for $name {
|
||||
fn process_upward_message(
|
||||
origin: $crate::ParaId,
|
||||
impl $crate::ProcessMessage for $name {
|
||||
type Origin = $crate::ParaId;
|
||||
|
||||
fn process_message(
|
||||
msg: &[u8],
|
||||
max_weight: $crate::Weight,
|
||||
) -> Result<$crate::Weight, ($crate::MessageId, $crate::Weight)> {
|
||||
use $crate::{ump::UmpSink, TestExt};
|
||||
para: Self::Origin,
|
||||
meter: &mut $crate::WeightMeter,
|
||||
) -> Result<bool, $crate::ProcessMessageError> {
|
||||
use $crate::{Weight, AggregateMessageOrigin, UmpQueueId, ServiceQueues, EnqueueMessage};
|
||||
use $mq as message_queue;
|
||||
use $runtime_event as runtime_event;
|
||||
|
||||
Self::execute_with(|| {
|
||||
$crate::ump::XcmSink::<$crate::XcmExecutor<$xcm_config>, $runtime>::process_upward_message(
|
||||
origin, msg, max_weight,
|
||||
)
|
||||
<$mq as EnqueueMessage<AggregateMessageOrigin>>::enqueue_message(
|
||||
msg.try_into().expect("Message too long"),
|
||||
AggregateMessageOrigin::Ump(UmpQueueId::Para(para.clone()))
|
||||
);
|
||||
|
||||
<$system>::reset_events();
|
||||
<$mq as ServiceQueues>::service_queues(Weight::MAX);
|
||||
let events = <$system>::events();
|
||||
let event = events.last().expect("There must be at least one event");
|
||||
|
||||
match &event.event {
|
||||
runtime_event::MessageQueue(
|
||||
pallet_message_queue::Event::Processed {origin, ..}) => {
|
||||
assert_eq!(origin, &AggregateMessageOrigin::Ump(UmpQueueId::Para(para)));
|
||||
},
|
||||
event => panic!("Unexpected event: {:#?}", event),
|
||||
}
|
||||
Ok(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -286,19 +313,23 @@ macro_rules! decl_test_network {
|
||||
|
||||
/// Process all messages originating from parachains.
|
||||
fn process_para_messages() -> $crate::XcmResult {
|
||||
use $crate::{UmpSink, XcmpMessageHandlerT};
|
||||
use $crate::{ProcessMessage, XcmpMessageHandlerT};
|
||||
|
||||
while let Some((para_id, destination, message)) = $crate::PARA_MESSAGE_BUS.with(
|
||||
|b| b.borrow_mut().pop_front()) {
|
||||
match destination.interior() {
|
||||
$crate::Junctions::Here if destination.parent_count() == 1 => {
|
||||
let encoded = $crate::encode_xcm(message, $crate::MessageKind::Ump);
|
||||
let r = <$relay_chain>::process_upward_message(
|
||||
para_id, &encoded[..],
|
||||
$crate::Weight::MAX,
|
||||
let r = <$relay_chain>::process_message(
|
||||
encoded.as_slice(), para_id,
|
||||
&mut $crate::WeightMeter::max_limit(),
|
||||
);
|
||||
if let Err((id, required)) = r {
|
||||
return Err($crate::XcmError::WeightLimitReached(required));
|
||||
match r {
|
||||
Err($crate::ProcessMessageError::Overweight(required)) =>
|
||||
return Err($crate::XcmError::WeightLimitReached(required)),
|
||||
// Not really the correct error, but there is no "undecodable".
|
||||
Err(_) => return Err($crate::XcmError::Unimplemented),
|
||||
Ok(_) => (),
|
||||
}
|
||||
},
|
||||
$(
|
||||
@@ -353,7 +384,7 @@ macro_rules! decl_test_network {
|
||||
destination: &mut Option<$crate::MultiLocation>,
|
||||
message: &mut Option<$crate::Xcm<()>>,
|
||||
) -> $crate::SendResult<($crate::ParaId, $crate::MultiLocation, $crate::Xcm<()>)> {
|
||||
use $crate::{UmpSink, XcmpMessageHandlerT};
|
||||
use $crate::XcmpMessageHandlerT;
|
||||
|
||||
let d = destination.take().ok_or($crate::SendError::MissingArgument)?;
|
||||
match (d.interior(), d.parent_count()) {
|
||||
|
||||
Reference in New Issue
Block a user