diff --git a/Cargo.lock b/Cargo.lock
index ad75224fefdc..aa016e8054cf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -14011,6 +14011,7 @@ dependencies = [
"pallet-balances",
"pallet-broker",
"pallet-message-queue",
+ "pallet-mmr",
"pallet-session",
"pallet-staking",
"pallet-timestamp",
@@ -14040,6 +14041,7 @@ dependencies = [
"sp-runtime",
"sp-session",
"sp-staking",
+ "sp-std 14.0.0",
"sp-tracing 16.0.0",
"staging-xcm",
"staging-xcm-executor",
diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml
index 7afdf49fe551..cfe373e8cba2 100644
--- a/polkadot/runtime/parachains/Cargo.toml
+++ b/polkadot/runtime/parachains/Cargo.toml
@@ -30,6 +30,7 @@ sp-keystore = { optional = true, workspace = true }
sp-application-crypto = { optional = true, workspace = true }
sp-tracing = { optional = true, workspace = true }
sp-arithmetic = { workspace = true }
+sp-std = { workspace = true, optional = true }
pallet-authority-discovery = { workspace = true }
pallet-authorship = { workspace = true }
@@ -37,6 +38,7 @@ pallet-balances = { workspace = true }
pallet-babe = { workspace = true }
pallet-broker = { workspace = true }
pallet-message-queue = { workspace = true }
+pallet-mmr = { workspace = true, optional = true }
pallet-session = { workspace = true }
pallet-staking = { workspace = true }
pallet-timestamp = { workspace = true }
@@ -86,6 +88,7 @@ std = [
"pallet-balances/std",
"pallet-broker/std",
"pallet-message-queue/std",
+ "pallet-mmr?/std",
"pallet-session/std",
"pallet-staking/std",
"pallet-timestamp/std",
@@ -109,6 +112,7 @@ std = [
"sp-runtime/std",
"sp-session/std",
"sp-staking/std",
+ "sp-std?/std",
"xcm-executor/std",
"xcm/std",
]
@@ -120,6 +124,7 @@ runtime-benchmarks = [
"pallet-balances/runtime-benchmarks",
"pallet-broker/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
+ "pallet-mmr/runtime-benchmarks",
"pallet-staking/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-vesting/runtime-benchmarks",
@@ -128,6 +133,7 @@ runtime-benchmarks = [
"sp-application-crypto",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
+ "sp-std",
"static_assertions",
"xcm-executor/runtime-benchmarks",
]
@@ -141,6 +147,7 @@ try-runtime = [
"pallet-balances/try-runtime",
"pallet-broker/try-runtime",
"pallet-message-queue/try-runtime",
+ "pallet-mmr/try-runtime",
"pallet-session/try-runtime",
"pallet-staking/try-runtime",
"pallet-timestamp/try-runtime",
diff --git a/polkadot/runtime/parachains/src/paras/benchmarking.rs b/polkadot/runtime/parachains/src/paras/benchmarking.rs
index 630b86132ab8..7bf8b833ed91 100644
--- a/polkadot/runtime/parachains/src/paras/benchmarking.rs
+++ b/polkadot/runtime/parachains/src/paras/benchmarking.rs
@@ -24,6 +24,7 @@ use polkadot_primitives::{
};
use sp_runtime::traits::{One, Saturating};
+pub mod mmr_setup;
mod pvf_check;
use self::pvf_check::{VoteCause, VoteOutcome};
diff --git a/polkadot/runtime/parachains/src/paras/benchmarking/mmr_setup.rs b/polkadot/runtime/parachains/src/paras/benchmarking/mmr_setup.rs
new file mode 100644
index 000000000000..ab007692e78d
--- /dev/null
+++ b/polkadot/runtime/parachains/src/paras/benchmarking/mmr_setup.rs
@@ -0,0 +1,40 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! Implements benchmarking setup for the `merkle-mountain-range` pallet.
+
+use crate::paras::*;
+use pallet_mmr::BenchmarkHelper;
+use sp_std::vec;
+
+/// Struct to setup benchmarks for the `merkle-mountain-range` pallet.
+pub struct MmrSetup(core::marker::PhantomData);
+
+impl BenchmarkHelper for MmrSetup
+where
+ T: Config,
+{
+ fn setup() {
+ // Create a head with 1024 bytes of data.
+ let head = vec![42u8; 1024];
+
+ for para in 0..MAX_PARA_HEADS {
+ let id = (para as u32).into();
+ let h = head.clone().into();
+ Pallet::::heads_insert(&id, h);
+ }
+ }
+}
diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs
index 3f0b8659b159..a4c404de2a65 100644
--- a/polkadot/runtime/parachains/src/paras/mod.rs
+++ b/polkadot/runtime/parachains/src/paras/mod.rs
@@ -135,7 +135,7 @@ use serde::{Deserialize, Serialize};
pub use crate::Origin as ParachainOrigin;
#[cfg(feature = "runtime-benchmarks")]
-pub(crate) mod benchmarking;
+pub mod benchmarking;
#[cfg(test)]
pub(crate) mod tests;
@@ -1222,6 +1222,15 @@ const INVALID_TX_BAD_VALIDATOR_IDX: u8 = 1;
const INVALID_TX_BAD_SUBJECT: u8 = 2;
const INVALID_TX_DOUBLE_VOTE: u8 = 3;
+/// This is intermediate "fix" for this issue:
+///
+///
+/// It does not actually fix it, but makes the worst case better. Without that limit someone
+/// could completely DoS the relay chain by registering a ridiculously high amount of paras.
+/// With this limit the same attack could lead to some parachains ceasing to being able to
+/// communicate via offchain XCMP. Snowbridge will still work as it only cares about `BridgeHub`.
+pub const MAX_PARA_HEADS: usize = 1024;
+
impl Pallet {
/// This is a call to schedule code upgrades for parachains which is safe to be called
/// outside of this module. That means this function does all checks necessary to ensure
@@ -1291,6 +1300,16 @@ impl Pallet {
})
}
+ /// Get a list of the first [`MAX_PARA_HEADS`] para heads sorted by para_id.
+ /// This method is likely to be removed in the future.
+ pub fn sorted_para_heads() -> Vec<(u32, Vec)> {
+ let mut heads: Vec<(u32, Vec)> =
+ Heads::::iter().map(|(id, head)| (id.into(), head.0)).collect();
+ heads.sort_by_key(|(id, _)| *id);
+ heads.truncate(MAX_PARA_HEADS);
+ heads
+ }
+
// Apply all para actions queued for the given session index.
//
// The actions to take are based on the lifecycle of of the paras.
diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml
index f93a3ad65754..50970965e11e 100644
--- a/polkadot/runtime/rococo/Cargo.toml
+++ b/polkadot/runtime/rococo/Cargo.toml
@@ -226,6 +226,7 @@ runtime-benchmarks = [
"pallet-asset-rate/runtime-benchmarks",
"pallet-babe/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
+ "pallet-beefy-mmr/runtime-benchmarks",
"pallet-bounties/runtime-benchmarks",
"pallet-child-bounties/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
@@ -330,7 +331,10 @@ metadata-hash = ["substrate-wasm-builder/metadata-hash"]
# Set timing constants (e.g. session period) to faster versions to speed up testing.
fast-runtime = ["rococo-runtime-constants/fast-runtime"]
-runtime-metrics = ["polkadot-runtime-parachains/runtime-metrics", "sp-io/with-tracing"]
+runtime-metrics = [
+ "polkadot-runtime-parachains/runtime-metrics",
+ "sp-io/with-tracing",
+]
# A feature that should be enabled when the runtime should be built for on-chain
# deployment. This will disable stuff that shouldn't be part of the on-chain wasm
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 5adffbd7422f..c7da339b9815 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -1307,9 +1307,11 @@ impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = mmr::INDEXING_PREFIX;
type Hashing = Keccak256;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest;
- type WeightInfo = ();
type LeafData = pallet_beefy_mmr::Pallet;
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider;
+ type WeightInfo = weights::pallet_mmr::WeightInfo;
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = parachains_paras::benchmarking::mmr_setup::MmrSetup;
}
parameter_types! {
@@ -1319,13 +1321,8 @@ parameter_types! {
pub struct ParaHeadsRootProvider;
impl BeefyDataProvider for ParaHeadsRootProvider {
fn extra_data() -> H256 {
- let mut para_heads: Vec<(u32, Vec)> = parachains_paras::Parachains::::get()
- .into_iter()
- .filter_map(|id| {
- parachains_paras::Heads::::get(&id).map(|head| (id.into(), head.0))
- })
- .collect();
- para_heads.sort();
+ let para_heads: Vec<(u32, Vec)> =
+ parachains_paras::Pallet::::sorted_para_heads();
binary_merkle_tree::merkle_root::(
para_heads.into_iter().map(|pair| pair.encode()),
)
@@ -1746,6 +1743,7 @@ mod benches {
[pallet_identity, Identity]
[pallet_indices, Indices]
[pallet_message_queue, MessageQueue]
+ [pallet_mmr, Mmr]
[pallet_multisig, Multisig]
[pallet_parameters, Parameters]
[pallet_preimage, Preimage]
diff --git a/polkadot/runtime/rococo/src/weights/mod.rs b/polkadot/runtime/rococo/src/weights/mod.rs
index 3c6845dfb43e..c9204cc944fa 100644
--- a/polkadot/runtime/rococo/src/weights/mod.rs
+++ b/polkadot/runtime/rococo/src/weights/mod.rs
@@ -25,6 +25,7 @@ pub mod pallet_conviction_voting;
pub mod pallet_identity;
pub mod pallet_indices;
pub mod pallet_message_queue;
+pub mod pallet_mmr;
pub mod pallet_multisig;
pub mod pallet_nis;
pub mod pallet_parameters;
diff --git a/polkadot/runtime/rococo/src/weights/pallet_mmr.rs b/polkadot/runtime/rococo/src/weights/pallet_mmr.rs
new file mode 100644
index 000000000000..361bfc7a661b
--- /dev/null
+++ b/polkadot/runtime/rococo/src/weights/pallet_mmr.rs
@@ -0,0 +1,77 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! Autogenerated weights for `pallet_mmr`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-07-15, STEPS: `5`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/testnet/polkadot
+// benchmark
+// pallet
+// --steps=5
+// --repeat=1
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --pallet=pallet_mmr
+// --chain=westend-dev
+// --header=./polkadot/file_header.txt
+// --output=./polkadot/runtime/westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `pallet_mmr`.
+pub struct WeightInfo(PhantomData);
+impl pallet_mmr::WeightInfo for WeightInfo {
+ /// Storage: `Mmr::NumberOfLeaves` (r:1 w:1)
+ /// Proof: `Mmr::NumberOfLeaves` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
+ /// Storage: `System::ParentHash` (r:1 w:0)
+ /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
+ /// Storage: `Paras::Heads` (r:2049 w:0)
+ /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
+ /// Storage: `BeefyMmrLeaf::BeefyNextAuthorities` (r:1 w:0)
+ /// Proof: `BeefyMmrLeaf::BeefyNextAuthorities` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`)
+ /// Storage: `System::Digest` (r:1 w:1)
+ /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+ /// Storage: `Mmr::Nodes` (r:0 w:1000)
+ /// Proof: `Mmr::Nodes` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`)
+ /// Storage: `Mmr::RootHash` (r:0 w:1)
+ /// Proof: `Mmr::RootHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
+ /// The range of component `x` is `[1, 1000]`.
+ fn on_initialize(x: u32) -> Weight {
+ // Proof Size summary in bytes:
+ // Measured: `2140817`
+ // Estimated: `7213082`
+ // Minimum execution time: 20_387_000_000 picoseconds.
+ Weight::from_parts(223_625_477_528, 0)
+ .saturating_add(Weight::from_parts(0, 7213082))
+ // Standard Error: 310_550_970
+ .saturating_add(Weight::from_parts(16_906_397_286, 0).saturating_mul(x.into()))
+ .saturating_add(T::DbWeight::get().reads(2053))
+ .saturating_add(T::DbWeight::get().writes(3))
+ .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into())))
+ }
+}
diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml
index 9e739f4c7fe6..d2bafb33d2cb 100644
--- a/polkadot/runtime/westend/Cargo.toml
+++ b/polkadot/runtime/westend/Cargo.toml
@@ -240,6 +240,7 @@ runtime-benchmarks = [
"pallet-babe/runtime-benchmarks",
"pallet-bags-list/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
+ "pallet-beefy-mmr/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
"pallet-conviction-voting/runtime-benchmarks",
"pallet-delegated-staking/runtime-benchmarks",
@@ -346,7 +347,10 @@ metadata-hash = ["substrate-wasm-builder/metadata-hash"]
# Set timing constants (e.g. session period) to faster versions to speed up testing.
fast-runtime = []
-runtime-metrics = ["polkadot-runtime-parachains/runtime-metrics", "sp-io/with-tracing"]
+runtime-metrics = [
+ "polkadot-runtime-parachains/runtime-metrics",
+ "sp-io/with-tracing",
+]
# A feature that should be enabled when the runtime should be built for on-chain
# deployment. This will disable stuff that shouldn't be part of the on-chain wasm
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index f0b16e731d9e..acd6f96878c9 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -342,9 +342,11 @@ impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = mmr::INDEXING_PREFIX;
type Hashing = Keccak256;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest;
- type WeightInfo = ();
type LeafData = pallet_beefy_mmr::Pallet;
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider;
+ type WeightInfo = weights::pallet_mmr::WeightInfo;
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = parachains_paras::benchmarking::mmr_setup::MmrSetup;
}
/// MMR helper types.
@@ -366,13 +368,8 @@ parameter_types! {
pub struct ParaHeadsRootProvider;
impl BeefyDataProvider for ParaHeadsRootProvider {
fn extra_data() -> H256 {
- let mut para_heads: Vec<(u32, Vec)> = parachains_paras::Parachains::::get()
- .into_iter()
- .filter_map(|id| {
- parachains_paras::Heads::::get(&id).map(|head| (id.into(), head.0))
- })
- .collect();
- para_heads.sort_by_key(|k| k.0);
+ let para_heads: Vec<(u32, Vec)> =
+ parachains_paras::Pallet::::sorted_para_heads();
binary_merkle_tree::merkle_root::(
para_heads.into_iter().map(|pair| pair.encode()),
)
@@ -1755,6 +1752,7 @@ mod benches {
[pallet_identity, Identity]
[pallet_indices, Indices]
[pallet_message_queue, MessageQueue]
+ [pallet_mmr, Mmr]
[pallet_multisig, Multisig]
[pallet_nomination_pools, NominationPoolsBench::]
[pallet_offences, OffencesBench::]
diff --git a/polkadot/runtime/westend/src/weights/mod.rs b/polkadot/runtime/westend/src/weights/mod.rs
index f6a9008d7187..c3ed2b5a75ec 100644
--- a/polkadot/runtime/westend/src/weights/mod.rs
+++ b/polkadot/runtime/westend/src/weights/mod.rs
@@ -26,6 +26,7 @@ pub mod pallet_fast_unstake;
pub mod pallet_identity;
pub mod pallet_indices;
pub mod pallet_message_queue;
+pub mod pallet_mmr;
pub mod pallet_multisig;
pub mod pallet_nomination_pools;
pub mod pallet_preimage;
diff --git a/polkadot/runtime/westend/src/weights/pallet_mmr.rs b/polkadot/runtime/westend/src/weights/pallet_mmr.rs
new file mode 100644
index 000000000000..1a410e7fc46e
--- /dev/null
+++ b/polkadot/runtime/westend/src/weights/pallet_mmr.rs
@@ -0,0 +1,76 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! Autogenerated weights for `pallet_mmr`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-07-17, STEPS: `5`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `am1max.local`, CPU: ``
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/testnet/polkadot
+// benchmark
+// pallet
+// --steps=5
+// --repeat=1
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --pallet=pallet_mmr
+// --chain=westend-dev
+// --header=./polkadot/file_header.txt
+// --output=./polkadot/runtime/westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `pallet_mmr`.
+pub struct WeightInfo(PhantomData);
+impl pallet_mmr::WeightInfo for WeightInfo {
+ /// Storage: `Mmr::NumberOfLeaves` (r:1 w:1)
+ /// Proof: `Mmr::NumberOfLeaves` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
+ /// Storage: `System::ParentHash` (r:1 w:0)
+ /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
+ /// Storage: `Paras::Heads` (r:1025 w:0)
+ /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`)
+ /// Storage: `BeefyMmrLeaf::BeefyNextAuthorities` (r:1 w:0)
+ /// Proof: `BeefyMmrLeaf::BeefyNextAuthorities` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`)
+ /// Storage: `Mmr::Nodes` (r:8 w:4)
+ /// Proof: `Mmr::Nodes` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`)
+ /// Storage: `System::Digest` (r:1 w:1)
+ /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+ /// Storage: `Mmr::RootHash` (r:0 w:1)
+ /// Proof: `Mmr::RootHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
+ /// The range of component `x` is `[1, 1000]`.
+ fn on_initialize(x: u32, ) -> Weight {
+ // Proof Size summary in bytes:
+ // Measured: `1071043 + x * (39 ±0)`
+ // Estimated: `3608787 + x * (39 ±6)`
+ // Minimum execution time: 11_102_000_000 picoseconds.
+ Weight::from_parts(21_772_042_215, 0)
+ .saturating_add(Weight::from_parts(0, 3608787))
+ .saturating_add(T::DbWeight::get().reads(1031))
+ .saturating_add(T::DbWeight::get().writes(4))
+ .saturating_add(Weight::from_parts(0, 39).saturating_mul(x.into()))
+ }
+}
diff --git a/prdoc/pr_4751.prdoc b/prdoc/pr_4751.prdoc
new file mode 100644
index 000000000000..5a2c42209088
--- /dev/null
+++ b/prdoc/pr_4751.prdoc
@@ -0,0 +1,22 @@
+title: "Use all parachain heads for BEEFY MMR extra data"
+
+doc:
+ - audience: Runtime Dev
+ description: |
+ Previously, the extra data in an MMR leaf nodes was only computed based on lease-based parachain heads.
+ This PR extends the extra data to include others, including on-demand parachain heads.
+ Currently, the number of heads is limited to the first 1024 heads sorted by para id.
+
+crates:
+ - name: polkadot-runtime-parachains
+ bump: minor
+ - name: rococo-runtime
+ bump: minor
+ - name: westend-runtime
+ bump: minor
+ - name: pallet-mmr
+ bump: major
+ - name: pallet-beefy-mmr
+ bump: minor
+ - name: polkadot-sdk
+ bump: minor
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index a1896325ee93..78c7bba64579 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -1605,6 +1605,8 @@ impl pallet_mmr::Config for Runtime {
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest;
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider;
type WeightInfo = ();
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = ();
}
parameter_types! {
diff --git a/substrate/frame/beefy-mmr/Cargo.toml b/substrate/frame/beefy-mmr/Cargo.toml
index 11a7b281e87d..92e903af138d 100644
--- a/substrate/frame/beefy-mmr/Cargo.toml
+++ b/substrate/frame/beefy-mmr/Cargo.toml
@@ -64,3 +64,10 @@ try-runtime = [
"pallet-session/try-runtime",
"sp-runtime/try-runtime",
]
+runtime-benchmarks = [
+ "frame-support/runtime-benchmarks",
+ "frame-system/runtime-benchmarks",
+ "pallet-mmr/runtime-benchmarks",
+ "sp-runtime/runtime-benchmarks",
+ "sp-staking/runtime-benchmarks",
+]
diff --git a/substrate/frame/beefy-mmr/src/mock.rs b/substrate/frame/beefy-mmr/src/mock.rs
index 0521bdabbe49..3adef4f32bf4 100644
--- a/substrate/frame/beefy-mmr/src/mock.rs
+++ b/substrate/frame/beefy-mmr/src/mock.rs
@@ -93,6 +93,9 @@ impl pallet_mmr::Config for Test {
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider;
type WeightInfo = ();
+
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = ();
}
impl pallet_beefy::Config for Test {
diff --git a/substrate/frame/merkle-mountain-range/src/benchmarking.rs b/substrate/frame/merkle-mountain-range/src/benchmarking.rs
index 9eb676a4ee44..07afd9529eb2 100644
--- a/substrate/frame/merkle-mountain-range/src/benchmarking.rs
+++ b/substrate/frame/merkle-mountain-range/src/benchmarking.rs
@@ -28,10 +28,13 @@ benchmarks_instance_pallet! {
let x in 1 .. 1_000;
let leaves = x as NodeIndex;
- }: {
- for b in 0..leaves {
- Pallet::::on_initialize((b as u32).into());
+
+ <>::BenchmarkHelper as BenchmarkHelper>::setup();
+ for leaf in 0..(leaves - 1) {
+ Pallet::::on_initialize((leaf as u32).into());
}
+ }: {
+ Pallet::::on_initialize((leaves as u32 - 1).into());
} verify {
assert_eq!(crate::NumberOfLeaves::::get(), leaves);
}
diff --git a/substrate/frame/merkle-mountain-range/src/default_weights.rs b/substrate/frame/merkle-mountain-range/src/default_weights.rs
index 52e3f130383f..b0ef0539018c 100644
--- a/substrate/frame/merkle-mountain-range/src/default_weights.rs
+++ b/substrate/frame/merkle-mountain-range/src/default_weights.rs
@@ -24,7 +24,8 @@ use frame_support::weights::{
};
impl crate::WeightInfo for () {
- fn on_initialize(peaks: u64) -> Weight {
+ fn on_initialize(peaks: u32) -> Weight {
+ let peaks = u64::from(peaks);
// Reading the parent hash.
let leaf_weight = DbWeight::get().reads(1);
// Blake2 hash cost.
diff --git a/substrate/frame/merkle-mountain-range/src/lib.rs b/substrate/frame/merkle-mountain-range/src/lib.rs
index cacb33b50434..0ab44711bcf5 100644
--- a/substrate/frame/merkle-mountain-range/src/lib.rs
+++ b/substrate/frame/merkle-mountain-range/src/lib.rs
@@ -124,7 +124,18 @@ impl BlockHashProvider, T::Hash>
}
pub trait WeightInfo {
- fn on_initialize(peaks: NodeIndex) -> Weight;
+ fn on_initialize(peaks: u32) -> Weight;
+}
+
+/// This trait decoples dependencies on pallets needed for benchmarking.
+#[cfg(feature = "runtime-benchmarks")]
+pub trait BenchmarkHelper {
+ fn setup();
+}
+
+#[cfg(feature = "runtime-benchmarks")]
+impl BenchmarkHelper for () {
+ fn setup() {}
}
/// An MMR specific to the pallet.
@@ -205,6 +216,10 @@ pub mod pallet {
/// Weights for this pallet.
type WeightInfo: WeightInfo;
+
+ /// Benchmarking setup helper trait.
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper: BenchmarkHelper;
}
/// Latest MMR Root hash.
@@ -238,14 +253,14 @@ pub mod pallet {
// MMR push never fails, but better safe than sorry.
if mmr.push(data).is_none() {
log::error!(target: "runtime::mmr", "MMR push failed");
- return T::WeightInfo::on_initialize(peaks_before)
+ return T::WeightInfo::on_initialize(peaks_before as u32)
}
// Update the size, `mmr.finalize()` should also never fail.
let (leaves, root) = match mmr.finalize() {
Ok((leaves, root)) => (leaves, root),
Err(e) => {
log::error!(target: "runtime::mmr", "MMR finalize failed: {:?}", e);
- return T::WeightInfo::on_initialize(peaks_before)
+ return T::WeightInfo::on_initialize(peaks_before as u32)
},
};
>::on_new_root(&root);
@@ -255,7 +270,7 @@ pub mod pallet {
let peaks_after = sp_mmr_primitives::utils::NodesUtils::new(leaves).number_of_peaks();
- T::WeightInfo::on_initialize(peaks_before.max(peaks_after))
+ T::WeightInfo::on_initialize(peaks_before.max(peaks_after) as u32)
}
}
}
diff --git a/substrate/frame/merkle-mountain-range/src/mock.rs b/substrate/frame/merkle-mountain-range/src/mock.rs
index 8318b20e8307..606719c6deba 100644
--- a/substrate/frame/merkle-mountain-range/src/mock.rs
+++ b/substrate/frame/merkle-mountain-range/src/mock.rs
@@ -46,6 +46,8 @@ impl Config for Test {
type OnNewRoot = ();
type BlockHashProvider = DefaultBlockHashProvider;
type WeightInfo = ();
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = ();
}
#[derive(Encode, Decode, Clone, Default, Eq, PartialEq, Debug)]
diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml
index 94ba09421d40..79e7c0c38eda 100644
--- a/umbrella/Cargo.toml
+++ b/umbrella/Cargo.toml
@@ -269,6 +269,7 @@ runtime-benchmarks = [
"pallet-babe?/runtime-benchmarks",
"pallet-bags-list?/runtime-benchmarks",
"pallet-balances?/runtime-benchmarks",
+ "pallet-beefy-mmr?/runtime-benchmarks",
"pallet-bounties?/runtime-benchmarks",
"pallet-bridge-grandpa?/runtime-benchmarks",
"pallet-bridge-messages?/runtime-benchmarks",