Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
df7f0fe
Introduce `MaxParachainBlockWeight` and related functionality
bkchr Nov 13, 2025
e73e10e
Merge remote-tracking branch 'origin/master' into bkchr-parachain-blo…
bkchr Nov 13, 2025
2712aef
Update cumulus/pallets/parachain-system/src/block_weight/transaction_…
bkchr Nov 14, 2025
2917609
Update cumulus/pallets/parachain-system/src/block_weight/transaction_…
bkchr Nov 14, 2025
86ad20f
New test and some fixes
bkchr Nov 14, 2025
5b5190b
Ensure we ignore the block weight mode from the previous block
bkchr Nov 14, 2025
a8641d6
Update cumulus/pallets/parachain-system/src/validate_block/implementa…
bkchr Nov 14, 2025
eba0d14
Allow MBMs to take the full core
bkchr Nov 14, 2025
9de019e
Fixes
bkchr Nov 14, 2025
58620b1
Merge remote-tracking branch 'refs/remotes/origin/bkchr-parachain-blo…
bkchr Nov 14, 2025
8901237
Fix benchmark
bkchr Nov 14, 2025
ef27858
FMT
bkchr Nov 14, 2025
066cd7c
Support full core weight for pre transactions
bkchr Nov 18, 2025
0b98e3f
Fix unsigned transactions
bkchr Nov 19, 2025
3499274
Respect the dispatch class max weight
bkchr Nov 19, 2025
1cea268
Fix `on_idle`
bkchr Nov 19, 2025
5ed9e29
Test `on_poll`
bkchr Nov 20, 2025
3404f67
More docs
bkchr Nov 20, 2025
e262e6c
Merge remote-tracking branch 'origin/master' into bkchr-parachain-blo…
bkchr Dec 2, 2025
836b091
Fix test
bkchr Dec 3, 2025
915f6ae
Update from github-actions[bot] running command 'fmt'
github-actions[bot] Dec 4, 2025
ee19d58
Ensure we support uneven number of blocks
bkchr Dec 10, 2025
001c7de
Make clippy happy
bkchr Dec 11, 2025
ea5c5d9
Ensure we check the block weight after executing a transaction
bkchr Dec 15, 2025
a92ca43
Review feedback
bkchr Feb 6, 2026
406d101
Merge remote-tracking branch 'origin/master' into bkchr-parachain-blo…
bkchr Feb 6, 2026
535054f
Ensure UMP + HRMP messages fit into the limits
bkchr Feb 9, 2026
2c42cbb
Merge remote-tracking branch 'origin/master' into bkchr-parachain-blo…
bkchr Mar 10, 2026
44911d4
Also take the size into account for UMP messages
bkchr Mar 10, 2026
3f04aaf
Update from github-actions[bot] running command 'fmt'
github-actions[bot] Mar 10, 2026
249b846
Prdoc + fixes
bkchr Mar 10, 2026
39f6ffc
More fixes
bkchr Mar 10, 2026
eacf91b
Fix errors
bkchr Mar 11, 2026
d3e8abb
Better tracking
bkchr Mar 12, 2026
9766f5d
Docs
bkchr Mar 12, 2026
0d96d86
Merge branch 'master' into bkchr-parachain-block-weight
bkchr Mar 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion cumulus/pallets/parachain-system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ workspace = true
array-bytes = { workspace = true }
bytes = { workspace = true }
codec = { features = ["derive"], workspace = true }
derive-where = { workspace = true }
environmental = { workspace = true }
hashbrown = { workspace = true }
impl-trait-for-tuples = { workspace = true }
Expand Down Expand Up @@ -42,6 +43,7 @@ sp-version = { workspace = true }

# Polkadot
polkadot-parachain-primitives = { features = ["wasm-api"], workspace = true }
polkadot-primitives = { workspace = true }
polkadot-runtime-parachains = { workspace = true }
xcm = { workspace = true }
xcm-builder = { workspace = true }
Expand All @@ -52,6 +54,9 @@ cumulus-primitives-core = { workspace = true }
cumulus-primitives-parachain-inherent = { workspace = true }
cumulus-primitives-proof-size-hostfunction = { workspace = true }

# For building docs
docify = { workspace = true }

[dev-dependencies]
assert_matches = { workspace = true }
futures = { workspace = true }
Expand All @@ -60,15 +65,16 @@ rand = { workspace = true, default-features = true }
rstest = { workspace = true }
trie-standardmap = { workspace = true }


# Substrate
frame-executive = { workspace = true }
sc-consensus = { workspace = true }
sp-api = { workspace = true, default-features = true }
sp-consensus-slots = { workspace = true, default-features = true }
sp-crypto-hashing = { workspace = true, default-features = true }
sp-keyring = { workspace = true, default-features = true }
sp-tracing = { workspace = true, default-features = true }
sp-version = { workspace = true, default-features = true }

# Cumulus
cumulus-test-client = { workspace = true }
cumulus-test-relay-sproof-builder = { workspace = true, default-features = true }
Expand All @@ -84,11 +90,13 @@ std = [
"cumulus-primitives-proof-size-hostfunction/std",
"environmental/std",
"frame-benchmarking/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-message-queue/std",
"polkadot-parachain-primitives/std",
"polkadot-primitives/std",
"polkadot-runtime-parachains/std",
"scale-info/std",
"sp-api/std",
Expand Down Expand Up @@ -116,13 +124,15 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm/runtime-benchmarks",
]

try-runtime = [
"frame-executive/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-message-queue/try-runtime",
Expand Down
207 changes: 203 additions & 4 deletions cumulus/pallets/parachain-system/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,33 @@
#![cfg(feature = "runtime-benchmarks")]

use super::*;
use crate::parachain_inherent::InboundDownwardMessages;
use cumulus_primitives_core::{relay_chain::Hash as RelayHash, InboundDownwardMessage};
use crate::{
block_weight::{
BlockWeightMode, DynamicMaxBlockWeight, MaxParachainBlockWeight, FULL_CORE_WEIGHT,
},
parachain_inherent::InboundDownwardMessages,
};
use cumulus_primitives_core::{
relay_chain::Hash as RelayHash, BundleInfo, CoreInfo, InboundDownwardMessage,
};
use frame_benchmarking::v2::*;
use sp_runtime::traits::BlakeTwo256;
use frame_support::{
dispatch::{DispatchInfo, PostDispatchInfo},
weights::constants::WEIGHT_REF_TIME_PER_SECOND,
};
use frame_system::RawOrigin;
use sp_core::ConstU32;
use sp_runtime::traits::{BlakeTwo256, DispatchTransaction, Dispatchable};

#[benchmarks]
fn has_use_full_core_digest<T: Config>() -> bool {
let digest = frame_system::Pallet::<T>::digest();
CumulusDigestItem::contains_use_full_core(&digest)
}

#[benchmarks(where
T: Send + Sync,
T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
)]
mod benchmarks {
use super::*;

Expand Down Expand Up @@ -64,6 +85,184 @@ mod benchmarks {
head
}

/// The worst-case scenario for the block weight transaction extension.
///
/// Before executing an extrinsic `FractionOfCore` is set, changed to `PotentialFullCore` and
/// post dispatch switches to `FullCore`.
#[benchmark]
fn block_weight_tx_extension_max_weight() -> Result<(), BenchmarkError> {
let caller = account("caller", 0, 0);

frame_system::Pallet::<T>::note_inherents_applied();

frame_system::Pallet::<T>::set_extrinsic_index(1);

frame_system::Pallet::<T>::deposit_log(
BundleInfo { index: 0, maybe_last: false }.to_digest_item(),
);
frame_system::Pallet::<T>::deposit_log(
CoreInfo {
selector: 0.into(),
claim_queue_offset: 0.into(),
number_of_cores: 1.into(),
}
.to_digest_item(),
);
let target_weight = MaxParachainBlockWeight::<T, ConstU32<4>>::target_block_weight();

let info = DispatchInfo {
// The weight needs to be more than the target weight.
call_weight: target_weight
.saturating_add(Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, 0)),
extension_weight: Weight::zero(),
class: DispatchClass::Normal,
..Default::default()
};
let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into();
let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Default::default() };
let len = 0_usize;

crate::BlockWeightMode::<T>::put(BlockWeightMode::fraction_of_core(None));

let ext = DynamicMaxBlockWeight::<T, (), ConstU32<4>>::new(());

#[block]
{
ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, 0, |_| {
// Normally this is done by `CheckWeight`
frame_system::Pallet::<T>::register_extra_weight_unchecked(
info.call_weight,
DispatchClass::Normal,
);
Ok(post_info)
})
.unwrap()
.unwrap();
}

assert_eq!(crate::BlockWeightMode::<T>::get().unwrap(), BlockWeightMode::full_core());
assert!(has_use_full_core_digest::<T>());
assert_eq!(MaxParachainBlockWeight::<T, ConstU32<4>>::get(), FULL_CORE_WEIGHT);

Ok(())
}

/// A benchmark that assumes that an extrinsic was executed with `FractionOfCore` set.
#[benchmark]
fn block_weight_tx_extension_stays_fraction_of_core() -> Result<(), BenchmarkError> {
let caller = account("caller", 0, 0);

frame_system::Pallet::<T>::note_inherents_applied();

frame_system::Pallet::<T>::set_extrinsic_index(1);

frame_system::Pallet::<T>::deposit_log(
BundleInfo { index: 0, maybe_last: false }.to_digest_item(),
);
frame_system::Pallet::<T>::deposit_log(
CoreInfo {
selector: 0.into(),
claim_queue_offset: 0.into(),
number_of_cores: 1.into(),
}
.to_digest_item(),
);
let target_weight = MaxParachainBlockWeight::<T, ConstU32<4>>::target_block_weight();

let info = DispatchInfo {
call_weight: Weight::from_parts(1024, 1024),
extension_weight: Weight::zero(),
class: DispatchClass::Normal,
..Default::default()
};
let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into();
let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Default::default() };
let len = 0_usize;

crate::BlockWeightMode::<T>::put(BlockWeightMode::fraction_of_core(None));

let ext = DynamicMaxBlockWeight::<T, (), ConstU32<4>>::new(());

#[block]
{
ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, 0, |_| {
// Normally this is done by `CheckWeight`
frame_system::Pallet::<T>::register_extra_weight_unchecked(
info.call_weight,
DispatchClass::Normal,
);
Ok(post_info)
})
.unwrap()
.unwrap();
}

assert_eq!(
crate::BlockWeightMode::<T>::get().unwrap(),
BlockWeightMode::fraction_of_core(Some(1))
);
assert!(!has_use_full_core_digest::<T>());
assert_eq!(MaxParachainBlockWeight::<T, ConstU32<4>>::get(), target_weight);

Ok(())
}

/// A benchmark that assumes that `FullCore` was set already before executing an extrinsic.
#[benchmark]
fn block_weight_tx_extension_full_core() -> Result<(), BenchmarkError> {
let caller = account("caller", 0, 0);

frame_system::Pallet::<T>::set_block_number(1u32.into());

frame_system::Pallet::<T>::note_inherents_applied();

frame_system::Pallet::<T>::set_extrinsic_index(1);

frame_system::Pallet::<T>::deposit_log(
BundleInfo { index: 0, maybe_last: false }.to_digest_item(),
);
frame_system::Pallet::<T>::deposit_log(
CoreInfo {
selector: 0.into(),
claim_queue_offset: 0.into(),
number_of_cores: 1.into(),
}
.to_digest_item(),
);

let info = DispatchInfo {
call_weight: Weight::from_parts(1024, 1024),
extension_weight: Weight::zero(),
class: DispatchClass::Normal,
..Default::default()
};
let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into();
let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Default::default() };
let len = 0_usize;

crate::BlockWeightMode::<T>::put(BlockWeightMode::full_core());

let ext = DynamicMaxBlockWeight::<T, (), ConstU32<4>>::new(());

#[block]
{
ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, 0, |_| {
// Normally this is done by `CheckWeight`
frame_system::Pallet::<T>::register_extra_weight_unchecked(
info.call_weight,
DispatchClass::Normal,
);
Ok(post_info)
})
.unwrap()
.unwrap();
}

assert_eq!(crate::BlockWeightMode::<T>::get().unwrap(), BlockWeightMode::full_core());

Ok(())
}

impl_benchmark_test_suite! {
Pallet,
crate::mock::new_test_ext(),
Expand Down
Loading
Loading