From 35bdba5a4338d1cd5c07cbce7aa60c3ef70308ff Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 11 Nov 2022 16:32:16 +0100 Subject: [PATCH] Migrate away from weights in host config --- Cargo.lock | 23 +- Cargo.toml | 244 ------ node/service/src/chain_spec.rs | 2 - roadmap/implementers-guide/src/runtime/ump.md | 32 +- .../implementers-guide/src/types/runtime.md | 5 - runtime/parachains/Cargo.toml | 1 + runtime/parachains/src/configuration.rs | 39 +- .../src/configuration/benchmarking.rs | 2 - .../parachains/src/configuration/migration.rs | 167 ++-- runtime/parachains/src/configuration/tests.rs | 12 - runtime/parachains/src/inclusion/mod.rs | 174 +++- runtime/parachains/src/initializer.rs | 7 +- runtime/parachains/src/lib.rs | 3 +- runtime/parachains/src/mock.rs | 107 ++- runtime/parachains/src/paras_inherent/mod.rs | 6 +- runtime/parachains/src/runtime_api_impl/v2.rs | 20 +- runtime/parachains/src/ump.rs | 761 ------------------ runtime/parachains/src/ump/benchmarking.rs | 5 +- runtime/parachains/src/ump/tests.rs | 187 +---- xcm/xcm-builder/src/lib.rs | 2 +- xcm/xcm-builder/src/process_xcm_message.rs | 42 +- 21 files changed, 371 insertions(+), 1470 deletions(-) delete mode 100644 runtime/parachains/src/ump.rs diff --git a/Cargo.lock b/Cargo.lock index 01f4b5f25fea..3b9fc541807c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5013,6 +5013,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-message-queue" +version = "0.9.29" +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" @@ -6990,6 +7008,7 @@ dependencies = [ "pallet-authorship", "pallet-babe", "pallet-balances", + "pallet-message-queue", "pallet-session", "pallet-staking", "pallet-timestamp", @@ -12698,10 +12717,6 @@ version = "3.0.0-dev" name = "pallet-lottery" version = "4.0.0-dev" -[[patch.unused]] -name = "pallet-message-queue" -version = "0.9.29" - [[patch.unused]] name = "pallet-nicks" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 72b539f4cd60..0ed0892593d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,250 +197,6 @@ try-runtime = [ "polkadot-cli/try-runtime" ] fast-runtime = [ "polkadot-cli/fast-runtime" ] runtime-metrics = [ "polkadot-cli/runtime-metrics" ] pyroscope = ["polkadot-cli/pyroscope"] -[patch."https://github.com/paritytech/substrate"] -node-template ={path = "/Users/gav/Core/substrate/bin/node-template/node" } -frame-benchmarking ={path = "/Users/gav/Core/substrate/frame/benchmarking" } -frame-support ={path = "/Users/gav/Core/substrate/frame/support" } -frame-support-procedural ={path = "/Users/gav/Core/substrate/frame/support/procedural" } -frame-support-procedural-tools ={path = "/Users/gav/Core/substrate/frame/support/procedural/tools" } -frame-support-procedural-tools-derive ={path = "/Users/gav/Core/substrate/frame/support/procedural/tools/derive" } -sp-api ={path = "/Users/gav/Core/substrate/primitives/api" } -sp-api-proc-macro ={path = "/Users/gav/Core/substrate/primitives/api/proc-macro" } -sp-core ={path = "/Users/gav/Core/substrate/primitives/core" } -sp-core-hashing ={path = "/Users/gav/Core/substrate/primitives/core/hashing" } -sp-std ={path = "/Users/gav/Core/substrate/primitives/std" } -sp-debug-derive ={path = "/Users/gav/Core/substrate/primitives/debug-derive" } -sp-externalities ={path = "/Users/gav/Core/substrate/primitives/externalities" } -sp-storage ={path = "/Users/gav/Core/substrate/primitives/storage" } -sp-runtime-interface ={path = "/Users/gav/Core/substrate/primitives/runtime-interface" } -sp-runtime-interface-proc-macro ={path = "/Users/gav/Core/substrate/primitives/runtime-interface/proc-macro" } -sp-tracing ={path = "/Users/gav/Core/substrate/primitives/tracing" } -sp-wasm-interface ={path = "/Users/gav/Core/substrate/primitives/wasm-interface" } -sp-io ={path = "/Users/gav/Core/substrate/primitives/io" } -sp-keystore ={path = "/Users/gav/Core/substrate/primitives/keystore" } -sp-state-machine ={path = "/Users/gav/Core/substrate/primitives/state-machine" } -sp-panic-handler ={path = "/Users/gav/Core/substrate/primitives/panic-handler" } -sp-trie ={path = "/Users/gav/Core/substrate/primitives/trie" } -sp-runtime ={path = "/Users/gav/Core/substrate/primitives/runtime" } -sp-application-crypto ={path = "/Users/gav/Core/substrate/primitives/application-crypto" } -sp-arithmetic ={path = "/Users/gav/Core/substrate/primitives/arithmetic" } -sp-weights ={path = "/Users/gav/Core/substrate/primitives/weights" } -substrate-test-runtime-client ={path = "/Users/gav/Core/substrate/test-utils/runtime/client" } -sc-block-builder ={path = "/Users/gav/Core/substrate/client/block-builder" } -sc-client-api ={path = "/Users/gav/Core/substrate/client/api" } -substrate-prometheus-endpoint ={path = "/Users/gav/Core/substrate/utils/prometheus" } -sc-executor ={path = "/Users/gav/Core/substrate/client/executor" } -sc-executor-common ={path = "/Users/gav/Core/substrate/client/executor/common" } -sc-allocator ={path = "/Users/gav/Core/substrate/client/allocator" } -sp-maybe-compressed-blob ={path = "/Users/gav/Core/substrate/primitives/maybe-compressed-blob" } -sp-sandbox ={path = "/Users/gav/Core/substrate/primitives/sandbox" } -sc-executor-wasmi ={path = "/Users/gav/Core/substrate/client/executor/wasmi" } -sc-executor-wasmtime ={path = "/Users/gav/Core/substrate/client/executor/wasmtime" } -sc-runtime-test ={path = "/Users/gav/Core/substrate/client/executor/runtime-test" } -sp-tasks ={path = "/Users/gav/Core/substrate/primitives/tasks" } -substrate-wasm-builder ={path = "/Users/gav/Core/substrate/utils/wasm-builder" } -sp-core-hashing-proc-macro ={path = "/Users/gav/Core/substrate/primitives/core/hashing/proc-macro" } -sp-version ={path = "/Users/gav/Core/substrate/primitives/version" } -sp-version-proc-macro ={path = "/Users/gav/Core/substrate/primitives/version/proc-macro" } -sc-tracing ={path = "/Users/gav/Core/substrate/client/tracing" } -sc-rpc-server ={path = "/Users/gav/Core/substrate/client/rpc-servers" } -sc-tracing-proc-macro ={path = "/Users/gav/Core/substrate/client/tracing/proc-macro" } -sp-blockchain ={path = "/Users/gav/Core/substrate/primitives/blockchain" } -sp-consensus ={path = "/Users/gav/Core/substrate/primitives/consensus/common" } -sp-inherents ={path = "/Users/gav/Core/substrate/primitives/inherents" } -sp-test-primitives ={path = "/Users/gav/Core/substrate/primitives/test-primitives" } -sp-database ={path = "/Users/gav/Core/substrate/primitives/database" } -sp-rpc ={path = "/Users/gav/Core/substrate/primitives/rpc" } -substrate-test-runtime ={path = "/Users/gav/Core/substrate/test-utils/runtime" } -beefy-merkle-tree ={path = "/Users/gav/Core/substrate/frame/beefy-mmr/primitives" } -beefy-primitives ={path = "/Users/gav/Core/substrate/primitives/beefy" } -sp-mmr-primitives ={path = "/Users/gav/Core/substrate/primitives/merkle-mountain-range" } -frame-system ={path = "/Users/gav/Core/substrate/frame/system" } -frame-system-rpc-runtime-api ={path = "/Users/gav/Core/substrate/frame/system/rpc/runtime-api" } -pallet-babe ={path = "/Users/gav/Core/substrate/frame/babe" } -pallet-authorship ={path = "/Users/gav/Core/substrate/frame/authorship" } -sp-authorship ={path = "/Users/gav/Core/substrate/primitives/authorship" } -pallet-session ={path = "/Users/gav/Core/substrate/frame/session" } -pallet-timestamp ={path = "/Users/gav/Core/substrate/frame/timestamp" } -sp-timestamp ={path = "/Users/gav/Core/substrate/primitives/timestamp" } -sp-session ={path = "/Users/gav/Core/substrate/primitives/session" } -sp-staking ={path = "/Users/gav/Core/substrate/primitives/staking" } -sp-consensus-babe ={path = "/Users/gav/Core/substrate/primitives/consensus/babe" } -sp-consensus-slots ={path = "/Users/gav/Core/substrate/primitives/consensus/slots" } -sp-consensus-vrf ={path = "/Users/gav/Core/substrate/primitives/consensus/vrf" } -frame-election-provider-support ={path = "/Users/gav/Core/substrate/frame/election-provider-support" } -frame-election-provider-solution-type ={path = "/Users/gav/Core/substrate/frame/election-provider-support/solution-type" } -sp-npos-elections ={path = "/Users/gav/Core/substrate/primitives/npos-elections" } -substrate-test-utils ={path = "/Users/gav/Core/substrate/test-utils" } -substrate-test-utils-derive ={path = "/Users/gav/Core/substrate/test-utils/derive" } -sc-service ={path = "/Users/gav/Core/substrate/client/service" } -sc-chain-spec ={path = "/Users/gav/Core/substrate/client/chain-spec" } -sc-chain-spec-derive ={path = "/Users/gav/Core/substrate/client/chain-spec/derive" } -sc-network-common ={path = "/Users/gav/Core/substrate/client/network/common" } -sc-consensus ={path = "/Users/gav/Core/substrate/client/consensus/common" } -sc-utils ={path = "/Users/gav/Core/substrate/client/utils" } -sc-peerset ={path = "/Users/gav/Core/substrate/client/peerset" } -sp-finality-grandpa ={path = "/Users/gav/Core/substrate/primitives/finality-grandpa" } -sc-telemetry ={path = "/Users/gav/Core/substrate/client/telemetry" } -sc-client-db ={path = "/Users/gav/Core/substrate/client/db" } -sc-state-db ={path = "/Users/gav/Core/substrate/client/state-db" } -kitchensink-runtime ={path = "/Users/gav/Core/substrate/bin/node/runtime" } -frame-executive ={path = "/Users/gav/Core/substrate/frame/executive" } -frame-try-runtime ={path = "/Users/gav/Core/substrate/frame/try-runtime" } -pallet-balances ={path = "/Users/gav/Core/substrate/frame/balances" } -pallet-transaction-payment ={path = "/Users/gav/Core/substrate/frame/transaction-payment" } -frame-system-benchmarking ={path = "/Users/gav/Core/substrate/frame/system/benchmarking" } -node-primitives ={path = "/Users/gav/Core/substrate/bin/node/primitives" } -pallet-alliance ={path = "/Users/gav/Core/substrate/frame/alliance" } -pallet-collective ={path = "/Users/gav/Core/substrate/frame/collective" } -pallet-identity ={path = "/Users/gav/Core/substrate/frame/identity" } -pallet-asset-tx-payment ={path = "/Users/gav/Core/substrate/frame/transaction-payment/asset-tx-payment" } -pallet-assets ={path = "/Users/gav/Core/substrate/frame/assets" } -pallet-authority-discovery ={path = "/Users/gav/Core/substrate/frame/authority-discovery" } -sp-authority-discovery ={path = "/Users/gav/Core/substrate/primitives/authority-discovery" } -pallet-bags-list ={path = "/Users/gav/Core/substrate/frame/bags-list" } -pallet-bounties ={path = "/Users/gav/Core/substrate/frame/bounties" } -pallet-treasury ={path = "/Users/gav/Core/substrate/frame/treasury" } -pallet-child-bounties ={path = "/Users/gav/Core/substrate/frame/child-bounties" } -pallet-contracts ={path = "/Users/gav/Core/substrate/frame/contracts" } -pallet-contracts-primitives ={path = "/Users/gav/Core/substrate/frame/contracts/primitives" } -pallet-contracts-proc-macro ={path = "/Users/gav/Core/substrate/frame/contracts/proc-macro" } -pallet-randomness-collective-flip ={path = "/Users/gav/Core/substrate/frame/randomness-collective-flip" } -pallet-utility ={path = "/Users/gav/Core/substrate/frame/utility" } -pallet-conviction-voting ={path = "/Users/gav/Core/substrate/frame/conviction-voting" } -pallet-scheduler ={path = "/Users/gav/Core/substrate/frame/scheduler" } -pallet-preimage ={path = "/Users/gav/Core/substrate/frame/preimage" } -pallet-democracy ={path = "/Users/gav/Core/substrate/frame/democracy" } -pallet-election-provider-multi-phase ={path = "/Users/gav/Core/substrate/frame/election-provider-multi-phase" } -pallet-election-provider-support-benchmarking ={path = "/Users/gav/Core/substrate/frame/election-provider-support/benchmarking" } -pallet-elections-phragmen ={path = "/Users/gav/Core/substrate/frame/elections-phragmen" } -pallet-fast-unstake ={path = "/Users/gav/Core/substrate/frame/fast-unstake" } -pallet-staking ={path = "/Users/gav/Core/substrate/frame/staking" } -pallet-staking-reward-curve ={path = "/Users/gav/Core/substrate/frame/staking/reward-curve" } -pallet-gilt ={path = "/Users/gav/Core/substrate/frame/gilt" } -pallet-grandpa ={path = "/Users/gav/Core/substrate/frame/grandpa" } -pallet-offences ={path = "/Users/gav/Core/substrate/frame/offences" } -sp-keyring ={path = "/Users/gav/Core/substrate/primitives/keyring" } -pallet-im-online ={path = "/Users/gav/Core/substrate/frame/im-online" } -pallet-indices ={path = "/Users/gav/Core/substrate/frame/indices" } -pallet-lottery ={path = "/Users/gav/Core/substrate/frame/lottery" } -frame-support-test ={path = "/Users/gav/Core/substrate/frame/support/test" } -frame-support-test-pallet ={path = "/Users/gav/Core/substrate/frame/support/test/pallet" } -pallet-membership ={path = "/Users/gav/Core/substrate/frame/membership" } -pallet-message-queue ={path = "/Users/gav/Core/substrate/frame/message-queue" } -pallet-mmr ={path = "/Users/gav/Core/substrate/frame/merkle-mountain-range" } -pallet-multisig ={path = "/Users/gav/Core/substrate/frame/multisig" } -pallet-nomination-pools ={path = "/Users/gav/Core/substrate/frame/nomination-pools" } -pallet-nomination-pools-benchmarking ={path = "/Users/gav/Core/substrate/frame/nomination-pools/benchmarking" } -pallet-nomination-pools-runtime-api ={path = "/Users/gav/Core/substrate/frame/nomination-pools/runtime-api" } -pallet-offences-benchmarking ={path = "/Users/gav/Core/substrate/frame/offences/benchmarking" } -pallet-proxy ={path = "/Users/gav/Core/substrate/frame/proxy" } -pallet-ranked-collective ={path = "/Users/gav/Core/substrate/frame/ranked-collective" } -pallet-recovery ={path = "/Users/gav/Core/substrate/frame/recovery" } -pallet-referenda ={path = "/Users/gav/Core/substrate/frame/referenda" } -pallet-remark ={path = "/Users/gav/Core/substrate/frame/remark" } -pallet-session-benchmarking ={path = "/Users/gav/Core/substrate/frame/session/benchmarking" } -pallet-society ={path = "/Users/gav/Core/substrate/frame/society" } -pallet-state-trie-migration ={path = "/Users/gav/Core/substrate/frame/state-trie-migration" } -remote-externalities ={path = "/Users/gav/Core/substrate/utils/frame/remote-externalities" } -substrate-rpc-client ={path = "/Users/gav/Core/substrate/utils/frame/rpc/client" } -sc-rpc-api ={path = "/Users/gav/Core/substrate/client/rpc-api" } -sc-transaction-pool-api ={path = "/Users/gav/Core/substrate/client/transaction-pool/api" } -substrate-state-trie-migration-rpc ={path = "/Users/gav/Core/substrate/utils/frame/rpc/state-trie-migration-rpc" } -pallet-sudo ={path = "/Users/gav/Core/substrate/frame/sudo" } -pallet-tips ={path = "/Users/gav/Core/substrate/frame/tips" } -pallet-transaction-payment-rpc-runtime-api ={path = "/Users/gav/Core/substrate/frame/transaction-payment/rpc/runtime-api" } -pallet-transaction-storage ={path = "/Users/gav/Core/substrate/frame/transaction-storage" } -sp-transaction-storage-proof ={path = "/Users/gav/Core/substrate/primitives/transaction-storage-proof" } -pallet-uniques ={path = "/Users/gav/Core/substrate/frame/uniques" } -pallet-vesting ={path = "/Users/gav/Core/substrate/frame/vesting" } -pallet-whitelist ={path = "/Users/gav/Core/substrate/frame/whitelist" } -sp-block-builder ={path = "/Users/gav/Core/substrate/primitives/block-builder" } -sp-offchain ={path = "/Users/gav/Core/substrate/primitives/offchain" } -sp-transaction-pool ={path = "/Users/gav/Core/substrate/primitives/transaction-pool" } -sc-informant ={path = "/Users/gav/Core/substrate/client/informant" } -sc-keystore ={path = "/Users/gav/Core/substrate/client/keystore" } -sc-network ={path = "/Users/gav/Core/substrate/client/network" } -fork-tree ={path = "/Users/gav/Core/substrate/utils/fork-tree" } -sc-network-light ={path = "/Users/gav/Core/substrate/client/network/light" } -sc-network-sync ={path = "/Users/gav/Core/substrate/client/network/sync" } -sc-network-bitswap ={path = "/Users/gav/Core/substrate/client/network/bitswap" } -sc-network-transactions ={path = "/Users/gav/Core/substrate/client/network/transactions" } -sc-offchain ={path = "/Users/gav/Core/substrate/client/offchain" } -sc-transaction-pool ={path = "/Users/gav/Core/substrate/client/transaction-pool" } -substrate-test-runtime-transaction-pool ={path = "/Users/gav/Core/substrate/test-utils/runtime/transaction-pool" } -sc-rpc ={path = "/Users/gav/Core/substrate/client/rpc" } -sc-rpc-spec-v2 ={path = "/Users/gav/Core/substrate/client/rpc-spec-v2" } -sc-sysinfo ={path = "/Users/gav/Core/substrate/client/sysinfo" } -sp-consensus-aura ={path = "/Users/gav/Core/substrate/primitives/consensus/aura" } -substrate-test-client ={path = "/Users/gav/Core/substrate/test-utils/client" } -sp-runtime-interface-test-wasm ={path = "/Users/gav/Core/substrate/primitives/runtime-interface/test-wasm" } -sp-serializer ={path = "/Users/gav/Core/substrate/primitives/serializer" } -frame-benchmarking-cli ={path = "/Users/gav/Core/substrate/utils/frame/benchmarking-cli" } -sc-cli ={path = "/Users/gav/Core/substrate/client/cli" } -node-template-runtime ={path = "/Users/gav/Core/substrate/bin/node-template/runtime" } -pallet-aura ={path = "/Users/gav/Core/substrate/frame/aura" } -pallet-template ={path = "/Users/gav/Core/substrate/bin/node-template/pallets/template" } -pallet-transaction-payment-rpc ={path = "/Users/gav/Core/substrate/frame/transaction-payment/rpc" } -sc-basic-authorship ={path = "/Users/gav/Core/substrate/client/basic-authorship" } -sc-proposer-metrics ={path = "/Users/gav/Core/substrate/client/proposer-metrics" } -sc-consensus-aura ={path = "/Users/gav/Core/substrate/client/consensus/aura" } -sc-consensus-slots ={path = "/Users/gav/Core/substrate/client/consensus/slots" } -sc-network-test ={path = "/Users/gav/Core/substrate/client/network/test" } -sc-finality-grandpa ={path = "/Users/gav/Core/substrate/client/finality-grandpa" } -sc-network-gossip ={path = "/Users/gav/Core/substrate/client/network-gossip" } -substrate-frame-rpc-system ={path = "/Users/gav/Core/substrate/utils/frame/rpc/system" } -try-runtime-cli ={path = "/Users/gav/Core/substrate/utils/frame/try-runtime/cli" } -substrate-build-script-utils ={path = "/Users/gav/Core/substrate/utils/build-script-utils" } -node-bench ={path = "/Users/gav/Core/substrate/bin/node/bench" } -node-testing ={path = "/Users/gav/Core/substrate/bin/node/testing" } -node-executor ={path = "/Users/gav/Core/substrate/bin/node/executor" } -node-cli ={path = "/Users/gav/Core/substrate/bin/node/cli" } -node-inspect ={path = "/Users/gav/Core/substrate/bin/node/inspect" } -node-rpc ={path = "/Users/gav/Core/substrate/bin/node/rpc" } -pallet-mmr-rpc ={path = "/Users/gav/Core/substrate/frame/merkle-mountain-range/rpc" } -sc-consensus-babe ={path = "/Users/gav/Core/substrate/client/consensus/babe" } -sc-consensus-epochs ={path = "/Users/gav/Core/substrate/client/consensus/epochs" } -sc-consensus-babe-rpc ={path = "/Users/gav/Core/substrate/client/consensus/babe/rpc" } -sc-finality-grandpa-rpc ={path = "/Users/gav/Core/substrate/client/finality-grandpa/rpc" } -sc-sync-state-rpc ={path = "/Users/gav/Core/substrate/client/sync-state-rpc" } -sc-authority-discovery ={path = "/Users/gav/Core/substrate/client/authority-discovery" } -sc-consensus-uncles ={path = "/Users/gav/Core/substrate/client/consensus/uncles" } -sc-service-test ={path = "/Users/gav/Core/substrate/client/service/test" } -substrate-frame-cli ={path = "/Users/gav/Core/substrate/utils/frame/frame-utilities-cli" } -chain-spec-builder ={path = "/Users/gav/Core/substrate/bin/utils/chain-spec-builder" } -subkey ={path = "/Users/gav/Core/substrate/bin/utils/subkey" } -beefy-gadget ={path = "/Users/gav/Core/substrate/client/beefy" } -beefy-gadget-rpc ={path = "/Users/gav/Core/substrate/client/beefy/rpc" } -sc-consensus-manual-seal ={path = "/Users/gav/Core/substrate/client/consensus/manual-seal" } -sc-consensus-pow ={path = "/Users/gav/Core/substrate/client/consensus/pow" } -sp-consensus-pow ={path = "/Users/gav/Core/substrate/primitives/consensus/pow" } -pallet-atomic-swap ={path = "/Users/gav/Core/substrate/frame/atomic-swap" } -pallet-bags-list-fuzzer ={path = "/Users/gav/Core/substrate/frame/bags-list/fuzzer" } -pallet-bags-list-remote-tests ={path = "/Users/gav/Core/substrate/frame/bags-list/remote-tests" } -pallet-beefy ={path = "/Users/gav/Core/substrate/frame/beefy" } -pallet-beefy-mmr ={path = "/Users/gav/Core/substrate/frame/beefy-mmr" } -frame-election-solution-type-fuzzer ={path = "/Users/gav/Core/substrate/frame/election-provider-support/solution-type/fuzzer" } -pallet-example-basic ={path = "/Users/gav/Core/substrate/frame/examples/basic" } -pallet-example-offchain-worker ={path = "/Users/gav/Core/substrate/frame/examples/offchain-worker" } -pallet-example-parallel ={path = "/Users/gav/Core/substrate/frame/examples/parallel" } -pallet-nicks ={path = "/Users/gav/Core/substrate/frame/nicks" } -pallet-node-authorization ={path = "/Users/gav/Core/substrate/frame/node-authorization" } -pallet-nomination-pools-test-staking ={path = "/Users/gav/Core/substrate/frame/nomination-pools/test-staking" } -pallet-scored-pool ={path = "/Users/gav/Core/substrate/frame/scored-pool" } -pallet-staking-reward-fn ={path = "/Users/gav/Core/substrate/frame/staking/reward-fn" } -pallet-root-offences ={path = "/Users/gav/Core/substrate/frame/root-offences" } -frame-support-test-compile-pass ={path = "/Users/gav/Core/substrate/frame/support/test/compile_pass" } -sp-api-test ={path = "/Users/gav/Core/substrate/primitives/api/test" } -sp-application-crypto-test ={path = "/Users/gav/Core/substrate/primitives/application-crypto/test" } -sp-arithmetic-fuzzer ={path = "/Users/gav/Core/substrate/primitives/arithmetic/fuzzer" } -sp-npos-elections-fuzzer ={path = "/Users/gav/Core/substrate/primitives/npos-elections/fuzzer" } -sp-runtime-interface-test ={path = "/Users/gav/Core/substrate/primitives/runtime-interface/test" } -sp-runtime-interface-test-wasm-deprecated ={path = "/Users/gav/Core/substrate/primitives/runtime-interface/test-wasm-deprecated" } -substrate-test-utils-test-crate ={path = "/Users/gav/Core/substrate/test-utils/test-crate" } -substrate-frame-rpc-support ={path = "/Users/gav/Core/substrate/utils/frame/rpc/support" } -generate-bags ={path = "/Users/gav/Core/substrate/utils/frame/generate-bags" } -node-runtime-generate-bags ={path = "/Users/gav/Core/substrate/utils/frame/generate-bags/node-runtime" } # Configuration for building a .deb package - for use with `cargo-deb` [package.metadata.deb] diff --git a/node/service/src/chain_spec.rs b/node/service/src/chain_spec.rs index e2c0a7bfdf94..b8080641771a 100644 --- a/node/service/src/chain_spec.rs +++ b/node/service/src/chain_spec.rs @@ -190,8 +190,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_ref_time(100_000_000_000) - .set_proof_size(MAX_POV_SIZE as u64), max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, diff --git a/roadmap/implementers-guide/src/runtime/ump.md b/roadmap/implementers-guide/src/runtime/ump.md index 79e06e5ed0af..0d5109ec165a 100644 --- a/roadmap/implementers-guide/src/runtime/ump.md +++ b/roadmap/implementers-guide/src/runtime/ump.md @@ -52,36 +52,18 @@ Candidate Acceptance Function: * `check_upward_messages(P: ParaId, Vec`): 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 + 1. Verify that queuing up the messages could not result in exceeding the queue's footprint + according to the config items. 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)`: 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. + 1. Place in the dispatch queue according to its para ID (or handle it immediately). ## 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. +1. Nothing specific needs to be done, however the channel's dispatch queue may possibly be "swept" +which would prevent the dispatch queue from automatically being serviced. This is a consideration +for the chain and specific behaviour is not defined. diff --git a/roadmap/implementers-guide/src/types/runtime.md b/roadmap/implementers-guide/src/types/runtime.md index d3d00d5163b3..74e9f6ad575b 100644 --- a/roadmap/implementers-guide/src/types/runtime.md +++ b/roadmap/implementers-guide/src/types/runtime.md @@ -65,11 +65,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`. diff --git a/runtime/parachains/Cargo.toml b/runtime/parachains/Cargo.toml index 3f34566013e6..44a8bc7f1bcf 100644 --- a/runtime/parachains/Cargo.toml +++ b/runtime/parachains/Cargo.toml @@ -57,6 +57,7 @@ test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../pri sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } thousands = "0.2.0" assert_matches = "1" +pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs index 2ebaff1b8282..719da3b9b9e7 100644 --- a/runtime/parachains/src/configuration.rs +++ b/runtime/parachains/src/configuration.rs @@ -19,7 +19,7 @@ //! Configuration can change only at session boundaries and is buffered until then. use crate::shared; -use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_PER_MILLIS}; +use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use parity_scale_codec::{Decode, Encode}; use primitives::v2::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE}; @@ -126,11 +126,6 @@ pub struct HostConfiguration { /// 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. @@ -210,9 +205,6 @@ pub struct HostConfiguration { 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 @@ -272,7 +264,6 @@ impl> Default for HostConfiguration> Default for HostConfiguration 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, }) @@ -858,18 +847,6 @@ pub mod pallet { }) } - /// Sets the soft limit for the phase of dispatching dispatchable upward messages. - #[pallet::weight(( - T::WeightInfo::set_config_with_weight(), - DispatchClass::Operational, - ))] - pub fn set_ump_service_total_weight(origin: OriginFor, 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::weight(( T::WeightInfo::set_config_with_u32(), @@ -1044,18 +1021,6 @@ pub mod pallet { }) } - /// Sets the maximum amount of weight any individual upward message may consume. - #[pallet::weight(( - T::WeightInfo::set_config_with_weight(), - DispatchClass::Operational, - ))] - pub fn set_ump_max_individual_weight(origin: OriginFor, 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::weight(( // Using u32 here is a little bit of cheating, but that should be fine. diff --git a/runtime/parachains/src/configuration/benchmarking.rs b/runtime/parachains/src/configuration/benchmarking.rs index 71e0c03e696b..4e2813bafeeb 100644 --- a/runtime/parachains/src/configuration/benchmarking.rs +++ b/runtime/parachains/src/configuration/benchmarking.rs @@ -26,8 +26,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_ref_time(3_000_000)) - set_hrmp_open_request_ttl {}: { Err(BenchmarkError::Override( BenchmarkResult::from_weight(T::BlockWeights::get().max_block) diff --git a/runtime/parachains/src/configuration/migration.rs b/runtime/parachains/src/configuration/migration.rs index d87c98f6ae78..d02f01fff796 100644 --- a/runtime/parachains/src/configuration/migration.rs +++ b/runtime/parachains/src/configuration/migration.rs @@ -16,12 +16,8 @@ //! A module that is responsible for migration of storage. -use crate::configuration::{self, Config, Pallet, Store, MAX_POV_SIZE}; -use frame_support::{ - pallet_prelude::*, - traits::StorageVersion, - weights::{OldWeight, Weight}, -}; +use crate::configuration::{self, Config, Pallet, Store}; +use frame_support::{pallet_prelude::*, traits::StorageVersion, weights::Weight}; use frame_system::pallet_prelude::BlockNumberFor; /// The current storage version. @@ -29,15 +25,16 @@ use frame_system::pallet_prelude::BlockNumberFor; /// v0-v1: /// v1-v2: /// v2-v3: -pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(3); +/// v3-v4: (remove weights) +pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); -pub mod v3 { +pub mod v4 { use super::*; use frame_support::traits::OnRuntimeUpgrade; use primitives::v2::{Balance, SessionIndex}; // Copied over from configuration.rs @ de9e147695b9f1be8bd44e07861a31e483c8343a and removed - // all the comments, and changed the Weight struct to OldWeight + // all the comments, and changed the Weight struct to Weight #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug)] pub struct OldHostConfiguration { pub max_code_size: u32, @@ -51,7 +48,7 @@ pub mod v3 { pub validation_upgrade_delay: BlockNumber, pub max_pov_size: u32, pub max_downward_message_size: u32, - pub ump_service_total_weight: OldWeight, + 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, @@ -79,7 +76,7 @@ pub mod v3 { pub zeroth_delay_tranche_width: u32, pub needed_approvals: u32, pub relay_vrf_modulo_samples: u32, - pub ump_max_individual_weight: OldWeight, + pub ump_max_individual_weight: Weight, pub pvf_checking_enabled: bool, pub pvf_voting_ttl: SessionIndex, pub minimum_validation_upgrade_delay: BlockNumber, @@ -114,7 +111,7 @@ pub mod v3 { max_upward_queue_count: Default::default(), max_upward_queue_size: Default::default(), max_downward_message_size: Default::default(), - ump_service_total_weight: OldWeight(Default::default()), + ump_service_total_weight: Weight::zero(), max_upward_message_size: Default::default(), max_upward_message_num_per_candidate: Default::default(), hrmp_sender_deposit: Default::default(), @@ -127,9 +124,7 @@ pub mod v3 { 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: OldWeight( - frame_support::weights::constants::WEIGHT_PER_MILLIS.ref_time() * 20, - ), + ump_max_individual_weight: Weight::zero(), pvf_checking_enabled: false, pvf_voting_ttl: 2u32.into(), minimum_validation_upgrade_delay: 2.into(), @@ -137,32 +132,32 @@ pub mod v3 { } } - pub struct MigrateToV3(sp_std::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV3 { + pub struct MigrateToV4(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV4 { fn on_runtime_upgrade() -> Weight { - if StorageVersion::get::>() == 2 { - let weight_consumed = migrate_to_v3::(); + if StorageVersion::get::>() == 3 { + let weight_consumed = migrate_to_v4::(); - log::info!(target: configuration::LOG_TARGET, "MigrateToV3 executed successfully"); + log::info!(target: configuration::LOG_TARGET, "MigrateToV4 executed successfully"); STORAGE_VERSION.put::>(); weight_consumed } else { - log::warn!(target: configuration::LOG_TARGET, "MigrateToV3 should be removed."); + log::warn!(target: configuration::LOG_TARGET, "MigrateToV4 should be removed."); T::DbWeight::get().reads(1) } } } } -fn migrate_to_v3() -> Weight { +fn migrate_to_v4() -> 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: v3::OldHostConfiguration>| -> + |pre: v4::OldHostConfiguration>| -> configuration::HostConfiguration> { super::HostConfiguration { @@ -207,9 +202,6 @@ 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, - -ump_service_total_weight: Weight::from_ref_time(pre.ump_service_total_weight.0).set_proof_size(MAX_POV_SIZE as u64), -ump_max_individual_weight: Weight::from_ref_time(pre.ump_max_individual_weight.0).set_proof_size(MAX_POV_SIZE as u64), } }; @@ -234,31 +226,31 @@ mod tests { use crate::mock::{new_test_ext, Test}; #[test] - fn v2_deserialized_from_actual_data() { + fn v3_deserialized_from_actual_data() { // Fetched at Kusama 14,703,780 (0x3b2c305d01bd4adf1973d32a2d55ca1260a55eea8dfb3168e317c57f2841fdf1) // // 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!["0000a000005000000a00000000c8000000c800000a0000000a000000100e0000580200000000500000c8000000e87648170000001e00000000000000005039278c0400000000000000000000005039278c0400000000000000000000e8030000009001001e00000000000000009001008070000000000000000000000a0000000a0000000a00000001000000010500000001c8000000060000005802000002000000580200000200000059000000000000001e0000002800000000c817a804000000000200000014000000"]; - let v2 = - v3::OldHostConfiguration::::decode(&mut &raw_config[..]) + let v3 = + v4::OldHostConfiguration::::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!(v2.max_code_size, 10_485_760); - assert_eq!(v2.validation_upgrade_cooldown, 3600); - assert_eq!(v2.max_pov_size, 5_242_880); - assert_eq!(v2.hrmp_channel_max_message_size, 102_400); - assert_eq!(v2.dispute_max_spam_slots, 2); - assert_eq!(v2.n_delay_tranches, 89); - assert_eq!(v2.ump_max_individual_weight, OldWeight(20_000_000_000)); - assert_eq!(v2.minimum_validation_upgrade_delay, 20); + assert_eq!(v3.max_code_size, 10_485_760); + assert_eq!(v3.validation_upgrade_cooldown, 3600); + assert_eq!(v3.max_pov_size, 5_242_880); + assert_eq!(v3.hrmp_channel_max_message_size, 102_400); + assert_eq!(v3.dispute_max_spam_slots, 2); + assert_eq!(v3.n_delay_tranches, 89); + assert_eq!(v3.ump_max_individual_weight, Weight::zero()); + assert_eq!(v3.minimum_validation_upgrade_delay, 20); } #[test] - fn test_migrate_to_v3() { + fn test_migrate_to_v4() { // Host configuration has lots of fields. However, in this migration we add only a couple of // fields. 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 @@ -267,8 +259,8 @@ mod tests { // 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 v2 = v3::OldHostConfiguration:: { - ump_max_individual_weight: OldWeight(0x71616e6f6e0au64), + let v3 = v4::OldHostConfiguration:: { + ump_max_individual_weight: Weight::from_ref_time(0x71616e6f6e0au64), needed_approvals: 69, thread_availability_period: 55, hrmp_recipient_deposit: 1337, @@ -279,64 +271,59 @@ mod tests { }; new_test_ext(Default::default()).execute_with(|| { - // Implant the v2 version in the state. + // Implant the v3 version in the state. frame_support::storage::unhashed::put_raw( &configuration::ActiveConfig::::hashed_key(), - &v2.encode(), + &v3.encode(), ); - migrate_to_v3::(); + migrate_to_v4::(); - let v3 = configuration::ActiveConfig::::get(); + let v4 = configuration::ActiveConfig::::get(); #[rustfmt::skip] { - assert_eq!(v2.max_code_size , v3.max_code_size); - assert_eq!(v2.max_head_data_size , v3.max_head_data_size); - assert_eq!(v2.max_upward_queue_count , v3.max_upward_queue_count); - assert_eq!(v2.max_upward_queue_size , v3.max_upward_queue_size); - assert_eq!(v2.max_upward_message_size , v3.max_upward_message_size); - assert_eq!(v2.max_upward_message_num_per_candidate , v3.max_upward_message_num_per_candidate); - assert_eq!(v2.hrmp_max_message_num_per_candidate , v3.hrmp_max_message_num_per_candidate); - assert_eq!(v2.validation_upgrade_cooldown , v3.validation_upgrade_cooldown); - assert_eq!(v2.validation_upgrade_delay , v3.validation_upgrade_delay); - assert_eq!(v2.max_pov_size , v3.max_pov_size); - assert_eq!(v2.max_downward_message_size , v3.max_downward_message_size); - assert_eq!(v2.hrmp_max_parachain_outbound_channels , v3.hrmp_max_parachain_outbound_channels); - assert_eq!(v2.hrmp_max_parathread_outbound_channels , v3.hrmp_max_parathread_outbound_channels); - assert_eq!(v2.hrmp_sender_deposit , v3.hrmp_sender_deposit); - assert_eq!(v2.hrmp_recipient_deposit , v3.hrmp_recipient_deposit); - assert_eq!(v2.hrmp_channel_max_capacity , v3.hrmp_channel_max_capacity); - assert_eq!(v2.hrmp_channel_max_total_size , v3.hrmp_channel_max_total_size); - assert_eq!(v2.hrmp_max_parachain_inbound_channels , v3.hrmp_max_parachain_inbound_channels); - assert_eq!(v2.hrmp_max_parathread_inbound_channels , v3.hrmp_max_parathread_inbound_channels); - assert_eq!(v2.hrmp_channel_max_message_size , v3.hrmp_channel_max_message_size); - assert_eq!(v2.code_retention_period , v3.code_retention_period); - assert_eq!(v2.parathread_cores , v3.parathread_cores); - assert_eq!(v2.parathread_retries , v3.parathread_retries); - assert_eq!(v2.group_rotation_frequency , v3.group_rotation_frequency); - assert_eq!(v2.chain_availability_period , v3.chain_availability_period); - assert_eq!(v2.thread_availability_period , v3.thread_availability_period); - assert_eq!(v2.scheduling_lookahead , v3.scheduling_lookahead); - assert_eq!(v2.max_validators_per_core , v3.max_validators_per_core); - assert_eq!(v2.max_validators , v3.max_validators); - assert_eq!(v2.dispute_period , v3.dispute_period); - assert_eq!(v2.dispute_post_conclusion_acceptance_period, v3.dispute_post_conclusion_acceptance_period); - assert_eq!(v2.dispute_max_spam_slots , v3.dispute_max_spam_slots); - assert_eq!(v2.dispute_conclusion_by_time_out_period , v3.dispute_conclusion_by_time_out_period); - assert_eq!(v2.no_show_slots , v3.no_show_slots); - assert_eq!(v2.n_delay_tranches , v3.n_delay_tranches); - assert_eq!(v2.zeroth_delay_tranche_width , v3.zeroth_delay_tranche_width); - assert_eq!(v2.needed_approvals , v3.needed_approvals); - assert_eq!(v2.relay_vrf_modulo_samples , v3.relay_vrf_modulo_samples); - assert_eq!(v2.pvf_checking_enabled , v3.pvf_checking_enabled); - assert_eq!(v2.pvf_voting_ttl , v3.pvf_voting_ttl); - assert_eq!(v2.minimum_validation_upgrade_delay , v3.minimum_validation_upgrade_delay); - - assert_eq!(v2.ump_service_total_weight, OldWeight(v3.ump_service_total_weight.ref_time())); - assert_eq!(v2.ump_max_individual_weight, OldWeight(v3.ump_max_individual_weight.ref_time())); - assert_eq!(v3.ump_service_total_weight.proof_size(), MAX_POV_SIZE as u64); - assert_eq!(v3.ump_max_individual_weight.proof_size(), MAX_POV_SIZE as u64); + assert_eq!(v3.max_code_size , v4.max_code_size); + assert_eq!(v3.max_head_data_size , v4.max_head_data_size); + assert_eq!(v3.max_upward_queue_count , v4.max_upward_queue_count); + assert_eq!(v3.max_upward_queue_size , v4.max_upward_queue_size); + assert_eq!(v3.max_upward_message_size , v4.max_upward_message_size); + assert_eq!(v3.max_upward_message_num_per_candidate , v4.max_upward_message_num_per_candidate); + assert_eq!(v3.hrmp_max_message_num_per_candidate , v4.hrmp_max_message_num_per_candidate); + assert_eq!(v3.validation_upgrade_cooldown , v4.validation_upgrade_cooldown); + assert_eq!(v3.validation_upgrade_delay , v4.validation_upgrade_delay); + assert_eq!(v3.max_pov_size , v4.max_pov_size); + assert_eq!(v3.max_downward_message_size , v4.max_downward_message_size); + assert_eq!(v3.hrmp_max_parachain_outbound_channels , v4.hrmp_max_parachain_outbound_channels); + assert_eq!(v3.hrmp_max_parathread_outbound_channels , v4.hrmp_max_parathread_outbound_channels); + assert_eq!(v3.hrmp_sender_deposit , v4.hrmp_sender_deposit); + assert_eq!(v3.hrmp_recipient_deposit , v4.hrmp_recipient_deposit); + assert_eq!(v3.hrmp_channel_max_capacity , v4.hrmp_channel_max_capacity); + assert_eq!(v3.hrmp_channel_max_total_size , v4.hrmp_channel_max_total_size); + assert_eq!(v3.hrmp_max_parachain_inbound_channels , v4.hrmp_max_parachain_inbound_channels); + assert_eq!(v3.hrmp_max_parathread_inbound_channels , v4.hrmp_max_parathread_inbound_channels); + assert_eq!(v3.hrmp_channel_max_message_size , v4.hrmp_channel_max_message_size); + assert_eq!(v3.code_retention_period , v4.code_retention_period); + assert_eq!(v3.parathread_cores , v4.parathread_cores); + assert_eq!(v3.parathread_retries , v4.parathread_retries); + assert_eq!(v3.group_rotation_frequency , v4.group_rotation_frequency); + assert_eq!(v3.chain_availability_period , v4.chain_availability_period); + assert_eq!(v3.thread_availability_period , v4.thread_availability_period); + assert_eq!(v3.scheduling_lookahead , v4.scheduling_lookahead); + assert_eq!(v3.max_validators_per_core , v4.max_validators_per_core); + assert_eq!(v3.max_validators , v4.max_validators); + assert_eq!(v3.dispute_period , v4.dispute_period); + assert_eq!(v3.dispute_post_conclusion_acceptance_period, v4.dispute_post_conclusion_acceptance_period); + assert_eq!(v3.dispute_max_spam_slots , v4.dispute_max_spam_slots); + assert_eq!(v3.dispute_conclusion_by_time_out_period , v4.dispute_conclusion_by_time_out_period); + assert_eq!(v3.no_show_slots , v4.no_show_slots); + assert_eq!(v3.n_delay_tranches , v4.n_delay_tranches); + assert_eq!(v3.zeroth_delay_tranche_width , v4.zeroth_delay_tranche_width); + assert_eq!(v3.needed_approvals , v4.needed_approvals); + assert_eq!(v3.relay_vrf_modulo_samples , v4.relay_vrf_modulo_samples); + assert_eq!(v3.pvf_checking_enabled , v4.pvf_checking_enabled); + assert_eq!(v3.pvf_voting_ttl , v4.pvf_voting_ttl); + assert_eq!(v3.minimum_validation_upgrade_delay , v4.minimum_validation_upgrade_delay); }; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression. }); } diff --git a/runtime/parachains/src/configuration/tests.rs b/runtime/parachains/src/configuration/tests.rs index 6f2faf6cb204..28e71c2fa4ae 100644 --- a/runtime/parachains/src/configuration/tests.rs +++ b/runtime/parachains/src/configuration/tests.rs @@ -319,7 +319,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_ref_time(20000), max_upward_message_size: 448, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 22, @@ -332,7 +331,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_ref_time(909), pvf_checking_enabled: true, pvf_voting_ttl: 3, minimum_validation_upgrade_delay: 20, @@ -442,11 +440,6 @@ fn setting_pending_config_members() { 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, @@ -507,11 +500,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, diff --git a/runtime/parachains/src/inclusion/mod.rs b/runtime/parachains/src/inclusion/mod.rs index f74a8cfd3f8d..15911b048eec 100644 --- a/runtime/parachains/src/inclusion/mod.rs +++ b/runtime/parachains/src/inclusion/mod.rs @@ -21,27 +21,40 @@ //! 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::{ + pallet_prelude::*, + traits::{EnqueueMessage, Footprint}, + BoundedSlice, +}; use parity_scale_codec::{Decode, Encode}; use primitives::v2::{ - AvailabilityBitfield, BackedCandidate, CandidateCommitments, CandidateDescriptor, - CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash, - HeadData, Id as ParaId, SigningContext, UncheckedSignedAvailabilityBitfields, ValidatorId, - ValidatorIndex, ValidityAttestation, + 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_std::{collections::btree_set::BTreeSet, prelude::*}; +use sp_std::{collections::btree_set::BTreeSet, fmt, prelude::*}; pub use pallet::*; #[cfg(test)] pub(crate) mod tests; +/// Maximum value that `config.max_upward_message_size` can be set to +/// +/// This is used for benchmarking sanely bounding relevant storate items. It is expected from the `configurations` +/// pallet to check these values before setting. +pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 50 * 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. /// @@ -194,13 +207,15 @@ pub mod pallet { + shared::Config + paras::Config + dmp::Config - + ump::Config + hrmp::Config + configuration::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; type DisputesHandler: disputes::DisputesHandler; type RewardValidators: RewardValidators; + + /// The system message queue. + type MessageQueue: EnqueueMessage; } #[pallet::event] @@ -212,6 +227,8 @@ pub mod pallet { CandidateIncluded(CandidateReceipt, HeadData, CoreIndex, GroupIndex), /// A candidate timed out. `[candidate, head_data]` CandidateTimedOut(CandidateReceipt, HeadData, CoreIndex), + /// Some upward messages have been received and will be processed. + UpwardMessagesReceived { from: ParaId, count: u32 }, } #[pallet::error] @@ -300,6 +317,53 @@ pub mod pallet { const LOG_TARGET: &str = "runtime::inclusion"; +#[derive(derive_more::From, Debug)] +enum AcceptanceCheckErr { + HeadDataTooLarge, + PrematureCodeUpgrade, + NewCodeTooLarge, + ProcessedDownwardMessages(dmp::ProcessedDownwardMessagesAcceptanceErr), + UpwardMessages(UmpAcceptanceCheckErr), + HrmpWatermark(hrmp::HrmpWatermarkAcceptanceErr), + OutboundHrmp(hrmp::OutboundHrmpAcceptanceErr), +} + +/// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance +/// criteria rules. +pub enum UmpAcceptanceCheckErr { + 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 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, + ), + } + } +} + impl Pallet { /// Block initialization logic, called by initializer. pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight { @@ -765,10 +829,8 @@ impl Pallet { receipt.descriptor.para_id, commitments.processed_downward_messages, ); - weight += >::receive_upward_messages( - receipt.descriptor.para_id, - commitments.upward_messages, - ); + weight += + Self::receive_upward_messages(receipt.descriptor.para_id, commitments.upward_messages); weight += >::prune_hrmp( receipt.descriptor.para_id, T::BlockNumber::from(commitments.hrmp_watermark), @@ -793,6 +855,79 @@ impl Pallet { ) } + /// 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, + para: ParaId, + upward_messages: &[UpwardMessage], + ) -> Result<(), UmpAcceptanceCheckErr> { + if upward_messages.len() as u32 > config.max_upward_message_num_per_candidate { + return Err(UmpAcceptanceCheckErr::MoreMessagesThanPermitted { + sent: upward_messages.len() as u32, + permitted: config.max_upward_message_num_per_candidate, + }) + } + + let fp = T::MessageQueue::footprint(para); + let (mut para_queue_count, mut para_queue_size) = (fp.count, fp.size); + + 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(UmpAcceptanceCheckErr::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(UmpAcceptanceCheckErr::CapacityExceeded { + count: para_queue_count, + limit: config.max_upward_queue_count, + }) + } + if para_queue_size > config.max_upward_queue_size { + return Err(UmpAcceptanceCheckErr::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: Vec, + ) -> Weight { + if !upward_messages.is_empty() { + let count = upward_messages.len() as u32; + Self::deposit_event(Event::UpwardMessagesReceived { from: para, count }); + } + let messages = upward_messages.iter().filter_map(|d| BoundedSlice::try_from(&d[..]).ok()); + T::MessageQueue::enqueue_messages(messages, para); + + let Footprint { count, size } = T::MessageQueue::footprint(para); + // TODO: Consider placing the remaining capacity into the well known key, rather than the + // amount used. This is way more useful for the parachain. + // TODO: Consider doing this at the end of the block, after any messages might have been + // executed, to report more accurate numbers to the para. + let key = well_known_keys::relay_dispatch_queue_size(para); + (count, size).using_encoded(|d| sp_io::storage::set(&key, d)); + + // TODO: calculate worst-case enqueue (largest possible message with the most recent page + // being almost full) and return. + Weight::zero() + } + /// Cleans up all paras pending availability that the predicate returns true for. /// /// The predicate accepts the index of the core and the block number the core has been occupied @@ -906,17 +1041,6 @@ const fn availability_threshold(n_validators: usize) -> usize { threshold } -#[derive(derive_more::From, Debug)] -enum AcceptanceCheckErr { - HeadDataTooLarge, - PrematureCodeUpgrade, - NewCodeTooLarge, - ProcessedDownwardMessages(dmp::ProcessedDownwardMessagesAcceptanceErr), - UpwardMessages(ump::AcceptanceCheckErr), - HrmpWatermark(hrmp::HrmpWatermarkAcceptanceErr), - OutboundHrmp(hrmp::OutboundHrmpAcceptanceErr), -} - impl AcceptanceCheckErr { /// Returns the same error so that it can be threaded through a needle of `DispatchError` and /// ultimately returned from a `Dispatchable`. @@ -1063,7 +1187,7 @@ impl CandidateCheckContext { // check if the candidate passes the messaging acceptance criteria >::check_processed_downward_messages(para_id, processed_downward_messages)?; - >::check_upward_messages(&self.config, para_id, upward_messages)?; + Pallet::::check_upward_messages(&self.config, para_id, upward_messages)?; >::check_hrmp_watermark(para_id, self.relay_parent_number, hrmp_watermark)?; >::check_outbound_hrmp(&self.config, para_id, horizontal_messages)?; diff --git a/runtime/parachains/src/initializer.rs b/runtime/parachains/src/initializer.rs index eaa4510fafcf..f6539a8500b0 100644 --- a/runtime/parachains/src/initializer.rs +++ b/runtime/parachains/src/initializer.rs @@ -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}, @@ -114,7 +114,6 @@ pub mod pallet { + session_info::Config + disputes::Config + dmp::Config - + ump::Config + hrmp::Config { /// A randomness beacon. @@ -169,7 +168,6 @@ pub mod pallet { T::DisputesHandler::initializer_initialize(now) + T::SlashingHandler::initializer_initialize(now) + dmp::Pallet::::initializer_initialize(now) + - ump::Pallet::::initializer_initialize(now) + hrmp::Pallet::::initializer_initialize(now); HasInitialized::::set(Some(())); @@ -180,7 +178,6 @@ pub mod pallet { fn on_finalize(now: T::BlockNumber) { // reverse initialization order. hrmp::Pallet::::initializer_finalize(); - ump::Pallet::::initializer_finalize(); dmp::Pallet::::initializer_finalize(); T::SlashingHandler::initializer_finalize(); T::DisputesHandler::initializer_finalize(); @@ -268,7 +265,7 @@ impl Pallet { T::DisputesHandler::initializer_on_new_session(¬ification); T::SlashingHandler::initializer_on_new_session(session_index); dmp::Pallet::::initializer_on_new_session(¬ification, &outgoing_paras); - ump::Pallet::::initializer_on_new_session(¬ification, &outgoing_paras); + // ump::Pallet::::initializer_on_new_session(¬ification, &outgoing_paras); hrmp::Pallet::::initializer_on_new_session(¬ification, &outgoing_paras); } diff --git a/runtime/parachains/src/lib.rs b/runtime/parachains/src/lib.rs index 2005861a6c4b..4a307d0b45cc 100644 --- a/runtime/parachains/src/lib.rs +++ b/runtime/parachains/src/lib.rs @@ -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; diff --git a/runtime/parachains/src/mock.rs b/runtime/parachains/src/mock.rs index bc576fa9d4a6..b248c47a134a 100644 --- a/runtime/parachains/src/mock.rs +++ b/runtime/parachains/src/mock.rs @@ -18,14 +18,15 @@ use crate::{ configuration, disputes, dmp, hrmp, inclusion, initializer, origin, paras, paras_inherent, - scheduler, session_info, shared, - ump::{self, MessageId, UmpSink}, - ParaId, + scheduler, session_info, shared, ParaId, }; use frame_support::{ parameter_types, - traits::{GenesisBuild, KeyOwnerProofSystem, ValidatorSet, ValidatorSetWithIdentification}, + traits::{ + GenesisBuild, KeyOwnerProofSystem, ProcessMessage, ProcessMessageError, ValidatorSet, + ValidatorSetWithIdentification, + }, weights::Weight, }; use frame_support_test::TestRandomness; @@ -34,7 +35,7 @@ use primitives::v2::{ AuthorityDiscoveryId, Balance, BlockNumber, CandidateHash, Header, Moment, SessionIndex, UpwardMessage, ValidatorIndex, }; -use sp_core::H256; +use sp_core::{ConstU32, H256}; use sp_io::TestExternalities; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, @@ -54,6 +55,7 @@ frame_support::construct_runtime!( { System: frame_system, Balances: pallet_balances, + MessageQueue: pallet_message_queue, Paras: paras, Configuration: configuration, ParasShared: shared, @@ -62,7 +64,6 @@ frame_support::construct_runtime!( Scheduler: scheduler, Initializer: initializer, Dmp: dmp, - Ump: ump, Hrmp: hrmp, ParachainsOrigin: origin, SessionInfo: session_info, @@ -145,25 +146,18 @@ impl pallet_babe::Config for Test { // session module is the trigger type EpochChangeTrigger = pallet_babe::ExternalTrigger; - type DisabledValidators = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type KeyOwnerProofSystem = (); - type HandleEquivocation = (); - type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; } @@ -227,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; - type WeightInfo = crate::ump::TestWeightInfo; -} - impl crate::hrmp::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeEvent = RuntimeEvent; @@ -293,10 +279,43 @@ impl crate::disputes::SlashingHandler for Test { impl crate::scheduler::Config for Test {} +pub struct TestWeightInfo; +impl pallet_message_queue::WeightInfo for TestWeightInfo { + fn service_page_base() -> Weight { + Weight::zero() + } + fn service_queue_base() -> Weight { + Weight::zero() + } + fn service_page_process_message() -> Weight { + Weight::zero() + } + fn bump_service_head() -> Weight { + Weight::zero() + } + fn service_page_item() -> Weight { + Weight::zero() + } + fn ready_ring_unknit() -> Weight { + Weight::zero() + } +} + +impl pallet_message_queue::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = TestWeightInfo; + type MessageProcessor = TestProcessMessage; + type Size = u32; + type HeapSize = ConstU32<65536>; + type MaxStale = ConstU32<8>; + type ServiceWeight = (); +} + impl crate::inclusion::Config for Test { type RuntimeEvent = RuntimeEvent; type DisputesHandler = Disputes; type RewardValidators = TestRewardValidators; + type MessageQueue = MessageQueue; } impl crate::paras_inherent::Config for Test { @@ -386,26 +405,26 @@ pub fn take_processed() -> Vec<(ParaId, UpwardMessage)> { /// /// 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 { - let weight = match u32::decode(&mut &actual_msg[..]) { - Ok(w) => Weight::from_ref_time(w as u64), - Err(_) => return Ok(Weight::zero()), // same as the real `UmpSink` +pub struct TestProcessMessage; +impl ProcessMessage for TestProcessMessage { + type Origin = ParaId; + fn process_message( + message: &[u8], + origin: ParaId, + weight_limit: Weight, + ) -> Result<(bool, Weight), ProcessMessageError> { + let weight = 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 weight.any_gt(max_weight) { - let id = sp_io::hashing::blake2_256(actual_msg); - return Err((id, weight)) + if weight.any_gt(weight_limit) { + return Err(ProcessMessageError::Overweight(weight)) } PROCESSED.with(|opt_hook| { - opt_hook.borrow_mut().push((actual_origin, actual_msg.to_owned())); + opt_hook.borrow_mut().push((origin, message.to_owned())); }); - Ok(weight) + Ok((true, weight)) } } @@ -464,3 +483,19 @@ 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(generic_events: E) +where + E: DoubleEndedIterator + ExactSizeIterator, +{ + for (i, (got, want)) in frame_system::Pallet::::events() + .into_iter() + .rev() + .map(|e| e.event) + .zip(generic_events.rev().map(::RuntimeEvent::from)) + .rev() + .enumerate() + { + assert_eq!((i, got), (i, want)); + } +} diff --git a/runtime/parachains/src/paras_inherent/mod.rs b/runtime/parachains/src/paras_inherent/mod.rs index 188a8f677979..0bcfedfdca08 100644 --- a/runtime/parachains/src/paras_inherent/mod.rs +++ b/runtime/parachains/src/paras_inherent/mod.rs @@ -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::{ @@ -534,10 +534,6 @@ impl Pallet { // Note which of the scheduled cores were actually occupied by a backed candidate. >::occupied(&occupied); - // Give some time slice to dispatch pending upward messages. - // this is max config.ump_service_total_weight - let _ump_weight = >::process_pending_upward_messages(); - METRICS.on_after_filter(total_consumed_weight.ref_time()); Ok(Some(total_consumed_weight).into()) diff --git a/runtime/parachains/src/runtime_api_impl/v2.rs b/runtime/parachains/src/runtime_api_impl/v2.rs index 77ea96742b54..fa877468ab75 100644 --- a/runtime/parachains/src/runtime_api_impl/v2.rs +++ b/runtime/parachains/src/runtime_api_impl/v2.rs @@ -330,14 +330,18 @@ where >::read_events_no_consensus() .into_iter() .filter_map(|record| extract_event(record.event)) - .map(|event| match event { - RawEvent::::CandidateBacked(c, h, core, group) => - CandidateEvent::CandidateBacked(c, h, core, group), - RawEvent::::CandidateIncluded(c, h, core, group) => - CandidateEvent::CandidateIncluded(c, h, core, group), - RawEvent::::CandidateTimedOut(c, h, core) => - CandidateEvent::CandidateTimedOut(c, h, core), - RawEvent::::__Ignore(_, _) => unreachable!("__Ignore cannot be used"), + .filter_map(|event| { + Some(match event { + RawEvent::::CandidateBacked(c, h, core, group) => + CandidateEvent::CandidateBacked(c, h, core, group), + RawEvent::::CandidateIncluded(c, h, core, group) => + CandidateEvent::CandidateIncluded(c, h, core, group), + RawEvent::::CandidateTimedOut(c, h, core) => + CandidateEvent::CandidateTimedOut(c, h, core), + // Not needed for candidate events. + RawEvent::::UpwardMessagesReceived { .. } => return None, + RawEvent::::__Ignore(_, _) => unreachable!("__Ignore cannot be used"), + }) }) .collect() } diff --git a/runtime/parachains/src/ump.rs b/runtime/parachains/src/ump.rs deleted file mode 100644 index 63e6e2c4692b..000000000000 --- a/runtime/parachains/src/ump.rs +++ /dev/null @@ -1,761 +0,0 @@ -// 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 . - -use crate::{ - configuration::{self, HostConfiguration}, - initializer, -}; -use frame_support::{pallet_prelude::*, traits::EnsureOrigin}; -use frame_system::pallet_prelude::*; -use primitives::v2::{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 storate items. It is expected from the `configurations` -/// pallet to check these values before setting. -pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 50 * 1024; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[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; -} - -/// 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 { - 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(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, C: Config> UmpSink - for XcmSink -{ - fn process_upward_message( - origin: ParaId, - mut data: &[u8], - max_weight: Weight, - ) -> Result { - 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::::decode_all_with_depth_limit( - xcm::MAX_XCM_DECODE_DEPTH, - &mut data, - ) - .map(|xcm| { - ( - Xcm::::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. - ::WeightInfo::process_upward_message(data.len() as u32), - ) - }); - match maybe_msg_and_weight { - Err(_) => { - Pallet::::deposit_event(Event::InvalidFormat(id)); - Ok(Weight::zero()) - }, - Ok((Err(()), weight_used)) => { - Pallet::::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.ref_time()); - match outcome { - Outcome::Error(XcmError::WeightLimitReached(required)) => - Err((id, Weight::from_ref_time(required))), - outcome => { - let outcome_weight = Weight::from_ref_time(outcome.weight_used()); - Pallet::::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::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config + configuration::Config { - /// The aggregate event. - type RuntimeEvent: From + IsType<::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; - - /// Origin which is allowed to execute overweight messages. - type ExecuteOverweightOrigin: EnsureOrigin; - - /// 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 { - /// 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 = - StorageMap<_, Twox64Concat, ParaId, Vec, 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 = - 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 = StorageValue<_, Vec, 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 = StorageValue<_, ParaId>; - - /// The messages that exceeded max individual message weight budget. - /// - /// These messages stay there until manually dispatched. - #[pallet::storage] - pub type Overweight = - StorageMap<_, Twox64Concat, OverweightIndex, (ParaId, Vec), OptionQuery>; - - /// The number of overweight messages ever recorded in `Overweight` (and thus the lowest free - /// index). - #[pallet::storage] - pub type OverweightCount = StorageValue<_, OverweightIndex, ValueQuery>; - - #[pallet::call] - impl Pallet { - /// 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::weight(weight_limit.saturating_add(::WeightInfo::service_overweight()))] - pub fn service_overweight( - origin: OriginFor, - index: OverweightIndex, - weight_limit: Weight, - ) -> DispatchResultWithPostInfo { - T::ExecuteOverweightOrigin::ensure_origin(origin)?; - - let (sender, data) = - Overweight::::get(index).ok_or(Error::::UnknownMessageIndex)?; - let used = T::UmpSink::process_upward_message(sender, &data[..], weight_limit) - .map_err(|_| Error::::WeightOverLimit)?; - Overweight::::remove(index); - Self::deposit_event(Event::OverweightServiced(index, used)); - Ok(Some(used.saturating_add(::WeightInfo::service_overweight())).into()) - } - } -} - -/// Routines related to the upward message passing. -impl Pallet { - /// 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, - 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::remove(outgoing_para); - ::RelayDispatchQueues::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::mutate(|v| { - if let Ok(i) = v.binary_search(outgoing_para) { - v.remove(i); - } - }); - ::NextDispatchRoundStartWith::mutate(|v| { - *v = v.filter(|p| p == outgoing_para) - }); - - ::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, - 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::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: Vec, - ) -> 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::mutate(¶, |v| { - v.extend(upward_messages.into_iter()) - }); - - ::RelayDispatchQueueSize::mutate( - ¶, - |(ref mut cnt, ref mut size)| { - *cnt += extra_count; - *size += extra_size; - }, - ); - - ::NeedsDispatch::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 { - let mut weight_used = Weight::zero(); - - let config = >::config(); - let mut cursor = NeedsDispatchCursor::new::(); - let mut queue_cache = QueueCache::new(); - - while let Some(dispatchee) = cursor.peek() { - if weight_used.any_gte(config.ump_service_total_weight) { - // 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::(dispatchee); - if let Some(upward_message) = maybe_next { - match T::UmpSink::process_upward_message(dispatchee, upward_message, max_weight) { - Ok(used) => { - weight_used += used; - let _ = queue_cache.consume_front::(dispatchee); - }, - Err((id, required)) => { - if required.any_gt(config.ump_max_individual_weight) { - // overweight - add to overweight queue and continue with message - // execution consuming the message. - let upward_message = queue_cache.consume_front::(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::(dispatchee) { - // the queue is empty now - this para doesn't need attention anymore. - cursor.remove(); - } else { - cursor.advance(); - } - } - - cursor.flush::(); - queue_cache.flush::(); - - 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) -> OverweightIndex { - let index = ::OverweightCount::mutate(|count| { - let index = *count; - *count += 1; - index - }); - - ::Overweight::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); - -struct QueueCacheEntry { - queue: Vec, - total_size: u32, - consumed_count: usize, - consumed_size: usize, -} - -impl QueueCache { - fn new() -> Self { - Self(BTreeMap::new()) - } - - fn ensure_cached(&mut self, para: ParaId) -> &mut QueueCacheEntry { - self.0.entry(para).or_insert_with(|| { - let queue = RelayDispatchQueues::::get(¶); - let (_, total_size) = RelayDispatchQueueSize::::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(&mut self, para: ParaId) -> Option<&UpwardMessage> { - let entry = self.ensure_cached::(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(&mut self, para: ParaId) -> Option { - let cache_entry = self.ensure_cached::(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(&mut self, para: ParaId) -> bool { - let cache_entry = self.ensure_cached::(para); - cache_entry.consumed_count >= cache_entry.queue.len() - } - - /// Flushes the updated queues into the storage. - fn flush(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::::remove(¶); - RelayDispatchQueueSize::::remove(¶); - } else if entry.consumed_count > 0 { - RelayDispatchQueues::::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::::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, - index: usize, -} - -impl NeedsDispatchCursor { - fn new() -> Self { - let needs_dispatch: Vec = as Store>::NeedsDispatch::get(); - let start_with = as Store>::NextDispatchRoundStartWith::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 { - 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(self) { - let next_one = self.peek(); - as Store>::NextDispatchRoundStartWith::set(next_one); - as Store>::NeedsDispatch::put(self.needs_dispatch); - } -} diff --git a/runtime/parachains/src/ump/benchmarking.rs b/runtime/parachains/src/ump/benchmarking.rs index 206829599f9b..667d42bff063 100644 --- a/runtime/parachains/src/ump/benchmarking.rs +++ b/runtime/parachains/src/ump/benchmarking.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . - +/* use super::{Pallet as Ump, *}; use frame_system::RawOrigin; use xcm::prelude::*; @@ -107,7 +107,7 @@ frame_benchmarking::benchmarks! { service_overweight { let host_conf = configuration::ActiveConfig::::get(); - let weight = host_conf.ump_max_individual_weight + host_conf.ump_max_individual_weight + Weight::from_ref_time(1000000); + let weight = Weight::from_ref_time(1000000); 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. @@ -137,3 +137,4 @@ frame_benchmarking::impl_benchmark_test_suite!( crate::mock::new_test_ext(crate::ump::tests::GenesisConfigBuilder::default().build()), crate::mock::Test ); +*/ \ No newline at end of file diff --git a/runtime/parachains/src/ump/tests.rs b/runtime/parachains/src/ump/tests.rs index 23c5159eab0f..9a41a4d29ea9 100644 --- a/runtime/parachains/src/ump/tests.rs +++ b/runtime/parachains/src/ump/tests.rs @@ -27,8 +27,6 @@ pub(super) struct GenesisConfigBuilder { 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 { @@ -38,8 +36,6 @@ impl Default for GenesisConfigBuilder { max_upward_message_num_per_candidate: 2, max_upward_queue_count: 4, max_upward_queue_size: 64, - ump_service_total_weight: Weight::from_ref_time(1000).set_proof_size(1000), - ump_max_individual_weight: Weight::from_ref_time(100).set_proof_size(100), } } } @@ -53,8 +49,6 @@ impl GenesisConfigBuilder { 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 } } @@ -76,7 +70,7 @@ fn queue_upward_msg(para: ParaId, msg: UpwardMessage) { 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::iter() { @@ -154,19 +148,13 @@ fn dispatch_resume_after_exceeding_dispatch_stage_weight() { 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_ref_time(500).set_proof_size(500), - ..Default::default() - } - .build(), - ) - .execute_with(|| { + 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()); + //ump_service_total_weight: Weight::from_ref_time(500).set_proof_size(500), assert_storage_consistency_exhaustive(); // we expect only two first messages to fit in the first iteration. @@ -194,171 +182,4 @@ fn dispatch_resume_after_exceeding_dispatch_stage_weight() { }); } -#[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_ref_time(500).set_proof_size(500), - ump_max_individual_weight: Weight::from_ref_time(300).set_proof_size(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_ref_time(900).set_proof_size(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::v2::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_ref_time(1000)), - Error::::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_ref_time(900).set_proof_size(900), - ump_max_individual_weight: Weight::from_ref_time(300).set_proof_size(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_ref_time(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_ref_time(499)), - Error::::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_ref_time(500))); - assert_last_event(Event::OverweightServiced(0, Weight::from_ref_time(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_ref_time(1000)), - Error::::UnknownMessageIndex - ); - }); -} +*/ \ No newline at end of file diff --git a/xcm/xcm-builder/src/lib.rs b/xcm/xcm-builder/src/lib.rs index f77aa157bbbb..b7a4c4a6da13 100644 --- a/xcm/xcm-builder/src/lib.rs +++ b/xcm/xcm-builder/src/lib.rs @@ -85,4 +85,4 @@ pub use universal_exports::{ }; mod process_xcm_message; -pub use process_xcm_message::{ProcessXcmMessage}; +pub use process_xcm_message::ProcessXcmMessage; diff --git a/xcm/xcm-builder/src/process_xcm_message.rs b/xcm/xcm-builder/src/process_xcm_message.rs index 0e6acfe11cf3..2c506fb95428 100644 --- a/xcm/xcm-builder/src/process_xcm_message.rs +++ b/xcm/xcm-builder/src/process_xcm_message.rs @@ -16,20 +16,26 @@ //! Implementation of `ProcessMessage` for an `ExecuteXcm` implementation. -use sp_std::{fmt::Debug, marker::PhantomData}; -use sp_io::hashing::blake2_256; -use sp_weights::Weight; +use frame_support::{ + ensure, + traits::{ProcessMessage, ProcessMessageError}, +}; use parity_scale_codec::{Decode, FullCodec, MaxEncodedLen}; use scale_info::TypeInfo; -use frame_support::{ensure, traits::{ProcessMessage, ProcessMessageError}}; +use sp_io::hashing::blake2_256; +use sp_std::{fmt::Debug, marker::PhantomData}; +use sp_weights::Weight; use xcm::prelude::*; -pub struct ProcessXcmMessage(PhantomData<(MessageOrigin, XcmExecutor, Call)>); +pub struct ProcessXcmMessage( + PhantomData<(MessageOrigin, XcmExecutor, Call)>, +); impl< - MessageOrigin: Into + FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug, - XcmExecutor: ExecuteXcm, - Call, -> ProcessMessage for ProcessXcmMessage { + MessageOrigin: Into + FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug, + XcmExecutor: ExecuteXcm, + Call, + > ProcessMessage for ProcessXcmMessage +{ type Origin = MessageOrigin; /// Process the given message, using no more than `weight_limit` in weight to do so. @@ -47,15 +53,9 @@ impl< let weight = Weight::from_ref_time(pre.weight_of()); ensure!(weight.all_lte(weight_limit), ProcessMessageError::Overweight(weight)); match XcmExecutor::execute(origin.into(), pre, hash, 0) { - Outcome::Complete(w) => { - Ok((true, Weight::from_ref_time(w))) - }, - Outcome::Incomplete(w, _) => { - Ok((false, Weight::from_ref_time(w))) - }, - Outcome::Error(_) => { - Err(ProcessMessageError::Unsupported) - } + Outcome::Complete(w) => Ok((true, Weight::from_ref_time(w))), + Outcome::Incomplete(w, _) => Ok((false, Weight::from_ref_time(w))), + Outcome::Error(_) => Err(ProcessMessageError::Unsupported), } } } @@ -63,7 +63,5 @@ impl< #[cfg(test)] mod tests { #[test] - fn process_message_works() { - - } -} \ No newline at end of file + fn process_message_works() {} +}