diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index c507db59087a3..6a1cf59b9b1f0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -2698,3 +2698,20 @@ fn ensure_key_ss58() { AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); assert_eq!(acc, RootMigController::sorted_members()[0]); } + +#[test] +fn ensure_epmb_weights_sane() { + use sp_io::TestExternalities; + use sp_runtime::Percent; + sp_tracing::try_init_simple(); + TestExternalities::default().execute_with(|| { + pallet_election_provider_multi_block::Pallet::::check_all_weights( + // of the max block weights.. + ::BlockWeights::get().max_block, + // more than 75% is a hard stop.. + Some(Percent::from_percent(75)), + // and more than 50% a warning. + Some(Percent::from_percent(50)), + ) + }); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs index 58e103e674fe2..fb171ebe60421 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs @@ -135,6 +135,7 @@ impl multi_block::Config for Runtime { // Revert back to signed phase if nothing is submitted and queued, so we prolong the election. type AreWeDone = multi_block::RevertToSignedIfNotQueuedOf; type OnRoundRotation = multi_block::CleanRound; + type Signed = MultiBlockElectionSigned; type WeightInfo = weights::pallet_election_provider_multi_block::WeightInfo; } @@ -498,3 +499,20 @@ where UncheckedExtrinsic::new_bare(call) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn all_epmb_weights_sane() { + sp_tracing::try_init_simple(); + sp_io::TestExternalities::default().execute_with(|| { + pallet_election_provider_multi_block::Pallet::::check_all_weights( + ::BlockWeights::get().max_block, + Some(sp_runtime::Percent::from_percent(75)), + Some(sp_runtime::Percent::from_percent(50)), + ); + }) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block.rs index 9b3e86d628a49..7c95246f9adfb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_election_provider_multi_block` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-11-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-11-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `e7fc875cf0e9`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -54,20 +54,20 @@ impl pallet_election_provider_multi_block::WeightInfo f /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - fn on_initialize_nothing() -> Weight { + fn per_block_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `223` - // Estimated: `3688` - // Minimum execution time: 9_014_000 picoseconds. - Weight::from_parts(9_476_000, 0) - .saturating_add(Weight::from_parts(0, 3688)) - .saturating_add(T::DbWeight::get().reads(3)) + // Measured: `118` + // Estimated: `1603` + // Minimum execution time: 7_356_000 picoseconds. + Weight::from_parts(7_708_000, 0) + .saturating_add(Weight::from_parts(0, 1603)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `Staking::ValidatorCount` (r:1 w:0) /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) @@ -76,28 +76,26 @@ impl pallet_election_provider_multi_block::WeightInfo f /// Proof: `Staking::CounterForValidators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `Staking::Validators` (r:1001 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElection::DesiredTargets` (r:0 w:1) /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:0 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) - fn on_initialize_into_snapshot_msp() -> Weight { + fn per_block_snapshot_msp() -> Weight { // Proof Size summary in bytes: - // Measured: `48451` - // Estimated: `2526916` - // Minimum execution time: 6_260_099_000 picoseconds. - Weight::from_parts(6_346_593_000, 0) - .saturating_add(Weight::from_parts(0, 2526916)) - .saturating_add(T::DbWeight::get().reads(1007)) + // Measured: `48346` + // Estimated: `2526811` + // Minimum execution time: 6_024_190_000 picoseconds. + Weight::from_parts(6_087_417_000, 0) + .saturating_add(Weight::from_parts(0, 2526811)) + .saturating_add(T::DbWeight::get().reads(1006)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) /// Proof: `Staking::VoterSnapshotStatus` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `Measured`) /// Storage: `VoterList::CounterForListNodes` (r:1 w:0) @@ -116,10 +114,6 @@ impl pallet_election_provider_multi_block::WeightInfo f /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) /// Storage: `VoterList::Lock` (r:0 w:1) @@ -128,92 +122,34 @@ impl pallet_election_provider_multi_block::WeightInfo f /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_snapshot_rest() -> Weight { + fn per_block_snapshot_rest() -> Weight { // Proof Size summary in bytes: - // Measured: `1495743` - // Estimated: `3241608` - // Minimum execution time: 35_371_801_000 picoseconds. - Weight::from_parts(36_135_165_000, 0) - .saturating_add(Weight::from_parts(0, 3241608)) - .saturating_add(T::DbWeight::get().reads(2924)) + // Measured: `1495638` + // Estimated: `3241503` + // Minimum execution time: 31_899_661_000 picoseconds. + Weight::from_parts(33_446_559_000, 0) + .saturating_add(Weight::from_parts(0, 3241503)) + .saturating_add(T::DbWeight::get().reads(2923)) .saturating_add(T::DbWeight::get().writes(6)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) - /// Proof: `Staking::VoterSnapshotStatus` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `Measured`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:0) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `VoterList::ListNodes` (r:705 w:0) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `Measured`) - /// Storage: `Staking::Bonded` (r:703 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `Measured`) - /// Storage: `Staking::Ledger` (r:703 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(753), added: 3228, mode: `Measured`) - /// Storage: `Staking::Nominators` (r:703 w:0) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `Measured`) - /// Storage: `VoterList::ListBags` (r:2 w:0) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `Measured`) - /// Storage: `Staking::Validators` (r:37 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElection::Round` (r:1 w:0) - /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) - /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) - /// Storage: `VoterList::Lock` (r:0 w:1) - /// Proof: `VoterList::Lock` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_signed() -> Weight { - // Proof Size summary in bytes: - // Measured: `1527537` - // Estimated: `3273402` - // Minimum execution time: 34_672_020_000 picoseconds. - Weight::from_parts(36_788_513_000, 0) - .saturating_add(Weight::from_parts(0, 3273402)) - .saturating_add(T::DbWeight::get().reads(2860)) - .saturating_add(T::DbWeight::get().writes(6)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - fn on_initialize_into_signed_validation() -> Weight { - // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `3882` - // Minimum execution time: 40_009_000 picoseconds. - Weight::from_parts(48_764_000, 0) - .saturating_add(Weight::from_parts(0, 3882)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElection::Round` (r:1 w:0) + /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - fn on_initialize_into_unsigned() -> Weight { + fn per_block_start_signed_validation() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `3882` - // Minimum execution time: 43_182_000 picoseconds. - Weight::from_parts(50_229_000, 0) - .saturating_add(Weight::from_parts(0, 3882)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `592` + // Estimated: `4057` + // Minimum execution time: 51_167_000 picoseconds. + Weight::from_parts(59_251_000, 0) + .saturating_add(Weight::from_parts(0, 4057)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -234,8 +170,8 @@ impl pallet_election_provider_multi_block::WeightInfo f // Proof Size summary in bytes: // Measured: `1479` // Estimated: `4944` - // Minimum execution time: 79_265_000 picoseconds. - Weight::from_parts(97_578_000, 0) + // Minimum execution time: 73_201_000 picoseconds. + Weight::from_parts(93_569_000, 0) .saturating_add(Weight::from_parts(0, 4944)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -272,8 +208,8 @@ impl pallet_election_provider_multi_block::WeightInfo f // Proof Size summary in bytes: // Measured: `4847` // Estimated: `85037` - // Minimum execution time: 286_577_000 picoseconds. - Weight::from_parts(411_747_000, 0) + // Minimum execution time: 272_512_000 picoseconds. + Weight::from_parts(324_716_000, 0) .saturating_add(Weight::from_parts(0, 85037)) .saturating_add(T::DbWeight::get().reads(104)) .saturating_add(T::DbWeight::get().writes(106)) @@ -298,8 +234,8 @@ impl pallet_election_provider_multi_block::WeightInfo f // Proof Size summary in bytes: // Measured: `372173` // Estimated: `375638` - // Minimum execution time: 3_130_891_000 picoseconds. - Weight::from_parts(3_242_891_000, 0) + // Minimum execution time: 2_971_188_000 picoseconds. + Weight::from_parts(3_184_664_000, 0) .saturating_add(Weight::from_parts(0, 375638)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(2)) @@ -318,8 +254,8 @@ impl pallet_election_provider_multi_block::WeightInfo f // Proof Size summary in bytes: // Measured: `308` // Estimated: `3773` - // Minimum execution time: 58_785_000 picoseconds. - Weight::from_parts(72_105_000, 0) + // Minimum execution time: 59_840_000 picoseconds. + Weight::from_parts(71_832_000, 0) .saturating_add(Weight::from_parts(0, 3773)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_signed.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_signed.rs index b466ffcb617b1..2f38e49209338 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_signed.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_signed.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_election_provider_multi_block::signed` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-11-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-11-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `4e4e89597de4`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -66,8 +66,8 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `3252` // Estimated: `6717` - // Minimum execution time: 84_228_000 picoseconds. - Weight::from_parts(86_570_000, 0) + // Minimum execution time: 85_153_000 picoseconds. + Weight::from_parts(87_582_000, 0) .saturating_add(Weight::from_parts(0, 6717)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -90,8 +90,8 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `7851` // Estimated: `88041` - // Minimum execution time: 222_687_000 picoseconds. - Weight::from_parts(230_636_000, 0) + // Minimum execution time: 230_285_000 picoseconds. + Weight::from_parts(237_361_000, 0) .saturating_add(Weight::from_parts(0, 88041)) .saturating_add(T::DbWeight::get().reads(39)) .saturating_add(T::DbWeight::get().writes(37)) @@ -114,8 +114,8 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `3785` // Estimated: `7250` - // Minimum execution time: 165_801_000 picoseconds. - Weight::from_parts(176_562_000, 0) + // Minimum execution time: 177_318_000 picoseconds. + Weight::from_parts(196_911_000, 0) .saturating_add(Weight::from_parts(0, 7250)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -138,8 +138,8 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `3887` // Estimated: `7352` - // Minimum execution time: 160_561_000 picoseconds. - Weight::from_parts(170_941_000, 0) + // Minimum execution time: 164_593_000 picoseconds. + Weight::from_parts(207_127_000, 0) .saturating_add(Weight::from_parts(0, 7352)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -160,8 +160,8 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `4717` // Estimated: `84907` - // Minimum execution time: 138_704_000 picoseconds. - Weight::from_parts(144_347_000, 0) + // Minimum execution time: 141_746_000 picoseconds. + Weight::from_parts(146_143_000, 0) .saturating_add(Weight::from_parts(0, 84907)) .saturating_add(T::DbWeight::get().reads(37)) .saturating_add(T::DbWeight::get().writes(35)) @@ -183,11 +183,11 @@ impl pallet_election_provider_multi_block::signed::Weig // Proof Size summary in bytes: // Measured: `3709 + p * (32 ±0)` // Estimated: `7174 + p * (2507 ±0)` - // Minimum execution time: 85_763_000 picoseconds. - Weight::from_parts(87_799_824, 0) + // Minimum execution time: 86_306_000 picoseconds. + Weight::from_parts(88_268_158, 0) .saturating_add(Weight::from_parts(0, 7174)) - // Standard Error: 6_631 - .saturating_add(Weight::from_parts(1_108_464, 0).saturating_mul(p.into())) + // Standard Error: 7_479 + .saturating_add(Weight::from_parts(1_129_962, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_unsigned.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_unsigned.rs index 86087ca3a50d7..4a6ae8a0de7e7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_unsigned.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_unsigned.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_election_provider_multi_block::unsigned` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-11-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-11-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `4e4e89597de4`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -68,8 +68,8 @@ impl pallet_election_provider_multi_block::unsigned::We // Proof Size summary in bytes: // Measured: `351` // Estimated: `3816` - // Minimum execution time: 39_296_000 picoseconds. - Weight::from_parts(47_914_000, 0) + // Minimum execution time: 37_670_000 picoseconds. + Weight::from_parts(45_454_000, 0) .saturating_add(Weight::from_parts(0, 3816)) .saturating_add(T::DbWeight::get().reads(7)) } @@ -95,8 +95,8 @@ impl pallet_election_provider_multi_block::unsigned::We // Proof Size summary in bytes: // Measured: `760999` // Estimated: `766939` - // Minimum execution time: 1_231_740_000 picoseconds. - Weight::from_parts(1_412_905_000, 0) + // Minimum execution time: 1_214_154_000 picoseconds. + Weight::from_parts(1_377_229_000, 0) .saturating_add(Weight::from_parts(0, 766939)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_verifier.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_verifier.rs index 25ab56e76fece..7395024b39471 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_verifier.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_verifier.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_election_provider_multi_block::verifier` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-11-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-11-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `4e4e89597de4`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -68,20 +68,18 @@ impl pallet_election_provider_multi_block::verifier::We /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) - fn on_initialize_valid_non_terminal() -> Weight { + fn verification_valid_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `373231` - // Estimated: `376696` - // Minimum execution time: 644_343_000 picoseconds. - Weight::from_parts(679_857_000, 0) - .saturating_add(Weight::from_parts(0, 376696)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `373126` + // Estimated: `376591` + // Minimum execution time: 686_534_000 picoseconds. + Weight::from_parts(743_184_000, 0) + .saturating_add(Weight::from_parts(0, 376591)) + .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -110,18 +108,16 @@ impl pallet_election_provider_multi_block::verifier::We /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) - fn on_initialize_valid_terminal() -> Weight { + fn verification_valid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `409786` - // Estimated: `492451` - // Minimum execution time: 1_103_713_000 picoseconds. - Weight::from_parts(1_174_958_000, 0) - .saturating_add(Weight::from_parts(0, 492451)) - .saturating_add(T::DbWeight::get().reads(77)) + // Measured: `409681` + // Estimated: `492346` + // Minimum execution time: 1_194_264_000 picoseconds. + Weight::from_parts(1_276_313_000, 0) + .saturating_add(Weight::from_parts(0, 492346)) + .saturating_add(T::DbWeight::get().reads(76)) .saturating_add(T::DbWeight::get().writes(72)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -152,16 +148,14 @@ impl pallet_election_provider_multi_block::verifier::We /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:31 w:32) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - fn on_initialize_invalid_terminal() -> Weight { + fn verification_invalid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `409786` - // Estimated: `492451` - // Minimum execution time: 1_080_694_000 picoseconds. - Weight::from_parts(1_155_637_000, 0) - .saturating_add(Weight::from_parts(0, 492451)) - .saturating_add(T::DbWeight::get().reads(108)) + // Measured: `409681` + // Estimated: `492346` + // Minimum execution time: 1_242_495_000 picoseconds. + Weight::from_parts(1_320_314_000, 0) + .saturating_add(Weight::from_parts(0, 492346)) + .saturating_add(T::DbWeight::get().reads(107)) .saturating_add(T::DbWeight::get().writes(102)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -192,19 +186,17 @@ impl pallet_election_provider_multi_block::verifier::We /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// The range of component `v` is `[0, 31]`. - fn on_initialize_invalid_non_terminal(v: u32, ) -> Weight { + fn verification_invalid_non_terminal(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `417197 + v * (37 ±0)` - // Estimated: `488349 + v * (2550 ±72)` - // Minimum execution time: 813_783_000 picoseconds. - Weight::from_parts(886_800_578, 0) - .saturating_add(Weight::from_parts(0, 488349)) - // Standard Error: 111_448 - .saturating_add(Weight::from_parts(3_520_338, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(44)) + // Measured: `417092 + v * (37 ±0)` + // Estimated: `488244 + v * (2550 ±72)` + // Minimum execution time: 866_408_000 picoseconds. + Weight::from_parts(997_133_252, 0) + .saturating_add(Weight::from_parts(0, 488244)) + // Standard Error: 143_927 + .saturating_add(Weight::from_parts(2_282_980, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(43)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().writes(38)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(v.into()))) diff --git a/prdoc/pr_9925.prdoc b/prdoc/pr_9925.prdoc new file mode 100644 index 0000000000000..170262751b0e2 --- /dev/null +++ b/prdoc/pr_9925.prdoc @@ -0,0 +1,17 @@ +title: 'Staking-Async + EPMB: Migrate operations to `poll`' +doc: +- audience: Runtime Dev + description: Migrate staking-async and its election provider pallet to `on_poll` +crates: +- name: pallet-election-provider-multi-block + bump: major +- name: pallet-staking-async + bump: major +- name: pallet-election-provider-multi-phase + bump: patch +- name: frame-election-provider-support + bump: major +- name: asset-hub-westend-runtime + bump: minor +- name: pallet-fast-unstake + bump: patch \ No newline at end of file diff --git a/substrate/frame/election-provider-multi-block/src/benchmarking.rs b/substrate/frame/election-provider-multi-block/src/benchmarking.rs index d452bfb9c238c..5021009f948db 100644 --- a/substrate/frame/election-provider-multi-block/src/benchmarking.rs +++ b/substrate/frame/election-provider-multi-block/src/benchmarking.rs @@ -24,9 +24,10 @@ use frame_election_provider_support::{ElectionDataProvider, ElectionProvider}; use frame_support::{assert_ok, pallet_prelude::*}; const SNAPSHOT_NOT_BIG_ENOUGH: &'static str = "Snapshot page is not full, you should run this \ -benchmark with enough genesis stakers in staking (DataProvider) to fill a page of voters/targets \ +benchmark with enough genesis stakers in staking to fill a page of voters/targets \ as per VoterSnapshotPerBlock and TargetSnapshotPerBlock. Generate at least \ -2 * VoterSnapshotPerBlock) nominators and TargetSnapshotPerBlock validators"; +2 * VoterSnapshotPerBlock nominators and TargetSnapshotPerBlock validators. Use `dev_stakers` in \ +genesis config."; // TODO: remove unwraps from all benchmarks of this pallet -- it makes debugging via wasm harder @@ -35,12 +36,12 @@ mod benchmarks { use super::*; #[benchmark(pov_mode = Measured)] - fn on_initialize_nothing() -> Result<(), BenchmarkError> { + fn per_block_nothing() -> Result<(), BenchmarkError> { assert_eq!(CurrentPhase::::get(), Phase::Off); #[block] { - Pallet::::roll_next(true, false); + Pallet::::roll_next(false); } assert_eq!(CurrentPhase::::get(), Phase::Off); @@ -48,7 +49,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_into_snapshot_msp() -> Result<(), BenchmarkError> { + fn per_block_snapshot_msp() -> Result<(), BenchmarkError> { assert!(T::Pages::get() >= 2, "this benchmark only works in a runtime with 2 pages or more, set at least `type Pages = 2` for benchmark run"); #[cfg(test)] @@ -59,7 +60,7 @@ mod benchmarks { #[block] { - Pallet::::roll_next(true, false); + Pallet::::roll_next(false); } // we have collected the target snapshot only @@ -76,7 +77,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_into_snapshot_rest() -> Result<(), BenchmarkError> { + fn per_block_snapshot_rest() -> Result<(), BenchmarkError> { assert!(T::Pages::get() >= 2, "this benchmark only works in a runtime with 2 pages or more, set at least `type Pages = 2` for benchmark run"); #[cfg(test)] @@ -99,7 +100,7 @@ mod benchmarks { // take one more snapshot page. #[block] { - Pallet::::roll_next(true, false); + Pallet::::roll_next(false); } // we have now collected the first page of voters. @@ -115,29 +116,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_into_signed() -> Result<(), BenchmarkError> { - #[cfg(test)] - crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); - crate::Pallet::::start().unwrap(); - - Pallet::::roll_until_before_matches(|| { - matches!(CurrentPhase::::get(), Phase::Signed(_)) - }); - - assert_eq!(CurrentPhase::::get(), Phase::Snapshot(0)); - - #[block] - { - Pallet::::roll_next(true, false); - } - - assert!(CurrentPhase::::get().is_signed()); - - Ok(()) - } - - #[benchmark(pov_mode = Measured)] - fn on_initialize_into_signed_validation() -> Result<(), BenchmarkError> { + fn per_block_start_signed_validation() -> Result<(), BenchmarkError> { #[cfg(test)] crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); crate::Pallet::::start().unwrap(); @@ -150,29 +129,11 @@ mod benchmarks { #[block] { - Pallet::::roll_next(true, false); + Pallet::::roll_next(false); } - Ok(()) - } - - #[benchmark(pov_mode = Measured)] - fn on_initialize_into_unsigned() -> Result<(), BenchmarkError> { - #[cfg(test)] - crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); - crate::Pallet::::start().unwrap(); - - Pallet::::roll_until_before_matches(|| { - matches!(CurrentPhase::::get(), Phase::Unsigned(_)) - }); - assert!(matches!(CurrentPhase::::get(), Phase::SignedValidation(_))); - - #[block] - { - Pallet::::roll_next(true, false); - } + assert!(CurrentPhase::::get().is_signed_validation()); - assert!(matches!(CurrentPhase::::get(), Phase::Unsigned(_))); Ok(()) } diff --git a/substrate/frame/election-provider-multi-block/src/lib.rs b/substrate/frame/election-provider-multi-block/src/lib.rs index bd956cba23595..4d88877809604 100644 --- a/substrate/frame/election-provider-multi-block/src/lib.rs +++ b/substrate/frame/election-provider-multi-block/src/lib.rs @@ -43,8 +43,7 @@ //! //! This pallet will only function in a sensible way if it is peered with its companion pallets. //! -//! - The [`verifier`] pallet provides a standard implementation of the [`verifier::Verifier`]. This -//! pallet is mandatory. +//! - The [`verifier`] pallet provides a standard implementation of the [`verifier::Verifier`]. //! - The [`unsigned`] module provides the implementation of unsigned submission by validators. If //! this pallet is included, then [`Config::UnsignedPhase`] will determine its duration. //! - The [`signed`] module provides the implementation of the signed submission by any account. If @@ -55,24 +54,13 @@ //! the shared information that all child pallets use. All child pallets depend on the top level //! pallet ONLY, but not the other way around. For those cases, traits are used. //! -//! As in, notice that [`crate::verifier::Config`] relies on [`crate::Config`], but for the -//! reverse, we rely on [`crate::verifier::Verifier`] trait, which is indeed part of -//! [`crate::Config`]. This is merely an implementation opinion. +//! For reverse linking, or child-linking, only explicit traits with clear interfaces are used. For +//! example, the following traits facilitate other communication: //! -//! ### Pallet Ordering: -//! -//! TODO: @kiaenigma: this needs clarification and a enforcement. Signed pallet should come first. -//! Fixing this should yield removing `verifier_done` from the phase transition. -//! -//! The ordering of these pallets in a runtime should be: -//! * parent -//! * verifier -//! * signed -//! * unsigned -//! -//! This is critical for the phase transition to work. -//! -//! > This should be manually checked, there is not automated way to test it. +//! * [`crate::types::SignedInterface`]: Parent talking to signed. +//! * [`crate::verifier::Verifier`]: Parent talking to verifier. +//! * [`crate::verifier::SolutionDataProvider`]: Verifier talking to signed. + //! //! ## Pagination //! @@ -94,7 +82,7 @@ //! //! ## Phases //! -//! The operations in this pallet are divided intor rounds, a `u32` number stored in [`Round`]. +//! The operations in this pallet are divided into rounds, a `u32` number stored in [`Round`]. //! This value helps this pallet organize itself, and leaves the door open for lazy deletion of any //! stale data. A round, under the happy path, starts by receiving the call to //! [`ElectionProvider::start`], and is terminated by receiving a call to @@ -127,6 +115,20 @@ //! > Given this, it is rather important for the user of this pallet to ensure it always terminates //! > election via `elect` before requesting a new one. //! +//! ### Phase Transition +//! +//! Within all 4 pallets only the parent pallet is allowed to move the phases forward. As of now, +//! the transition happens `on-poll`, ensuring that we don't consume too much weight. The parent +//! pallet is in charge of aggregating the work to be done by all pallets, checking if it can fit +//! within the current block's weight limits, and executing it if so. +//! +//! Occasional phase transition stalling is not a critical issue. Every instance of phase transition +//! failing is accompanied by a [`Event::UnexpectedPhaseTransitionOutOfWeight`] for visibility. +//! +//! Note this pallet transitions phases all the way into [`crate::types::Phase::Done`]. At this +//! point, we will move to `Export` phase an onwards by calls into `elect`. A call to `elect(0)` +//! rotates the round, as stated above. +//! //! ## Feasible Solution (correct solution) //! //! All submissions must undergo a feasibility check. Signed solutions are checked one by one at the @@ -197,7 +199,7 @@ #[cfg(any(feature = "runtime-benchmarks", test))] use crate::signed::{CalculateBaseDeposit, CalculatePageDeposit}; -use crate::verifier::Verifier; +use crate::verifier::{AsynchronousVerifier, Verifier}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_election_provider_support::{ onchain, BoundedSupportsOf, DataProviderBounds, ElectionDataProvider, ElectionProvider, @@ -207,6 +209,7 @@ use frame_support::{ dispatch::PostDispatchInfo, pallet_prelude::*, traits::{Defensive, EnsureOrigin}, + weights::WeightMeter, DebugNoBound, Twox64Concat, }; use frame_system::pallet_prelude::*; @@ -271,8 +274,8 @@ impl ElectionProvider for InitiateEmergencyPhase { Err("Emergency phase started.") } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } fn start() -> Result<(), Self::Error> { @@ -324,8 +327,8 @@ impl ElectionProvider for Continue { Zero::zero() } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } @@ -545,8 +548,7 @@ pub mod pallet { /// Duration of the singed validation phase. /// /// The duration of this should not be less than `T::Pages`, and there is no point in it - /// being more than `SignedPhase::MaxSubmission::get() * T::Pages`. TODO: integrity test for - /// it. + /// being more than `SignedPhase::MaxSubmission::get() * T::Pages`. #[pallet::constant] type SignedValidationPhase: Get>; @@ -602,6 +604,9 @@ pub mod pallet { AccountId = Self::AccountId, > + verifier::AsynchronousVerifier; + /// Interface signed pallet's interface. + type Signed: SignedInterface; + /// The origin that can perform administration operations on this pallet. /// /// This is the highest privilege origin of this pallet, and should be configured @@ -708,51 +713,69 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - fn on_initialize(_now: BlockNumberFor) -> Weight { - let current_phase = CurrentPhase::::get(); - let weight1 = match current_phase { - Phase::Snapshot(x) if x == T::Pages::get() => { - // create the target snapshot - Self::create_targets_snapshot(); - T::WeightInfo::on_initialize_into_snapshot_msp() - }, - Phase::Snapshot(x) => { - // create voter snapshot - Self::create_voters_snapshot_paged(x); - T::WeightInfo::on_initialize_into_snapshot_rest() - }, - _ => T::WeightInfo::on_initialize_nothing(), - }; - - // Only transition if not in Export phase - if !matches!(current_phase, Phase::Export(_)) { - let next_phase = current_phase.next(); + fn on_poll(_now: BlockNumberFor, weight_meter: &mut WeightMeter) { + // first check we can at least read one storage. + if !weight_meter.can_consume(T::DbWeight::get().reads(1)) { + Self::deposit_event(Event::UnexpectedPhaseTransitionHalt { + required: T::DbWeight::get().reads(1), + had: weight_meter.remaining(), + }); + return; + } - let weight2 = match next_phase { - Phase::Signed(_) => T::WeightInfo::on_initialize_into_signed(), - Phase::SignedValidation(_) => - T::WeightInfo::on_initialize_into_signed_validation(), - Phase::Unsigned(_) => T::WeightInfo::on_initialize_into_unsigned(), - _ => T::WeightInfo::on_initialize_nothing(), - }; + // if so, consume and prepare the next phase. + let current_phase = Self::current_phase(); + weight_meter.consume(T::DbWeight::get().reads(1)); + + let (self_weight, self_exec) = Self::per_block_exec(current_phase); + let (verifier_weight, verifier_exc) = T::Verifier::per_block_exec(); + + // The following will combine `Self::per_block_exec` and `T::Verifier::per_block_exec` + // into a single tuple of `(Weight, Box<_>)`. Can be moved into a reusable combinator + // function if we have this pattern in more places. + let (combined_weight, combined_exec) = ( + // pre-exec weight is simply addition. + self_weight.saturating_add(verifier_weight), + // our new exec is.. + Box::new(move |meter: &mut WeightMeter| { + self_exec(meter); + verifier_exc(meter); + }), + ); - Self::phase_transition(next_phase); + log!( + trace, + "worst-case required weight for transition from {:?} to {:?} is {:?}, has {:?}", + current_phase, + current_phase.next(), + combined_weight, + weight_meter.remaining() + ); + if weight_meter.can_consume(combined_weight) { + combined_exec(weight_meter); + } else { + Self::deposit_event(Event::UnexpectedPhaseTransitionOutOfWeight { + from: current_phase, + to: current_phase.next(), + required: combined_weight, + had: weight_meter.remaining(), + }); + } - // bit messy, but for now this works best. - #[cfg(test)] - { - let test_election_start: BlockNumberFor = - (crate::mock::ElectionStart::get() as u32).into(); - if _now == test_election_start { - crate::log!(info, "TESTING: Starting election at block {}", _now); - crate::mock::MultiBlock::start().unwrap(); - } + // NOTE: why in here? because it is more accessible, for example `roll_to_with_ocw`. + #[cfg(test)] + { + if _now > 200u32.into() { + panic!("Looping to death: in case of errors in election start time in tests, we might loop \ + infinitely. This panic is preventing you from that. Double check `mock::ElectionStart` or increase \ + the 200 limit"); + } + let test_election_start: BlockNumberFor = + (crate::mock::ElectionStart::get() as u32).into(); + if _now == test_election_start { + crate::log!(info, "TESTING: Starting election at block {}", _now); + crate::mock::MultiBlock::start().unwrap(); } - - weight1 + weight2 - } else { - // If in Export phase, do nothing. - weight1 } } @@ -832,10 +855,19 @@ pub mod pallet { /// The target phase to: Phase, }, - /// Target snapshot creation failed + /// Target snapshot creation failed. UnexpectedTargetSnapshotFailed, - /// Voter snapshot creation failed + /// Voter snapshot creation failed. UnexpectedVoterSnapshotFailed, + /// Phase transition could not proceed due to being out of weight. + UnexpectedPhaseTransitionOutOfWeight { + from: Phase, + to: Phase, + required: Weight, + had: Weight, + }, + /// Phase transition could not even begin becaseu of being out of weight. + UnexpectedPhaseTransitionHalt { required: Weight, had: Weight }, } /// Error of the pallet that can be returned in response to dispatches. @@ -1247,6 +1279,131 @@ impl Pallet { Zero::zero() } + /// > Note: Consider this a shared documentation block for [`Pallet::on_poll`] and this + /// > function, as they work together. + /// + /// The meta-phase transition logic that applies to all pallets. Includes the following: + /// + /// * Creating snapshot once `ElectionProvider::start` has instructed us to do so. + /// * Transition into `Phase::Signed`. + /// * Upon last page of `Phase::Signed`, instruct the `Verifier` to start, if any solution + /// exists. + /// * And moving forward all other phases as necessary. + /// + /// What it does not do: + /// + /// * Instruct the verifier to move forward. This happens through + /// [`verifier::Verifier::per_block_exec`], called in [`Pallet::on_poll`]. On each block, + /// [`T::Verifier`] is given a chance to do something. Under the hood, if the `Status` is set, + /// it will do something, regardless of which phase we are in. In this pallet we only move + /// [`Phase::SignedValidation`] forward. + /// * Move us forward if we are in either of `Phase::Done` or `Phase::Export`. These are + /// controlled by the caller of our [`T::ElectionProvider`] implementation, i.e. staking. Note + /// that this pallet always transitions us from `current_phase` to `current_phase.next()`, but + /// the [`crate::types::Phase::next`] function is a noop for `Done` and `Export`. + /// + /// ### Type + /// + /// The commonly used `(Weight, Box)` should be interpreted as such: + /// + /// * The `Weight` is the pre-computed worst case weight of the operation that we are going to + /// do. + /// * The `Box` is the function that represents that the work that + /// will at most consume the said amount of weight. While executing, it will alter the given + /// weight meter to consume the actual weight used. Indeed, the weight that is registered in + /// the `WeightMeter` must never be more than the `Weight` returned as the first item of the + /// tuple. + /// + /// In essence, the caller must: + /// + /// 1. given an existing `meter`, receive `(worst_weight, exec)` + /// 2. ensure `meter` can consume up to `worst_weight`. + /// 3. if so, call `exec(meter)`, knowing `meter` will accumulate at most `worst_weight` extra. + /// + /// ### Returned Weight + /// + /// The weights returned are as follows: + /// + /// * `just_next_phase` returns a benchmarked weight that should be equal to only reading and + /// writing the `Phase`. This is used for: + /// * `Off` phase, which does not do anything `on_poll`. + /// * `Signed` phase except last page, which starts the verifier. + /// * `Unsigned` phase, which does not do anything `on_poll` and managed its own extrinsic + /// weights. + /// * `Emergency` phase, which does not do anything `on_poll`. + /// * `Done` phase, which does not do anything `on_poll`. + /// * `SignedValidation` phase, because in this pallet we only move the phase forward and we + /// don't know (or want to know) how much weight `Verifier` is consuming. This is handled by + /// combining the weight of [`T::Verifier::per_block_exec`] with this function in + /// [`Pallet::on_poll`]. + /// * `Export` phase, which does not do anything `on_poll` on this pallet, yet we return the + /// weight that [`Config::ElectionProvider`]'s caller should register via + /// [`ElectionProvider::status`]. + /// + /// The only special cases, from the perspective of this pallet, are: + /// * Last page of signed phase registers `per_block_start_signed_validation`. + /// * The snapshots are handled by this pallet, which registers `per_block_snapshot_msp` and + /// `per_block_snapshot_rest`. + fn per_block_exec(current_phase: Phase) -> (Weight, Box) { + type ExecuteFn = Box; + let next_phase = current_phase.next(); + + let just_next_phase: (Weight, ExecuteFn) = ( + T::WeightInfo::per_block_nothing(), + Box::new(move |_| { + // Note `Phase.next` for some variants is a noop, for example `Done`. + Self::phase_transition(next_phase); + }), + ); + + match current_phase { + Phase::Snapshot(x) if x == T::Pages::get() => { + // first snapshot + let weight = T::WeightInfo::per_block_snapshot_msp(); + let exec: ExecuteFn = Box::new(move |meter: &mut WeightMeter| { + Self::create_targets_snapshot(); + Self::phase_transition(next_phase); + meter.consume(weight) + }); + (weight, exec) + }, + + Phase::Snapshot(x) => { + // rest of the snapshot, incl last one. + let weight = T::WeightInfo::per_block_snapshot_rest(); + let exec: ExecuteFn = Box::new(move |meter: &mut WeightMeter| { + Self::create_voters_snapshot_paged(x); + Self::phase_transition(next_phase); + meter.consume(weight) + }); + (weight, exec) + }, + Phase::Signed(x) => { + // Signed pallet should prep the best winner, and send the start signal, if some + // exists. + if x.is_zero() && T::Signed::has_leader(Self::round()) { + let weight = T::WeightInfo::per_block_start_signed_validation(); + let exec: ExecuteFn = Box::new(move |meter: &mut WeightMeter| { + // defensive: signed phase has just began, verifier should be in a clear + // state and ready to accept a solution. + let _ = T::Verifier::start().defensive(); + Self::phase_transition(next_phase); + meter.consume(weight) + }); + (weight, exec) + } else { + just_next_phase + } + }, + Phase::SignedValidation(_) | + Phase::Unsigned(_) | + Phase::Off | + Phase::Emergency | + Phase::Done | + Phase::Export(_) => just_next_phase, + } + } + /// Return the `length` most significant pages. /// /// For example, if `Pages = 4`, and `length = 2`, our full snapshot range would be [0, @@ -1258,6 +1415,9 @@ impl Pallet { pub(crate) fn phase_transition(to: Phase) { let from = Self::current_phase(); + if from == to { + return; + } use sp_std::mem::discriminant; if discriminant(&from) != discriminant(&to) { log!(debug, "transitioning phase from {:?} to {:?}", from, to); @@ -1437,6 +1597,172 @@ impl Pallet { } } +#[cfg(feature = "std")] +impl Pallet { + fn analyze_weight( + op_name: &str, + op_weight: Weight, + limit_weight: Weight, + maybe_max_ratio: Option, + maybe_max_warn_ratio: Option, + ) { + use frame_support::weights::constants::{ + WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MILLIS, + }; + + let ref_time_ms = op_weight.ref_time() / WEIGHT_REF_TIME_PER_MILLIS; + let ref_time_ratio = + sp_runtime::Percent::from_rational(op_weight.ref_time(), limit_weight.ref_time()); + let proof_size_kb = op_weight.proof_size() / WEIGHT_PROOF_SIZE_PER_KB; + let proof_size_ratio = + sp_runtime::Percent::from_rational(op_weight.proof_size(), limit_weight.proof_size()); + let limit_ms = limit_weight.ref_time() / WEIGHT_REF_TIME_PER_MILLIS; + let limit_kb = limit_weight.proof_size() / WEIGHT_PROOF_SIZE_PER_KB; + log::info!( + target: crate::LOG_PREFIX, + "weight of {op_name:?} is: ref-time: {ref_time_ms}ms, {ref_time_ratio:?} of total, proof-size: {proof_size_kb}KiB, {proof_size_ratio:?} of total (total: {limit_ms}ms, {limit_kb}KiB)", + ); + + if let Some(max_ratio) = maybe_max_ratio { + assert!(ref_time_ratio <= max_ratio && proof_size_ratio <= max_ratio,) + } + if let Some(warn_ratio) = maybe_max_warn_ratio { + if ref_time_ratio > warn_ratio || proof_size_ratio > warn_ratio { + log::warn!( + target: crate::LOG_PREFIX, + "weight of {op_name:?} is above {warn_ratio:?} of the block limit", + ); + } + } + } + + /// Helper function to check the weights of all significant operations of this this pallet + /// against a runtime. + /// + /// Will check the weights for: + /// + /// * snapshot + /// * signed submission and cleanip + /// * unsigned solution submission + /// * signed validation + /// * export. + /// + /// Arguments: + /// + /// * `limit_weight` should be the maximum block weight (often obtained from `frame_system`). + /// * `maybe_max_ratio` is the maximum ratio of `limit_weight` that we may consume, else we + /// panic. + /// * `maybe_max_warn_rati` has the same effect, but it emits a warning instead of panic. + /// + /// A reasonable value for `maybe_max_weight` would be 75%, and 50% for `maybe_max_warn_ratio`. + pub fn check_all_weights( + limit_weight: Weight, + maybe_max_ratio: Option, + maybe_max_warn_ratio: Option, + ) where + T: crate::verifier::Config + crate::signed::Config + crate::unsigned::Config, + { + use crate::weights::traits::{ + pallet_election_provider_multi_block_signed::WeightInfo as _, + pallet_election_provider_multi_block_unsigned::WeightInfo as _, + pallet_election_provider_multi_block_verifier::WeightInfo as _, + }; + + // -------------- snapshot + Self::analyze_weight( + "snapshot_msp", + ::WeightInfo::per_block_snapshot_msp(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + Self::analyze_weight( + "snapshot_rest", + ::WeightInfo::per_block_snapshot_rest(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + // -------------- signed + Self::analyze_weight( + "signed_clear_all_pages", + ::WeightInfo::clear_old_round_data(T::Pages::get()), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + Self::analyze_weight( + "signed_submit_single_pages", + ::WeightInfo::submit_page(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + // -------------- unsigned + Self::analyze_weight( + "verify unsigned solution", + ::WeightInfo::submit_unsigned(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + // -------------- verification + Self::analyze_weight( + "verifier valid terminal", + ::WeightInfo::verification_valid_terminal(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + Self::analyze_weight( + "verifier invalid terminal", + ::WeightInfo::verification_invalid_terminal(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + Self::analyze_weight( + "verifier valid non terminal", + ::WeightInfo::verification_valid_non_terminal(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + Self::analyze_weight( + "verifier invalid non terminal", + ::WeightInfo::verification_invalid_non_terminal( + T::Pages::get(), + ), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + // -------------- export + Self::analyze_weight( + "export non-terminal", + ::WeightInfo::export_non_terminal(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + + Self::analyze_weight( + "export terminal", + ::WeightInfo::export_terminal(), + limit_weight, + maybe_max_ratio, + maybe_max_warn_ratio, + ); + } +} + #[allow(unused)] #[cfg(any(feature = "runtime-benchmarks", test))] // helper code for testing and benchmarking @@ -1448,7 +1774,7 @@ where /// Progress blocks until the criteria is met. pub(crate) fn roll_until_matches(criteria: impl FnOnce() -> bool + Copy) { loop { - Self::roll_next(true, false); + Self::roll_next(false); if criteria() { break; } @@ -1461,7 +1787,7 @@ where loop { let should_break = frame_support::storage::with_transaction( || -> TransactionOutcome> { - Pallet::::roll_next(true, false); + Pallet::::roll_next(false); if criteria() { TransactionOutcome::Rollback(Ok(true)) } else { @@ -1556,21 +1882,24 @@ where } /// Roll all pallets forward, for the given number of blocks. - pub(crate) fn roll_to(n: BlockNumberFor, with_signed: bool, try_state: bool) { + pub(crate) fn roll_to(n: BlockNumberFor, try_state: bool) { let now = frame_system::Pallet::::block_number(); assert!(n > now, "cannot roll to current or past block"); let one: BlockNumberFor = 1u32.into(); let mut i = now + one; while i <= n { - frame_system::Pallet::::set_block_number(i); + // remove previous weight usage in system. + frame_system::BlockWeight::::kill(); - Pallet::::on_initialize(i); - verifier::Pallet::::on_initialize(i); - unsigned::Pallet::::on_initialize(i); + frame_system::Pallet::::set_block_number(i); + let mut meter = frame_system::Pallet::::remaining_block_weight(); + Pallet::::on_poll(i, &mut meter); - if with_signed { - signed::Pallet::::on_initialize(i); - } + // register the new weight in system + frame_system::Pallet::::register_extra_weight_unchecked( + meter.consumed(), + DispatchClass::Mandatory, + ); // invariants must hold at the end of each block. if try_state { @@ -1585,12 +1914,8 @@ where } /// Roll to next block. - pub(crate) fn roll_next(with_signed: bool, try_state: bool) { - Self::roll_to( - frame_system::Pallet::::block_number() + 1u32.into(), - with_signed, - try_state, - ); + pub(crate) fn roll_next(try_state: bool) { + Self::roll_to(frame_system::Pallet::::block_number() + 1u32.into(), try_state); } } @@ -1668,20 +1993,26 @@ impl ElectionProvider for Pallet { Self::average_election_duration().into() } - fn status() -> Result { + fn status() -> Result, ()> { match >::get() { // we're not doing anything. Phase::Off => Err(()), - // we're doing sth but not read. + // we're doing something but not ready. Phase::Signed(_) | Phase::SignedValidation(_) | Phase::Unsigned(_) | Phase::Snapshot(_) | - Phase::Emergency => Ok(false), + Phase::Emergency => Ok(None), // we're ready - Phase::Done | Phase::Export(_) => Ok(true), + Phase::Done => Ok(Some(T::WeightInfo::export_non_terminal())), + Phase::Export(p) => + if p.is_zero() { + Ok(Some(T::WeightInfo::export_terminal())) + } else { + Ok(Some(T::WeightInfo::export_non_terminal())) + }, } } @@ -1698,7 +2029,7 @@ impl ElectionProvider for Pallet { #[cfg(test)] mod phase_rotation { use super::{Event, *}; - use crate::{mock::*, Phase}; + use crate::{mock::*, verifier::Status, Phase}; use frame_election_provider_support::ElectionProvider; use frame_support::assert_ok; @@ -2022,6 +2353,82 @@ mod phase_rotation { }) } + #[test] + fn weights_registered() { + // ensure we never forget to call `meter.consume` or similar in poll and alike. + // Our mock setup is: + // + // * each db read or write is 1 ref time. + // * each epmb op weight are: + // * snapshots: 5 + // * validation: 3 to start, rest 7 + ExtBuilder::full().build_and_execute(|| { + roll_to(10); + assert!(MultiBlock::current_phase().is_off()); + // note: 2 becuase 1 read registered by the parent pallet, 1 by verifier. + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 0)); + + // roll to this phase, no weight meter is consumed yet other than 1 read + 1 write. + roll_next_and_phase(Phase::Snapshot(3)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 0)); + + roll_next_and_phase(Phase::Snapshot(2)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 5)); + + roll_next_and_phase(Phase::Snapshot(1)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 5)); + + roll_next_and_phase(Phase::Snapshot(0)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 5)); + + roll_next_and_phase(Phase::Signed(SignedPhase::get() - 1)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 5)); + + // Now snapshot is done, and during signed phase we do a noop. + roll_next_and_phase(Phase::Signed(SignedPhase::get() - 2)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 0)); + + // but let's submit a signed solution to be verified while we're here + { + let paged = mine_full_solution().unwrap(); + load_signed_for_verification(999, paged.clone()); + } + + // let's go forward to start of signed validation + roll_to_signed_validation_open(); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 3)); + + roll_next_and_phase_verifier( + Phase::SignedValidation(SignedValidationPhase::get() - 1), + Status::Ongoing(1), + ); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(1, 7)); + + roll_next_and_phase_verifier( + Phase::SignedValidation(SignedValidationPhase::get() - 2), + Status::Ongoing(0), + ); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(1, 7)); + + roll_next_and_phase_verifier( + Phase::SignedValidation(SignedValidationPhase::get() - 3), + Status::Nothing, + ); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(1, 7)); + + // we also don't do anything during unsigned phase. + roll_to_unsigned_open(); + assert!(MultiBlock::current_phase().is_unsigned()); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 0)); + + roll_next_and_phase(Phase::Unsigned(UnsignedPhase::get() - 2)); + assert_eq!(System::remaining_block_weight().consumed(), Weight::from_parts(2, 0)); + + // Export weight is computed by us, but registered by whoever calls `elect`, not our + // business to check. + }); + } + #[test] fn no_unsigned_phase() { ExtBuilder::full() @@ -2226,18 +2633,14 @@ mod phase_rotation { ] ); - roll_next(); // we are back to signed phase - assert_eq!(MultiBlock::current_phase(), Phase::Signed(SignedPhase::get() - 1)); + roll_next_and_phase(Phase::Signed(SignedPhase::get() - 1)); // round is still the same assert_eq!(MultiBlock::round(), 0); // we proceed to normally again: - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::Signed(SignedPhase::get() - 2)); - - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::Signed(SignedPhase::get() - 3)); + roll_next_and_phase(Phase::Signed(SignedPhase::get() - 2)); + roll_next_and_phase(Phase::Signed(SignedPhase::get() - 3)); }); } @@ -2253,36 +2656,21 @@ mod phase_rotation { assert_eq!(MultiBlock::current_phase(), Phase::Done); // Test that on_initialize does NOT advance the phase when in Done - roll_next(); - assert_eq!( - MultiBlock::current_phase(), - Phase::Done, - "Done phase should not auto-transition" - ); + roll_next_and_phase(Phase::Done); // Start export by calling elect(max_page) assert_ok!(MultiBlock::elect(2)); // max_page = 2 for 3 pages assert_eq!(MultiBlock::current_phase(), Phase::Export(1)); // Test that on_initialize does NOT advance the phase when in Export - roll_next(); - assert_eq!( - MultiBlock::current_phase(), - Phase::Export(1), - "Export phase should not auto-transition" - ); + roll_next_and_phase(Phase::Export(1)); // Only elect() should advance the Export phase assert_ok!(MultiBlock::elect(1)); assert_eq!(MultiBlock::current_phase(), Phase::Export(0)); // Test Export(0) also blocks on_initialize transitions - roll_next(); - assert_eq!( - MultiBlock::current_phase(), - Phase::Export(0), - "Export(0) should not auto-transition" - ); + roll_next_and_phase(Phase::Export(0)); // Complete the export manually assert_ok!(MultiBlock::elect(0)); @@ -2359,7 +2747,7 @@ mod election_provider { use crate::{ mock::*, unsigned::miner::OffchainWorkerMiner, - verifier::{AsynchronousVerifier, Verifier}, + verifier::{AsynchronousVerifier, Status, Verifier}, Phase, }; use frame_election_provider_support::{BoundedSupport, BoundedSupports, ElectionProvider}; @@ -2389,7 +2777,10 @@ mod election_provider { assert_eq!( multi_block_events(), vec![ - Event::PhaseTransitioned { from: Phase::Off, to: Phase::Snapshot(3) }, + Event::PhaseTransitioned { + from: Phase::Off, + to: Phase::Snapshot(Pages::get()) + }, Event::PhaseTransitioned { from: Phase::Snapshot(0), to: Phase::Signed(SignedPhase::get() - 1) @@ -2400,39 +2791,26 @@ mod election_provider { } ] ); - assert_eq!(verifier_events(), vec![]); + assert_eq!(verifier_events_since_last_call(), vec![]); // there is no queued solution prior to the last page of the solution getting verified assert_eq!(::Verifier::queued_score(), None); - assert_eq!(::Verifier::status(), verifier::Status::Nothing); - - // next block, signed will start the verifier, although nothing is verified yet. - roll_next(); assert_eq!( ::Verifier::status(), verifier::Status::Ongoing(2) ); - assert_eq!(verifier_events(), vec![]); - // proceed until it is fully verified. - roll_next(); - assert_eq!(verifier_events(), vec![verifier::Event::Verified(2, 2)]); + // next block, signed will start the verifier, although nothing is verified yet. + roll_next_and_phase_verifier(Phase::SignedValidation(5), Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![verifier::Event::Verified(2, 2)]); - roll_next(); - assert_eq!( - verifier_events(), - vec![verifier::Event::Verified(2, 2), verifier::Event::Verified(1, 2)] - ); + roll_next_and_phase_verifier(Phase::SignedValidation(4), Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![verifier::Event::Verified(1, 2)]); - roll_next(); + roll_next_and_phase_verifier(Phase::SignedValidation(3), Status::Nothing); assert_eq!( - verifier_events(), - vec![ - verifier::Event::Verified(2, 2), - verifier::Event::Verified(1, 2), - verifier::Event::Verified(0, 2), - verifier::Event::Queued(score, None), - ] + verifier_events_since_last_call(), + vec![verifier::Event::Verified(0, 2), verifier::Event::Queued(score, None)] ); // there is now a queued solution. @@ -2455,7 +2833,7 @@ mod election_provider { if page == 0 { assert!(MultiBlock::current_phase().is_off()) } else { - assert!(MultiBlock::current_phase().is_export()) + assert_eq!(MultiBlock::current_phase(), Phase::Export(page - 1)) } }) .collect::>(); @@ -2469,8 +2847,8 @@ mod election_provider { // and the snapshot is cleared, assert_storage_noop!(Snapshot::::kill()); // signed pallet is clean. - // NOTE: in the future, if and when we add lazy cleanup to the signed pallet, this - // assertion might break. + // NOTE: signed pallet lazily deletes all other solutions, except the winner, which is + // actually deleted. assert_ok!(signed::Submissions::::ensure_killed(0)); }); } @@ -2490,14 +2868,13 @@ mod election_provider { // there is no queued solution prior to the last page of the solution getting verified assert_eq!(::Verifier::queued_score(), None); - // roll to the block it is finalized. 1 block to start the verifier, and 3 to verify - roll_next(); - roll_next(); - roll_next(); - roll_next(); + // roll to the block it is finalized. + roll_next_and_phase_verifier(Phase::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(4), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::SignedValidation(3), Status::Nothing); assert_eq!( - verifier_events(), + verifier_events_since_last_call(), vec![ verifier::Event::Verified(2, 2), verifier::Event::Verified(1, 2), @@ -2518,7 +2895,7 @@ mod election_provider { assert_full_snapshot(); // there are 3 pages (indexes 2..=0), but we short circuit by just calling 0. - let _solution = crate::Pallet::::elect(0).unwrap(); + let _supports = crate::Pallet::::elect(0).unwrap(); // round is incremented. assert_eq!(MultiBlock::round(), round + 1); @@ -2550,13 +2927,12 @@ mod election_provider { assert_eq!(::Verifier::queued_score(), None); // roll to the block it is finalized. 1 block to start the verifier, and 3 to verify. - roll_next(); - roll_next(); - roll_next(); - roll_next(); + roll_next_and_phase_verifier(Phase::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(4), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::SignedValidation(3), Status::Nothing); assert_eq!( - verifier_events(), + verifier_events_since_last_call(), vec![ verifier::Event::Verified(2, 2), verifier::Event::Verified(1, 2), @@ -2594,7 +2970,7 @@ mod election_provider { } #[test] - fn elect_advances_phase_even_on_error() { + fn continue_fallback_works() { // Use Continue fallback to avoid emergency phase when both primary and fallback fail. ExtBuilder::full().fallback_mode(FallbackModes::Continue).build_and_execute(|| { // Move to unsigned phase @@ -2674,7 +3050,7 @@ mod election_provider { // the phase is off, assert_eq!(MultiBlock::current_phase(), Phase::Off); // the snapshot is cleared, - assert_storage_noop!(Snapshot::::kill()); + assert_none_snapshot(); // and signed pallet is clean. assert_ok!(signed::Submissions::::ensure_killed(round)); }); @@ -2809,23 +3185,11 @@ mod election_provider { }); } - #[test] - #[should_panic] - fn continue_fallback_works() { - todo!() - } - - #[test] - #[should_panic] - fn emergency_fallback_works() { - todo!(); - } - #[test] fn elect_call_when_not_ongoing() { ExtBuilder::full().fallback_mode(FallbackModes::Onchain).build_and_execute(|| { roll_to_snapshot_created(); - assert_eq!(MultiBlock::status(), Ok(false)); + assert_eq!(MultiBlock::status(), Ok(None)); assert!(MultiBlock::elect(0).is_ok()); }); ExtBuilder::full().fallback_mode(FallbackModes::Onchain).build_and_execute(|| { diff --git a/substrate/frame/election-provider-multi-block/src/mock/mod.rs b/substrate/frame/election-provider-multi-block/src/mock/mod.rs index d2e5412f973f6..a1967b61a0e4e 100644 --- a/substrate/frame/election-provider-multi-block/src/mock/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/mock/mod.rs @@ -28,7 +28,7 @@ use crate::{ self as unsigned_pallet, miner::{MinerConfig, OffchainMinerError, OffchainWorkerMiner}, }, - verifier::{self as verifier_pallet, AsynchronousVerifier, Status}, + verifier::{self as verifier_pallet, AsynchronousVerifier, Status, StatusStorage}, }; use codec::{Decode, Encode, MaxEncodedLen}; use frame_election_provider_support::{ @@ -39,7 +39,7 @@ pub use frame_support::{assert_noop, assert_ok}; use frame_support::{ derive_impl, ord_parameter_types, parameter_types, traits::{fungible::InspectHold, Hooks}, - weights::{constants, Weight}, + weights::{constants, RuntimeDbWeight, Weight}, }; use frame_system::EnsureRoot; use parking_lot::RwLock; @@ -88,6 +88,10 @@ frame_election_provider_support::generate_solution_type!( >(16) ); +parameter_types! { + pub DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 1}; +} + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Hashing = BlakeTwo256; @@ -97,6 +101,7 @@ impl frame_system::Config for Runtime { type BlockWeights = BlockWeights; type AccountData = pallet_balances::AccountData; type Block = frame_system::mocking::MockBlock; + type DbWeight = DbWeight; } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -228,13 +233,14 @@ impl crate::Config for Runtime { type TargetSnapshotPerBlock = TargetSnapshotPerBlock; type VoterSnapshotPerBlock = VoterSnapshotPerBlock; type MinerConfig = Self; - type WeightInfo = (); type Verifier = VerifierPallet; type AdminOrigin = EnsureRoot; type ManagerOrigin = frame_system::EnsureSignedBy; type Pages = Pages; type AreWeDone = AreWeDone; + type Signed = SignedPallet; type OnRoundRotation = CleanRound; + type WeightInfo = (); } parameter_types! { @@ -275,8 +281,8 @@ impl ElectionProvider for MockFallback { Ok(()) } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } @@ -333,14 +339,7 @@ impl ExtBuilder { Self {} } - pub fn verifier() -> Self { - SignedPhase::set(0); - SignedValidationPhase::set(0); - signed::SignedPhaseSwitch::set(signed::SignedSwitch::Mock); - Self {} - } - - pub fn unsigned() -> Self { + pub fn mock_signed() -> Self { SignedPhase::set(0); SignedValidationPhase::set(0); signed::SignedPhaseSwitch::set(signed::SignedSwitch::Mock); @@ -656,11 +655,7 @@ pub fn verifier_events_since_last_call() -> Vec> /// proceed block number to `n`. pub fn roll_to(n: BlockNumber) { - crate::Pallet::::roll_to( - n, - matches!(SignedPhaseSwitch::get(), SignedSwitch::Real), - true, - ); + crate::Pallet::::roll_to(n, true); } /// proceed block number to whenever the snapshot is fully created (`Phase::Snapshot(0)`). @@ -695,10 +690,17 @@ pub fn roll_to_signed_open() { /// proceed block number to whenever the signed validation phase is open /// (`Phase::SignedValidation(_)`). +/// +/// Also ensure that the start signal is already sent. pub fn roll_to_signed_validation_open() { while !matches!(MultiBlock::current_phase(), Phase::SignedValidation(_)) { roll_next() } + assert_eq!(StatusStorage::::get(), Status::Ongoing(Pages::get() - 1)); + assert_eq!( + MultiBlock::current_phase(), + Phase::::SignedValidation(SignedValidationPhase::get()) + ); } /// proceed block number until we reach the done phase (`Phase::Done`). @@ -709,11 +711,36 @@ pub fn roll_to_done() { } /// Proceed one block. -pub fn roll_next() { +/// +/// This is intentionally made private and should not be exposed to tests. They should use other +/// helper functions that impose some checks. +fn roll_next() { let now = System::block_number(); roll_to(now + 1); } +/// Proceed one block and ensure the new phase is `expect`. +pub fn roll_next_and_phase(expect: Phase) { + let now = System::block_number(); + roll_to(now + 1); + assert_eq!(MultiBlock::current_phase(), expect); +} + +/// Proceed one block and ensure the new phase is `expect`, and signed validation is in `status`. +pub fn roll_next_and_phase_verifier(expect: Phase, status: Status) { + let now = System::block_number(); + roll_to(now + 1); + assert_eq!(MultiBlock::current_phase(), expect); + assert_eq!(VerifierPallet::status(), status); +} + +/// Proceed one block and ensure the new signed validation is in `status`. +pub fn roll_next_and_verifier(status: Status) { + let now = System::block_number(); + roll_to(now + 1); + assert_eq!(VerifierPallet::status(), status); +} + /// Proceed one block, and execute offchain workers as well. pub fn roll_next_with_ocw(maybe_pool: Option>>) { roll_to_with_ocw(System::block_number() + 1, maybe_pool) @@ -745,19 +772,9 @@ pub fn roll_to_with_ocw(n: BlockNumber, maybe_pool: Option System::set_block_number(i); - MultiBlock::on_initialize(i); - VerifierPallet::on_initialize(i); - UnsignedPallet::on_initialize(i); - if matches!(SignedPhaseSwitch::get(), SignedSwitch::Real) { - SignedPallet::on_initialize(i); - } + MultiBlock::on_poll(i, &mut WeightMeter::new()); - MultiBlock::offchain_worker(i); - VerifierPallet::offchain_worker(i); UnsignedPallet::offchain_worker(i); - if matches!(SignedPhaseSwitch::get(), SignedSwitch::Real) { - SignedPallet::offchain_worker(i); - } // invariants must hold at the end of each block. all_pallets_sanity_checks() diff --git a/substrate/frame/election-provider-multi-block/src/signed/mod.rs b/substrate/frame/election-provider-multi-block/src/signed/mod.rs index 1aa0dadb2d452..a878d3d87d03e 100644 --- a/substrate/frame/election-provider-multi-block/src/signed/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/signed/mod.rs @@ -111,6 +111,12 @@ pub struct SubmissionMetadata { pages: BoundedVec, } +impl crate::types::SignedInterface for Pallet { + fn has_leader(round: u32) -> bool { + Submissions::::has_leader(round) + } +} + impl SolutionDataProvider for Pallet { type Solution = SolutionOf; @@ -950,31 +956,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - fn on_initialize(_: BlockNumberFor) -> Weight { - // this code is only called when at the boundary of phase transition, which is already - // captured by the parent pallet. No need for weight. - let weight_taken_into_account: Weight = Default::default(); - - if crate::Pallet::::current_phase().is_signed_validation_opened_now() { - let maybe_leader = Submissions::::leader(Self::current_round()); - sublog!( - debug, - "signed", - "signed validation started, sending validation start signal? {:?}", - maybe_leader.is_some() - ); - - // start an attempt to verify our best thing. - if maybe_leader.is_some() { - // defensive: signed phase has just began, verifier should be in a clear state - // and ready to accept a solution. - let _ = ::start().defensive(); - } - } - - weight_taken_into_account - } - #[cfg(feature = "try-runtime")] fn try_state(n: BlockNumberFor) -> Result<(), sp_runtime::TryRuntimeError> { Self::do_try_state(n) @@ -1044,8 +1025,7 @@ impl Pallet { { // Only start verification if there are sufficient blocks remaining // Note: SignedValidation(N) means N+1 blocks remaining in the phase - let actual_blocks_remaining = remaining_blocks.saturating_add(One::one()); - if actual_blocks_remaining >= T::Pages::get().into() { + if remaining_blocks >= T::Pages::get().into() { if Submissions::::has_leader(current_round) { // defensive: verifier just reported back a result, it must be in clear // state. @@ -1056,7 +1036,7 @@ impl Pallet { warn, "signed", "SignedValidation phase has {:?} blocks remaining, which are insufficient for {} pages", - actual_blocks_remaining, + remaining_blocks, T::Pages::get() ); } diff --git a/substrate/frame/election-provider-multi-block/src/signed/tests.rs b/substrate/frame/election-provider-multi-block/src/signed/tests.rs index 085cec58935c4..d9fc9398d731b 100644 --- a/substrate/frame/election-provider-multi-block/src/signed/tests.rs +++ b/substrate/frame/election-provider-multi-block/src/signed/tests.rs @@ -525,19 +525,50 @@ mod e2e { ) ] ); + assert_eq!( + signed_events_since_last_call(), + vec![ + SignedEvent::Registered( + 0, + 99, + ElectionScore { minimal_stake: 10, sum_stake: 10, sum_stake_squared: 100 } + ), + SignedEvent::Stored(0, 99, 0), + SignedEvent::Registered( + 0, + 999, + ElectionScore { + minimal_stake: 55, + sum_stake: 130, + sum_stake_squared: 8650 + } + ), + SignedEvent::Stored(0, 999, 0), + SignedEvent::Stored(0, 999, 1), + SignedEvent::Stored(0, 999, 2), + SignedEvent::Registered( + 0, + 92, + ElectionScore { + minimal_stake: 110, + sum_stake: 130, + sum_stake_squared: 8650 + } + ) + ] + ); roll_to_signed_validation_open(); - // 92 is slashed in 3+1 blocks, 999 becomes rewarded in 3 blocks, and 99 is discarded. - roll_next(); - roll_next(); - roll_next(); - roll_next(); + // 92 is slashed in 3 blocks, 999 becomes rewarded in 3 blocks, and 99 is discarded. + roll_next_and_phase_verifier(Phase::::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::::SignedValidation(4), Status::Ongoing(0)); + // Note `Ongoing(2)` -- verifier is signaled to continue. + roll_next_and_phase_verifier(Phase::::SignedValidation(3), Status::Ongoing(2)); // Check events after first solution (92) is rejected - let events_after_first_rejection = verifier_events_since_last_call(); assert_eq!( - events_after_first_rejection, + verifier_events_since_last_call(), vec![ crate::verifier::Event::Verified(2, 0), crate::verifier::Event::Verified(1, 0), @@ -545,6 +576,8 @@ mod e2e { crate::verifier::Event::VerificationFailed(0, FeasibilityError::InvalidScore), ] ); + // and that submitter is slashed. + assert_eq!(signed_events_since_last_call(), vec![SignedEvent::Slashed(0, 92, 5)]); assert_eq!( Submissions::::leaderboard(0) @@ -554,14 +587,13 @@ mod e2e { vec![99, 999] ); - roll_next(); - roll_next(); - roll_next(); + roll_next_and_phase_verifier(Phase::::SignedValidation(2), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::::SignedValidation(1), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::::SignedValidation(0), Status::Nothing); // Check events after second solution (999) is accepted - let events_after_acceptance = verifier_events_since_last_call(); assert_eq!( - events_after_acceptance, + verifier_events_since_last_call(), vec![ crate::verifier::Event::Verified(2, 2), crate::verifier::Event::Verified(1, 2), @@ -577,45 +609,7 @@ mod e2e { ] ); - assert_eq!( - signed_events_since_last_call(), - vec![ - Event::Registered( - 0, - 99, - ElectionScore { minimal_stake: 10, sum_stake: 10, sum_stake_squared: 100 } - ), - Event::Stored(0, 99, 0), - Event::Registered( - 0, - 999, - ElectionScore { - minimal_stake: 55, - sum_stake: 130, - sum_stake_squared: 8650 - } - ), - Event::Stored(0, 999, 0), - Event::Stored(0, 999, 1), - Event::Stored(0, 999, 2), - Event::Registered( - 0, - 92, - ElectionScore { - minimal_stake: 110, - sum_stake: 130, - sum_stake_squared: 8650 - } - ), - Event::Slashed(0, 92, 5), - Event::Rewarded(0, 999, 7), - ] - ); - - assert!( - verifier_events_since_last_call().is_empty(), - "No additional verifier events should occur" - ); + assert_eq!(signed_events_since_last_call(), vec![SignedEvent::Rewarded(0, 999, 7)]); // 99 is discarded -- for now they have some deposit collected, which they have to // manually collect next. @@ -675,7 +669,6 @@ mod e2e { assert_eq!(Submissions::::submitters_count(current_round), 1); roll_to_signed_validation_open(); - roll_next(); // one block so signed pallet will send start signal. roll_to_full_verification(); // Check that rejection events were properly generated @@ -691,23 +684,22 @@ mod e2e { // Check that expected events were emitted for the rejection assert_eq!( - signed_events(), + signed_events_since_last_call(), vec![Event::Registered(0, 99, invalid_score), Event::Slashed(0, 99, 5),] ); // Verify no-restart conditions are met - assert!(crate::Pallet::::current_phase().is_signed_validation()); + assert!(MultiBlock::current_phase().is_signed_validation()); assert!(!Submissions::::has_leader(current_round)); assert_eq!(Submissions::::submitters_count(current_round), 0); assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); // Verifier should remain idle for the rest of the signed validation phase while crate::Pallet::::current_phase().is_signed_validation() { - roll_next(); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); + roll_next_and_verifier(Status::Nothing); } - roll_next(); + roll_next_and_phase(Phase::::Done); assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); }); } @@ -745,9 +737,9 @@ mod e2e { // Verify the metadata shows correct page submission status assert_eq!( - Submissions::::metadata_of(0, submitter).unwrap().pages.into_inner(), - vec![true, false, false] - ); + Submissions::::metadata_of(0, submitter).unwrap().pages.into_inner(), + vec![true, false, false] + ); // Verify that the solution data provider can access all pages without errors let page_0 = SignedPallet::get_page(0); @@ -763,10 +755,9 @@ mod e2e { roll_to_signed_validation_open(); // The verification should proceed and treat the missing pages as empty - roll_next(); // set status to ongoing - roll_next(); // Process page 2 (missing, treated as empty) - roll_next(); // Process page 1 (missing, treated as empty) - roll_next(); // Process page 0 (submitted with real data) + roll_next_and_phase_verifier(Phase::::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::::SignedValidation(4), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::::SignedValidation(3), Status::Nothing); // Check only the events from this verification assert_eq!( @@ -785,9 +776,8 @@ mod e2e { #[test] fn not_all_solutions_verified_signed_verification_to_unsigned() { // Test that in case of multiple verifications when not all of them are verified within the - // signed validation phase, the verifier should stop and go back to - // idle when transitioning from signed validation to unsigned phase, while keeping not yet - // verified solutions. + // signed validation phase, the verifier should stop and go back to idle when transitioning + // from signed validation to unsigned phase, while keeping not yet verified solutions. // NOTE: the signed validation phase must be a multiple of the number of pages, which // ensures that solutions cannot be halfway verified ExtBuilder::signed() @@ -811,88 +801,75 @@ mod e2e { load_signed_for_verification(999, strong_solution.clone()); } + assert_eq!( + signed_events_since_last_call(), + vec![ + SignedEvent::Registered( + 0, + 99, + ElectionScore { + minimal_stake: 110, + sum_stake: 130, + sum_stake_squared: 8650 + } + ), + SignedEvent::Registered( + 0, + 999, + ElectionScore { + minimal_stake: 55, + sum_stake: 130, + sum_stake_squared: 8650 + } + ), + SignedEvent::Stored(0, 999, 0), + SignedEvent::Stored(0, 999, 1), + SignedEvent::Stored(0, 999, 2), + ] + ); + let current_round = SignedPallet::current_round(); assert_eq!(Submissions::::submitters_count(current_round), 2); roll_to_signed_validation_open(); - assert_eq!(MultiBlock::current_phase(), Phase::SignedValidation(3)); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Nothing)); - roll_next(); // one block so signed-pallet will send the start signal - assert_eq!(MultiBlock::current_phase(), Phase::SignedValidation(2)); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(2))); + assert_eq!(verifier_events_since_last_call(), vec![]); + + roll_next_and_phase_verifier(Phase::SignedValidation(2), Status::Ongoing(1)); + assert_eq!( + verifier_events_since_last_call(), + vec![crate::verifier::Event::Verified(2, 0)] + ); // Initial verifier state should have no queued solution assert_eq!(VerifierPallet::queued_score(), None); - // Bad solution is the current leader - let mut remaining_leader = Submissions::::leader(current_round).unwrap(); - assert_eq!(remaining_leader.0, 99); - // Bad solution starts verification - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::SignedValidation(1)); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::SignedValidation(0)); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::SignedValidation(0)); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Nothing)); + roll_next_and_phase_verifier(Phase::SignedValidation(1), Status::Ongoing(0)); + assert_eq!( + verifier_events_since_last_call(), + vec![crate::verifier::Event::Verified(1, 0)] + ); - // Check events after bad solution verification completes + roll_next_and_phase_verifier(Phase::SignedValidation(0), Status::Nothing); assert_eq!( verifier_events_since_last_call(), vec![ - crate::verifier::Event::Verified(2, 0), - crate::verifier::Event::Verified(1, 0), crate::verifier::Event::Verified(0, 0), crate::verifier::Event::VerificationFailed( 0, FeasibilityError::InvalidScore - ), + ) ] ); - // Verify phase transition to unsigned - roll_next(); - assert_eq!(MultiBlock::current_phase(), Phase::Unsigned(UnsignedPhase::get() - 1)); + roll_next_and_phase(Phase::Unsigned(UnsignedPhase::get() - 1)); // Check that invalid solution is slashed but good solution remains assert_eq!(Submissions::::submitters_count(current_round), 1); assert!(Submissions::::has_leader(current_round)); - remaining_leader = Submissions::::leader(current_round).unwrap(); - assert_eq!(remaining_leader.0, 999); // Good solution remains // Check that expected events were emitted for the rejection - assert_eq!( - signed_events(), - vec![ - Event::Registered( - 0, - 99, - ElectionScore { - minimal_stake: 110, - sum_stake: 130, - sum_stake_squared: 8650 - } - ), - Event::Registered( - 0, - 999, - ElectionScore { - minimal_stake: 55, - sum_stake: 130, - sum_stake_squared: 8650 - } - ), - Event::Stored(0, 999, 0), - Event::Stored(0, 999, 1), - Event::Stored(0, 999, 2), - Event::Slashed(0, 99, 5), - ] - ); + assert_eq!(signed_events_since_last_call(), vec![Event::Slashed(0, 99, 5)]); // Verify no additional events occurred assert!( @@ -930,16 +907,16 @@ mod e2e { let good_solution = mine_full_solution().unwrap(); load_signed_for_verification(999, good_solution); } + // skip registration events + let _ = signed_events_since_last_call(); roll_to_signed_validation_open(); - let _ = signed_events_since_last_call(); // henceforth we proceed block-by-block for better visibility of what is happening. - // 3 blocks to reject the first one: 1 to set status to ongoing, and 2 to verify - roll_next(); - roll_next(); - roll_next(); + // 2 blocks to reject the first one + roll_next_and_phase_verifier(Phase::SignedValidation(2), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(1), Status::Nothing); assert_eq!( verifier_events_since_last_call(), @@ -958,21 +935,20 @@ mod e2e { vec![crate::signed::Event::Slashed(0, 99, 8)] ); - // we have 1 block left in signed verification, but we cannot do anything here. - assert_eq!(crate::Pallet::::current_phase(), Phase::SignedValidation(0)); + // we have 2 blocks left in signed verification (1 and 3), but we cannot do anything + // here. Status remains idle. + roll_next_and_phase_verifier(Phase::SignedValidation(0), Status::Nothing); // we go back to signed next - roll_next(); - assert_eq!(crate::Pallet::::current_phase(), Phase::Signed(4)); + roll_next_and_phase(Phase::Signed(4)); // no one submits again, and we go to verification again roll_to_signed_validation_open(); // 4 block to verify: 1 to set status, and 3 to verify - roll_next(); - roll_next(); - roll_next(); - roll_next(); + roll_next_and_phase_verifier(Phase::SignedValidation(2), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(1), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::SignedValidation(0), Status::Nothing); assert_eq!( verifier_events_since_last_call(), @@ -997,133 +973,19 @@ mod e2e { // verifier is `Nothing`, and will remain so as signed-pallet will not start it // again. - assert_eq!(crate::Pallet::::current_phase(), Phase::SignedValidation(0)); assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); // next block we go to done - roll_next(); - assert_eq!(crate::Pallet::::current_phase(), Phase::Done); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); + roll_next_and_phase_verifier(Phase::Done, Status::Nothing); }) } - #[test] - fn not_all_solutions_verified_signed_verification_incomplete_to_signed() { - // Test that demonstrates early failure and no verifier restart due to insufficient blocks: - // - SignedValidation phase of 3 blocks with 3-page solutions - // - Bad solution with high score fails early on page 1 with invalid voter index - // - Good solution with lower score is submitted but cannot be verified - // - After bad solution fails, verifier is NOT restarted because there are only 2 blocks - // remaining and we need 3 blocks for a 3-page solution - // - System transitions back to Signed phase with good solution still queued for next round - ExtBuilder::signed() - .pages(3) - .signed_validation_phase(3) // 3 blocks for validation - .are_we_done(crate::mock::AreWeDoneModes::BackToSigned) // Revert to signed if no solution - .build_and_execute(|| { - roll_to_signed_open(); - - // Submit bad solution with high score that will fail early during verification - { - let mut bad_solution = mine_full_solution().unwrap(); - bad_solution.score.minimal_stake *= 2; - bad_solution.solution_pages[1usize].corrupt(); - load_signed_for_verification(99, bad_solution); - } - - // Submit good solution with lower score (all pages valid) - { - let good_solution = mine_full_solution().unwrap(); - load_signed_for_verification(999, good_solution.clone()); - } - - let current_round = SignedPallet::current_round(); - assert_eq!(Submissions::::submitters_count(current_round), 2); - - roll_to_signed_validation_open(); - roll_next(); // one block so signed-pallet will send the start signal - assert!(matches!(MultiBlock::current_phase(), Phase::SignedValidation(_))); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - - // Bad solution is the current leader (higher score) - let leader = Submissions::::leader(current_round).unwrap(); - assert_eq!(leader.0, 99); - - // Block 1: Start verification of bad solution (page 2) - roll_next(); // SignedValidation(2) -> SignedValidation(1) - assert!(matches!(MultiBlock::current_phase(), Phase::SignedValidation(1))); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - - // Should verify page 2 successfully - assert_eq!( - verifier_events_since_last_call(), - vec![crate::verifier::Event::Verified(2, 2)] - ); - - // Block 2: Continue verification (page 1) - bad solution should fail here - roll_next(); // SignedValidation(1) -> SignedValidation(0) - assert!(matches!(MultiBlock::current_phase(), Phase::SignedValidation(0))); - - // Bad solution should fail early with NposElection error on page 1 verification - assert_eq!( - verifier_events_since_last_call(), - vec![crate::verifier::Event::VerificationFailed( - 1, - FeasibilityError::NposElection( - sp_npos_elections::Error::SolutionInvalidIndex - ) - )] - ); - - // Block 3: No more verification needed - bad solution already failed - roll_next(); // SignedValidation(0) -> transitions to next phase - - // Check that bad solution is removed and good solution remains - assert_eq!(Submissions::::submitters_count(current_round), 1); - let remaining_leader = Submissions::::leader(current_round).unwrap(); - assert_eq!(remaining_leader.0, 999); // Good solution is now leader - - // CRITICAL: Verifier should NOT restart because there are only 2 blocks remaining - // (after using 1 block and failing early, but still need 3 blocks for a full - // solution) Should transition back to Signed phase since verification cannot - // restart - assert!(matches!(MultiBlock::current_phase(), Phase::Signed(_))); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); - - // Check events - bad solution should be slashed - let all_signed_events = signed_events(); - assert!(all_signed_events.iter().any(|e| matches!(e, Event::Slashed(0, 99, _)))); - - // At the end of signed phase, verifier is still idle - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); - - roll_to_signed_validation_open(); - roll_next(); // one block so signed-pallet will send the start signal - - // Now in the next validation phase, the good solution starts verification - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - assert_eq!(Submissions::::submitters_count(current_round), 1); - - // Verify the good solution over 3 blocks - roll_next(); // Process page 2 - roll_next(); // Process page 1 - roll_next(); // Process page 0 - - // Good solution should be fully verified and accepted - assert_eq!(crate::Pallet::::current_phase(), Phase::SignedValidation(0)); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); - assert_eq!(Submissions::::submitters_count(current_round), 0); - }); - } - #[test] fn max_queue_with_single_valid_solution_at_end() { // Test that when the submission queue is at capacity (MaxSubmissions = 3), with only the // third submission being valid, the verifier processes the entire queue sequentially and // eventually accepts the final valid solution. - - // Set max submissions to 3 for this test ExtBuilder::signed() .max_signed_submissions(3) .signed_validation_phase(9) // 3 solutions * 3 pages per solution = 9 blocks needed @@ -1134,23 +996,32 @@ mod e2e { let current_round = SignedPallet::current_round(); // Submit two invalid solutions (register but don't submit pages) - let invalid_score1 = { - let mut score = mine_full_solution().unwrap().score; - score.minimal_stake *= 2; // Make it attractive but it will be invalid - score - }; - assert_ok!(SignedPallet::register(RuntimeOrigin::signed(91), invalid_score1)); + { + let invalid_score1 = { + let mut score = mine_full_solution().unwrap().score; + score.minimal_stake *= 2; // Make it attractive but it will be invalid + score + }; + assert_ok!(SignedPallet::register(RuntimeOrigin::signed(91), invalid_score1)); + } - let invalid_score2 = { - let mut score = mine_full_solution().unwrap().score; - score.minimal_stake *= 3; // Make it even more attractive but still invalid - score - }; - assert_ok!(SignedPallet::register(RuntimeOrigin::signed(92), invalid_score2)); + { + let invalid_score2 = { + let mut score = mine_full_solution().unwrap().score; + score.minimal_stake *= 3; // Make it even more attractive but still invalid + score + }; + assert_ok!(SignedPallet::register(RuntimeOrigin::signed(92), invalid_score2)); + } // Submit one valid solution at the end - let valid_solution = mine_full_solution().unwrap(); - load_signed_for_verification(99, valid_solution.clone()); + let valid_score = { + let valid_solution = mine_full_solution().unwrap(); + load_signed_for_verification(99, valid_solution.clone()); + valid_solution.score + }; + // skip registration events + let _ = signed_events_since_last_call(); // Verify we have 3 submissions at max capacity assert_eq!(Submissions::::submitters_count(current_round), 3); @@ -1158,18 +1029,15 @@ mod e2e { // Move to verification phase roll_to_signed_validation_open(); - roll_next(); // one block so signed-pallet will send the start signal - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - // Process first invalid solution (91) - roll_next(); // Process page 2 - roll_next(); // Process page 1 - roll_next(); // Process page 0 and reject solution + roll_next_and_phase_verifier(Phase::SignedValidation(8), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(7), Status::Ongoing(0)); + // Note `Status::Ongoing(2)` -- we are signaled to start again in then next block. + roll_next_and_phase_verifier(Phase::SignedValidation(6), Status::Ongoing(2)); // Check events after first solution (91) is rejected - let events_first_solution = verifier_events_since_last_call(); assert_eq!( - events_first_solution, + verifier_events_since_last_call(), vec![ crate::verifier::Event::Verified(2, 0), crate::verifier::Event::Verified(1, 0), @@ -1180,15 +1048,15 @@ mod e2e { ), ] ); + assert_eq!(signed_events_since_last_call(), vec![SignedEvent::Slashed(0, 92, 5)]); // Verify first solution was slashed and removed assert_eq!(Submissions::::submitters_count(current_round), 2); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); - // Process second invalid solution (92) - roll_next(); // Process page 2 - roll_next(); // Process page 1 - roll_next(); // Process page 0 and reject solution + roll_next_and_phase_verifier(Phase::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(4), Status::Ongoing(0)); + // Note `Status::Ongoing(2)` -- we are signaled to start again in then next block. + roll_next_and_phase_verifier(Phase::SignedValidation(3), Status::Ongoing(2)); // Check events after second solution (92) is rejected assert_eq!( @@ -1203,19 +1071,19 @@ mod e2e { ), ] ); + assert_eq!(signed_events_since_last_call(), vec![SignedEvent::Slashed(0, 91, 5)]); // Verify second solution was slashed and removed assert_eq!(Submissions::::submitters_count(current_round), 1); - assert!(matches!(VerifierPallet::status(), crate::verifier::Status::Ongoing(_))); // Verify the last remaining solution is our valid one let leader = Submissions::::leader(current_round).unwrap(); assert_eq!(leader.0, 99); - // Process the final valid solution - roll_next(); // Process page 2 of valid solution - roll_next(); // Process page 1 of valid solution - roll_next(); // Process page 0 of valid solution and accept it + // Process the final valid solution. We are done _exactly on time_. + roll_next_and_phase_verifier(Phase::SignedValidation(2), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(1), Status::Ongoing(0)); + roll_next_and_phase_verifier(Phase::SignedValidation(0), Status::Nothing); // Check events after valid solution (99) is accepted assert_eq!( @@ -1224,34 +1092,15 @@ mod e2e { crate::verifier::Event::Verified(2, 2), crate::verifier::Event::Verified(1, 2), crate::verifier::Event::Verified(0, 2), - crate::verifier::Event::Queued(valid_solution.score, None), + crate::verifier::Event::Queued(valid_score, None), ] ); - assert_eq!(crate::Pallet::::current_phase(), Phase::SignedValidation(0)); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); - // Check that all expected events were emitted in the correct order - assert_eq!( - signed_events(), - vec![ - Event::Registered(0, 91, invalid_score1), - Event::Registered(0, 92, invalid_score2), - Event::Registered(0, 99, valid_solution.score), - Event::Stored(0, 99, 0), - Event::Stored(0, 99, 1), - Event::Stored(0, 99, 2), - Event::Slashed(0, 92, 5), - Event::Slashed(0, 91, 5), - Event::Rewarded(0, 99, 7), - ] - ); + assert_eq!(signed_events_since_last_call(), vec![Event::Rewarded(0, 99, 7)]); // finally done - roll_next(); - assert_eq!(crate::Pallet::::current_phase(), Phase::Done); - // verifier has done nothing - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); + roll_next_and_phase_verifier(Phase::Done, Status::Nothing); assert!( verifier_events_since_last_call().is_empty(), "No additional verifier events should occur" @@ -1520,7 +1369,6 @@ mod invulnerables { let _ = signed_events_since_last_call(); roll_to_signed_validation_open(); - roll_next(); roll_to_full_verification(); assert_eq!( @@ -1542,9 +1390,8 @@ mod invulnerables { assert_eq!(signed_events_since_last_call(), vec![Event::Rewarded(0, 98, 7)]); // not relevant: signed will not start verification again - roll_next(); + roll_next_and_phase_verifier(Phase::SignedValidation(2), Status::Nothing); assert!(verifier_events_since_last_call().is_empty()); - assert_eq!(VerifierPallet::status(), crate::verifier::Status::Nothing); // fast-forward to round being over roll_to_done(); @@ -1605,7 +1452,6 @@ mod invulnerables { assert_ok!(SignedPallet::register(RuntimeOrigin::signed(99), invalid_score)); roll_to_signed_validation_open(); - roll_next(); // one block so signed pallet will send start signal. roll_to_full_verification(); // Check that rejection events were properly generated @@ -1655,12 +1501,6 @@ mod defensive_tests { // Submit a solution page to have something to verify assert_ok!(SignedPallet::submit_page(RuntimeOrigin::signed(99), 0, Default::default())); - - assert_ok!(::start()); - - roll_next(); // Process page 2 - roll_next(); // Process page 1 - assert_eq!( signed_events_since_last_call(), vec![ @@ -1673,16 +1513,19 @@ mod defensive_tests { ] ); - // Now mutate storage to delete the score of the leader. - let current_round = SignedPallet::current_round(); + // verify 2 of the pages. + roll_to_signed_validation_open(); + roll_next_and_phase_verifier(Phase::SignedValidation(5), Status::Ongoing(1)); + roll_next_and_phase_verifier(Phase::SignedValidation(4), Status::Ongoing(0)); // Delete the score storage - let full_key = - crate::signed::pallet::SortedScores::::hashed_key_for(current_round); + let full_key = crate::signed::pallet::SortedScores::::hashed_key_for( + SignedPallet::current_round(), + ); unhashed::kill(&full_key); // Complete verification - this should trigger score unavailable detection - roll_next(); + roll_next_and_phase(Phase::SignedValidation(3)); }); } diff --git a/substrate/frame/election-provider-multi-block/src/types.rs b/substrate/frame/election-provider-multi-block/src/types.rs index 41dffb49c7c4d..913684c1b9f75 100644 --- a/substrate/frame/election-provider-multi-block/src/types.rs +++ b/substrate/frame/election-provider-multi-block/src/types.rs @@ -271,8 +271,8 @@ pub enum Phase { /// The inner value should be read as "`remaining` number of pages are left to be fetched". /// Thus, if inner value is `0` if the snapshot is complete and we are ready to move on. /// - /// This value should be interpreted after `on_initialize` of this pallet has already been - /// called. + /// This value should be interpreted after `on_initialize`/`on_poll` of this pallet has already + /// been called. Snapshot(PageIndex), /// Snapshot is done, and we are waiting for `Export` to kick in. Done, @@ -361,10 +361,9 @@ impl Phase { // Done. Wait for export to start. Self::Done => Self::Done, - // Export - Self::Export(0) => Self::Off, - Self::Export(non_zero_left) => - Self::Export(non_zero_left.defensive_saturating_sub(One::one())), + // Export never moves forward via this function, and is always manually set in the + // `elect` code path. + Self::Export(x) => Self::Export(x), } } @@ -419,6 +418,15 @@ impl Phase { } } +/// Slim interface for the parent pallet to be able to inspect the state of the signed pallet. +/// +/// Intentionally left different from [`crate::verifier::SolutionDataProvider`], as that is +/// specialized for communication between `verifier <> signed`. +pub trait SignedInterface { + /// Returns `true` if there is a candidate solution to be verified. + fn has_leader(round: u32) -> bool; +} + #[cfg(test)] mod pagify { use super::{PadSolutionPages, Pagify}; diff --git a/substrate/frame/election-provider-multi-block/src/unsigned/benchmarking.rs b/substrate/frame/election-provider-multi-block/src/unsigned/benchmarking.rs index 2cab1d5997079..72b3e30ac3ec6 100644 --- a/substrate/frame/election-provider-multi-block/src/unsigned/benchmarking.rs +++ b/substrate/frame/election-provider-multi-block/src/unsigned/benchmarking.rs @@ -77,6 +77,7 @@ mod benchmarks { Ok(()) } + /// NOTE: make sure this benchmark is being run with the correct `type Solver` in `MinerConfig`. #[benchmark(extra, pov_mode = Measured)] fn mine_solution(p: Linear<1, { T::Pages::get() }>) -> Result<(), BenchmarkError> { #[cfg(test)] diff --git a/substrate/frame/election-provider-multi-block/src/unsigned/miner.rs b/substrate/frame/election-provider-multi-block/src/unsigned/miner.rs index 6e2e11aa16942..1a5d57d0fc4e2 100644 --- a/substrate/frame/election-provider-multi-block/src/unsigned/miner.rs +++ b/substrate/frame/election-provider-multi-block/src/unsigned/miner.rs @@ -1007,7 +1007,7 @@ mod trimming { #[test] fn solution_without_any_trimming() { - ExtBuilder::unsigned().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1023,7 +1023,6 @@ mod trimming { ); assert_eq!(solution.solution_pages.encoded_size(), 105); - load_mock_signed_and_start(solution); let supports = roll_to_full_verification(); @@ -1051,7 +1050,7 @@ mod trimming { #[test] fn trim_length() { - ExtBuilder::unsigned().miner_max_length(104).build_and_execute(|| { + ExtBuilder::mock_signed().miner_max_length(104).build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1095,7 +1094,7 @@ mod trimming { #[test] fn trim_length_2() { - ExtBuilder::unsigned().miner_max_length(98).build_and_execute(|| { + ExtBuilder::mock_signed().miner_max_length(98).build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1137,7 +1136,7 @@ mod trimming { #[test] fn trim_length_3() { - ExtBuilder::unsigned().miner_max_length(92).build_and_execute(|| { + ExtBuilder::mock_signed().miner_max_length(92).build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1179,7 +1178,7 @@ mod trimming { #[test] fn trim_backers_per_page_works() { - ExtBuilder::unsigned().max_backers_per_winner(2).build_and_execute(|| { + ExtBuilder::mock_signed().max_backers_per_winner(2).build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1223,7 +1222,7 @@ mod trimming { fn trim_backers_per_page_works_2() { // This one is more interesting, as it also shows that as we trim backers, we re-distribute // their weight elsewhere. - ExtBuilder::unsigned().max_backers_per_winner(1).build_and_execute(|| { + ExtBuilder::mock_signed().max_backers_per_winner(1).build_and_execute(|| { // adjust the voters a bit, such that they are all different backings let mut current_voters = Voters::get(); current_voters.iter_mut().for_each(|(who, stake, ..)| *stake = *who); @@ -1262,7 +1261,7 @@ mod trimming { #[test] fn trim_backers_final_works() { - ExtBuilder::unsigned() + ExtBuilder::mock_signed() .max_backers_per_winner(4) .max_backers_per_winner_final(4) .build_and_execute(|| { @@ -1305,7 +1304,7 @@ mod trimming { #[test] fn trim_backers_per_page_and_final_works() { - ExtBuilder::unsigned() + ExtBuilder::mock_signed() .max_backers_per_winner_final(4) .max_backers_per_winner(2) .build_and_execute(|| { @@ -1349,7 +1348,7 @@ mod trimming { fn aggressive_backer_trimming_maintains_winner_count() { // Test the scenario where aggressive backer trimming is applied but the solution // should still maintain the correct winner count to avoid WrongWinnerCount errors. - ExtBuilder::unsigned() + ExtBuilder::mock_signed() .desired_targets(3) .max_winners_per_page(2) .pages(2) @@ -1404,7 +1403,7 @@ mod base_miner { #[test] fn pagination_does_not_affect_score() { - let score_1 = ExtBuilder::unsigned() + let score_1 = ExtBuilder::mock_signed() .pages(1) .voter_per_page(12) .build_unchecked() @@ -1412,7 +1411,7 @@ mod base_miner { roll_to_snapshot_created(); mine_full_solution().unwrap().score }); - let score_2 = ExtBuilder::unsigned() + let score_2 = ExtBuilder::mock_signed() .pages(2) .voter_per_page(6) .build_unchecked() @@ -1420,7 +1419,7 @@ mod base_miner { roll_to_snapshot_created(); mine_full_solution().unwrap().score }); - let score_3 = ExtBuilder::unsigned() + let score_3 = ExtBuilder::mock_signed() .pages(3) .voter_per_page(4) .build_unchecked() @@ -1435,7 +1434,7 @@ mod base_miner { #[test] fn mine_solution_single_page_works() { - ExtBuilder::unsigned().pages(1).voter_per_page(8).build_and_execute(|| { + ExtBuilder::mock_signed().pages(1).voter_per_page(8).build_and_execute(|| { roll_to_snapshot_created(); ensure_voters(1, 8); @@ -1487,7 +1486,7 @@ mod base_miner { #[test] fn mine_solution_double_page_works() { - ExtBuilder::unsigned().pages(2).voter_per_page(4).build_and_execute(|| { + ExtBuilder::mock_signed().pages(2).voter_per_page(4).build_and_execute(|| { roll_to_snapshot_created(); // 2 pages of 8 voters @@ -1573,7 +1572,7 @@ mod base_miner { #[test] fn mine_solution_triple_page_works() { - ExtBuilder::unsigned().pages(3).voter_per_page(4).build_and_execute(|| { + ExtBuilder::mock_signed().pages(3).voter_per_page(4).build_and_execute(|| { roll_to_snapshot_created(); ensure_voters(3, 12); @@ -1664,7 +1663,7 @@ mod base_miner { #[test] fn mine_solution_choses_most_significant_pages() { - ExtBuilder::unsigned().pages(2).voter_per_page(4).build_and_execute(|| { + ExtBuilder::mock_signed().pages(2).voter_per_page(4).build_and_execute(|| { roll_to_snapshot_created(); ensure_voters(2, 8); @@ -1735,7 +1734,7 @@ mod base_miner { #[test] fn mine_solution_2_out_of_3_pages() { - ExtBuilder::unsigned().pages(3).voter_per_page(4).build_and_execute(|| { + ExtBuilder::mock_signed().pages(3).voter_per_page(4).build_and_execute(|| { roll_to_snapshot_created(); ensure_voters(3, 12); @@ -1834,7 +1833,7 @@ mod base_miner { #[test] fn can_reduce_solution() { - ExtBuilder::unsigned().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let full_edges = OffchainWorkerMiner::::mine_solution(Pages::get(), false) .unwrap() @@ -1863,7 +1862,7 @@ mod offchain_worker_miner { #[test] fn lock_prevents_frequent_execution() { - let (mut ext, _) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, _) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); @@ -1901,7 +1900,7 @@ mod offchain_worker_miner { #[test] fn lock_released_after_successful_execution() { // first, ensure that a successful execution releases the lock - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { let guard = StorageValueRef::persistent(&OffchainWorkerMiner::::OFFCHAIN_LOCK); let last_block = @@ -1925,7 +1924,7 @@ mod offchain_worker_miner { #[test] fn lock_prevents_overlapping_execution() { // ensure that if the guard is in hold, a new execution is not allowed. - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); @@ -1952,7 +1951,7 @@ mod offchain_worker_miner { #[test] fn initial_ocw_runs_and_saves_new_cache() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); @@ -1975,7 +1974,7 @@ mod offchain_worker_miner { #[test] fn ocw_pool_submission_works() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); @@ -1996,7 +1995,7 @@ mod offchain_worker_miner { #[test] fn resubmits_after_offchain_repeat() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); roll_to_unsigned_open(); @@ -2021,7 +2020,7 @@ mod offchain_worker_miner { #[test] fn regenerates_and_resubmits_after_offchain_repeat_if_no_cache() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); roll_to_unsigned_open(); @@ -2055,7 +2054,7 @@ mod offchain_worker_miner { #[test] fn altering_snapshot_invalidates_solution_cache() { // by infeasible, we mean here that if the snapshot fingerprint has changed. - let (mut ext, pool) = ExtBuilder::unsigned().unsigned_phase(999).build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().unsigned_phase(999).build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); roll_to_unsigned_open(); @@ -2098,7 +2097,7 @@ mod offchain_worker_miner { fn wont_resubmit_if_weak_score() { // common case, if the score is weak, don't bother with anything, ideally check from the // logs that we don't run feasibility in this call path. Score check must come before. - let (mut ext, pool) = ExtBuilder::unsigned().unsigned_phase(999).build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().unsigned_phase(999).build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); // unfortunately there's no pretty way to run the ocw code such that it generates a @@ -2135,7 +2134,7 @@ mod offchain_worker_miner { #[test] fn ocw_submission_e2e_works() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { assert!(VerifierPallet::queued_score().is_none()); roll_to_with_ocw(25 + 1, Some(pool.clone())); @@ -2153,7 +2152,7 @@ mod offchain_worker_miner { #[test] fn ocw_e2e_submits_and_queued_msp_only() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { // roll to mine roll_to_unsigned_open_with_ocw(None); @@ -2192,7 +2191,7 @@ mod offchain_worker_miner { #[test] fn multi_page_ocw_e2e_submits_and_queued_msp_only() { - let (mut ext, pool) = ExtBuilder::unsigned().miner_pages(2).build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().miner_pages(2).build_offchainify(); ext.execute_with_sanity_checks(|| { // roll to mine roll_to_unsigned_open_with_ocw(None); @@ -2232,7 +2231,7 @@ mod offchain_worker_miner { #[test] fn full_multi_page_ocw_e2e_submits_and_queued_msp_only() { - let (mut ext, pool) = ExtBuilder::unsigned().miner_pages(3).build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().miner_pages(3).build_offchainify(); ext.execute_with_sanity_checks(|| { // roll to mine roll_to_unsigned_open_with_ocw(None); @@ -2278,7 +2277,7 @@ mod offchain_worker_miner { #[test] fn will_not_mine_if_not_enough_winners() { // also see `trim_weight_too_much_makes_solution_invalid`. - let (mut ext, _) = ExtBuilder::unsigned().desired_targets(77).build_offchainify(); + let (mut ext, _) = ExtBuilder::mock_signed().desired_targets(77).build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); ensure_voters(3, 12); @@ -2299,7 +2298,7 @@ mod offchain_worker_miner { // - Initial run: mines and submits without caching // - Resubmission: re-mines fresh solution instead of restoring from cache let (mut ext, pool) = - ExtBuilder::unsigned().offchain_storage(false).build_offchainify(); + ExtBuilder::mock_signed().offchain_storage(false).build_offchainify(); ext.execute_with_sanity_checks(|| { let offchain_repeat = ::OffchainRepeat::get(); roll_to_unsigned_open(); diff --git a/substrate/frame/election-provider-multi-block/src/unsigned/mod.rs b/substrate/frame/election-provider-multi-block/src/unsigned/mod.rs index 0d646e04f5040..91f62dccf699a 100644 --- a/substrate/frame/election-provider-multi-block/src/unsigned/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/unsigned/mod.rs @@ -381,11 +381,17 @@ mod validate_unsigned { use crate::{mock::*, types::*, verifier::Verifier}; #[test] +<<<<<<< HEAD fn retracts_weak_score_accepts_threshold_better() { ExtBuilder::unsigned() .solution_improvement_threshold(sp_runtime::Perbill::from_percent(10)) .build_and_execute(|| { roll_to_snapshot_created(); +======= + fn retracts_weak_score_accepts_better() { + ExtBuilder::mock_signed().build_and_execute(|| { + roll_to_snapshot_created(); +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) let solution = mine_full_solution().unwrap(); load_mock_signed_and_start(solution.clone()); @@ -443,7 +449,7 @@ mod validate_unsigned { #[test] fn retracts_wrong_round() { - ExtBuilder::unsigned().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_unsigned_open(); let mut attempt = @@ -461,7 +467,7 @@ mod validate_unsigned { #[test] fn retracts_too_many_pages_unsigned() { - ExtBuilder::unsigned().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // NOTE: unsigned solutions should have just 1 page, regardless of the configured // page count. roll_to_unsigned_open(); @@ -491,7 +497,7 @@ mod validate_unsigned { #[test] fn retracts_wrong_winner_count() { - ExtBuilder::unsigned().desired_targets(2).build_and_execute(|| { + ExtBuilder::mock_signed().desired_targets(2).build_and_execute(|| { roll_to_unsigned_open(); let paged = raw_paged_from_supports( @@ -511,7 +517,7 @@ mod validate_unsigned { #[test] fn retracts_wrong_phase() { - ExtBuilder::unsigned().signed_phase(5, 6).build_and_execute(|| { + ExtBuilder::mock_signed().signed_phase(5, 6).build_and_execute(|| { let solution = raw_paged_solution_low_score(); let call = Call::submit_unsigned { paged_solution: Box::new(solution.clone()) }; @@ -561,7 +567,7 @@ mod validate_unsigned { #[test] fn priority_is_set() { - ExtBuilder::unsigned() + ExtBuilder::mock_signed() .miner_tx_priority(20) .desired_targets(0) .build_and_execute(|| { @@ -591,7 +597,7 @@ mod call { #[test] fn unsigned_submission_e2e() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); @@ -619,7 +625,7 @@ mod call { expected = "Invalid unsigned submission must produce invalid block and deprive validator from their authoring reward." )] fn unfeasible_solution_panics() { - let (mut ext, pool) = ExtBuilder::unsigned().build_offchainify(); + let (mut ext, pool) = ExtBuilder::mock_signed().build_offchainify(); ext.execute_with_sanity_checks(|| { roll_to_unsigned_open(); diff --git a/substrate/frame/election-provider-multi-block/src/verifier/benchmarking.rs b/substrate/frame/election-provider-multi-block/src/verifier/benchmarking.rs index 50c3e73fbe5c6..6cc5deb8f3eea 100644 --- a/substrate/frame/election-provider-multi-block/src/verifier/benchmarking.rs +++ b/substrate/frame/election-provider-multi-block/src/verifier/benchmarking.rs @@ -39,7 +39,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_valid_non_terminal() -> Result<(), BenchmarkError> { + fn verification_valid_non_terminal() -> Result<(), BenchmarkError> { #[cfg(test)] crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); crate::Pallet::::start().unwrap(); @@ -51,15 +51,13 @@ mod benchmarks { crate::Pallet::::roll_until_matches(|| { matches!(CurrentPhase::::get(), Phase::SignedValidation(_)) }); - // send start signal - crate::Pallet::::roll_next(true, false); // start signal must have been sent by now assert_eq!(StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp())); #[block] { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } assert_eq!(StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp() - 1)); @@ -67,7 +65,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_valid_terminal() -> Result<(), BenchmarkError> { + fn verification_valid_terminal() -> Result<(), BenchmarkError> { #[cfg(test)] crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); crate::Pallet::::start().unwrap(); @@ -83,13 +81,11 @@ mod benchmarks { crate::Pallet::::roll_until_matches(|| { matches!(CurrentPhase::::get(), Phase::SignedValidation(_)) }); - // send start signal - crate::Pallet::::roll_next(true, false); // start signal must have been sent by now assert_eq!(StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp())); for _ in 0..(T::Pages::get() - 1) { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } // we must have verified all pages by now, minus the last one. @@ -101,7 +97,7 @@ mod benchmarks { // verify the last page. #[block] { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } // we are done @@ -116,7 +112,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_invalid_terminal() -> Result<(), BenchmarkError> { + fn verification_invalid_terminal() -> Result<(), BenchmarkError> { // this is the verification of the current page + removing all of the previously valid // pages. The worst case is therefore when the last page is invalid, for example the final // score. @@ -137,13 +133,11 @@ mod benchmarks { crate::Pallet::::roll_until_matches(|| { matches!(CurrentPhase::::get(), Phase::SignedValidation(_)) }); - // send start signal - crate::Pallet::::roll_next(true, false); assert_eq!(StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp())); // verify all pages, except for the last one. for i in 0..T::Pages::get() - 1 { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); assert_eq!( StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp() - 1 - i) @@ -159,7 +153,7 @@ mod benchmarks { #[block] { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } // we are now reset. @@ -177,7 +171,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn on_initialize_invalid_non_terminal( + fn verification_invalid_non_terminal( // number of valid pages that have been verified, before we verify the non-terminal invalid // page. v: Linear<0, { T::Pages::get() - 1 }>, @@ -206,15 +200,13 @@ mod benchmarks { crate::Pallet::::roll_until_matches(|| { matches!(CurrentPhase::::get(), Phase::SignedValidation(_)) }); - // send start signal - crate::Pallet::::roll_next(true, false); // we should be ready to go assert_eq!(StatusStorage::::get(), Status::Ongoing(crate::Pallet::::msp())); // validate the the parameterized number of valid pages. for _ in 0..v { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } // we are still ready to continue @@ -223,7 +215,7 @@ mod benchmarks { // verify one page, which will be invalid. #[block] { - crate::Pallet::::roll_next(true, false); + crate::Pallet::::roll_next(false); } // we are now reset, because this page was invalid. diff --git a/substrate/frame/election-provider-multi-block/src/verifier/impls.rs b/substrate/frame/election-provider-multi-block/src/verifier/impls.rs index 6047f2018d4ee..d7bb43da267f1 100644 --- a/substrate/frame/election-provider-multi-block/src/verifier/impls.rs +++ b/substrate/frame/election-provider-multi-block/src/verifier/impls.rs @@ -33,7 +33,7 @@ use frame_election_provider_support::{ use frame_support::{ ensure, pallet_prelude::{ValueQuery, *}, - traits::{defensive_prelude::*, Get}, + traits::{defensive_prelude::*, DefensiveSaturating, Get}, }; use frame_system::pallet_prelude::*; use pallet::*; @@ -614,10 +614,6 @@ pub(crate) mod pallet { assert!(T::MaxBackersPerWinner::get() <= T::MaxBackersPerWinnerFinal::get()); } - fn on_initialize(_n: BlockNumberFor) -> Weight { - Self::do_on_initialize() - } - #[cfg(feature = "try-runtime")] fn try_state(_now: BlockNumberFor) -> Result<(), sp_runtime::TryRuntimeError> { Self::do_try_state(_now) @@ -626,11 +622,21 @@ pub(crate) mod pallet { } impl Pallet { - fn do_on_initialize() -> Weight { - if let Status::Ongoing(current_page) = Self::status_storage() { + fn do_per_block_exec() -> (Weight, Box) { + let Status::Ongoing(current_page) = Self::status_storage() else { + let weight = T::DbWeight::get().reads(1); + return (weight, Box::new(move |meter: &mut WeightMeter| meter.consume(weight))) + }; + + // before executing, we don't know which weight we will consume; return the max. + let worst_case_weight = VerifierWeightsOf::::verification_valid_non_terminal() + .max(VerifierWeightsOf::::verification_valid_terminal()) + .max(VerifierWeightsOf::::verification_invalid_non_terminal(T::Pages::get())) + .max(VerifierWeightsOf::::verification_invalid_terminal()); + + let execute = Box::new(move |meter: &mut WeightMeter| { let page_solution = ::get_page(current_page); - let maybe_supports = Self::feasibility_check_page_inner(page_solution, current_page); sublog!( @@ -640,27 +646,29 @@ impl Pallet { current_page, maybe_supports.as_ref().map(|s| s.len()) ); - match maybe_supports { Ok(supports) => { Self::deposit_event(Event::::Verified(current_page, supports.len() as u32)); QueuedSolution::::set_invalid_page(current_page, supports); if current_page > crate::Pallet::::lsp() { - // not last page, just tick forward. - StatusStorage::::put(Status::Ongoing(current_page.saturating_sub(1))); - VerifierWeightsOf::::on_initialize_valid_non_terminal() + // not last page, just move forward. + StatusStorage::::put(Status::Ongoing( + current_page.defensive_saturating_sub(1), + )); + meter.consume(VerifierWeightsOf::::verification_valid_non_terminal()) } else { // last page, finalize everything. Get the claimed score. let claimed_score = T::SolutionDataProvider::get_score(); - // in both cases of the following match, we are back to the nothing state. + // in both cases of the following match, we are back to the nothing + // state. StatusStorage::::put(Status::Nothing); match Self::finalize_async_verification(claimed_score) { Ok(_) => { T::SolutionDataProvider::report_result(VerificationResult::Queued); - VerifierWeightsOf::::on_initialize_valid_terminal() + meter.consume(VerifierWeightsOf::::verification_valid_terminal()) }, Err(_) => { T::SolutionDataProvider::report_result( @@ -668,7 +676,8 @@ impl Pallet { ); // In case of any of the errors, kill the solution. QueuedSolution::::clear_invalid_and_backings(); - VerifierWeightsOf::::on_initialize_invalid_terminal() + meter + .consume(VerifierWeightsOf::::verification_invalid_terminal()) }, } } @@ -677,9 +686,9 @@ impl Pallet { // the page solution was invalid. Self::deposit_event(Event::::VerificationFailed(current_page, err)); - sublog!(warn, "verifier", "Clearing any ongoing unverified solutions."); - // Clear any ongoing solution that has not been verified, regardless of the - // current state. + sublog!(warn, "verifier", "Clearing any ongoing unverified solution."); + // Clear any ongoing solution that has not been verified, regardless of + // the current state. QueuedSolution::::clear_invalid_and_backings_unchecked(); // we also mutate the status back to doing nothing. @@ -690,12 +699,14 @@ impl Pallet { T::SolutionDataProvider::report_result(VerificationResult::Rejected); } let wasted_pages = T::Pages::get().saturating_sub(current_page); - VerifierWeightsOf::::on_initialize_invalid_non_terminal(wasted_pages) + meter.consume(VerifierWeightsOf::::verification_invalid_non_terminal( + wasted_pages, + )) }, } - } else { - T::DbWeight::get().reads(1) - } + }); + + (worst_case_weight, execute) } fn do_verify_synchronous_multi( @@ -992,6 +1003,10 @@ impl Verifier for Pallet { Self::deposit_event(Event::::Queued(score, QueuedSolution::::queued_score())); QueuedSolution::::force_set_single_page_valid(page, partial_supports, score); } + + fn per_block_exec() -> (Weight, Box) { + Self::do_per_block_exec() + } } impl AsynchronousVerifier for Pallet { diff --git a/substrate/frame/election-provider-multi-block/src/verifier/mod.rs b/substrate/frame/election-provider-multi-block/src/verifier/mod.rs index a561de63e9008..27fe5013b0afe 100644 --- a/substrate/frame/election-provider-multi-block/src/verifier/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/verifier/mod.rs @@ -77,10 +77,12 @@ mod tests; pub use crate::weights::traits::pallet_election_provider_multi_block_verifier::*; use frame_election_provider_support::PageIndex; +use frame_support::weights::WeightMeter; use impls::SupportsOfVerifier; pub use impls::{feasibility_check_page_inner_with_snapshot, pallet::*, Status}; use sp_core::Get; use sp_npos_elections::ElectionScore; +use sp_runtime::Weight; use sp_std::{fmt::Debug, prelude::*}; /// Errors that can happen in the feasibility check. @@ -213,6 +215,12 @@ pub trait Verifier { page: PageIndex, score: ElectionScore, ); + + /// Return the execution schedule of this pallet's work to be done per-block (`on_poll`, + /// `on_init` independent). + /// + /// Returns a `(Weight, ExecFn)` tuple in-line with `per_block_exec` of the parent block. + fn per_block_exec() -> (Weight, Box); } /// Simple enum to encapsulate the result of the verification of a candidate solution. diff --git a/substrate/frame/election-provider-multi-block/src/verifier/tests.rs b/substrate/frame/election-provider-multi-block/src/verifier/tests.rs index ffa04df8f6eb8..ca968a1b952fd 100644 --- a/substrate/frame/election-provider-multi-block/src/verifier/tests.rs +++ b/substrate/frame/election-provider-multi-block/src/verifier/tests.rs @@ -35,7 +35,7 @@ mod feasibility_check { #[test] fn missing_snapshot() { - ExtBuilder::verifier().build_unchecked().execute_with(|| { + ExtBuilder::mock_signed().build_unchecked().execute_with(|| { // create snapshot just so that we can create a solution.. roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -49,7 +49,7 @@ mod feasibility_check { ); }); - ExtBuilder::verifier().pages(2).build_unchecked().execute_with(|| { + ExtBuilder::mock_signed().pages(2).build_unchecked().execute_with(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -62,7 +62,7 @@ mod feasibility_check { ); }); - ExtBuilder::verifier().pages(2).build_unchecked().execute_with(|| { + ExtBuilder::mock_signed().pages(2).build_unchecked().execute_with(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -75,7 +75,7 @@ mod feasibility_check { )); }); - ExtBuilder::verifier().pages(2).build_unchecked().execute_with(|| { + ExtBuilder::mock_signed().pages(2).build_unchecked().execute_with(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -88,7 +88,7 @@ mod feasibility_check { ); }); - ExtBuilder::verifier().pages(2).build_unchecked().execute_with(|| { + ExtBuilder::mock_signed().pages(2).build_unchecked().execute_with(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -104,7 +104,7 @@ mod feasibility_check { #[test] fn winner_indices_single_page_must_be_in_bounds() { - ExtBuilder::verifier().pages(1).desired_targets(2).build_and_execute(|| { + ExtBuilder::mock_signed().pages(1).desired_targets(2).build_and_execute(|| { roll_to_snapshot_created(); let mut paged = mine_full_solution().unwrap(); assert_eq!(crate::Snapshot::::targets().unwrap().len(), 4); @@ -126,7 +126,7 @@ mod feasibility_check { #[test] fn voter_indices_per_page_must_be_in_bounds() { - ExtBuilder::verifier() + ExtBuilder::mock_signed() .pages(1) .voter_per_page(Bounded::max_value()) .desired_targets(2) @@ -160,7 +160,7 @@ mod feasibility_check { #[test] fn voter_must_have_same_targets_as_snapshot() { - ExtBuilder::verifier() + ExtBuilder::mock_signed() .pages(1) .voter_per_page(Bounded::max_value()) .desired_targets(2) @@ -191,7 +191,7 @@ mod feasibility_check { #[test] fn prevents_duplicate_voter_index() { - ExtBuilder::verifier().pages(1).build_and_execute(|| { + ExtBuilder::mock_signed().pages(1).build_and_execute(|| { roll_to_snapshot_created(); // let's build a manual, bogus solution with duplicate voters, on top of page 0 of @@ -216,7 +216,7 @@ mod feasibility_check { #[test] fn prevents_duplicate_target_index() { - ExtBuilder::verifier().pages(1).build_and_execute(|| { + ExtBuilder::mock_signed().pages(1).build_and_execute(|| { roll_to_snapshot_created(); // A bad solution with duplicate targets for a single voter in votes2. @@ -237,7 +237,7 @@ mod feasibility_check { #[test] fn heuristic_max_backers_per_winner_per_page() { - ExtBuilder::verifier().max_backers_per_winner(2).build_and_execute(|| { + ExtBuilder::mock_signed().max_backers_per_winner(2).build_and_execute(|| { roll_to_snapshot_created(); // these votes are all valid, but some dude has 3 supports in a single page. @@ -256,7 +256,7 @@ mod feasibility_check { #[test] fn heuristic_desired_target_check_per_page() { - ExtBuilder::verifier().desired_targets(2).build_and_execute(|| { + ExtBuilder::mock_signed().desired_targets(2).build_and_execute(|| { roll_to(25); assert_full_snapshot(); @@ -288,7 +288,7 @@ mod async_verification { #[test] fn basic_single_verification_works() { - ExtBuilder::verifier().pages(1).build_and_execute(|| { + ExtBuilder::mock_signed().pages(1).build_and_execute(|| { // load a solution after the snapshot has been created. roll_to_snapshot_created(); @@ -296,10 +296,9 @@ mod async_verification { load_mock_signed_and_start(solution.clone()); // now let it verify - roll_next(); + roll_next_and_verifier(Status::Nothing); // It done after just one block. - assert_eq!(VerifierPallet::status(), Status::Nothing); assert_eq!( verifier_events(), vec![ @@ -313,7 +312,7 @@ mod async_verification { #[test] fn basic_multi_verification_works() { - ExtBuilder::verifier().pages(3).build_and_execute(|| { + ExtBuilder::mock_signed().pages(3).build_and_execute(|| { // load a solution after the snapshot has been created. roll_to_snapshot_created(); @@ -325,18 +324,13 @@ mod async_verification { assert_eq!(QueuedSolution::::valid_iter().count(), 0); // now let it verify - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); // 1 page verified, stored as invalid. assert_eq!(QueuedSolution::::invalid_iter().count(), 1); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); - assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 2), Event::::Verified(1, 2)] - ); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 2)]); // 2 pages verified, stored as invalid. assert_eq!(QueuedSolution::::invalid_iter().count(), 2); @@ -346,13 +340,10 @@ mod async_verification { assert!(QueuedSolution::::queued_score().is_none()); // last block. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Nothing); + roll_next_and_verifier(Status::Nothing); assert_eq!( - verifier_events(), + verifier_events_since_last_call(), vec![ - Event::::Verified(2, 2), - Event::::Verified(1, 2), Event::::Verified(0, 2), Event::::Queued(solution.score, None), ] @@ -367,7 +358,7 @@ mod async_verification { #[test] fn basic_multi_verification_partial() { - ExtBuilder::verifier().pages(3).build_and_execute(|| { + ExtBuilder::mock_signed().pages(3).build_and_execute(|| { // load a solution after the snapshot has been created. roll_to_snapshot_created(); @@ -380,18 +371,13 @@ mod async_verification { assert_eq!(QueuedSolution::::valid_iter().count(), 0); // now let it verify - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); // 1 page verified, stored as invalid. assert_eq!(QueuedSolution::::invalid_iter().count(), 1); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); - assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 2), Event::::Verified(1, 2),] - ); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 2)]); // 2 page verified, stored as invalid. assert_eq!(QueuedSolution::::invalid_iter().count(), 2); @@ -400,15 +386,11 @@ mod async_verification { assert_eq!(QueuedSolution::::valid_iter().count(), 0); assert!(QueuedSolution::::queued_score().is_none()); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Nothing); + roll_next_and_verifier(Status::Nothing); assert_eq!( - verifier_events(), + verifier_events_since_last_call(), vec![ - Event::::Verified(2, 2), - Event::::Verified(1, 2), - // this is a partial solution, no one in this page (lsp). Event::::Verified(0, 0), Event::::Queued(solution.score, None), ] @@ -429,12 +411,11 @@ mod async_verification { #[test] fn solution_data_provider_empty_data_solution() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // not super important, but anyways.. roll_to_snapshot_created(); // The solution data provider is empty. - assert_eq!(SignedPhaseSwitch::get(), SignedSwitch::Mock); assert_eq!(MockSignedNextSolution::get(), None); // nothing happens.. @@ -442,33 +423,34 @@ mod async_verification { assert_ok!(::start()); assert_eq!(VerifierPallet::status(), Status::Ongoing(2)); - roll_next(); + roll_next_and_verifier(Status::Ongoing(1)); // After first roll, only page 2 is processed (as empty page), status is still // Ongoing(1). - assert_eq!(verifier_events(), vec![Event::::Verified(2, 0)]); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 0)]); // Process the next page (page 1). - roll_next(); - assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 0), Event::::Verified(1, 0)] - ); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 0)]); // Process the final page (page 0). - roll_next(); + roll_next_and_verifier(Status::Nothing); // Missing score data returns default score which fails quality checks and gets // rejected. - assert_eq!(VerifierPallet::status(), Status::Nothing); assert_eq!(MockSignedResults::get(), vec![VerificationResult::Rejected]); + assert_eq!( + verifier_events_since_last_call(), + vec![ + Event::Verified(0, 0), + Event::VerificationFailed(0, FeasibilityError::InvalidScore) + ] + ); }); } #[test] fn solution_data_provider_empty_data_midway() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let solution = mine_full_solution().unwrap(); @@ -477,9 +459,8 @@ mod async_verification { assert_eq!(VerifierPallet::status(), Status::Ongoing(2)); // now let it verify. first one goes fine. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); assert_eq!(MockSignedResults::get(), vec![]); // 1 page verified, stored as invalid. @@ -492,20 +473,13 @@ mod async_verification { MockSignedNextSolution::set(None); // Roll through the remaining pages, which will be treated as empty. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); - assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 2), Event::::Verified(1, 0)] - ); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 0)]); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Nothing); + roll_next_and_verifier(Status::Nothing); assert_eq!( - verifier_events(), + verifier_events_since_last_call(), vec![ - Event::::Verified(2, 2), - Event::::Verified(1, 0), Event::::Verified(0, 0), Event::::VerificationFailed(0, FeasibilityError::InvalidScore), ] @@ -523,7 +497,7 @@ mod async_verification { #[test] fn solution_data_provider_missing_score_at_end() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let solution = mine_full_solution().unwrap(); @@ -532,9 +506,8 @@ mod async_verification { assert_eq!(VerifierPallet::status(), Status::Ongoing(2)); // First page is fine. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); assert_eq!(MockSignedResults::get(), vec![]); // Now clear both the solution and the score to simulate missing score at the end. @@ -542,38 +515,38 @@ mod async_verification { MockSignedNextScore::set(Default::default()); // Roll through remaining pages. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 0)]); + roll_next_and_verifier(Status::Nothing); assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 2), Event::::Verified(1, 0)] + verifier_events_since_last_call(), + vec![ + Event::::Verified(0, 0), + Event::::VerificationFailed(0, FeasibilityError::InvalidScore), + ] ); - roll_next(); // Missing score data returns default score which fails quality checks and gets // rejected. - assert_eq!(VerifierPallet::status(), Status::Nothing); assert_eq!(MockSignedResults::get(), vec![VerificationResult::Rejected]); }); } #[test] fn rejects_new_verification_via_start_if_ongoing() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let solution = mine_full_solution().unwrap(); load_mock_signed_and_start(solution.clone()); - assert_eq!(VerifierPallet::status(), Status::Ongoing(2)); // nada assert_noop!(::start(), "verification ongoing"); // now let it verify. first one goes fine. - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); assert_eq!(MockSignedResults::get(), vec![]); // retry, still nada. @@ -583,30 +556,30 @@ mod async_verification { #[test] fn verification_failure_clears_everything() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let mut solution = mine_full_solution().unwrap(); // Make the solution invalid by corrupting the first page - solution.solution_pages[0].votes1[0] = (0, 1000); // Invalid vote weight + solution.solution_pages[0].corrupt(); load_mock_signed_and_start(solution.clone()); - assert_eq!(VerifierPallet::status(), Status::Ongoing(2)); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(1)); - assert_eq!(verifier_events(), vec![Event::::Verified(2, 2)]); + roll_next_and_verifier(Status::Ongoing(1)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(2, 2)]); - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Ongoing(0)); - assert_eq!( - verifier_events(), - vec![Event::::Verified(2, 2), Event::::Verified(1, 2)] - ); + roll_next_and_verifier(Status::Ongoing(0)); + assert_eq!(verifier_events_since_last_call(), vec![Event::::Verified(1, 2)]); // Verification fails on the last page due to invalid solution - roll_next(); - assert_eq!(VerifierPallet::status(), Status::Nothing); + roll_next_and_verifier(Status::Nothing); + assert_eq!( + verifier_events_since_last_call(), + vec![Event::::VerificationFailed( + 0, + FeasibilityError::NposElection(sp_npos_elections::Error::SolutionInvalidIndex) + ),] + ); // everything is cleared when verification fails. assert_eq!(QueuedSolution::::invalid_iter().count(), 0); @@ -620,7 +593,7 @@ mod async_verification { #[test] fn weak_valid_solution_is_insta_rejected() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -671,7 +644,7 @@ mod async_verification { #[test] fn better_valid_solution_replaces() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); // a weak one, which we will still accept. @@ -728,7 +701,7 @@ mod async_verification { #[test] fn invalid_solution_bad_score() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let mut paged = mine_full_solution().unwrap(); @@ -757,7 +730,7 @@ mod async_verification { #[test] fn invalid_solution_bad_minimum_score() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -785,7 +758,7 @@ mod async_verification { #[test] fn invalid_solution_bad_desired_targets() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); assert_eq!(crate::Snapshot::::desired_targets().unwrap(), 2); let paged = mine_full_solution().unwrap(); @@ -816,7 +789,7 @@ mod async_verification { #[test] fn invalid_solution_bad_bounds_per_page() { - ExtBuilder::verifier() + ExtBuilder::mock_signed() .desired_targets(1) .max_backers_per_winner(1) // in each page we allow 1 baker to be presented. .build_and_execute(|| { @@ -865,7 +838,7 @@ mod async_verification { #[test] fn invalid_solution_bad_bounds_final() { - ExtBuilder::verifier() + ExtBuilder::mock_signed() .desired_targets(1) .max_backers_per_winner(2) .max_backers_per_winner_final(2) @@ -923,7 +896,7 @@ mod async_verification { #[test] fn invalid_solution_does_not_alter_queue() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let mut paged = mine_full_solution().unwrap(); let correct_score = paged.score; @@ -979,7 +952,7 @@ mod multi_page_sync_verification { #[test] fn basic_sync_verification_works() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let paged = mine_solution(2).unwrap(); @@ -1007,7 +980,7 @@ mod multi_page_sync_verification { #[test] fn basic_sync_verification_works_full() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let paged = mine_full_solution().unwrap(); @@ -1036,7 +1009,7 @@ mod multi_page_sync_verification { #[test] fn incorrect_score_checked_at_end() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // A solution that where each individual page is valid, but the final score is bad. roll_to_snapshot_created(); let mut paged = mine_solution(2).unwrap(); @@ -1069,7 +1042,7 @@ mod multi_page_sync_verification { #[test] fn invalid_second_page() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // A solution that where the second validated page is invalid. use frame_election_provider_support::traits::NposSolution; roll_to_snapshot_created(); @@ -1107,7 +1080,7 @@ mod multi_page_sync_verification { #[test] fn too_may_max_backers_per_winner_second_page() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { // A solution that where the at the second page with hit the final max backers per // winner final bound. roll_to_snapshot_created(); @@ -1183,7 +1156,7 @@ mod single_page_sync_verification { #[test] fn basic_sync_verification_works() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1210,7 +1183,7 @@ mod single_page_sync_verification { #[test] fn winner_count_more() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1242,7 +1215,7 @@ mod single_page_sync_verification { #[test] fn winner_count_less() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1275,7 +1248,7 @@ mod single_page_sync_verification { #[test] fn incorrect_score_is_rejected() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1304,7 +1277,7 @@ mod single_page_sync_verification { #[test] fn minimum_untrusted_score_is_rejected() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1334,7 +1307,7 @@ mod single_page_sync_verification { #[test] fn bad_bounds_rejected_max_backers_per_winner() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1363,7 +1336,7 @@ mod single_page_sync_verification { #[test] fn bad_bounds_rejected_max_winners_per_page() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1392,7 +1365,7 @@ mod single_page_sync_verification { #[test] fn bad_bounds_rejected_max_backers_per_winner_final() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let single_page = mine_solution(1).unwrap(); @@ -1420,11 +1393,17 @@ mod single_page_sync_verification { } #[test] +<<<<<<< HEAD fn solution_improvement_threshold_respected() { ExtBuilder::verifier() .solution_improvement_threshold(Perbill::from_percent(10)) .build_and_execute(|| { roll_to_snapshot_created(); +======= + fn solution_improvement_respected() { + ExtBuilder::mock_signed().build_and_execute(|| { + roll_to_snapshot_created(); +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // submit something good. let single_page = mine_solution(1).unwrap(); @@ -1435,12 +1414,19 @@ mod single_page_sync_verification { ) .unwrap(); +<<<<<<< HEAD // the slightly better solution need not even be correct. We improve it by 5%, but // we need 10%. let mut better_score = single_page.score; let improvement = Perbill::from_percent(5) * better_score.minimal_stake; better_score.minimal_stake += improvement; let slightly_better = fake_solution(better_score); +======= + #[test] + fn exact_same_score_is_rejected() { + ExtBuilder::mock_signed().build_and_execute(|| { + roll_to_snapshot_created(); +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) assert_eq!( ::verify_synchronous( @@ -1456,7 +1442,7 @@ mod single_page_sync_verification { #[test] fn weak_score_is_insta_rejected() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); // queue something useful. @@ -1498,7 +1484,7 @@ mod single_page_sync_verification { #[test] fn good_solution_replaces() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); let weak_solution = solution_from_supports( @@ -1549,7 +1535,7 @@ mod single_page_sync_verification { #[test] fn weak_valid_is_discarded() { - ExtBuilder::verifier().build_and_execute(|| { + ExtBuilder::mock_signed().build_and_execute(|| { roll_to_snapshot_created(); // first, submit something good diff --git a/substrate/frame/election-provider-multi-block/src/weights/mod.rs b/substrate/frame/election-provider-multi-block/src/weights/mod.rs index 4d02c7e3ec867..39a2f5dc0645f 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/mod.rs @@ -44,6 +44,7 @@ pub mod traits { fn clear_old_round_data(p: u32) -> Weight; } + #[cfg(feature = "std")] impl WeightInfo for () { fn bail() -> Weight { Default::default() @@ -79,6 +80,7 @@ pub mod traits { } } + #[cfg(feature = "std")] impl WeightInfo for () { fn validate_unsigned() -> Weight { Default::default() @@ -94,24 +96,25 @@ pub mod traits { /// Weight functions needed for `pallet_election_provider_multi_block_verifier`. pub trait WeightInfo { - fn on_initialize_valid_non_terminal() -> Weight; - fn on_initialize_valid_terminal() -> Weight; - fn on_initialize_invalid_terminal() -> Weight; - fn on_initialize_invalid_non_terminal(v: u32) -> Weight; + fn verification_valid_non_terminal() -> Weight; + fn verification_valid_terminal() -> Weight; + fn verification_invalid_terminal() -> Weight; + fn verification_invalid_non_terminal(v: u32) -> Weight; } + #[cfg(feature = "std")] impl WeightInfo for () { - fn on_initialize_valid_non_terminal() -> Weight { - Default::default() + fn verification_valid_non_terminal() -> Weight { + Weight::from_parts(0, 7) } - fn on_initialize_valid_terminal() -> Weight { - Default::default() + fn verification_valid_terminal() -> Weight { + Weight::from_parts(0, 7) } - fn on_initialize_invalid_terminal() -> Weight { - Default::default() + fn verification_invalid_terminal() -> Weight { + Weight::from_parts(0, 7) } - fn on_initialize_invalid_non_terminal(_v: u32) -> Weight { - Default::default() + fn verification_invalid_non_terminal(_v: u32) -> Weight { + Weight::from_parts(0, 7) } } } @@ -121,36 +124,29 @@ pub mod traits { /// Weight functions needed for `pallet_election_provider_multi_block`. pub trait WeightInfo { - fn on_initialize_nothing() -> Weight; - fn on_initialize_into_snapshot_msp() -> Weight; - fn on_initialize_into_snapshot_rest() -> Weight; - fn on_initialize_into_signed() -> Weight; - fn on_initialize_into_signed_validation() -> Weight; - fn on_initialize_into_unsigned() -> Weight; + fn per_block_nothing() -> Weight; + fn per_block_snapshot_msp() -> Weight; + fn per_block_snapshot_rest() -> Weight; + fn per_block_start_signed_validation() -> Weight; fn export_non_terminal() -> Weight; fn export_terminal() -> Weight; fn admin_set() -> Weight; fn manage_fallback() -> Weight; } + #[cfg(feature = "std")] impl WeightInfo for () { - fn on_initialize_nothing() -> Weight { + fn per_block_nothing() -> Weight { Default::default() } - fn on_initialize_into_snapshot_msp() -> Weight { - Default::default() + fn per_block_snapshot_msp() -> Weight { + Weight::from_parts(0, 5) } - fn on_initialize_into_snapshot_rest() -> Weight { - Default::default() + fn per_block_snapshot_rest() -> Weight { + Weight::from_parts(0, 5) } - fn on_initialize_into_signed() -> Weight { - Default::default() - } - fn on_initialize_into_signed_validation() -> Weight { - Default::default() - } - fn on_initialize_into_unsigned() -> Weight { - Default::default() + fn per_block_start_signed_validation() -> Weight { + Weight::from_parts(0, 3) } fn export_non_terminal() -> Weight { Default::default() diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_dot_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_dot_size.rs index da450c69a114b..1c0045b259ea5 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_dot_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_dot_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-dot // --template @@ -67,23 +67,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - fn on_initialize_nothing() -> Weight { + fn per_block_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `250` - // Estimated: `3715` - // Minimum execution time: 24_100_000 picoseconds. - Weight::from_parts(25_330_000, 3715) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `118` + // Estimated: `1603` + // Minimum execution time: 11_890_000 picoseconds. + Weight::from_parts(12_290_000, 1603) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `Staking::ValidatorCount` (r:1 w:0) /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) @@ -94,29 +92,27 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Staking::CounterForValidators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `Staking::Validators` (r:2001 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElection::DesiredTargets` (r:0 w:1) /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:0 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) - fn on_initialize_into_snapshot_msp() -> Weight { + fn per_block_snapshot_msp() -> Weight { // Proof Size summary in bytes: - // Measured: `95465` - // Estimated: `5048930` - // Minimum execution time: 18_878_131_000 picoseconds. - Weight::from_parts(18_983_212_000, 5048930) - .saturating_add(T::DbWeight::get().reads(2009_u64)) + // Measured: `95360` + // Estimated: `5048825` + // Minimum execution time: 17_142_277_000 picoseconds. + Weight::from_parts(17_250_897_000, 5048825) + .saturating_add(T::DbWeight::get().reads(2008_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) @@ -137,10 +133,6 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) /// Storage: `VoterList::Lock` (r:0 w:1) @@ -149,60 +141,13 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_snapshot_rest() -> Weight { + fn per_block_snapshot_rest() -> Weight { // Proof Size summary in bytes: - // Measured: `1449068` - // Estimated: `3194933` - // Minimum execution time: 45_723_834_000 picoseconds. - Weight::from_parts(45_910_816_000, 3194933) - .saturating_add(T::DbWeight::get().reads(3084_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) - /// Proof: `Staking::VoterSnapshotStatus` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `Measured`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:0) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `VoterList::ListNodes` (r:705 w:0) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `Measured`) - /// Storage: `Staking::Bonded` (r:703 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `Measured`) - /// Storage: `Staking::Ledger` (r:703 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(753), added: 3228, mode: `Measured`) - /// Storage: `Staking::Nominators` (r:703 w:0) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `Measured`) - /// Storage: `VoterList::ListBags` (r:1 w:0) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `Measured`) - /// Storage: `Staking::Validators` (r:45 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElection::Round` (r:1 w:0) - /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) - /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) - /// Storage: `VoterList::Lock` (r:0 w:1) - /// Proof: `VoterList::Lock` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_signed() -> Weight { - // Proof Size summary in bytes: - // Measured: `1516243` - // Estimated: `3262108` - // Minimum execution time: 50_546_380_000 picoseconds. - Weight::from_parts(51_815_377_000, 3262108) - .saturating_add(T::DbWeight::get().reads(2869_u64)) + // Measured: `1448963` + // Estimated: `3194828` + // Minimum execution time: 45_863_295_000 picoseconds. + Weight::from_parts(46_462_736_000, 3194828) + .saturating_add(T::DbWeight::get().reads(3083_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -211,34 +156,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElection::Round` (r:1 w:0) + /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - fn on_initialize_into_signed_validation() -> Weight { - // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 3_711_197_000 picoseconds. - Weight::from_parts(3_810_718_000, 3909) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - fn on_initialize_into_unsigned() -> Weight { + fn per_block_start_signed_validation() -> Weight { // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 3_740_878_000 picoseconds. - Weight::from_parts(3_808_557_000, 3909) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `586` + // Estimated: `4051` + // Minimum execution time: 74_560_000 picoseconds. + Weight::from_parts(89_270_000, 4051) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) @@ -266,13 +196,13 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:491) /// Proof: `Staking::ErasValidatorPrefs` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `Measured`) /// Storage: `Staking::ErasStakersPaged` (r:0 w:490) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(3152), added: 5627, mode: `Measured`) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(24656), added: 27131, mode: `Measured`) fn export_non_terminal() -> Weight { // Proof Size summary in bytes: // Measured: `167757` // Estimated: `1383972` - // Minimum execution time: 13_949_429_000 picoseconds. - Weight::from_parts(13_983_218_000, 1383972) + // Minimum execution time: 14_054_590_000 picoseconds. + Weight::from_parts(14_923_170_000, 1383972) .saturating_add(T::DbWeight::get().reads(991_u64)) .saturating_add(T::DbWeight::get().writes(1475_u64)) } @@ -302,8 +232,8 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Staking::ElectableStashes` (`max_values`: Some(1), `max_size`: Some(32002), added: 32497, mode: `Measured`) /// Storage: `Staking::ErasStakersOverview` (r:310 w:310) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) - /// Storage: `Staking::ErasStakersPaged` (r:310 w:345) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(3152), added: 5627, mode: `Measured`) + /// Storage: `Staking::ErasStakersPaged` (r:310 w:310) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(24656), added: 27131, mode: `Measured`) /// Storage: `Staking::ErasTotalStake` (r:1 w:1) /// Proof: `Staking::ErasTotalStake` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `Measured`) /// Storage: `Staking::Validators` (r:310 w:0) @@ -318,12 +248,12 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) fn export_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `770035` - // Estimated: `1538275` - // Minimum execution time: 18_379_354_000 picoseconds. - Weight::from_parts(19_010_697_000, 1538275) + // Measured: `1734835` + // Estimated: `2503075` + // Minimum execution time: 17_499_059_000 picoseconds. + Weight::from_parts(19_255_420_000, 2503075) .saturating_add(T::DbWeight::get().reads(1036_u64)) - .saturating_add(T::DbWeight::get().writes(1071_u64)) + .saturating_add(T::DbWeight::get().writes(1036_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_ksm_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_ksm_size.rs index f7accc21fe446..45591cc9621ad 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_ksm_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_ksm_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-ksm // --template @@ -67,23 +67,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - fn on_initialize_nothing() -> Weight { + fn per_block_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `250` - // Estimated: `3715` - // Minimum execution time: 24_070_000 picoseconds. - Weight::from_parts(25_070_000, 3715) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `118` + // Estimated: `1603` + // Minimum execution time: 11_830_000 picoseconds. + Weight::from_parts(12_020_000, 1603) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `Staking::ValidatorCount` (r:1 w:0) /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) @@ -92,31 +90,29 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `Staking::CounterForValidators` (r:1 w:0) /// Proof: `Staking::CounterForValidators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `Staking::Validators` (r:4001 w:0) + /// Storage: `Staking::Validators` (r:2501 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElection::DesiredTargets` (r:0 w:1) /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) - fn on_initialize_into_snapshot_msp() -> Weight { + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) + fn per_block_snapshot_msp() -> Weight { // Proof Size summary in bytes: - // Measured: `189963` - // Estimated: `10093428` - // Minimum execution time: 41_110_812_000 picoseconds. - Weight::from_parts(41_368_864_000, 10093428) - .saturating_add(T::DbWeight::get().reads(4009_u64)) + // Measured: `119137` + // Estimated: `6310102` + // Minimum execution time: 21_947_065_000 picoseconds. + Weight::from_parts(22_112_625_000, 6310102) + .saturating_add(T::DbWeight::get().reads(2508_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) @@ -137,10 +133,6 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) /// Storage: `VoterList::Lock` (r:0 w:1) @@ -149,60 +141,13 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_snapshot_rest() -> Weight { + fn per_block_snapshot_rest() -> Weight { // Proof Size summary in bytes: - // Measured: `1370478` - // Estimated: `3309393` - // Minimum execution time: 55_933_967_000 picoseconds. - Weight::from_parts(56_210_319_000, 3309393) - .saturating_add(T::DbWeight::get().reads(3590_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) - /// Proof: `Staking::VoterSnapshotStatus` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `Measured`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:0) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `VoterList::ListNodes` (r:783 w:0) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `Measured`) - /// Storage: `Staking::Bonded` (r:781 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `Measured`) - /// Storage: `Staking::Ledger` (r:781 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(753), added: 3228, mode: `Measured`) - /// Storage: `Staking::Nominators` (r:781 w:0) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `Measured`) - /// Storage: `VoterList::ListBags` (r:1 w:0) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `Measured`) - /// Storage: `Staking::Validators` (r:173 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `MultiBlockElection::Round` (r:1 w:0) - /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6358acd2035ec4bb863fa981e0c177b9` (r:1 w:0) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: `Staking::MinimumActiveStake` (r:0 w:1) - /// Proof: `Staking::MinimumActiveStake` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) - /// Storage: `VoterList::Lock` (r:0 w:1) - /// Proof: `VoterList::Lock` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) - /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:0 w:1) - /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) - fn on_initialize_into_signed() -> Weight { - // Proof Size summary in bytes: - // Measured: `1472353` - // Estimated: `3411268` - // Minimum execution time: 55_352_841_000 picoseconds. - Weight::from_parts(55_916_036_000, 3411268) - .saturating_add(T::DbWeight::get().reads(3309_u64)) + // Measured: `1370373` + // Estimated: `3309288` + // Minimum execution time: 50_135_617_000 picoseconds. + Weight::from_parts(50_591_808_000, 3309288) + .saturating_add(T::DbWeight::get().reads(3589_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) @@ -211,34 +156,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElection::Round` (r:1 w:0) + /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - fn on_initialize_into_signed_validation() -> Weight { - // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 202_762_000 picoseconds. - Weight::from_parts(2_761_480_000, 3909) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) - /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:0) - /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - fn on_initialize_into_unsigned() -> Weight { + fn per_block_start_signed_validation() -> Weight { // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 981_606_000 picoseconds. - Weight::from_parts(2_872_530_000, 3909) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `586` + // Estimated: `4051` + // Minimum execution time: 84_170_000 picoseconds. + Weight::from_parts(88_100_000, 4051) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) @@ -257,24 +187,24 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `Staking::ElectableStashes` (r:1 w:1) /// Proof: `Staking::ElectableStashes` (`max_values`: Some(1), `max_size`: Some(32002), added: 32497, mode: `Measured`) - /// Storage: `Staking::ErasStakersOverview` (r:792 w:792) + /// Storage: `Staking::ErasStakersOverview` (r:773 w:773) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) /// Storage: `Staking::ErasTotalStake` (r:1 w:1) /// Proof: `Staking::ErasTotalStake` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `Measured`) - /// Storage: `Staking::Validators` (r:792 w:0) + /// Storage: `Staking::Validators` (r:773 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) - /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:792) + /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:773) /// Proof: `Staking::ErasValidatorPrefs` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `Measured`) - /// Storage: `Staking::ErasStakersPaged` (r:0 w:740) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(3152), added: 5627, mode: `Measured`) + /// Storage: `Staking::ErasStakersPaged` (r:0 w:723) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(24656), added: 27131, mode: `Measured`) fn export_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `233920` - // Estimated: `2195110` - // Minimum execution time: 24_478_931_000 picoseconds. - Weight::from_parts(24_520_800_000, 2195110) - .saturating_add(T::DbWeight::get().reads(1593_u64)) - .saturating_add(T::DbWeight::get().writes(2327_u64)) + // Measured: `195526` + // Estimated: `2109691` + // Minimum execution time: 22_310_257_000 picoseconds. + Weight::from_parts(22_452_856_000, 2109691) + .saturating_add(T::DbWeight::get().reads(1555_u64)) + .saturating_add(T::DbWeight::get().writes(2272_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) @@ -293,37 +223,37 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:16 w:16) /// Proof: `MultiBlockElection::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:1) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshotHash` (r:1 w:1) /// Proof: `MultiBlockElection::PagedTargetSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `Staking::ElectableStashes` (r:1 w:1) /// Proof: `Staking::ElectableStashes` (`max_values`: Some(1), `max_size`: Some(32002), added: 32497, mode: `Measured`) - /// Storage: `Staking::ErasStakersOverview` (r:580 w:580) + /// Storage: `Staking::ErasStakersOverview` (r:571 w:571) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) - /// Storage: `Staking::ErasStakersPaged` (r:580 w:580) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(3152), added: 5627, mode: `Measured`) + /// Storage: `Staking::ErasStakersPaged` (r:571 w:571) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: Some(24656), added: 27131, mode: `Measured`) /// Storage: `Staking::ErasTotalStake` (r:1 w:1) /// Proof: `Staking::ErasTotalStake` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `Measured`) - /// Storage: `Staking::Validators` (r:580 w:0) + /// Storage: `Staking::Validators` (r:571 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) - /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:580) + /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:571) /// Proof: `Staking::ErasValidatorPrefs` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `Measured`) /// Storage: `MultiBlockElection::DesiredTargets` (r:0 w:1) /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) fn export_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1168790` - // Estimated: `2605280` - // Minimum execution time: 31_737_516_000 picoseconds. - Weight::from_parts(31_793_526_000, 2605280) - .saturating_add(T::DbWeight::get().reads(1798_u64)) - .saturating_add(T::DbWeight::get().writes(1798_u64)) + // Measured: `1079027` + // Estimated: `2493242` + // Minimum execution time: 29_991_252_000 picoseconds. + Weight::from_parts(30_181_686_000, 2493242) + .saturating_add(T::DbWeight::get().reads(1771_u64)) + .saturating_add(T::DbWeight::get().writes(1771_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_dot_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_dot_size.rs index 1ec37eea09351..3b9ba5345e680 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_dot_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_dot_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-dot // --template @@ -65,6 +65,8 @@ pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_signed::WeightInfo for WeightInfo { /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) @@ -79,13 +81,15 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `3312` // Estimated: `6777` - // Minimum execution time: 143_730_000 picoseconds. - Weight::from_parts(146_621_000, 6777) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 130_211_000 picoseconds. + Weight::from_parts(131_911_000, 6777) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) @@ -102,9 +106,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `7846` // Estimated: `88036` - // Minimum execution time: 345_252_000 picoseconds. - Weight::from_parts(348_112_000, 88036) - .saturating_add(T::DbWeight::get().reads(39_u64)) + // Minimum execution time: 314_814_000 picoseconds. + Weight::from_parts(323_504_000, 88036) + .saturating_add(T::DbWeight::get().reads(40_u64)) .saturating_add(T::DbWeight::get().writes(37_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -115,6 +119,8 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) @@ -125,9 +131,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `3845` // Estimated: `7310` - // Minimum execution time: 5_672_789_000 picoseconds. - Weight::from_parts(6_445_424_000, 7310) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 313_002_000 picoseconds. + Weight::from_parts(329_092_000, 7310) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -138,6 +144,8 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) @@ -148,9 +156,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `6737` // Estimated: `10202` - // Minimum execution time: 8_071_243_000 picoseconds. - Weight::from_parts(8_089_732_000, 10202) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 262_482_000 picoseconds. + Weight::from_parts(288_781_000, 10202) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -171,8 +179,8 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `4777` // Estimated: `84967` - // Minimum execution time: 234_231_000 picoseconds. - Weight::from_parts(240_031_000, 84967) + // Minimum execution time: 204_581_000 picoseconds. + Weight::from_parts(206_781_000, 84967) .saturating_add(T::DbWeight::get().reads(38_u64)) .saturating_add(T::DbWeight::get().writes(35_u64)) } @@ -188,16 +196,18 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// The range of component `p` is `[1, 32]`. fn clear_old_round_data(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3767 + p * (32 ±0)` - // Estimated: `7232 + p * (2507 ±0)` - // Minimum execution time: 143_121_000 picoseconds. - Weight::from_parts(141_105_005, 7232) - // Standard Error: 44_586 - .saturating_add(Weight::from_parts(1_987_686, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `3769 + p * (32 ±0)` + // Estimated: `7234 + p * (2507 ±0)` + // Minimum execution time: 128_480_000 picoseconds. + Weight::from_parts(127_828_412, 7234) + // Standard Error: 25_106 + .saturating_add(Weight::from_parts(1_389_687, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_ksm_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_ksm_size.rs index 7719f44f5a439..7d0274e09c49e 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_ksm_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_signed_ksm_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-ksm // --template @@ -65,6 +65,8 @@ pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_signed::WeightInfo for WeightInfo { /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) @@ -79,13 +81,15 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `3180` // Estimated: `6645` - // Minimum execution time: 141_781_000 picoseconds. - Weight::from_parts(144_891_000, 6645) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 130_501_000 picoseconds. + Weight::from_parts(132_060_000, 6645) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) @@ -102,9 +106,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `7144` // Estimated: `47734` - // Minimum execution time: 303_662_000 picoseconds. - Weight::from_parts(306_382_000, 47734) - .saturating_add(T::DbWeight::get().reads(23_u64)) + // Minimum execution time: 289_301_000 picoseconds. + Weight::from_parts(297_421_000, 47734) + .saturating_add(T::DbWeight::get().reads(24_u64)) .saturating_add(T::DbWeight::get().writes(21_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -115,6 +119,8 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) @@ -125,9 +131,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `3697` // Estimated: `7162` - // Minimum execution time: 2_316_144_000 picoseconds. - Weight::from_parts(2_483_425_000, 7162) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 286_851_000 picoseconds. + Weight::from_parts(298_461_000, 7162) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -138,6 +144,8 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) @@ -146,11 +154,11 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) fn unset_page() -> Weight { // Proof Size summary in bytes: - // Measured: `8620` - // Estimated: `12085` - // Minimum execution time: 2_016_652_000 picoseconds. - Weight::from_parts(2_284_763_000, 12085) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Measured: `8460` + // Estimated: `11925` + // Minimum execution time: 261_751_000 picoseconds. + Weight::from_parts(266_200_000, 11925) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) @@ -171,8 +179,8 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `4110` // Estimated: `44700` - // Minimum execution time: 200_051_000 picoseconds. - Weight::from_parts(201_981_000, 44700) + // Minimum execution time: 180_681_000 picoseconds. + Weight::from_parts(181_711_000, 44700) .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(19_u64)) } @@ -188,16 +196,18 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// The range of component `p` is `[1, 16]`. fn clear_old_round_data(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3622 + p * (31 ±0)` + // Measured: `3624 + p * (31 ±0)` // Estimated: `7089 + p * (2507 ±0)` - // Minimum execution time: 141_960_000 picoseconds. - Weight::from_parts(142_125_963, 7089) - // Standard Error: 117_080 - .saturating_add(Weight::from_parts(1_784_427, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 128_660_000 picoseconds. + Weight::from_parts(128_812_002, 7089) + // Standard Error: 48_513 + .saturating_add(Weight::from_parts(1_276_202, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_dot_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_dot_size.rs index 0eebcb65f1688..3257a91fc3ebc 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_dot_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_dot_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `3`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,16 +39,15 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 3 +// 10 // --genesis-builder-preset // fake-dot // --template // ../../../../../substrate/frame/election-provider-multi-block/src/template.hbs // --heap-pages // 65000 -// --extra // --output // ./pallet_election_provider_multi_block_unsigned_fake-dot.rs @@ -84,8 +83,8 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `378` // Estimated: `3843` - // Minimum execution time: 3_343_638_000 picoseconds. - Weight::from_parts(3_863_700_000, 3843) + // Minimum execution time: 872_562_000 picoseconds. + Weight::from_parts(884_363_000, 3843) .saturating_add(T::DbWeight::get().reads(8_u64)) } /// Storage: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (r:1 w:0) @@ -116,36 +115,9 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `1451085` // Estimated: `1461975` - // Minimum execution time: 27_632_103_000 picoseconds. - Weight::from_parts(27_843_954_000, 1461975) + // Minimum execution time: 21_018_046_000 picoseconds. + Weight::from_parts(21_116_907_000, 1461975) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `MultiBlockElection::Round` (r:1 w:0) - /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) - /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) - /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:32 w:0) - /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// The range of component `p` is `[1, 32]`. - fn mine_solution(p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + p * (360895 ±0)` - // Estimated: `332140 + p * (348312 ±2_731)` - // Minimum execution time: 926_273_131_000 picoseconds. - Weight::from_parts(926_273_131_000, 332140) - // Standard Error: 303_324_142_965 - .saturating_add(Weight::from_parts(6_610_814_674_792, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) - .saturating_add(Weight::from_parts(0, 348312).saturating_mul(p.into())) - } } diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_ksm_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_ksm_size.rs index 1c614472fe91a..2df4273187bb1 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_ksm_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_unsigned_ksm_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-18, STEPS: `5`, REPEAT: `3`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,16 +39,15 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 3 +// 10 // --genesis-builder-preset // fake-ksm // --template // ../../../../../substrate/frame/election-provider-multi-block/src/template.hbs // --heap-pages // 65000 -// --extra // --output // ./pallet_election_provider_multi_block_unsigned_fake-ksm.rs @@ -84,8 +83,8 @@ impl crate::weights::traits::pallet_election_provider_m // Proof Size summary in bytes: // Measured: `378` // Estimated: `3843` - // Minimum execution time: 2_236_486_000 picoseconds. - Weight::from_parts(2_276_596_000, 3843) + // Minimum execution time: 1_127_114_000 picoseconds. + Weight::from_parts(1_133_504_000, 3843) .saturating_add(T::DbWeight::get().reads(8_u64)) } /// Storage: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (r:1 w:0) @@ -99,7 +98,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockElectionVerifier::MinimumScore` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::MinimumScore` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `Measured`) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:4 w:0) @@ -114,38 +113,11 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) fn submit_unsigned() -> Weight { // Proof Size summary in bytes: - // Measured: `1440523` - // Estimated: `1451413` - // Minimum execution time: 30_959_432_000 picoseconds. - Weight::from_parts(31_005_092_000, 1451413) + // Measured: `1392523` + // Estimated: `1403413` + // Minimum execution time: 28_725_870_000 picoseconds. + Weight::from_parts(28_893_151_000, 1403413) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `MultiBlockElection::Round` (r:1 w:0) - /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) - /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) - /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) - /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:16 w:0) - /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) - /// The range of component `p` is `[1, 16]`. - fn mine_solution(p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `39458 + p * (349682 ±0)` - // Estimated: `26136 + p * (352057 ±1_160)` - // Minimum execution time: 3_353_004_496_000 picoseconds. - Weight::from_parts(3_353_004_496_000, 26136) - // Standard Error: 376_745_635_821 - .saturating_add(Weight::from_parts(6_831_608_018_289, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) - .saturating_add(Weight::from_parts(0, 352057).saturating_mul(p.into())) - } } diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_dot_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_dot_size.rs index 36d782c70c47f..129ec315256c6 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_dot_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_dot_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-dot // --template @@ -67,14 +67,14 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) @@ -87,33 +87,31 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) - fn on_initialize_valid_non_terminal() -> Weight { + fn verification_valid_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `337306` - // Estimated: `340771` - // Minimum execution time: 4_050_122_000 picoseconds. - Weight::from_parts(4_070_462_000, 340771) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Measured: `337201` + // Estimated: `340666` + // Minimum execution time: 4_365_357_000 picoseconds. + Weight::from_parts(4_431_208_000, 340666) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:32 w:32) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) @@ -134,31 +132,29 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) - fn on_initialize_valid_terminal() -> Weight { + fn verification_valid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1184612` - // Estimated: `1267277` - // Minimum execution time: 17_111_945_000 picoseconds. - Weight::from_parts(17_278_715_000, 1267277) - .saturating_add(T::DbWeight::get().reads(80_u64)) + // Measured: `1184507` + // Estimated: `1267172` + // Minimum execution time: 17_247_679_000 picoseconds. + Weight::from_parts(17_320_580_000, 1267172) + .saturating_add(T::DbWeight::get().reads(79_u64)) .saturating_add(T::DbWeight::get().writes(72_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:32 w:32) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) @@ -177,31 +173,31 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:31 w:32) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - fn on_initialize_invalid_terminal() -> Weight { + fn verification_invalid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1185633` - // Estimated: `1268298` - // Minimum execution time: 17_293_481_000 picoseconds. - Weight::from_parts(17_381_352_000, 1268298) + // Measured: `1185528` + // Estimated: `1268193` + // Minimum execution time: 17_116_788_000 picoseconds. + Weight::from_parts(17_320_458_000, 1268193) .saturating_add(T::DbWeight::get().reads(110_u64)) - .saturating_add(T::DbWeight::get().writes(101_u64)) + .saturating_add(T::DbWeight::get().writes(102_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:32 w:32) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(64026), added: 66501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) @@ -222,21 +218,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// The range of component `v` is `[0, 31]`. - fn on_initialize_invalid_non_terminal(v: u32, ) -> Weight { + fn verification_invalid_non_terminal(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `341548 + v * (4932 ±0)` - // Estimated: `443308 + v * (4988 ±806)` - // Minimum execution time: 1_165_016_000 picoseconds. - Weight::from_parts(1_057_101_975, 443308) - // Standard Error: 4_684_378 - .saturating_add(Weight::from_parts(27_427_295, 0).saturating_mul(v.into())) + // Measured: `353164 + v * (3034 ±0)` + // Estimated: `474195 + v * (2961 ±477)` + // Minimum execution time: 1_267_164_000 picoseconds. + Weight::from_parts(1_223_951_167, 474195) + // Standard Error: 1_944_459 + .saturating_add(Weight::from_parts(21_624_995, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(46_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(v.into()))) - .saturating_add(T::DbWeight::get().writes(37_u64)) + .saturating_add(T::DbWeight::get().writes(38_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_parts(0, 4988).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 2961).saturating_mul(v.into())) } } diff --git a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_ksm_size.rs b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_ksm_size.rs index 5243dc3d27c2f..c4e27336f53eb 100644 --- a/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_ksm_size.rs +++ b/substrate/frame/election-provider-multi-block/src/weights/pallet_election_provider_multi_block_verifier_ksm_size.rs @@ -22,7 +22,7 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-06-17, STEPS: `5`, REPEAT: `5`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -39,9 +39,9 @@ // --runtime // ../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm // --steps -// 5 +// 10 // --repeat -// 5 +// 10 // --genesis-builder-preset // fake-ksm // --template @@ -67,16 +67,16 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:1 w:0) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) @@ -87,35 +87,33 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) - fn on_initialize_valid_non_terminal() -> Weight { + fn verification_valid_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `350585` - // Estimated: `354050` - // Minimum execution time: 8_603_879_000 picoseconds. - Weight::from_parts(8_934_521_000, 354050) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Measured: `302068` + // Estimated: `305533` + // Minimum execution time: 5_113_427_000 picoseconds. + Weight::from_parts(5_191_017_000, 305533) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:16 w:16) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) @@ -134,33 +132,31 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) - fn on_initialize_valid_terminal() -> Weight { + fn verification_valid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1183276` - // Estimated: `1226341` - // Minimum execution time: 18_426_816_000 picoseconds. - Weight::from_parts(18_490_837_000, 1226341) - .saturating_add(T::DbWeight::get().reads(48_u64)) + // Measured: `1123155` + // Estimated: `1166220` + // Minimum execution time: 17_655_638_000 picoseconds. + Weight::from_parts(17_783_458_000, 1166220) + .saturating_add(T::DbWeight::get().reads(47_u64)) .saturating_add(T::DbWeight::get().writes(40_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:16 w:16) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) @@ -177,33 +173,33 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:15 w:16) /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - fn on_initialize_invalid_terminal() -> Weight { + fn verification_invalid_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1183625` - // Estimated: `1226690` - // Minimum execution time: 18_057_114_000 picoseconds. - Weight::from_parts(18_334_996_000, 1226690) + // Measured: `1123504` + // Estimated: `1166569` + // Minimum execution time: 17_623_388_000 picoseconds. + Weight::from_parts(18_013_619_000, 1166569) .saturating_add(T::DbWeight::get().reads(62_u64)) - .saturating_add(T::DbWeight::get().writes(53_u64)) + .saturating_add(T::DbWeight::get().writes(54_u64)) } /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockElectionVerifier::StatusStorage` (r:1 w:1) /// Proof: `MultiBlockElectionVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::Round` (r:1 w:0) /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:16 w:16) /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) - /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(128026), added: 130501, mode: `Measured`) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(80026), added: 82501, mode: `Measured`) /// Storage: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Proof: UNKNOWN KEY `0x5640fd84ada5e16d1b6739279282536c` (r:1 w:0) /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) @@ -222,19 +218,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) + /// Storage: `MultiBlockElectionSigned::Invulnerables` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::Invulnerables` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `Measured`) /// The range of component `v` is `[0, 15]`. - fn on_initialize_invalid_non_terminal(v: u32, ) -> Weight { + fn verification_invalid_non_terminal(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `384413 + v * (8974 ±0)` - // Estimated: `502395 + v * (7186 ±2_803)` - // Minimum execution time: 1_502_809_000 picoseconds. - Weight::from_parts(4_607_201_267, 502395) + // Measured: `446823` + // Estimated: `493569 + v * (813 ±1_678)` + // Minimum execution time: 1_320_902_000 picoseconds. + Weight::from_parts(1_471_494_315, 493569) + // Standard Error: 1_870_663 + .saturating_add(Weight::from_parts(13_057_611, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(30_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(v.into()))) - .saturating_add(T::DbWeight::get().writes(21_u64)) + .saturating_add(T::DbWeight::get().writes(22_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_parts(0, 7186).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 813).saturating_mul(v.into())) } } diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs index c47b49b59b4a8..9de0299f4473d 100644 --- a/substrate/frame/election-provider-multi-phase/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/src/lib.rs @@ -1841,13 +1841,14 @@ impl ElectionProvider for Pallet { Ok(()) } - fn status() -> Result { + fn status() -> Result, ()> { let has_queued = QueuedSolution::::exists(); let phase = CurrentPhase::::get(); match (phase, has_queued) { - (Phase::Unsigned(_), true) => Ok(true), + // This pallet is not advanced enough to report any weight, ergo `Default::default()`. + (Phase::Unsigned(_), true) => Ok(Some(Default::default())), (Phase::Off, _) => Err(()), - _ => Ok(false), + _ => Ok(None), } } diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index 78c631f67db40..05f0b8906cba8 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -340,8 +340,8 @@ impl ElectionProvider for MockFallback { Ok(()) } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } diff --git a/substrate/frame/election-provider-support/src/lib.rs b/substrate/frame/election-provider-support/src/lib.rs index 83ee955468905..86ded57e103ef 100644 --- a/substrate/frame/election-provider-support/src/lib.rs +++ b/substrate/frame/election-provider-support/src/lib.rs @@ -133,6 +133,7 @@ //! mod generic_election_provider { //! use super::*; //! use sp_runtime::traits::Zero; +//! use frame_support::pallet_prelude::Weight; //! //! pub struct GenericElectionProvider(std::marker::PhantomData); //! @@ -161,7 +162,7 @@ //! unimplemented!() //! } //! -//! fn status() -> Result { +//! fn status() -> Result, ()> { //! unimplemented!() //! } //! } @@ -523,10 +524,13 @@ pub trait ElectionProvider { /// Indicate whether this election provider is currently ongoing an asynchronous election. /// - /// `Err(())` should signal that we are not doing anything, and `elect` should def. not be - /// called. `Ok(false)` means we are doing something, but work is still ongoing. `elect` should - /// not be called. `Ok(true)` means we are done and ready for a call to `elect`. - fn status() -> Result; + /// * `Err(())` should signal that we are not doing anything, and `elect` should definitely not + /// be called. + /// * `Ok(None)` means we are doing something, but we are not done. `elect` should + /// not be called. + /// * `Ok(Some(Weight))` means we are done and ready for a call to `elect`, which should consume + /// at most the given weight when called. + fn status() -> Result, ()>; /// Signal the election provider that we are about to call `elect` asap, and it should prepare /// itself. @@ -585,7 +589,7 @@ where Zero::zero() } - fn status() -> Result { + fn status() -> Result, ()> { Err(()) } } @@ -790,7 +794,9 @@ pub trait NposSolver { /// Then it iterates over the voters and assigns them to the winners. /// /// It is only meant to be used in benchmarking. +#[cfg(feature = "runtime-benchmarks")] pub struct QuickDirtySolver(core::marker::PhantomData<(AccountId, Accuracy)>); +#[cfg(feature = "runtime-benchmarks")] impl NposSolver for QuickDirtySolver { @@ -819,11 +825,13 @@ impl NposSolver let mut final_winners = BTreeMap::::new(); for (voter, weight, votes) in voters { + // any of the `n` winners that we have voted for.. let our_winners = winners .iter() .filter(|w| votes.clone().into_iter().any(|v| v == **w)) .collect::>(); let our_winners_len = our_winners.len(); + // will get `1/n` of our stake/weight. let distribution = our_winners .into_iter() .map(|w| { diff --git a/substrate/frame/election-provider-support/src/onchain.rs b/substrate/frame/election-provider-support/src/onchain.rs index eb4911c7e24e3..f6fc29fe6b191 100644 --- a/substrate/frame/election-provider-support/src/onchain.rs +++ b/substrate/frame/election-provider-support/src/onchain.rs @@ -206,8 +206,8 @@ impl ElectionProvider for OnChainExecution { sp_runtime::traits::Zero::zero() } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } diff --git a/substrate/frame/fast-unstake/src/mock.rs b/substrate/frame/fast-unstake/src/mock.rs index 77b26a85cdbfc..c5f7e8edb215a 100644 --- a/substrate/frame/fast-unstake/src/mock.rs +++ b/substrate/frame/fast-unstake/src/mock.rs @@ -111,9 +111,9 @@ impl frame_election_provider_support::ElectionProvider for MockElection { 0 } - fn status() -> Result { + fn status() -> Result, ()> { if Ongoing::get() { - Ok(false) + Ok(None) } else { Err(()) } diff --git a/substrate/frame/staking-async/ahm-test/src/ah/mock.rs b/substrate/frame/staking-async/ahm-test/src/ah/mock.rs index e144cd7dbab9f..f40dfd2c4f0c2 100644 --- a/substrate/frame/staking-async/ahm-test/src/ah/mock.rs +++ b/substrate/frame/staking-async/ahm-test/src/ah/mock.rs @@ -21,7 +21,7 @@ use frame_election_provider_support::{ bounds::{ElectionBounds, ElectionBoundsBuilder}, SequentialPhragmen, }; -use frame_support::sp_runtime::testing::TestXt; +use frame_support::{sp_runtime::testing::TestXt, weights::WeightMeter}; use pallet_election_provider_multi_block as multi_block; use pallet_staking_async::Forcing; use pallet_staking_async_rc_client::{SessionReport, ValidatorSetReport}; @@ -49,18 +49,30 @@ construct_runtime! { // alias Runtime with T. pub type T = Runtime; +parameter_types! { + pub static NextPollWeight: Option = None; +} + pub fn roll_next() { let now = System::block_number(); let next = now + 1; System::set_block_number(next); + // Re-init frame-system, as execute would do. This resets the block weight usage counter, as we + // are using a realistic weight meter here. + frame_system::BlockWeight::::kill(); + + System::register_extra_weight_unchecked(Staking::on_initialize(next), DispatchClass::Mandatory); + System::register_extra_weight_unchecked( + RcClient::on_initialize(next), + DispatchClass::Mandatory, + ); - Staking::on_initialize(next); - RcClient::on_initialize(next); - MultiBlock::on_initialize(next); - MultiBlockVerifier::on_initialize(next); - MultiBlockSigned::on_initialize(next); - MultiBlockUnsigned::on_initialize(next); + let mut meter = NextPollWeight::take() + .map(WeightMeter::with_limit) + .unwrap_or_else(System::remaining_block_weight); + Staking::on_poll(next, &mut meter); + MultiBlock::on_poll(next, &mut meter); } pub fn roll_many(blocks: BlockNumber) { @@ -167,6 +179,7 @@ pub type AccountId = ::AccountId; pub type Balance = ::Balance; pub type Hash = ::Hash; pub type BlockNumber = BlockNumberFor; +pub type BlockWeights = ::BlockWeights; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { @@ -272,9 +285,10 @@ impl multi_block::Config for Runtime { type TargetSnapshotPerBlock = TargetSnapshotPerBlock; type VoterSnapshotPerBlock = VoterSnapshotPerBlock; type Verifier = MultiBlockVerifier; + type Signed = MultiBlockSigned; type AreWeDone = multi_block::ProceedRegardlessOf; type OnRoundRotation = multi_block::CleanRound; - type WeightInfo = (); + type WeightInfo = super::weights::MultiBlockElectionWeightInfo; } impl multi_block::verifier::Config for Runtime { @@ -283,17 +297,21 @@ impl multi_block::verifier::Config for Runtime { type MaxWinnersPerPage = MaxWinnersPerPage; type SolutionDataProvider = MultiBlockSigned; +<<<<<<< HEAD type SolutionImprovementThreshold = (); type WeightInfo = (); +======= + type WeightInfo = super::weights::MultiBlockElectionWeightInfo; +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } impl multi_block::unsigned::Config for Runtime { type MinerPages = ConstU32<1>; - type WeightInfo = (); type OffchainStorage = ConstBool; type MinerTxPriority = ConstU64<{ u64::MAX }>; type OffchainRepeat = (); type OffchainSolver = SequentialPhragmen; + type WeightInfo = super::weights::MultiBlockElectionWeightInfo; } parameter_types! { @@ -313,7 +331,7 @@ impl multi_block::signed::Config for Runtime { type EstimateCallFee = ConstU32<1>; type MaxSubmissions = MaxSubmissions; type RewardBase = RewardBase; - type WeightInfo = (); + type WeightInfo = super::weights::MultiBlockElectionWeightInfo; } parameter_types! { @@ -363,7 +381,7 @@ impl pallet_staking_async::Config for Runtime { type RcClientInterface = RcClient; - type WeightInfo = (); + type WeightInfo = super::weights::StakingAsyncWeightInfo; } impl pallet_staking_async_rc_client::Config for Runtime { @@ -537,6 +555,7 @@ impl ExtBuilder { parameter_types! { static StakingEventsIndex: usize = 0; static ElectionEventsIndex: usize = 0; + static VerifierEventsIndex: usize = 0; static RcClientEventsIndex: usize = 0; } @@ -573,3 +592,19 @@ pub(crate) fn election_events_since_last_call() -> Vec> { ElectionEventsIndex::set(all.len()); all.into_iter().skip(seen).collect() } + +pub(crate) fn verifier_events_since_last_call() -> Vec> { + let all: Vec<_> = System::events() + .into_iter() + .filter_map(|r| { + if let RuntimeEvent::MultiBlockVerifier(inner) = r.event { + Some(inner) + } else { + None + } + }) + .collect(); + let seen = VerifierEventsIndex::get(); + VerifierEventsIndex::set(all.len()); + all.into_iter().skip(seen).collect() +} diff --git a/substrate/frame/staking-async/ahm-test/src/ah/mod.rs b/substrate/frame/staking-async/ahm-test/src/ah/mod.rs index 7a5aa43baf0df..bc5273f03a713 100644 --- a/substrate/frame/staking-async/ahm-test/src/ah/mod.rs +++ b/substrate/frame/staking-async/ahm-test/src/ah/mod.rs @@ -17,6 +17,7 @@ pub mod mock; pub mod test; +pub mod weights; // re-export for easier use in dual runtime tests. pub use mock::*; diff --git a/substrate/frame/staking-async/ahm-test/src/ah/test.rs b/substrate/frame/staking-async/ahm-test/src/ah/test.rs index 3b2838b29e8e8..7abf8c13f3e0b 100644 --- a/substrate/frame/staking-async/ahm-test/src/ah/test.rs +++ b/substrate/frame/staking-async/ahm-test/src/ah/test.rs @@ -17,8 +17,12 @@ use crate::ah::mock::*; use frame::prelude::Perbill; +use frame_election_provider_support::Weight; use frame_support::assert_ok; -use pallet_election_provider_multi_block::{Event as ElectionEvent, Phase}; +use pallet_election_provider_multi_block::{ + unsigned::miner::OffchainWorkerMiner, verifier::Event as VerifierEvent, CurrentPhase, + ElectionScore, Event as ElectionEvent, Phase, +}; use pallet_staking_async::{ self as staking_async, session_rotation::Rotator, ActiveEra, ActiveEraInfo, CurrentEra, Event as StakingEvent, @@ -185,12 +189,17 @@ fn on_receive_session_report() { ] ); + // outgoing set is queued, sent in the next block. + assert!(pallet_staking_async_rc_client::OutgoingValidatorSet::::get().is_some()); + roll_next(); + assert!(pallet_staking_async_rc_client::OutgoingValidatorSet::::get().is_none()); + // New validator set xcm message is sent to RC. assert_eq!( LocalQueue::get().unwrap(), vec![( // this is the block number at which the message was sent. - 43, + 44, OutgoingMessages::ValidatorSet(ValidatorSetReport { new_validator_set: vec![3, 5, 6, 8], id: 1, @@ -340,6 +349,10 @@ fn validator_set_send_fail_retries() { ] ); + // outgoing set is queued, sent in the next block. + assert!(matches!(OutgoingValidatorSet::::get(), Some((_, 3)))); + roll_next(); + // but.. // nothing is queued @@ -360,7 +373,7 @@ fn validator_set_send_fail_retries() { LocalQueue::get().unwrap(), vec![( // this is the block number at which the message was sent. - 44, + 45, OutgoingMessages::ValidatorSet(ValidatorSetReport { new_validator_set: vec![3, 5, 6, 8], id: 1, @@ -1014,3 +1027,395 @@ fn on_offence_previous_era_instant_apply() { assert_eq!(staking_events_since_last_call(), vec![]); }); } + +mod poll_operations { + use super::*; + use pallet_election_provider_multi_block::verifier::{Status, Verifier}; + + #[test] + fn full_election_cycle_with_occasional_out_of_weight_completes() { + ExtBuilder::default().local_queue().build().execute_with(|| { + // given initial state of AH + assert_eq!(System::block_number(), 1); + assert_eq!(CurrentEra::::get(), Some(0)); + assert_eq!(Rotator::::active_era_start_session_index(), 0); + assert_eq!(ActiveEra::::get(), Some(ActiveEraInfo { index: 0, start: Some(0) })); + assert!(pallet_staking_async_rc_client::OutgoingValidatorSet::::get().is_none()); + + // receive first 3 session reports that don't trigger election + for i in 0..3 { + assert_ok!(rc_client::Pallet::::relay_session_report( + RuntimeOrigin::root(), + rc_client::SessionReport { + end_index: i, + validator_points: vec![(1, 10)], + activation_timestamp: None, + leftover: false, + } + )); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::SessionRotated { + starting_session: i + 1, + active_era: 0, + planned_era: 0 + }] + ); + } + + // receive session 4 which causes election to start + assert_ok!(rc_client::Pallet::::relay_session_report( + RuntimeOrigin::root(), + rc_client::SessionReport { + end_index: 3, + validator_points: vec![(1, 10)], + activation_timestamp: None, + leftover: false, + } + )); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::SessionRotated { + starting_session: 4, + active_era: 0, + // planned era 1 indicates election start signal is sent. + planned_era: 1 + }] + ); + + assert_eq!( + election_events_since_last_call(), + // Snapshot phase has started which will run for 3 blocks + vec![ElectionEvent::PhaseTransitioned { from: Phase::Off, to: Phase::Snapshot(3) }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Snapshot(3)); + + // create 1 snapshot page normally + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Snapshot(2)); + + // next block won't have enough weight + NextPollWeight::set(Some(crate::ah::weights::SMALL)); + roll_next(); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::UnexpectedPhaseTransitionOutOfWeight { + from: Phase::Snapshot(2), + to: Phase::Snapshot(1), + required: Weight::from_parts(100, 0), + had: Weight::from_parts(10, 0) + }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Snapshot(2)); + + // next 2 blocks happen fine + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Snapshot(1)); + + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Snapshot(0)); + + // transition to signed + roll_next(); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::PhaseTransitioned { + from: Phase::Snapshot(0), + to: Phase::Signed(3) + }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Signed(3)); + + // roll 1 + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Signed(2)); + + // unlikely: we have zero weight, we won't progress + NextPollWeight::set(Some(Weight::default())); + roll_next(); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::UnexpectedPhaseTransitionOutOfWeight { + from: Phase::Signed(2), + to: Phase::Signed(1), + required: Weight::from_parts(10, 0), + had: Weight::from_parts(0, 0) + }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Signed(2)); + + // submit a signed solution + let solution = OffchainWorkerMiner::::mine_solution(3, true).unwrap(); + assert_ok!(MultiBlockSigned::register(RuntimeOrigin::signed(1), solution.score)); + for (index, page) in solution.solution_pages.into_iter().enumerate() { + assert_ok!(MultiBlockSigned::submit_page( + RuntimeOrigin::signed(1), + index as u32, + Some(Box::new(page)) + )); + } + + // go to signed validation + roll_until_matches(|| CurrentPhase::::get() == Phase::SignedValidation(6), false); + assert_eq!(MultiBlockVerifier::status_storage(), Status::Ongoing(2)); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::PhaseTransitioned { + from: Phase::Signed(0), + to: Phase::SignedValidation(6) + }] + ); + + // first block rolls okay + roll_next(); + assert_eq!(verifier_events_since_last_call(), vec![VerifierEvent::Verified(2, 4)]); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::SignedValidation(5)); + assert_eq!(MultiBlockVerifier::status_storage(), Status::Ongoing(1)); + + // next block has not enough weight left for verification (verification of non-terminal + // pages requires MEDIUM) + NextPollWeight::set(Some(crate::ah::weights::SMALL)); + roll_next(); + assert_eq!(verifier_events_since_last_call(), vec![]); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::UnexpectedPhaseTransitionOutOfWeight { + from: Phase::SignedValidation(5), + to: Phase::SignedValidation(4), + required: Weight::from_parts(1010, 0), + had: Weight::from_parts(10, 0) + }] + ); + assert_eq!(CurrentPhase::::get(), Phase::SignedValidation(5)); + assert_eq!(MultiBlockVerifier::status_storage(), Status::Ongoing(1)); + + // rest go by fine, roll until done + roll_until_matches(|| CurrentPhase::::get() == Phase::Done, false); + assert_eq!( + verifier_events_since_last_call(), + vec![ + VerifierEvent::Verified(1, 0), + VerifierEvent::Verified(0, 3), + VerifierEvent::Queued( + ElectionScore { + minimal_stake: 100, + sum_stake: 800, + sum_stake_squared: 180000 + }, + None + ) + ] + ); + assert_eq!( + election_events_since_last_call(), + vec![ + ElectionEvent::PhaseTransitioned { + from: Phase::SignedValidation(0), + to: Phase::Unsigned(3) + }, + ElectionEvent::PhaseTransitioned { from: Phase::Unsigned(0), to: Phase::Done }, + ] + ); + + // first export page goes by fine + assert_eq!(pallet_staking_async::NextElectionPage::::get(), None); + roll_next(); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::PhaseTransitioned { from: Phase::Done, to: Phase::Export(1) }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Export(1)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::PagedElectionProceeded { page: 2, result: Ok(4) }] + ); + assert_eq!(pallet_staking_async::NextElectionPage::::get(), Some(1)); + + // second page goes by fine + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Export(0)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::PagedElectionProceeded { page: 1, result: Ok(0) }] + ); + assert_eq!(pallet_staking_async::NextElectionPage::::get(), Some(0)); + + // last (LARGE page) runs out of weight + NextPollWeight::set(Some(crate::ah::weights::MEDIUM)); + roll_next(); + assert_eq!(election_events_since_last_call(), vec![]); + assert_eq!(CurrentPhase::::get(), Phase::Export(0)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unexpected( + pallet_staking_async::UnexpectedKind::PagedElectionOutOfWeight { + page: 0, + required: Weight::from_parts(1000, 0), + had: Weight::from_parts(100, 0) + } + )] + ); + assert_eq!(pallet_staking_async::NextElectionPage::::get(), Some(0)); + + // next time it goes by fine + roll_next(); + assert_eq!( + election_events_since_last_call(), + vec![ElectionEvent::PhaseTransitioned { from: Phase::Export(0), to: Phase::Off }] + ); + assert_eq!(CurrentPhase::::get(), Phase::Off); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::PagedElectionProceeded { page: 0, result: Ok(0) }] + ); + assert_eq!(pallet_staking_async::NextElectionPage::::get(), None); + + // outgoing message is queued + assert!(pallet_staking_async_rc_client::OutgoingValidatorSet::::get().is_some()); + }) + } + + #[test] + fn slashing_processing_while_election() { + // This is merely a more realistic example of the above. As staking is ready to receive the + // election result, an ongoing slash will cause too much weight to be consumed + // on-initialize, causing not enough weight in the on-poll to process. Everything works as + // expected, but we get a bit slow. + // + // The only other meaningful difference is here that we see in action that first on-init + // runs, and then the leftover weight is given to on-poll. This is done through the mock + // setup of this test. + ExtBuilder::default().local_queue().build().execute_with(|| { + // first, we roll 1 era so have some validators to slash + let active_validators = roll_until_next_active(0); + let _ = staking_events_since_last_call(); + + // given initial state of AH + assert_eq!(System::block_number(), 27); + assert_eq!(CurrentEra::::get(), Some(1)); + assert_eq!(Rotator::::active_era_start_session_index(), 5); + assert_eq!(ActiveEra::::get(), Some(ActiveEraInfo { index: 1, start: Some(1000) })); + assert!(pallet_staking_async_rc_client::OutgoingValidatorSet::::get().is_none()); + + // receive first 3 session reports that don't trigger election + for i in 5..8 { + assert_ok!(rc_client::Pallet::::relay_session_report( + RuntimeOrigin::root(), + rc_client::SessionReport { + end_index: i, + validator_points: vec![(1, 10)], + activation_timestamp: None, + leftover: false, + } + )); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::SessionRotated { + starting_session: i + 1, + active_era: 1, + planned_era: 1 + }] + ); + } + + // receive session 4 which causes election to start + assert_ok!(rc_client::Pallet::::relay_session_report( + RuntimeOrigin::root(), + rc_client::SessionReport { + end_index: 8, + validator_points: vec![(1, 10)], + activation_timestamp: None, + leftover: false, + } + )); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::SessionRotated { + starting_session: 9, + active_era: 1, + // planned era 1 indicates election start signal is sent. + planned_era: 2 + }] + ); + + // roll until signed and submit a solution. + roll_until_matches(|| MultiBlock::current_phase().is_signed(), false); + let solution = OffchainWorkerMiner::::mine_solution(3, true).unwrap(); + assert_ok!(MultiBlockSigned::register(RuntimeOrigin::signed(1), solution.score)); + for (index, page) in solution.solution_pages.into_iter().enumerate() { + assert_ok!(MultiBlockSigned::submit_page( + RuntimeOrigin::signed(1), + index as u32, + Some(Box::new(page)) + )); + } + + // then roll to done, waiting for staking to start processing it. Indeed, something is + // queued for export now. + roll_until_matches(|| MultiBlock::current_phase().is_done(), false); + assert!(MultiBlockVerifier::queued_score().is_some()); + + assert_ok!(rc_client::Pallet::::relay_new_offence_paged( + RuntimeOrigin::root(), + vec![( + // index of the last received session report + 8, + rc_client::Offence { + offender: active_validators[0], + reporters: vec![], + slash_fraction: Perbill::from_percent(10), + } + )] + )); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::OffenceReported { + offence_era: 1, + validator: active_validators[0], + fraction: Perbill::from_percent(10) + }] + ); + + assert!(pallet_staking_async::NextElectionPage::::get().is_none()); + + // now as we roll-next, because weight of `process_offence_queue` is max block... + roll_next(); + // staking has not moved forward in terms of fetching election pages + assert!(pallet_staking_async::NextElectionPage::::get().is_none()); + // same with our EPMB + assert!(MultiBlock::current_phase().is_done()); + // and for tracking we have + assert_eq!( + staking_events_since_last_call(), + vec![ + // slash processing happened.. + StakingEvent::SlashComputed { + offence_era: 1, + slash_era: 3, + offender: active_validators[0], + page: 0 + }, + // but not this. + StakingEvent::Unexpected( + pallet_staking_async::UnexpectedKind::PagedElectionOutOfWeight { + page: 2, + required: Weight::from_parts(100, 0), + had: Weight::from_parts(0, 0) + } + ) + ] + ); + }); + } +} diff --git a/substrate/frame/staking-async/ahm-test/src/ah/weights.rs b/substrate/frame/staking-async/ahm-test/src/ah/weights.rs new file mode 100644 index 0000000000000..d581f6dc27eff --- /dev/null +++ b/substrate/frame/staking-async/ahm-test/src/ah/weights.rs @@ -0,0 +1,237 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Weights to be used with `full_election_cycle_with_occasional_out_of_weight_completes` test. +//! +//! Note: we put as many things as possible as `unreachable!()` to limit the scope. + +use frame::deps::frame_system; +use frame_election_provider_support::Weight; +use frame_support::traits::Get; +use pallet_election_provider_multi_block::weights::traits::{ + pallet_election_provider_multi_block_signed, pallet_election_provider_multi_block_unsigned, + pallet_election_provider_multi_block_verifier, +}; + +use crate::ah; + +pub const SMALL: Weight = Weight::from_parts(10, 0); +pub const MEDIUM: Weight = Weight::from_parts(100, 0); +pub const LARGE: Weight = Weight::from_parts(1_000, 0); + +pub struct MultiBlockElectionWeightInfo; +impl pallet_election_provider_multi_block::WeightInfo for MultiBlockElectionWeightInfo { + fn admin_set() -> Weight { + unreachable!() + } + fn manage_fallback() -> Weight { + unreachable!() + } + fn export_non_terminal() -> Weight { + MEDIUM + } + fn export_terminal() -> Weight { + LARGE + } + fn per_block_nothing() -> Weight { + SMALL + } + fn per_block_snapshot_msp() -> Weight { + LARGE + } + fn per_block_snapshot_rest() -> Weight { + MEDIUM + } + fn per_block_start_signed_validation() -> Weight { + SMALL + } +} + +impl pallet_election_provider_multi_block_verifier::WeightInfo for MultiBlockElectionWeightInfo { + fn verification_invalid_non_terminal(_: u32) -> Weight { + MEDIUM + } + fn verification_invalid_terminal() -> Weight { + LARGE + } + fn verification_valid_non_terminal() -> Weight { + MEDIUM + } + fn verification_valid_terminal() -> Weight { + LARGE + } +} + +impl pallet_election_provider_multi_block_signed::WeightInfo for MultiBlockElectionWeightInfo { + fn bail() -> Weight { + unreachable!() + } + fn clear_old_round_data(_: u32) -> Weight { + unreachable!() + } + fn register_eject() -> Weight { + unreachable!() + } + fn register_not_full() -> Weight { + // we submit pages in tests + Default::default() + } + fn submit_page() -> Weight { + unreachable!() + } + fn unset_page() -> Weight { + unreachable!() + } +} + +impl pallet_election_provider_multi_block_unsigned::WeightInfo for MultiBlockElectionWeightInfo { + fn mine_solution(_p: u32) -> Weight { + unreachable!() + } + fn submit_unsigned() -> Weight { + // NOTE: this one is checked in the integrity tests of the runtime, we don't care about it + // here. + Default::default() + } + fn validate_unsigned() -> Weight { + unreachable!() + } +} + +pub struct StakingAsyncWeightInfo; +impl pallet_staking_async::WeightInfo for StakingAsyncWeightInfo { + fn bond() -> Weight { + unreachable!() + } + fn bond_extra() -> Weight { + unreachable!() + } + fn unbond() -> Weight { + unreachable!() + } + fn withdraw_unbonded_update() -> Weight { + unreachable!() + } + fn withdraw_unbonded_kill() -> Weight { + unreachable!() + } + fn validate() -> Weight { + unreachable!() + } + fn kick(_: u32) -> Weight { + unreachable!() + } + fn nominate(_: u32) -> Weight { + unreachable!() + } + fn chill() -> Weight { + unreachable!() + } + fn set_payee() -> Weight { + unreachable!() + } + fn update_payee() -> Weight { + unreachable!() + } + fn set_controller() -> Weight { + unreachable!() + } + fn set_validator_count() -> Weight { + unreachable!() + } + fn force_no_eras() -> Weight { + unreachable!() + } + fn force_new_era() -> Weight { + unreachable!() + } + fn force_new_era_always() -> Weight { + unreachable!() + } + fn deprecate_controller_batch(_: u32) -> Weight { + unreachable!() + } + fn force_unstake() -> Weight { + unreachable!() + } + fn cancel_deferred_slash(_: u32) -> Weight { + unreachable!() + } + fn payout_stakers_alive_staked(_: u32) -> Weight { + unreachable!() + } + fn rebond(_: u32) -> Weight { + unreachable!() + } + fn reap_stash() -> Weight { + unreachable!() + } + fn set_staking_configs_all_set() -> Weight { + unreachable!() + } + fn set_staking_configs_all_remove() -> Weight { + unreachable!() + } + fn chill_other() -> Weight { + unreachable!() + } + fn force_apply_min_commission() -> Weight { + unreachable!() + } + fn set_min_commission() -> Weight { + unreachable!() + } + fn restore_ledger() -> Weight { + unreachable!() + } + fn migrate_currency() -> Weight { + unreachable!() + } + fn apply_slash() -> Weight { + Default::default() + } + fn process_offence_queue() -> Weight { + >::get().max_block + } + fn rc_on_offence(_: u32) -> Weight { + Default::default() + } + fn rc_on_session_report() -> Weight { + Default::default() + } + fn prune_era_stakers_paged(_: u32) -> Weight { + unreachable!() + } + fn prune_era_stakers_overview(_: u32) -> Weight { + unreachable!() + } + fn prune_era_validator_prefs(_: u32) -> Weight { + unreachable!() + } + fn prune_era_claimed_rewards(_: u32) -> Weight { + unreachable!() + } + fn prune_era_validator_reward() -> Weight { + unreachable!() + } + fn prune_era_reward_points() -> Weight { + unreachable!() + } + fn prune_era_total_stake() -> Weight { + unreachable!() + } +} diff --git a/substrate/frame/staking-async/runtimes/papi-tests/src/cmd.ts b/substrate/frame/staking-async/runtimes/papi-tests/src/cmd.ts index 200675d7ac895..01891effbd327 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/src/cmd.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/src/cmd.ts @@ -57,6 +57,7 @@ export async function runPresetUntilLaunched( // Extract log path from the last log command const lastCmd = logCmds[logCmds.length - 1]; const paraLog = lastCmd ? lastCmd.match(/tail -f\s+(.+\.log)/)?.[1] || null : null; + logger.verbose(`Parachain log file: ${paraLog}`); resolve({ killZn: () => { @@ -84,7 +85,7 @@ export async function spawnMiner(): Promise<() => void> { [ "--uri", "ws://127.0.0.1:9946", - "experimental-monitor-multi-block", + "monitor", "--seed-or-path", "//Bob", ], @@ -123,8 +124,8 @@ function prepPreset(paraPreset: Presets): void { `staging-chain-spec-builder`, ]); - cmd("rm", ["./parachain.json"]); - cmd("rm", ["./rc.json"]); + cmd("rm", ["-f", "./parachain.json"]); + cmd("rm", ["-f", "./rc.json"]); cmd(join(targetDir, "/release/chain-spec-builder"), [ "create", diff --git a/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts b/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts index 4a0db0c822fb8..6f8ca6690c79b 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts @@ -14,7 +14,7 @@ import { sr25519CreateDerive } from "@polkadot-labs/hdkd"; import { DEV_PHRASE, entropyToMiniSecret, mnemonicToEntropy, type KeyPair } from "@polkadot-labs/hdkd-helpers"; import { getPolkadotSigner } from "polkadot-api/signer"; -export const GlobalTimeout = 30 * 60 * 1000; +export const GlobalTimeout = 45 * 60 * 1000; export const aliceStash = "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY"; diff --git a/substrate/frame/staking-async/runtimes/papi-tests/tests/example.test.ts b/substrate/frame/staking-async/runtimes/papi-tests/tests/example.test.ts index a1477bd7a4aa2..95e7a388f4a30 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/tests/example.test.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/example.test.ts @@ -7,7 +7,7 @@ import { getApis, GlobalTimeout, logger, nullifySigned } from "../src/utils"; /// This is the preset against which your test will run. See the README or `PResets` for more info. const PRESET: Presets = Presets.FakeKsm; -test( +test.skip( `example test with preset ${PRESET}`, async () => { /// We run the test with our defined preset. diff --git a/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-dot.test.ts b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-dot.test.ts index 37a553b1bb61b..efc62999eebe4 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-dot.test.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-dot.test.ts @@ -13,9 +13,10 @@ test( const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); const apis = await getApis(); const killMiner = await spawnMiner(); + const expectedValidatorSetCount = await apis.paraApi.query.Staking.ValidatorCount.getValue(); const testCase = new TestCase( - commonSignedSteps(32, 500, apis), + commonSignedSteps(32, expectedValidatorSetCount, apis), true, () => { killMiner(); diff --git a/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-ksm.test.ts b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-ksm.test.ts index 20794c40ff5b7..ad42d1683337d 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-ksm.test.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-ksm.test.ts @@ -10,12 +10,13 @@ const PRESET: Presets = Presets.FakeKsm; test( `signed solution on ${PRESET}`, async () => { - const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); + const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); const apis = await getApis(); const killMiner = await spawnMiner(); + const expectedValidatorSetCount = await apis.paraApi.query.Staking.ValidatorCount.getValue(); const testCase = new TestCase( - commonSignedSteps(16, 1000, apis), + commonSignedSteps(16, expectedValidatorSetCount, apis), true, () => { killMiner(); diff --git a/substrate/frame/staking-async/runtimes/papi-tests/tests/unsigned-dev.test.ts b/substrate/frame/staking-async/runtimes/papi-tests/tests/unsigned-dev.test.ts index 57fc3b4acab8e..6b6bf804d7cdc 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/tests/unsigned-dev.test.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/unsigned-dev.test.ts @@ -13,7 +13,7 @@ test( const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); const apis = await getApis(); - const steps = commonUnsignedSteps(10, 4, 4, false, apis); + const steps = commonUnsignedSteps(10, 4, 4, true, apis); const testCase = new TestCase(steps, true, () => { killZn(); diff --git a/substrate/frame/staking-async/runtimes/papi-tests/tests/vmp-spamming.test.ts b/substrate/frame/staking-async/runtimes/papi-tests/tests/vmp-spamming.test.ts index 085d8ab73015e..f361d11a6b1bc 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/tests/vmp-spamming.test.ts +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/vmp-spamming.test.ts @@ -204,7 +204,7 @@ async function sendDown(api: TypedApi, count: number) { } } -test( +test.skip( `${PRESET} preset with vmp queues being spammed af`, async () => { const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); diff --git a/substrate/frame/staking-async/runtimes/papi-tests/zn-m.toml b/substrate/frame/staking-async/runtimes/papi-tests/zn-m.toml index fbcf63376ebf0..884fa6248d487 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/zn-m.toml +++ b/substrate/frame/staking-async/runtimes/papi-tests/zn-m.toml @@ -31,6 +31,7 @@ id = 1100 chain_spec_path = "./parachain.json" [parachains.collator] +command = "polkadot-parachain" name = "charlie" rpc_port = 9946 args = [ diff --git a/substrate/frame/staking-async/runtimes/papi-tests/zn-s.toml b/substrate/frame/staking-async/runtimes/papi-tests/zn-s.toml index bb360ae7f0a9b..eb9e45aa921a1 100644 --- a/substrate/frame/staking-async/runtimes/papi-tests/zn-s.toml +++ b/substrate/frame/staking-async/runtimes/papi-tests/zn-s.toml @@ -23,8 +23,9 @@ id = 1100 chain_spec_path = "./parachain.json" [parachains.collator] +command = "polkadot-parachain" name = "charlie" rpc_port = 9946 args = [ - "-lruntime::system=debug,runtime::multiblock-election=trace,runtime::staking=debug,runtime::staking::rc-client=trace,runtime::rc-client=debug,xcm=trace,parachain-system=debug,runtime=info", + "-lruntime::system=debug,runtime::multiblock-election=trace,runtime::staking=debug,runtime::staking::rc-client=trace,runtime::rc-client=debug,xcm=debug,parachain-system=debug,runtime=info", ] diff --git a/substrate/frame/staking-async/runtimes/parachain/bench_all.sh b/substrate/frame/staking-async/runtimes/parachain/bench_all.sh index f3b7efb7018ab..686d00c59cd29 100755 --- a/substrate/frame/staking-async/runtimes/parachain/bench_all.sh +++ b/substrate/frame/staking-async/runtimes/parachain/bench_all.sh @@ -2,16 +2,16 @@ source ~/.zshrc STEPS=2 -REPEAT=2 +REPEAT=22 # if any of the command line arguments are equal to `--log=X`, set X to the below log levels -LOG="runtime::multiblock-election=info,runtime::staking-async=info,polkadot_sdk_frame::benchmark=info" +LOG="runtime::multiblock-election=info,runtime::staking-async=info,frame::benchmark=info" if [[ "${NO_COMPILE}" == "1" ]]; then echo "Skipping compilation because 'NO_COMPILE' was set" else cargo build --release -p frame-omni-bencher - FORCE_WASM_BUILD=$RANDOM WASMTIME_BACKTRACE_DETAILS=1 RUST_LOG=${LOG} cargo build --release -p pallet-staking-async-parachain-runtime --features runtime-benchmarks + FORCE_WASM_BUILD=$RANDOM SKIP_PALLET_REVIVE_FIXTURES=1 WASMTIME_BACKTRACE_DETAILS=1 RUST_LOG=${LOG} cargo build --release -p pallet-staking-async-parachain-runtime --features runtime-benchmarks fi WASM_BLOB_PATH=../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm @@ -41,13 +41,13 @@ run_benchmark() { --output "$output_file" } -# run_benchmark "pallet_staking_async" "fake-dot" +run_benchmark "pallet_staking_async" "fake-dot" run_benchmark "pallet_election_provider_multi_block" "fake-dot" run_benchmark "pallet_election_provider_multi_block_signed" "fake-dot" run_benchmark "pallet_election_provider_multi_block_unsigned" "fake-dot" run_benchmark "pallet_election_provider_multi_block_verifier" "fake-dot" -# run_benchmark "pallet_staking_async" "fake-ksm" +run_benchmark "pallet_staking_async" "fake-ksm" run_benchmark "pallet_election_provider_multi_block" "fake-ksm" run_benchmark "pallet_election_provider_multi_block_signed" "fake-ksm" run_benchmark "pallet_election_provider_multi_block_unsigned" "fake-ksm" diff --git a/substrate/frame/staking-async/runtimes/parachain/src/genesis_config_presets.rs b/substrate/frame/staking-async/runtimes/parachain/src/genesis_config_presets.rs index a81bbfa424ba9..afafb67e28fcc 100644 --- a/substrate/frame/staking-async/runtimes/parachain/src/genesis_config_presets.rs +++ b/substrate/frame/staking-async/runtimes/parachain/src/genesis_config_presets.rs @@ -144,7 +144,7 @@ pub fn get_preset(id: &PresetId) -> Option> { staking_async_parachain_genesis(params, id.to_string()) }, "fake-dot" => { - params.validator_count = 500; + params.validator_count = 600; params.dev_stakers = Some((2_500, 25_000)); staking_async_parachain_genesis(params, id.to_string()) }, diff --git a/substrate/frame/staking-async/runtimes/parachain/src/staking.rs b/substrate/frame/staking-async/runtimes/parachain/src/staking.rs index 75970f229b9c8..eedeafd0f203e 100644 --- a/substrate/frame/staking-async/runtimes/parachain/src/staking.rs +++ b/substrate/frame/staking-async/runtimes/parachain/src/staking.rs @@ -294,6 +294,7 @@ impl multi_block::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type Fallback = frame_election_provider_support::onchain::OnChainExecution; type MinerConfig = Self; + type Signed = MultiBlockElectionSigned; type Verifier = MultiBlockElectionVerifier; type OnRoundRotation = multi_block::CleanRound; type WeightInfo = multi_block::weights::polkadot::MultiBlockWeightInfo; @@ -360,6 +361,9 @@ impl multi_block::unsigned::miner::MinerConfig for Runtime { type MaxVotesPerVoter = <::DataProvider as ElectionDataProvider>::MaxVotesPerVoter; type MaxLength = MinerMaxLength; + #[cfg(feature = "runtime-benchmarks")] + type Solver = frame_election_provider_support::QuickDirtySolver; + #[cfg(not(feature = "runtime-benchmarks"))] type Solver = ::OffchainSolver; type Pages = Pages; type Solution = NposCompactSolution16; @@ -687,6 +691,36 @@ mod tests { ); } + #[test] + fn ensure_epmb_weights_sane_polkadot() { + use sp_io::TestExternalities; + use sp_runtime::Percent; + sp_tracing::try_init_simple(); + TestExternalities::default().execute_with(|| { + super::enable_dot_preset(false); + pallet_election_provider_multi_block::Pallet::::check_all_weights( + ::BlockWeights::get().max_block, + Some(Percent::from_percent(75)), + Some(Percent::from_percent(50)), + ) + }); + } + + #[test] + fn ensure_epmb_weights_sane_kusama() { + use sp_io::TestExternalities; + use sp_runtime::Percent; + sp_tracing::try_init_simple(); + TestExternalities::default().execute_with(|| { + super::enable_ksm_preset(false); + pallet_election_provider_multi_block::Pallet::::check_all_weights( + ::BlockWeights::get().max_block, + Some(Percent::from_percent(75)), + Some(Percent::from_percent(50)), + ) + }); + } + #[test] fn signed_weight_ratios() { sp_tracing::try_init_simple(); diff --git a/substrate/frame/staking-async/src/mock.rs b/substrate/frame/staking-async/src/mock.rs index 2b9809426bfe3..5726f183e6766 100644 --- a/substrate/frame/staking-async/src/mock.rs +++ b/substrate/frame/staking-async/src/mock.rs @@ -37,7 +37,7 @@ use pallet_staking_async_rc_client as rc_client; use sp_core::{ConstBool, ConstU64}; use sp_io; use sp_npos_elections::BalancingConfig; -use sp_runtime::{traits::Zero, BuildStorage}; +use sp_runtime::{traits::Zero, BuildStorage, Weight}; use sp_staking::{ currency_to_vote::SaturatingCurrencyToVote, OnStakingUpdate, SessionIndex, StakingAccount, }; @@ -194,11 +194,11 @@ impl ElectionProvider for TestElectionProvider { fn duration() -> Self::BlockNumber { InnerElection::duration() + ElectionDelay::get() } - fn status() -> Result { + fn status() -> Result, ()> { let now = System::block_number(); match StartReceived::get() { - Some(at) if now - at >= ElectionDelay::get() => Ok(true), - Some(_) => Ok(false), + Some(at) if now - at >= ElectionDelay::get() => Ok(Some(Default::default())), + Some(_) => Ok(None), None => Err(()), } } @@ -243,6 +243,10 @@ impl Contains for MockedRestrictList { /// A representation of the session pallet that lives on the relay chain. pub mod session_mock { use super::*; + use frame_support::{ + traits::{OnInitialize, OnPoll}, + weights::WeightMeter, + }; use pallet_staking_async_rc_client::ValidatorSetReport; pub struct Session; @@ -269,7 +273,12 @@ pub mod session_mock { pub fn roll_next() { let now = System::block_number(); Timestamp::mutate(|ts| *ts += BLOCK_TIME); - System::run_to_block::(now + 1); + System::set_block_number(now + 1); + >::on_initialize(now + 1); + >::on_poll( + now + 1, + &mut WeightMeter::new(), + ); Self::maybe_rotate_session_now(); } diff --git a/substrate/frame/staking-async/src/pallet/mod.rs b/substrate/frame/staking-async/src/pallet/mod.rs index 11174e7f26ade..d0a2a127a5e6d 100644 --- a/substrate/frame/staking-async/src/pallet/mod.rs +++ b/substrate/frame/staking-async/src/pallet/mod.rs @@ -18,10 +18,11 @@ //! `pallet-staking-async`'s main `pallet` module. use crate::{ - asset, slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, - EraRewardPoints, ExposurePage, Forcing, LedgerIntegrityState, MaxNominationsOf, - NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, - StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, + asset, session_rotation::EraElectionPlanner, slashing, weights::WeightInfo, AccountIdLookupOf, + ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, ExposurePage, Forcing, + LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, + PositiveImbalanceOf, RewardDestination, StakingLedger, UnappliedSlash, UnlockChunk, + ValidatorPrefs, }; use alloc::{format, vec::Vec}; use codec::Codec; @@ -68,7 +69,7 @@ pub mod pallet { use crate::{session_rotation, PagedExposureMetadata, SnapshotStatus}; use codec::HasCompact; use frame_election_provider_support::{ElectionDataProvider, PageIndex}; - use frame_support::DefaultNoBound; + use frame_support::{weights::WeightMeter, DefaultNoBound}; /// Represents the current step in the era pruning process #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] @@ -1226,6 +1227,8 @@ pub mod pallet { EraDurationBoundExceeded, /// Received a validator activation event that is not recognized. UnknownValidatorActivation, + /// Failed to proceed paged election due to weight limits + PagedElectionOutOfWeight { page: PageIndex, required: Weight, had: Weight }, } #[pallet::error] @@ -1427,6 +1430,30 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { + fn on_poll(_now: BlockNumberFor, weight_meter: &mut WeightMeter) { + let (weight, exec) = EraElectionPlanner::::maybe_fetch_election_results(); + crate::log!( + trace, + "weight of fetching next election page is {:?}, have {:?}", + weight, + weight_meter.remaining() + ); + + if weight_meter.can_consume(weight) { + exec(weight_meter); + } else { + Self::deposit_event(Event::::Unexpected( + UnexpectedKind::PagedElectionOutOfWeight { + page: NextElectionPage::::get().unwrap_or( + EraElectionPlanner::::election_pages().defensive_saturating_sub(1), + ), + required: weight, + had: weight_meter.remaining(), + }, + )); + } + } + fn on_initialize(_now: BlockNumberFor) -> Weight { // process our queue. let mut consumed_weight = slashing::process_offence::(); @@ -1438,9 +1465,6 @@ pub mod pallet { consumed_weight.saturating_accrue(slash_weight); } - // maybe plan eras and stuff. Note that this is benchmark as a part of the - // election-provider's benchmarks. - session_rotation::EraElectionPlanner::::maybe_fetch_election_results(); consumed_weight } diff --git a/substrate/frame/staking-async/src/session_rotation.rs b/substrate/frame/staking-async/src/session_rotation.rs index ff0b1e12d52af..0d9338eb95297 100644 --- a/substrate/frame/staking-async/src/session_rotation.rs +++ b/substrate/frame/staking-async/src/session_rotation.rs @@ -77,12 +77,14 @@ //! * end 5, start 6, plan 7 // Session report contains activation timestamp with Current Era. use crate::*; -use alloc::vec::Vec; +use alloc::{boxed::Box, vec::Vec}; use frame_election_provider_support::{BoundedSupportsOf, ElectionProvider, PageIndex}; use frame_support::{ pallet_prelude::*, traits::{Defensive, DefensiveMax, DefensiveSaturating, OnUnbalanced, TryCollect}, + weights::WeightMeter, }; +use pallet_staking_async_rc_client::RcClientInterface; use sp_runtime::{Perbill, Percent, Saturating}; use sp_staking::{ currency_to_vote::CurrencyToVote, Exposure, Page, PagedExposureMetadata, SessionIndex, @@ -902,9 +904,13 @@ impl EraElectionPlanner { .inspect_err(|e| log!(warn, "Election provider failed to start: {:?}", e)) } - /// Hook to be used in the pallet's on-initialize. - pub(crate) fn maybe_fetch_election_results() { - if let Ok(true) = T::ElectionProvider::status() { + pub(crate) fn maybe_fetch_election_results() -> (Weight, Box) { + let Ok(Some(mut required_weight)) = T::ElectionProvider::status() else { + // no election ongoing + let weight = T::DbWeight::get().reads(1); + return (weight, Box::new(move |meter: &mut WeightMeter| meter.consume(weight))) + }; + let exec = Box::new(move |meter: &mut WeightMeter| { crate::log!( debug, "Election provider is ready, our status is {:?}", @@ -925,10 +931,7 @@ impl EraElectionPlanner { Self::do_elect_paged(current_page); NextElectionPage::::set(maybe_next_page); - // if current page was `Some`, and next is `None`, we have finished an election and - // we can report it now. if maybe_next_page.is_none() { - use pallet_staking_async_rc_client::RcClientInterface; let id = CurrentEra::::get().defensive_unwrap_or(0); let prune_up_to = Self::get_prune_up_to(); let rc_validators = ElectableStashes::::take().into_iter().collect::>(); @@ -940,10 +943,24 @@ impl EraElectionPlanner { id, prune_up_to ); - T::RcClientInterface::validator_set(rc_validators, id, prune_up_to); } - } + + // consume the reported worst case weight. + meter.consume(required_weight) + }); + + // Add a few things to the required weights that are not captured in `do_elect_paged`, which + // is benchmarked via `fetch_page`. + // * 1 extra read and write for `NextElectionPage` + // * 1 extra write for `RcClientInterface::validator_set` (implementation leak -- we assume + // that we know this writes one storage item under the hood) + // * 1 extra read for `CurrentEra` + // * 1 extra read for `BondedEras` in `get_prune_up_to` + // ElectableStashes already read in `do_elect_paged` + required_weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 2)); + + (required_weight, exec) } /// Get the right value of the first session that needs to be pruned on the RC's historical