From e51e296631f82f6ed9e409ab061834476dc8938e Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Thu, 30 Oct 2025 08:45:09 +0800 Subject: [PATCH 1/5] add authority benchmarks --- authority/Cargo.toml | 3 + authority/src/benchmarking.rs | 263 ++++++++++++++++++++++++++++++++++ authority/src/lib.rs | 7 + authority/src/mock.rs | 11 ++ 4 files changed, 284 insertions(+) create mode 100644 authority/src/benchmarking.rs diff --git a/authority/Cargo.toml b/authority/Cargo.toml index bed4752dc..b7918e347 100644 --- a/authority/Cargo.toml +++ b/authority/Cargo.toml @@ -12,6 +12,7 @@ parity-scale-codec = { workspace = true } scale-info = { workspace = true } serde = { workspace = true, optional = true } +frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } sp-core = { workspace = true } @@ -28,6 +29,7 @@ sp-io = { workspace = true, features = ["std"] } [features] default = [ "std" ] std = [ + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "parity-scale-codec/std", @@ -39,6 +41,7 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/authority/src/benchmarking.rs b/authority/src/benchmarking.rs new file mode 100644 index 000000000..2ec6ec8d9 --- /dev/null +++ b/authority/src/benchmarking.rs @@ -0,0 +1,263 @@ +pub use crate::*; + +use frame_benchmarking::v2::*; +use frame_support::assert_ok; +use frame_system::RawOrigin; +use sp_std::vec; + +/// Helper trait for benchmarking. +pub trait BenchmarkHelper { + fn get_as_origin_id_root() -> Option; +} + +impl BenchmarkHelper for () { + fn get_as_origin_id_root() -> Option { + None + } +} + +#[benchmarks(where + ::RuntimeCall: From> +)] +mod benchmarks { + use super::*; + + // dispatch a dispatchable as other origin + #[benchmark] + fn dispatch_as() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let call = frame_system::Call::remark { remark: vec![] }.into(); + + #[extrinsic_call] + _(RawOrigin::Root, as_origin, Box::new(call)); + } + + // schedule a dispatchable to be dispatched at later block. + #[benchmark] + fn schedule_dispatch_without_delay() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let sub_call = frame_system::Call::remark { remark: vec![] }.into(); + + let call: Call = Call::dispatch_as { + as_origin: as_origin, + call: Box::new(sub_call), + }; + + let encoded_call = call.encode(); + let bounded_call = Box::new(Bounded::Inline(encoded_call.try_into().unwrap())); + + #[extrinsic_call] + schedule_dispatch(RawOrigin::Root, DispatchTime::At(2u32.into()), 0, false, bounded_call); + } + + // schedule a dispatchable to be dispatched at later block. + // ensure that the delay is reached when scheduling + #[benchmark] + fn schedule_dispatch_with_delay() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let sub_call = frame_system::Call::remark { remark: vec![] }.into(); + + let call: Call = Call::dispatch_as { + as_origin: as_origin, + call: Box::new(sub_call), + }; + + let encoded_call = call.encode(); + let bounded_call = Box::new(Bounded::Inline(encoded_call.try_into().unwrap())); + + #[extrinsic_call] + schedule_dispatch(RawOrigin::Root, DispatchTime::At(2u32.into()), 0, true, bounded_call); + } + + // fast track a scheduled dispatchable. + #[benchmark] + fn fast_track_scheduled_dispatch() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let sub_call = frame_system::Call::remark { remark: vec![] }.into(); + + let call: Call = Call::dispatch_as { + as_origin: as_origin, + call: Box::new(sub_call), + }; + + let encoded_call = call.encode(); + let bounded_call = Box::new(Bounded::Inline(encoded_call.try_into().unwrap())); + + frame_system::Pallet::::set_block_number(1u32.into()); + assert_ok!(Pallet::::schedule_dispatch( + ::RuntimeOrigin::root(), + DispatchTime::At(2u32.into()), + 0, + true, + bounded_call + )); + + let schedule_origin = { + let origin: ::RuntimeOrigin = From::from(::RuntimeOrigin::root()); + let origin: ::RuntimeOrigin = + From::from(DelayedOrigin::, ::PalletsOrigin>::new( + 1u32.into(), + Box::new(origin.caller().clone()), + )); + origin + }; + + let pallets_origin = schedule_origin.caller().clone(); + + #[extrinsic_call] + fast_track_scheduled_dispatch( + RawOrigin::Root, + Box::new(pallets_origin), + 0, + DispatchTime::At(4u32.into()), + ); + } + + // delay a scheduled dispatchable. + #[benchmark] + fn delay_scheduled_dispatch() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let sub_call = frame_system::Call::remark { remark: vec![] }.into(); + + let call: Call = Call::dispatch_as { + as_origin: as_origin, + call: Box::new(sub_call), + }; + + let encoded_call = call.encode(); + let bounded_call = Box::new(Bounded::Inline(encoded_call.try_into().unwrap())); + + frame_system::Pallet::::set_block_number(1u32.into()); + assert_ok!(Pallet::::schedule_dispatch( + ::RuntimeOrigin::root(), + DispatchTime::At(2u32.into()), + 0, + true, + bounded_call + )); + + let schedule_origin = { + let origin: ::RuntimeOrigin = From::from(::RuntimeOrigin::root()); + let origin: ::RuntimeOrigin = + From::from(DelayedOrigin::, ::PalletsOrigin>::new( + 1u32.into(), + Box::new(origin.caller().clone()), + )); + origin + }; + + let pallets_origin = schedule_origin.caller().clone(); + + #[extrinsic_call] + _(RawOrigin::Root, Box::new(pallets_origin), 0, 5u32.into()); + } + + // cancel a scheduled dispatchable + #[benchmark] + fn cancel_scheduled_dispatch() { + let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + + let sub_call = frame_system::Call::remark { remark: vec![] }.into(); + + let call: Call = Call::dispatch_as { + as_origin: as_origin, + call: Box::new(sub_call), + }; + + let encoded_call = call.encode(); + let bounded_call = Box::new(Bounded::Inline(encoded_call.try_into().unwrap())); + + frame_system::Pallet::::set_block_number(1u32.into()); + assert_ok!(Pallet::::schedule_dispatch( + ::RuntimeOrigin::root(), + DispatchTime::At(2u32.into()), + 0, + true, + bounded_call + )); + + let schedule_origin = { + let origin: ::RuntimeOrigin = From::from(::RuntimeOrigin::root()); + let origin: ::RuntimeOrigin = + From::from(DelayedOrigin::, ::PalletsOrigin>::new( + 1u32.into(), + Box::new(origin.caller().clone()), + )); + origin + }; + + let pallets_origin = schedule_origin.caller().clone(); + + #[extrinsic_call] + _(RawOrigin::Root, Box::new(pallets_origin), 0u32.into()); + } + + // authorize a call that can be triggered later + #[benchmark] + fn authorize_call() { + let caller: T::AccountId = whitelisted_caller(); + + let call: ::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + let hash = ::Hashing::hash_of(&call); + + frame_system::Pallet::::set_block_number(1u32.into()); + + #[extrinsic_call] + _(RawOrigin::Root, Box::new(call.clone()), Some(caller.clone())); + + assert_eq!(Pallet::::saved_calls(&hash), Some((call, Some(caller)))); + } + + #[benchmark] + fn remove_authorized_call() { + let caller: T::AccountId = whitelisted_caller(); + + let call: ::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + let hash = ::Hashing::hash_of(&call); + + frame_system::Pallet::::set_block_number(1u32.into()); + assert_ok!(Pallet::::authorize_call( + RawOrigin::Root.into(), + Box::new(call.clone()), + Some(caller.clone()) + )); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), hash); + + assert_eq!(Pallet::::saved_calls(&hash), None); + } + + #[benchmark] + fn trigger_call() { + let caller: T::AccountId = whitelisted_caller(); + + let call: ::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + let hash = ::Hashing::hash_of(&call); + + let call_weight_bound = call.get_dispatch_info().call_weight; + + frame_system::Pallet::::set_block_number(1u32.into()); + assert_ok!(Pallet::::authorize_call( + RawOrigin::Root.into(), + Box::new(call.clone()), + Some(caller.clone()) + )); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), hash, call_weight_bound); + + assert_eq!(Pallet::::saved_calls(&hash), None); + } + + impl_benchmark_test_suite! { + Pallet, + crate::mock::ExtBuilder::default().build(), + crate::mock::Runtime, + } +} diff --git a/authority/src/lib.rs b/authority/src/lib.rs index 8d4c15b75..ffe57e375 100644 --- a/authority/src/lib.rs +++ b/authority/src/lib.rs @@ -49,10 +49,14 @@ use sp_std::prelude::*; use frame_support::traits::schedule::v3::Named as ScheduleNamed; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; mod mock; mod tests; mod weights; +#[cfg(feature = "runtime-benchmarks")] +pub use benchmarking::BenchmarkHelper; pub use weights::WeightInfo; /// A delayed origin. Can only be dispatched via `dispatch_as` with a delay. @@ -238,6 +242,9 @@ pub mod module { /// Weight information for extrinsics in this module. type WeightInfo: WeightInfo; + + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper: BenchmarkHelper; } #[pallet::error] diff --git a/authority/src/mock.rs b/authority/src/mock.rs index da8e5e720..1993e19e7 100644 --- a/authority/src/mock.rs +++ b/authority/src/mock.rs @@ -137,6 +137,15 @@ impl AsOriginId for MockAsOriginId { } } +#[cfg(feature = "runtime-benchmarks")] +pub struct MockBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for MockBenchmarkHelper { + fn get_as_origin_id_root() -> Option { + Some(MockAsOriginId::Root) + } +} + impl Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type PalletsOrigin = OriginCaller; @@ -145,6 +154,8 @@ impl Config for Runtime { type AsOriginId = MockAsOriginId; type AuthorityConfig = AuthorityConfigImpl; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = MockBenchmarkHelper; } type Block = frame_system::mocking::MockBlock; From bd93744a818d121bc084bf136bb84e9e3588f1db Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Thu, 30 Oct 2025 09:36:51 +0800 Subject: [PATCH 2/5] fix --- authority/src/benchmarking.rs | 16 ++++++++-------- authority/src/mock.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/authority/src/benchmarking.rs b/authority/src/benchmarking.rs index 2ec6ec8d9..7db1e7780 100644 --- a/authority/src/benchmarking.rs +++ b/authority/src/benchmarking.rs @@ -7,11 +7,11 @@ use sp_std::vec; /// Helper trait for benchmarking. pub trait BenchmarkHelper { - fn get_as_origin_id_root() -> Option; + fn get_as_origin_id() -> Option; } impl BenchmarkHelper for () { - fn get_as_origin_id_root() -> Option { + fn get_as_origin_id() -> Option { None } } @@ -25,7 +25,7 @@ mod benchmarks { // dispatch a dispatchable as other origin #[benchmark] fn dispatch_as() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let call = frame_system::Call::remark { remark: vec![] }.into(); @@ -36,7 +36,7 @@ mod benchmarks { // schedule a dispatchable to be dispatched at later block. #[benchmark] fn schedule_dispatch_without_delay() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let sub_call = frame_system::Call::remark { remark: vec![] }.into(); @@ -56,7 +56,7 @@ mod benchmarks { // ensure that the delay is reached when scheduling #[benchmark] fn schedule_dispatch_with_delay() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let sub_call = frame_system::Call::remark { remark: vec![] }.into(); @@ -75,7 +75,7 @@ mod benchmarks { // fast track a scheduled dispatchable. #[benchmark] fn fast_track_scheduled_dispatch() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let sub_call = frame_system::Call::remark { remark: vec![] }.into(); @@ -120,7 +120,7 @@ mod benchmarks { // delay a scheduled dispatchable. #[benchmark] fn delay_scheduled_dispatch() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let sub_call = frame_system::Call::remark { remark: vec![] }.into(); @@ -160,7 +160,7 @@ mod benchmarks { // cancel a scheduled dispatchable #[benchmark] fn cancel_scheduled_dispatch() { - let as_origin = T::BenchmarkHelper::get_as_origin_id_root().unwrap(); + let as_origin = T::BenchmarkHelper::get_as_origin_id().unwrap(); let sub_call = frame_system::Call::remark { remark: vec![] }.into(); diff --git a/authority/src/mock.rs b/authority/src/mock.rs index 1993e19e7..c7602b591 100644 --- a/authority/src/mock.rs +++ b/authority/src/mock.rs @@ -141,7 +141,7 @@ impl AsOriginId for MockAsOriginId { pub struct MockBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] impl BenchmarkHelper for MockBenchmarkHelper { - fn get_as_origin_id_root() -> Option { + fn get_as_origin_id() -> Option { Some(MockAsOriginId::Root) } } From 03e7e8fefc7a2d37945add2280e036de623b5687 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Fri, 31 Oct 2025 13:26:34 +0800 Subject: [PATCH 3/5] update --- tokens/src/benchmarking.rs | 12 ++++++------ vesting/src/benchmarking.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tokens/src/benchmarking.rs b/tokens/src/benchmarking.rs index 83856b15e..097b16da5 100644 --- a/tokens/src/benchmarking.rs +++ b/tokens/src/benchmarking.rs @@ -34,7 +34,7 @@ mod benchmarks { )); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); #[extrinsic_call] _(RawOrigin::Signed(from), to_lookup, currency_id, amount); @@ -55,7 +55,7 @@ mod benchmarks { )); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); #[extrinsic_call] _(RawOrigin::Signed(from.clone()), to_lookup, currency_id, false); @@ -79,7 +79,7 @@ mod benchmarks { )); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); #[extrinsic_call] _(RawOrigin::Signed(from), to_lookup, currency_id, amount); @@ -93,7 +93,7 @@ mod benchmarks { #[benchmark] fn force_transfer() { let from: T::AccountId = account("from", 0, 0); - let from_lookup = ::Lookup::unlookup(from.clone()); + let from_lookup = T::Lookup::unlookup(from.clone()); let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); @@ -104,7 +104,7 @@ mod benchmarks { )); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); #[extrinsic_call] _(RawOrigin::Root, from_lookup, to_lookup, currency_id, amount); @@ -118,7 +118,7 @@ mod benchmarks { #[benchmark] fn set_balance() { let who: T::AccountId = account("who", 0, 0); - let who_lookup = ::Lookup::unlookup(who.clone()); + let who_lookup = T::Lookup::unlookup(who.clone()); let (currency_id, amount) = T::BenchmarkHelper::get_currency_id_and_amount().unwrap(); diff --git a/vesting/src/benchmarking.rs b/vesting/src/benchmarking.rs index 0389b7949..578bccf12 100644 --- a/vesting/src/benchmarking.rs +++ b/vesting/src/benchmarking.rs @@ -46,7 +46,7 @@ mod benchmarks { set_balance::(&from, schedule.total_amount().unwrap() + amount); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); #[extrinsic_call] _(RawOrigin::Signed(from), to_lookup, schedule.clone()); @@ -71,7 +71,7 @@ mod benchmarks { ); let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); for _ in 0..i { schedule.start = i.into(); @@ -102,7 +102,7 @@ mod benchmarks { }; let to: T::AccountId = account("to", 0, 0); - let to_lookup = ::Lookup::unlookup(to.clone()); + let to_lookup = T::Lookup::unlookup(to.clone()); set_balance::(&to, schedule.total_amount().unwrap().saturating_mul(i.into())); From 6514248445c9cd161ee26328d63061ef74e19fc1 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Fri, 31 Oct 2025 17:17:33 +0800 Subject: [PATCH 4/5] update --- auction/src/benchmarking.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/auction/src/benchmarking.rs b/auction/src/benchmarking.rs index 7d58c6e18..4164b178f 100644 --- a/auction/src/benchmarking.rs +++ b/auction/src/benchmarking.rs @@ -2,7 +2,7 @@ pub use crate::*; use frame_benchmarking::v2::*; use frame_support::assert_ok; -use frame_system::{EventRecord, RawOrigin}; +use frame_system::RawOrigin; /// Helper trait for benchmarking. pub trait BenchmarkHelper { @@ -58,12 +58,8 @@ impl BenchmarkHelper, T::AccountId, T::Balance> for } } -fn assert_last_event(generic_event: ::RuntimeEvent) { - let events = frame_system::Pallet::::events(); - let system_event: ::RuntimeEvent = generic_event.into(); - // compare to the last event record - let EventRecord { event, .. } = &events[events.len() - 1]; - assert_eq!(event, &system_event); +fn assert_last_event(generic_event: T::RuntimeEvent) { + frame_system::Pallet::::assert_last_event(generic_event.into()); } #[benchmarks] From b13c1fc76a05d972d3d8ce1bcbde0440f43db6a3 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Fri, 31 Oct 2025 17:30:50 +0800 Subject: [PATCH 5/5] update --- auction/src/benchmarking.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/auction/src/benchmarking.rs b/auction/src/benchmarking.rs index 4164b178f..dcf183957 100644 --- a/auction/src/benchmarking.rs +++ b/auction/src/benchmarking.rs @@ -58,10 +58,6 @@ impl BenchmarkHelper, T::AccountId, T::Balance> for } } -fn assert_last_event(generic_event: T::RuntimeEvent) { - frame_system::Pallet::::assert_last_event(generic_event.into()); -} - #[benchmarks] mod benchmarks { use super::*; @@ -76,7 +72,7 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Signed(bidder.clone()), auction_id, bid_price); - assert_last_event::( + frame_system::Pallet::::assert_last_event( Event::Bid { auction_id, bidder: bidder,