Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
210 changes: 206 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,31 @@
#![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},
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 +83,189 @@ 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::FractionOfCore {
first_transaction_index: 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::FullCore);
assert!(has_use_full_core_digest::<T>());
assert_eq!(
MaxParachainBlockWeight::<T, ConstU32<4>>::get(),
MaxParachainBlockWeight::<T, ConstU32<4>>::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::FractionOfCore {
first_transaction_index: 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::FractionOfCore { first_transaction_index: 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>::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::FullCore);

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::FullCore);

Ok(())
}

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