Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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.

9 changes: 8 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 All @@ -40,6 +41,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 @@ -50,6 +52,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 @@ -58,15 +63,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 @@ -87,6 +93,7 @@ std = [
"log/std",
"pallet-message-queue/std",
"polkadot-parachain-primitives/std",
"polkadot-primitives/std",
"polkadot-runtime-parachains/std",
"scale-info/std",
"sp-consensus-babe/std",
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