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 93039369d862d..e98ce13287346 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -2633,3 +2633,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 7bc0ce142817d..2466fabd9269d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs @@ -133,7 +133,12 @@ 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; +<<<<<<< HEAD type WeightInfo = multi_block::weights::westend::MultiBlockWeightInfo; +======= + type Signed = MultiBlockElectionSigned; + type WeightInfo = weights::pallet_election_provider_multi_block::WeightInfo; +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } impl multi_block::verifier::Config for Runtime { @@ -501,3 +506,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 new file mode 100644 index 0000000000000..7c95246f9adfb --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block.rs @@ -0,0 +1,263 @@ +// 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. + +//! 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-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm +// --pallet=pallet_election_provider_multi_block +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_election_provider_multi_block`. +pub struct WeightInfo(PhantomData); +impl pallet_election_provider_multi_block::WeightInfo for WeightInfo { + /// 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`) + fn per_block_nothing() -> Weight { + // Proof Size summary in bytes: + // 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) + /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// 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:1001 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) + /// 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 per_block_snapshot_msp() -> Weight { + // Proof Size summary in bytes: + // 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) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `VoterList::ListBags` (r:1 w:0) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, 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: `Staking::Validators` (r:103 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: `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 per_block_snapshot_rest() -> Weight { + // Proof Size summary in bytes: + // 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: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (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 per_block_start_signed_validation() -> Weight { + // Proof Size summary in bytes: + // 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) + /// 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: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, 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::ErasTotalStake` (r:1 w:1) + /// Proof: `Staking::ErasTotalStake` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `Measured`) + fn export_non_terminal() -> Weight { + // Proof Size summary in bytes: + // Measured: `1479` + // Estimated: `4944` + // 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)) + } + /// 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:1) + /// Proof: `MultiBlockElection::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:32 w:32) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:32 w:32) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshotHash` (r:32 w:32) + /// 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(32026), added: 34501, 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::ErasTotalStake` (r:1 w:1) + /// Proof: `Staking::ErasTotalStake` (`max_values`: None, `max_size`: Some(28), added: 2503, 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: `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: `4847` + // Estimated: `85037` + // 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)) + } + /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) + /// 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: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionY` (r:0 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + fn manage_fallback() -> Weight { + // Proof Size summary in bytes: + // Measured: `372173` + // Estimated: `375638` + // 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)) + } + /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) + /// 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: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionY` (r:0 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + fn admin_set() -> Weight { + // Proof Size summary in bytes: + // Measured: `308` + // Estimated: `3773` + // 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 new file mode 100644 index 0000000000000..2f38e49209338 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_signed.rs @@ -0,0 +1,197 @@ +// 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. + +//! 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-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm +// --pallet=pallet_election_provider_multi_block::signed +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_election_provider_multi_block::signed`. +pub struct WeightInfo(PhantomData); +impl 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:0 w:1) + /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) + fn register_not_full() -> Weight { + // Proof Size summary in bytes: + // Measured: `3252` + // Estimated: `6717` + // 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)) + } + /// 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) + /// Storage: `Balances::Holds` (r:2 w:2) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:2) + /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:32 w:32) + /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(46478), added: 48953, mode: `Measured`) + fn register_eject() -> Weight { + // Proof Size summary in bytes: + // Measured: `7851` + // Estimated: `88041` + // 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)) + } + /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) + /// 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::SubmissionMetadataStorage` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, 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: `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) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(46478), added: 48953, mode: `Measured`) + fn submit_page() -> Weight { + // Proof Size summary in bytes: + // Measured: `3785` + // Estimated: `7250` + // 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)) + } + /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) + /// 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::SubmissionMetadataStorage` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, 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: `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) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(265), added: 2740, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionStorage` (r:1 w:1) + /// Proof: `MultiBlockElectionSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(46478), added: 48953, mode: `Measured`) + fn unset_page() -> Weight { + // Proof Size summary in bytes: + // Measured: `3887` + // Estimated: `7352` + // 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)) + } + /// Storage: `MultiBlockElection::CurrentPhase` (r:1 w:0) + /// 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: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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:1) + /// 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`) + fn bail() -> Weight { + // Proof Size summary in bytes: + // Measured: `4717` + // Estimated: `84907` + // 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)) + } + /// 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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:1) + /// 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: `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: `3709 + p * (32 ±0)` + // Estimated: `7174 + p * (2507 ±0)` + // Minimum execution time: 86_306_000 picoseconds. + Weight::from_parts(88_268_158, 0) + .saturating_add(Weight::from_parts(0, 7174)) + // 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)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) + .saturating_add(Weight::from_parts(0, 2507).saturating_mul(p.into())) + } +} 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 new file mode 100644 index 0000000000000..4a6ae8a0de7e7 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_unsigned.rs @@ -0,0 +1,104 @@ +// 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. + +//! 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-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm +// --pallet=pallet_election_provider_multi_block::unsigned +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_election_provider_multi_block::unsigned`. +pub struct WeightInfo(PhantomData); +impl pallet_election_provider_multi_block::unsigned::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: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (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: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::MinimumScore` (r:1 w:0) + /// Proof: `MultiBlockElectionVerifier::MinimumScore` (`max_values`: Some(1), `max_size`: Some(48), added: 543, 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 `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) + fn validate_unsigned() -> Weight { + // Proof Size summary in bytes: + // Measured: `351` + // Estimated: `3816` + // 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)) + } + /// Storage: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x33ed3d010c1fea25c2adbfba9297161f` (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: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// 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(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:2 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `MultiBlockElectionVerifier::QueuedSolutionY` (r:0 w:2) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + fn submit_unsigned() -> Weight { + // Proof Size summary in bytes: + // Measured: `760999` + // Estimated: `766939` + // 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 new file mode 100644 index 0000000000000..7395024b39471 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_election_provider_multi_block_verifier.rs @@ -0,0 +1,205 @@ +// 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. + +//! 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-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `dc396778ddb0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm +// --pallet=pallet_election_provider_multi_block::verifier +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_election_provider_multi_block::verifier`. +pub struct WeightInfo(PhantomData); +impl pallet_election_provider_multi_block::verifier::WeightInfo for WeightInfo { + /// 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: `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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `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 verification_valid_non_terminal() -> Weight { + // Proof Size summary in bytes: + // 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) + /// 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: `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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// Proof: `MultiBlockElection::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedValidVariant` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedValidVariant` (`max_values`: None, `max_size`: Some(13), added: 2488, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:33 w:32) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionScore` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:1) + /// 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: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + fn verification_valid_terminal() -> Weight { + // Proof Size summary in bytes: + // 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) + /// 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: `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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:33 w:32) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:1) + /// 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: `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`) + fn verification_invalid_terminal() -> Weight { + // Proof Size summary in bytes: + // 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) + /// 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: `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(46478), added: 48953, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `MultiBlockElectionVerifier::QueuedSolutionX` (r:31 w:31) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionBackings` (r:31 w:31) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionBackings` (`max_values`: None, `max_size`: Some(52026), added: 54501, mode: `Measured`) + /// Storage: `MultiBlockElectionSigned::SubmissionMetadataStorage` (r:1 w:1) + /// 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: `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 verification_invalid_non_terminal(v: u32, ) -> Weight { + // Proof Size summary in bytes: + // 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()))) + .saturating_add(Weight::from_parts(0, 2550).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 f818cfc43ce11..190815804a228 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::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 236f42217cbfe..35273535cc46e 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,6 +199,10 @@ #[cfg(any(feature = "runtime-benchmarks", test))] use crate::signed::{CalculateBaseDeposit, CalculatePageDeposit}; +<<<<<<< HEAD +======= +use crate::verifier::{AsynchronousVerifier, Verifier}; +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) use codec::{Decode, Encode, MaxEncodedLen}; use frame_election_provider_support::{ onchain, BoundedSupportsOf, DataProviderBounds, ElectionDataProvider, ElectionProvider, @@ -205,6 +211,7 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{Defensive, EnsureOrigin}, + weights::WeightMeter, DebugNoBound, Twox64Concat, }; use frame_system::pallet_prelude::*; @@ -270,8 +277,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> { @@ -323,8 +330,8 @@ impl ElectionProvider for Continue { Zero::zero() } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } @@ -526,8 +533,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>; @@ -583,6 +589,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. type AdminOrigin: EnsureOrigin; @@ -660,51 +669,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 } } @@ -784,10 +811,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. @@ -1199,6 +1235,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, @@ -1210,6 +1371,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); @@ -1389,6 +1553,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 @@ -1400,7 +1730,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; } @@ -1413,7 +1743,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 { @@ -1502,21 +1832,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 { @@ -1531,12 +1864,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); } } @@ -1614,20 +1943,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())) + }, } } @@ -1644,7 +1979,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; #[test] @@ -1967,6 +2302,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() @@ -2171,18 +2582,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)); }); } @@ -2198,36 +2605,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)); @@ -2304,7 +2696,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}; @@ -2334,7 +2726,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) @@ -2345,39 +2740,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. @@ -2400,7 +2782,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::>(); @@ -2414,8 +2796,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)); }); } @@ -2435,14 +2817,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), @@ -2463,7 +2844,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); @@ -2495,13 +2876,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), @@ -2539,7 +2919,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 @@ -2619,7 +2999,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)); }); @@ -2754,23 +3134,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 27846e813600b..08be971bbc901 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, 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); @@ -224,12 +229,13 @@ impl crate::Config for Runtime { type TargetSnapshotPerBlock = TargetSnapshotPerBlock; type VoterSnapshotPerBlock = VoterSnapshotPerBlock; type MinerConfig = Self; - type WeightInfo = (); type Verifier = VerifierPallet; type AdminOrigin = EnsureRoot; type Pages = Pages; type AreWeDone = AreWeDone; + type Signed = SignedPallet; type OnRoundRotation = CleanRound; + type WeightInfo = (); } parameter_types! { @@ -270,8 +276,8 @@ impl ElectionProvider for MockFallback { Ok(()) } - fn status() -> Result { - Ok(true) + fn status() -> Result, ()> { + Ok(Some(Default::default())) } } @@ -328,14 +334,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); @@ -651,11 +650,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)`). @@ -690,10 +685,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`). @@ -704,11 +706,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) @@ -740,19 +767,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 7326e58861471..468e9786f97f0 100644 --- a/substrate/frame/election-provider-multi-block/src/signed/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/signed/mod.rs @@ -114,6 +114,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; @@ -937,31 +943,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) @@ -1030,8 +1011,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. @@ -1042,7 +1022,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 cbd64adf84c7d..1e13593548001 100644 --- a/substrate/frame/election-provider-multi-block/src/signed/tests.rs +++ b/substrate/frame/election-provider-multi-block/src/signed/tests.rs @@ -523,19 +523,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), @@ -543,6 +574,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) @@ -552,14 +585,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), @@ -575,45 +607,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. @@ -673,7 +667,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 @@ -689,23 +682,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); }); } @@ -743,9 +735,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); @@ -761,10 +753,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!( @@ -783,9 +774,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() @@ -809,88 +799,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!( @@ -928,16 +905,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(), @@ -956,21 +933,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(), @@ -995,133 +971,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 @@ -1132,23 +994,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); @@ -1156,18 +1027,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), @@ -1178,15 +1046,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!( @@ -1201,19 +1069,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!( @@ -1222,34 +1090,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" @@ -1487,7 +1336,6 @@ mod invulnerables { let _ = signed_events_since_last_call(); roll_to_signed_validation_open(); - roll_next(); roll_to_full_verification(); assert_eq!( @@ -1509,9 +1357,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(); @@ -1559,6 +1406,50 @@ mod invulnerables { assert_eq!(new_deposit, 5); // Should not be fixed deposit anymore }); } +<<<<<<< HEAD +======= + + #[test] + fn slashed_invulnerable_is_not_expelled() { + ExtBuilder::signed().build_and_execute(|| { + roll_to_signed_open(); + assert_full_snapshot(); + make_invulnerable(99); + assert!(Invulnerables::::get().contains(&99)); + + let invalid_score = score_from(777); + assert_ok!(SignedPallet::register(RuntimeOrigin::signed(99), invalid_score)); + + roll_to_signed_validation_open(); + roll_to_full_verification(); + + // Check that rejection events were properly generated + assert_eq!( + verifier_events_since_last_call(), + vec![ + crate::verifier::Event::Verified(2, 0), // empty page + crate::verifier::Event::Verified(1, 0), // empty page + crate::verifier::Event::Verified(0, 0), // empty page + crate::verifier::Event::VerificationFailed(0, FeasibilityError::InvalidScore), + ] + ); + + // Check that expected events were emitted for the rejection + assert_eq!( + signed_events(), + vec![Event::Registered(0, 99, invalid_score), Event::Slashed(0, 99, 7)] /* slash + * amount + * is indeed + * the invulnerable + * deposit + * (7) ^^^^ */ + ); + + // Verify invulnerable is not expelled. It remains in the list despite being slashed. + assert!(Invulnerables::::get().contains(&99)); + }); + } +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } mod defensive_tests { @@ -1580,12 +1471,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![ @@ -1598,16 +1483,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 c566e47e917cd..6f8fadac18d3f 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 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 574ae8db790a1..d3de3180b96a7 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,29 @@ mod benchmarks { Ok(()) } +<<<<<<< HEAD +======= + /// 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)] + crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value()); + crate::Pallet::::start().unwrap(); + + // roll to unsigned phase open + crate::Pallet::::roll_until_matches(|| { + matches!(CurrentPhase::::get(), Phase::Unsigned(_)) + }); + + #[block] + { + OffchainWorkerMiner::::mine_solution(p, true).unwrap(); + } + + Ok(()) + } + +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) impl_benchmark_test_suite!( Pallet, crate::mock::ExtBuilder::full().build_unchecked(), 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 6f425711e9ec0..be0ba449d835b 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 f382e37de98f7..e0bb4b62da463 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::*; @@ -612,10 +612,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) @@ -624,11 +620,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!( @@ -638,27 +644,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( @@ -666,7 +674,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()) }, } } @@ -675,9 +684,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. @@ -688,12 +697,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( @@ -990,6 +1001,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 5919ea30050ed..5e9b5de1fc60b 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() @@ -75,6 +76,7 @@ pub mod traits { fn submit_unsigned() -> Weight; } + #[cfg(feature = "std")] impl WeightInfo for () { fn validate_unsigned() -> Weight { Default::default() @@ -90,24 +92,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) } } } @@ -117,35 +120,28 @@ 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 manage() -> 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 80f3bfb6aba00..8f7bbed1212f9 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // dot_size // --template @@ -63,6 +71,7 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) @@ -80,12 +89,27 @@ impl crate::weights::traits::pallet_election_provider_m // Minimum execution time: 25_691_000 picoseconds. Weight::from_parts(26_460_000, 3649) .saturating_add(T::DbWeight::get().reads(5_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`) + fn per_block_nothing() -> Weight { + // Proof Size summary in bytes: + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::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: `MultiBlock::Round` (r:1 w:0) @@ -94,6 +118,7 @@ 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:1001 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) +<<<<<<< HEAD /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) @@ -119,6 +144,29 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::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: `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 per_block_snapshot_msp() -> Weight { + // Proof Size summary in bytes: + // 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) @@ -135,6 +183,7 @@ impl crate::weights::traits::pallet_election_provider_m /// 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`) +<<<<<<< HEAD /// Storage: `Staking::Validators` (r:216 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) @@ -149,10 +198,17 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshotHash` (r:0 w:1) /// Proof: `MultiBlock::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) +======= + /// Storage: `Staking::Validators` (r:261 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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`) +<<<<<<< HEAD fn on_initialize_into_snapshot_rest() -> Weight { // Proof Size summary in bytes: // Measured: `1465538` @@ -213,10 +269,28 @@ impl crate::weights::traits::pallet_election_provider_m } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, 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 per_block_snapshot_rest() -> Weight { + // Proof Size summary in bytes: + // 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) + /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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) +<<<<<<< HEAD /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) @@ -256,6 +330,22 @@ impl crate::weights::traits::pallet_election_provider_m Weight::from_parts(3_912_487_000, 3843) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) +======= + /// 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 per_block_start_signed_validation() -> Weight { + // Proof Size summary in bytes: + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) @@ -282,13 +372,20 @@ 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: +<<<<<<< HEAD // Measured: `169940` // Estimated: `1386155` // Minimum execution time: 13_245_264_000 picoseconds. Weight::from_parts(13_291_774_000, 1386155) +======= + // Measured: `167757` + // Estimated: `1383972` + // Minimum execution time: 14_054_590_000 picoseconds. + Weight::from_parts(14_923_170_000, 1383972) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().reads(991_u64)) .saturating_add(T::DbWeight::get().writes(1475_u64)) } @@ -318,8 +415,13 @@ 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:498 w:498) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) +<<<<<<< HEAD /// Storage: `Staking::ErasStakersPaged` (r:498 w:511) /// 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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:498 w:0) @@ -334,12 +436,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) fn export_terminal() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `1130014` // Estimated: `2363554` // Minimum execution time: 27_990_573_000 picoseconds. Weight::from_parts(33_969_464_000, 2363554) .saturating_add(T::DbWeight::get().reads(1600_u64)) .saturating_add(T::DbWeight::get().writes(1613_u64)) +======= + // 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(1036_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } fn manage() -> Weight { // Proof Size summary in bytes: 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 5361e28dcaa13..8daccee954d9a 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // ksm_size // --template @@ -63,6 +71,7 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) @@ -80,18 +89,34 @@ impl crate::weights::traits::pallet_election_provider_m // Minimum execution time: 25_161_000 picoseconds. Weight::from_parts(25_770_000, 3649) .saturating_add(T::DbWeight::get().reads(5_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`) + fn per_block_nothing() -> Weight { + // Proof Size summary in bytes: + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::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: `MultiBlock::Round` (r:1 w:0) /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `Staking::CounterForValidators` (r:1 w:0) /// Proof: `Staking::CounterForValidators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) +<<<<<<< HEAD /// Storage: `Staking::Validators` (r:1001 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) @@ -119,6 +144,31 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::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: `Staking::Validators` (r:2501 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) + /// 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(80026), added: 82501, mode: `Measured`) + fn per_block_snapshot_msp() -> Weight { + // Proof Size summary in bytes: + // 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `Staking::VoterSnapshotStatus` (r:1 w:1) @@ -135,6 +185,7 @@ impl crate::weights::traits::pallet_election_provider_m /// 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`) +<<<<<<< HEAD /// Storage: `Staking::Validators` (r:395 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) @@ -149,10 +200,17 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshotHash` (r:0 w:1) /// Proof: `MultiBlock::PagedVoterSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) +======= + /// Storage: `Staking::Validators` (r:455 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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`) +<<<<<<< HEAD fn on_initialize_into_snapshot_rest() -> Weight { // Proof Size summary in bytes: // Measured: `1460572` @@ -209,10 +267,28 @@ impl crate::weights::traits::pallet_election_provider_m } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, 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 per_block_snapshot_rest() -> Weight { + // Proof Size summary in bytes: + // 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) + /// Proof: `MultiBlockElection::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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) +<<<<<<< HEAD /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:0) /// Proof: `MultiBlockVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) @@ -252,6 +328,22 @@ impl crate::weights::traits::pallet_election_provider_m Weight::from_parts(2_392_569_000, 3843) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) +======= + /// 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 per_block_start_signed_validation() -> Weight { + // Proof Size summary in bytes: + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) @@ -269,6 +361,7 @@ 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`) +<<<<<<< HEAD /// Storage: `Staking::ErasStakersOverview` (r:829 w:829) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) /// Storage: `Staking::ErasTotalStake` (r:1 w:1) @@ -287,6 +380,26 @@ impl crate::weights::traits::pallet_election_provider_m Weight::from_parts(23_424_133_000, 2221345) .saturating_add(T::DbWeight::get().reads(1667_u64)) .saturating_add(T::DbWeight::get().writes(2467_u64)) +======= + /// 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:773 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `Measured`) + /// 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: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: `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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) @@ -300,6 +413,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) +<<<<<<< HEAD /// Storage: `MultiBlock::PagedVoterSnapshot` (r:16 w:16) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshotHash` (r:16 w:16) @@ -308,10 +422,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedTargetSnapshotHash` (r:1 w:1) /// Proof: `MultiBlock::PagedTargetSnapshotHash` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `Measured`) +======= + /// Storage: `MultiBlockElection::PagedVoterSnapshot` (r:16 w:16) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) + /// 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(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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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`) +<<<<<<< HEAD /// Storage: `Staking::ErasStakersOverview` (r:955 w:955) /// Proof: `Staking::ErasStakersOverview` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `Measured`) /// Storage: `Staking::ErasStakersPaged` (r:955 w:956) @@ -323,6 +448,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlock::DesiredTargets` (r:0 w:1) /// Proof: `MultiBlock::DesiredTargets` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `Measured`) /// Storage: `Staking::ErasValidatorPrefs` (r:0 w:955) +======= + /// 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: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: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:571) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Proof: `Staking::ErasValidatorPrefs` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:0 w:1) /// Proof: `MultiBlockVerifier::StatusStorage` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) @@ -330,12 +470,21 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) fn export_terminal() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `1918340` // Estimated: `4282955` // Minimum execution time: 50_064_025_000 picoseconds. Weight::from_parts(50_383_919_000, 4282955) .saturating_add(T::DbWeight::get().reads(2923_u64)) .saturating_add(T::DbWeight::get().writes(2924_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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } fn manage() -> Weight { // Proof Size summary in bytes: 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 a03718223d998..538c854ae82e3 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // dot_size // --template @@ -63,12 +71,23 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block_signed`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_signed::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +======= + /// 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) @@ -77,6 +96,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) fn register_not_full() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `3074` // Estimated: `6539` // Minimum execution time: 139_781_000 picoseconds. @@ -90,6 +110,23 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +======= + // Measured: `3312` + // Estimated: `6777` + // 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:2 w:2) @@ -100,11 +137,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) fn register_eject() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `7674` // Estimated: `87864` // Minimum execution time: 345_362_000 picoseconds. Weight::from_parts(351_381_000, 87864) .saturating_add(T::DbWeight::get().reads(39_u64)) +======= + // Measured: `7846` + // Estimated: `88036` + // Minimum execution time: 314_814_000 picoseconds. + Weight::from_parts(323_504_000, 88036) + .saturating_add(T::DbWeight::get().reads(40_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(37_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -115,19 +160,34 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::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) +<<<<<<< HEAD /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, 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: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockSigned::SubmissionStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) fn submit_page() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `3607` // Estimated: `7072` // Minimum execution time: 6_454_547_000 picoseconds. Weight::from_parts(6_585_090_000, 7072) .saturating_add(T::DbWeight::get().reads(7_u64)) +======= + // Measured: `3845` + // Estimated: `7310` + // Minimum execution time: 313_002_000 picoseconds. + Weight::from_parts(329_092_000, 7310) + .saturating_add(T::DbWeight::get().reads(8_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -138,19 +198,34 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::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) +<<<<<<< HEAD /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, 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: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockSigned::SubmissionStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(45072), added: 47547, mode: `Measured`) fn unset_page() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `15537` // Estimated: `19002` // Minimum execution time: 6_424_309_000 picoseconds. Weight::from_parts(8_822_282_000, 19002) .saturating_add(T::DbWeight::get().reads(7_u64)) +======= + // Measured: `6737` + // Estimated: `10202` + // Minimum execution time: 262_482_000 picoseconds. + Weight::from_parts(288_781_000, 10202) + .saturating_add(T::DbWeight::get().reads(8_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -169,10 +244,17 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn bail() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `4539` // Estimated: `84729` // Minimum execution time: 230_051_000 picoseconds. Weight::from_parts(232_931_000, 84729) +======= + // Measured: `4777` + // Estimated: `84967` + // Minimum execution time: 204_581_000 picoseconds. + Weight::from_parts(206_781_000, 84967) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().reads(38_u64)) .saturating_add(T::DbWeight::get().writes(35_u64)) } @@ -187,6 +269,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `p` is `[1, 32]`. fn clear_old_round_data(p: u32, ) -> Weight { @@ -198,6 +281,21 @@ impl crate::weights::traits::pallet_election_provider_m // Standard Error: 17_673 .saturating_add(Weight::from_parts(1_930_735, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) +======= + /// 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: `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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .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 6d122aa221535..110cbd1fd2ad3 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // ksm_size // --template @@ -63,12 +71,23 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block_signed`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_signed::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlock::Round` (r:1 w:0) /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +======= + /// 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) @@ -77,6 +96,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) fn register_not_full() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `3140` // Estimated: `6605` // Minimum execution time: 139_291_000 picoseconds. @@ -90,6 +110,23 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:1) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +======= + // Measured: `3180` + // Estimated: `6645` + // 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) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:2 w:2) @@ -100,11 +137,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) fn register_eject() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `7072` // Estimated: `47662` // Minimum execution time: 308_522_000 picoseconds. Weight::from_parts(314_313_000, 47662) .saturating_add(T::DbWeight::get().reads(23_u64)) +======= + // Measured: `7144` + // Estimated: `47734` + // Minimum execution time: 289_301_000 picoseconds. + Weight::from_parts(297_421_000, 47734) + .saturating_add(T::DbWeight::get().reads(24_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(21_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -115,19 +160,34 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::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) +<<<<<<< HEAD /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, 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: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockSigned::SubmissionStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) fn submit_page() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `3657` // Estimated: `7122` // Minimum execution time: 2_269_015_000 picoseconds. Weight::from_parts(3_552_353_000, 7122) .saturating_add(T::DbWeight::get().reads(7_u64)) +======= + // Measured: `3697` + // Estimated: `7162` + // Minimum execution time: 286_851_000 picoseconds. + Weight::from_parts(298_461_000, 7162) + .saturating_add(T::DbWeight::get().reads(8_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -138,19 +198,34 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockSigned::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) +<<<<<<< HEAD /// Storage: `MultiBlockSigned::SortedScores` (r:1 w:0) /// Proof: `MultiBlockSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, 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: `MultiBlockElectionSigned::SortedScores` (r:1 w:0) + /// Proof: `MultiBlockElectionSigned::SortedScores` (`max_values`: None, `max_size`: Some(653), added: 3128, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockSigned::SubmissionStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionStorage` (`max_values`: None, `max_size`: Some(50064), added: 52539, mode: `Measured`) fn unset_page() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `17806` // Estimated: `21271` // Minimum execution time: 3_049_939_000 picoseconds. Weight::from_parts(3_492_703_000, 21271) .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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `MultiBlock::CurrentPhase` (r:1 w:0) @@ -169,10 +244,17 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn bail() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `4070` // Estimated: `44660` // Minimum execution time: 195_501_000 picoseconds. Weight::from_parts(197_231_000, 44660) +======= + // Measured: `4110` + // Estimated: `44700` + // Minimum execution time: 180_681_000 picoseconds. + Weight::from_parts(181_711_000, 44700) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(19_u64)) } @@ -187,6 +269,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `p` is `[1, 16]`. fn clear_old_round_data(p: u32, ) -> Weight { @@ -198,6 +281,21 @@ impl crate::weights::traits::pallet_election_provider_m // Standard Error: 49_308 .saturating_add(Weight::from_parts(1_794_932, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) +======= + /// 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: `3624 + p * (31 ±0)` + // Estimated: `7089 + p * (2507 ±0)` + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .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 c5a0eea5db430..b4ea22df75489 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // dot_size // --template @@ -79,11 +87,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) fn validate_unsigned() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `365` // Estimated: `3830` // Minimum execution time: 2_976_183_000 picoseconds. Weight::from_parts(4_693_571_000, 3830) .saturating_add(T::DbWeight::get().reads(7_u64)) +======= + // Measured: `378` + // Estimated: `3843` + // Minimum execution time: 872_562_000 picoseconds. + Weight::from_parts(884_363_000, 3843) + .saturating_add(T::DbWeight::get().reads(8_u64)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) @@ -107,11 +123,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) fn submit_unsigned() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `1462493` // Estimated: `1473383` // Minimum execution time: 32_392_063_000 picoseconds. Weight::from_parts(35_743_638_000, 1473383) .saturating_add(T::DbWeight::get().reads(12_u64)) +======= + // Measured: `1451085` + // Estimated: `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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(5_u64)) } } 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 7635b9cf4cdfe..596c9c306c260 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // ksm_size // --template @@ -79,14 +87,23 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) fn validate_unsigned() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `365` // Estimated: `3830` // Minimum execution time: 3_958_575_000 picoseconds. Weight::from_parts(3_984_285_000, 3830) .saturating_add(T::DbWeight::get().reads(7_u64)) +======= + // Measured: `378` + // Estimated: `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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } /// Storage: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) /// Proof: UNKNOWN KEY `0xa143099d7a337c5fd879b91b2b157c2d` (r:1 w:0) +<<<<<<< HEAD /// Storage: `MultiBlock::Round` (r:1 w:0) /// Proof: `MultiBlock::Round` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) /// Storage: `MultiBlockVerifier::QueuedSolutionScore` (r:1 w:1) @@ -97,6 +114,20 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:4 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, 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::QueuedSolutionScore` (r:1 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionScore` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `Measured`) + /// 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(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) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -107,11 +138,19 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlockVerifier::QueuedSolutionY` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) fn submit_unsigned() -> Weight { // Proof Size summary in bytes: +<<<<<<< HEAD // Measured: `1395131` // Estimated: `1406021` // Minimum execution time: 32_324_705_000 picoseconds. Weight::from_parts(32_944_719_000, 1406021) .saturating_add(T::DbWeight::get().reads(12_u64)) +======= + // 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)) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().writes(5_u64)) } } 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 a53ef8dc7c158..eaf512bce8682 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // dot_size // --template @@ -63,6 +71,7 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block_verifier`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_verifier::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:1) @@ -118,6 +127,63 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +======= + /// 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: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: `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:1 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) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `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 verification_valid_non_terminal() -> Weight { + // Proof Size summary in bytes: + // 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: `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:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -131,6 +197,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) @@ -163,6 +230,38 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +======= + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) + fn verification_valid_terminal() -> Weight { + // Proof Size summary in bytes: + // 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: `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:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -174,6 +273,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockVerifier::QueuedSolutionX` (r:31 w:32) /// Proof: `MultiBlockVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(33794026), added: 33796501, mode: `Measured`) @@ -187,9 +287,23 @@ impl crate::weights::traits::pallet_election_provider_m // Estimated: `1306877` // Minimum execution time: 31_394_976_000 picoseconds. Weight::from_parts(32_094_625_000, 1306877) +======= + /// 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`) + fn verification_invalid_terminal() -> Weight { + // Proof Size summary in bytes: + // Measured: `1185528` + // Estimated: `1268193` + // Minimum execution time: 17_116_788_000 picoseconds. + Weight::from_parts(17_320_458_000, 1268193) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().reads(110_u64)) - .saturating_add(T::DbWeight::get().writes(101_u64)) + .saturating_add(T::DbWeight::get().writes(102_u64)) } +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:1) @@ -206,6 +320,26 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +======= + /// 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: `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:1 w:0) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(388785), added: 391260, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -219,24 +353,43 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(181), added: 2656, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) +======= + /// 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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: +<<<<<<< HEAD // Measured: `353985 + v * (2260 ±0)` // Estimated: `459489 + v * (3052 ±323)` // Minimum execution time: 1_115_777_000 picoseconds. Weight::from_parts(1_305_809_580, 459489) // Standard Error: 631_886 .saturating_add(Weight::from_parts(4_251_321, 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())) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .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()))) +<<<<<<< HEAD .saturating_add(Weight::from_parts(0, 3052).saturating_mul(v.into())) +======= + .saturating_add(Weight::from_parts(0, 2961).saturating_mul(v.into())) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } } 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 63e4fecc7dd25..7941b23a990c8 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,11 @@ // ! we don't want to generate the `trait WeightInfo`. //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +<<<<<<< HEAD //! DATE: 2025-05-30, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +======= +//! DATE: 2025-10-08, STEPS: `10`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `AMD EPYC 7232P 8-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -41,7 +45,11 @@ // --steps // 10 // --repeat +<<<<<<< HEAD // 20 +======= +// 10 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) // --genesis-builder-preset // ksm_size // --template @@ -63,6 +71,7 @@ use core::marker::PhantomData; /// Weights for `pallet_election_provider_multi_block_verifier`. pub struct WeightInfo(PhantomData); impl crate::weights::traits::pallet_election_provider_multi_block_verifier::WeightInfo for WeightInfo { +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:1) @@ -118,6 +127,63 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +======= + /// 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: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: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// 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) + /// 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) + /// Storage: `MultiBlockElection::DesiredTargets` (r:1 w:0) + /// 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: `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 verification_valid_non_terminal() -> Weight { + // Proof Size summary in bytes: + // 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: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// 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) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -131,6 +197,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) @@ -163,6 +230,38 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +======= + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `Measured`) + /// Storage: `MultiBlockElectionVerifier::QueuedSolutionX` (r:0 w:1) + /// Proof: `MultiBlockElectionVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) + fn verification_valid_terminal() -> Weight { + // Proof Size summary in bytes: + // 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: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// 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) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -174,6 +273,7 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `MultiBlockVerifier::QueuedSolutionX` (r:15 w:16) /// Proof: `MultiBlockVerifier::QueuedSolutionX` (`max_values`: None, `max_size`: Some(37538026), added: 37540501, mode: `Measured`) @@ -187,9 +287,23 @@ impl crate::weights::traits::pallet_election_provider_m // Estimated: `1240303` // Minimum execution time: 31_537_693_000 picoseconds. Weight::from_parts(31_987_188_000, 1240303) +======= + /// 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`) + fn verification_invalid_terminal() -> Weight { + // Proof Size summary in bytes: + // Measured: `1123504` + // Estimated: `1166569` + // Minimum execution time: 17_623_388_000 picoseconds. + Weight::from_parts(18_013_619_000, 1166569) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .saturating_add(T::DbWeight::get().reads(62_u64)) - .saturating_add(T::DbWeight::get().writes(53_u64)) + .saturating_add(T::DbWeight::get().writes(54_u64)) } +<<<<<<< HEAD /// Storage: `MultiBlock::CurrentPhase` (r:1 w:1) /// Proof: `MultiBlock::CurrentPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `Measured`) /// Storage: `MultiBlockVerifier::StatusStorage` (r:1 w:1) @@ -206,6 +320,26 @@ impl crate::weights::traits::pallet_election_provider_m /// Proof: `MultiBlock::PagedTargetSnapshot` (`max_values`: None, `max_size`: Some(32026), added: 34501, mode: `Measured`) /// Storage: `MultiBlock::PagedVoterSnapshot` (r:1 w:0) /// Proof: `MultiBlock::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +======= + /// 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: `MultiBlockElection::PagedTargetSnapshot` (r:1 w:0) + /// 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) + /// Proof: `MultiBlockElection::PagedVoterSnapshot` (`max_values`: None, `max_size`: Some(431919), added: 434394, mode: `Measured`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// Storage: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Proof: UNKNOWN KEY `0x6f320d44e42312c78638e6c92dff65af` (r:1 w:0) /// Storage: `MultiBlock::DesiredTargets` (r:1 w:0) @@ -219,22 +353,41 @@ impl crate::weights::traits::pallet_election_provider_m /// Storage: `MultiBlockSigned::SubmissionMetadataStorage` (r:1 w:1) /// Proof: `MultiBlockSigned::SubmissionMetadataStorage` (`max_values`: None, `max_size`: Some(165), added: 2640, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) +<<<<<<< HEAD /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Proof: UNKNOWN KEY `0x48384a816e4f71a936cb76dc9e303f2a` (r:1 w:0) /// Storage: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) /// Proof: UNKNOWN KEY `0xc209f5d8eb920681b56c64b8694ea78c` (r:1 w:0) +======= + /// 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`) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) /// 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: +<<<<<<< HEAD // Measured: `372628 + v * (6011 ±0)` // Estimated: `385475 + v * (7288 ±1_424)` // Minimum execution time: 1_318_647_000 picoseconds. Weight::from_parts(4_794_918_600, 385475) +======= + // 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())) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) .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()))) +<<<<<<< HEAD .saturating_add(Weight::from_parts(0, 7288).saturating_mul(v.into())) +======= + .saturating_add(Weight::from_parts(0, 813).saturating_mul(v.into())) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) } } 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 4d50d9934710d..66547fd26cd68 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 462e9ef41e515..52dc61b088a15 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 { @@ -271,9 +284,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 { @@ -282,17 +296,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! { @@ -312,7 +330,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! { @@ -362,7 +380,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 { @@ -536,6 +554,7 @@ impl ExtBuilder { parameter_types! { static StakingEventsIndex: usize = 0; static ElectionEventsIndex: usize = 0; + static VerifierEventsIndex: usize = 0; static RcClientEventsIndex: usize = 0; } @@ -572,3 +591,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 new file mode 100644 index 0000000000000..01891effbd327 --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/src/cmd.ts @@ -0,0 +1,171 @@ +import { spawn, spawnSync } from "child_process"; +import { Presets } from "./index"; +import { logger } from "./utils"; +import { join } from "path"; +import stripAnsi from "strip-ansi"; +import { createWriteStream } from "fs"; + +export function rcPresetFor(paraPreset: Presets): string { + return paraPreset == Presets.FakeDev || + paraPreset == Presets.FakeDot || + paraPreset == Presets.FakeKsm + ? "fake-s" + : paraPreset; +} + +export function znConfigFor(paraPreset: Presets): string { + return paraPreset == Presets.RealM ? "../zn-m.toml" : "../zn-s.toml"; +} + +/// Returns the parachain log file. +export async function runPreset(paraPreset: Presets): Promise { + prepPreset(paraPreset); + const znConfig = znConfigFor(paraPreset); + logger.info(`Launching ZN config for preset: ${paraPreset}, config: ${znConfig}`); + cmd("zombienet", ["--provider", "native", "-l", "text", "spawn", znConfig], "inherit"); +} + +export async function runPresetUntilLaunched( + paraPreset: Presets +): Promise<{ killZn: () => void; paraLog: string | null }> { + prepPreset(paraPreset); + const znConfig = znConfigFor(paraPreset); + logger.info(`Launching ZN config for preset: ${paraPreset}, config: ${znConfig}`); + const child = spawn("zombienet", ["--provider", "native", "-l", "text", "spawn", znConfig], { + stdio: "pipe", + cwd: __dirname, + }); + + return new Promise<{ killZn: () => void; paraLog: string | null }>((resolve, reject) => { + const logCmds: string[] = []; + child.stdout.on("data", (data) => { + const raw: string = stripAnsi(data.toString()); + if (raw.includes("Log Cmd : ")) { + raw.split("\n") + .filter((line) => line.includes("Log Cmd : ")) + .forEach((line) => { + logCmds.push(line.replace("Log Cmd : ", "").trim()); + }); + } + // our hacky way to know ZN is done. + if (raw.includes("Parachain ID : 1100")) { + for (const cmd of logCmds) { + logger.info(`${cmd}`); + } + logger.info(`Launched ZN: ${paraPreset}`); + + // 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: () => { + child.kill(); + logger.verbose(`Killed zn process`); + }, + paraLog, + }); + } + }); + + child.on("error", (err) => { + reject(err); + }); + }); +} + +export async function spawnMiner(): Promise<() => void> { + logger.info(`Spawning miner in background`); + + const logFile = createWriteStream(join(__dirname, "miner.log"), { flags: "a" }); + + const child = spawn( + "polkadot-staking-miner", + [ + "--uri", + "ws://127.0.0.1:9946", + "monitor", + "--seed-or-path", + "//Bob", + ], + { stdio: "pipe", cwd: __dirname } + ); + + child.stdout?.pipe(logFile); + child.stderr?.pipe(logFile); + + return new Promise<() => void>((resolve, reject) => { + child.on("error", (err) => { + logger.error(`Error in miner miner: ${err}`); + reject(err); + }); + resolve(() => { + logger.verbose(`Killing miner process`); + logFile.end(); + child.kill(); + }); + }); +} + +function prepPreset(paraPreset: Presets): void { + const rcPreset = rcPresetFor(paraPreset); + const targetDir = "../../../../../../target"; + + logger.info(`Running para-preset: ${paraPreset}, rc-preset: ${rcPreset}`); + cmd("cargo", [ + "build", + "--release", + `-p`, + `pallet-staking-async-rc-runtime`, + `-p`, + `pallet-staking-async-parachain-runtime`, + `-p`, + `staging-chain-spec-builder`, + ]); + + cmd("rm", ["-f", "./parachain.json"]); + cmd("rm", ["-f", "./rc.json"]); + + cmd(join(targetDir, "/release/chain-spec-builder"), [ + "create", + "-t", + "development", + "--runtime", + join( + targetDir, + "/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.compressed.wasm" + ), + "--relay-chain", + "rococo-local", + "--para-id", + "1100", + "named-preset", + paraPreset, + ]); + cmd("mv", ["chain_spec.json", "parachain.json"]); + + cmd(join(targetDir, "/release/chain-spec-builder"), [ + "create", + "-t", + "development", + "--runtime", + join( + targetDir, + "/release/wbuild/pallet-staking-async-rc-runtime/fast_runtime_binary.rs.wasm" + ), + "named-preset", + rcPreset, + ]); + cmd("mv", ["chain_spec.json", "rc.json"]); +} + +function cmd(cmd: string, args: string[], stdio: string = "ignore"): void { + logger.info(`Running command: ${cmd} ${args.join(" ")}`); + // @ts-ignore + const result = spawnSync(cmd, args, { stdio: stdio, cwd: __dirname }); + if (result.error || result.status !== 0) { + logger.error(`Error running command: ${cmd} ${args.join(" ")}`); + logger.error(`Status: ${result.status}`); + } +} diff --git a/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts b/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts new file mode 100644 index 0000000000000..6f8ca6690c79b --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/src/utils.ts @@ -0,0 +1,143 @@ +import { parachain, rc } from "@polkadot-api/descriptors"; +import { + Binary, + createClient, + type PolkadotClient, + type PolkadotSigner, + type TypedApi, +} from "polkadot-api"; +import { fromBufferToBase58 } from "@polkadot-api/substrate-bindings"; +import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat"; +import { getWsProvider } from "polkadot-api/ws-provider/web"; +import { createLogger, format, transports } from "winston"; +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 = 45 * 60 * 1000; +export const aliceStash = "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY"; + + +export const logger = createLogger({ + level: process.env.LOG_LEVEL || "verbose", + format: format.combine(format.timestamp(), format.cli()), + defaultMeta: { service: "staking-papi-tests" }, + transports: [new transports.Console()], +}); + +const miniSecret = entropyToMiniSecret(mnemonicToEntropy(DEV_PHRASE)); +const derive = sr25519CreateDerive(miniSecret); +const aliceKeyPair = derive("//Alice"); + +export const alice = getPolkadotSigner(aliceKeyPair.publicKey, "Sr25519", aliceKeyPair.sign); + +export function deriveFrom(s: string, d: string): KeyPair { + const miniSecret = entropyToMiniSecret(mnemonicToEntropy(s)); + const derive = sr25519CreateDerive(miniSecret); + return derive(d); +} + +export function derivePubkeyFrom(d: string): string { + const miniSecret = entropyToMiniSecret(mnemonicToEntropy(DEV_PHRASE)); + const derive = sr25519CreateDerive(miniSecret); + const keyPair = derive(d); + // Convert to SS58 address using Substrate format (42) + return ss58(keyPair.publicKey); +} + +export function ss58(key: Uint8Array): string { + return fromBufferToBase58(42)(key); +} + +export type ApiDeclarations = { + rcClient: PolkadotClient; + paraClient: PolkadotClient; + rcApi: TypedApi; + paraApi: TypedApi; +}; + +export async function nullifySigned( + paraApi: TypedApi, + signer: PolkadotSigner = alice +): Promise { + // signed and signed validation phase to 0 + const call = paraApi.tx.System.set_storage({ + items: [ + // SignedPhase key + [ + Binary.fromBytes( + Uint8Array.from([ + 99, 88, 172, 210, 3, 94, 196, 187, 134, 63, 169, 129, 224, 193, 119, 185, + ]) + ), + Binary.fromBytes(Uint8Array.from([0, 0, 0, 0])), + ], + // SignedValidation key + [ + Binary.fromBytes( + Uint8Array.from([ + 72, 56, 74, 129, 110, 79, 113, 169, 54, 203, 118, 220, 158, 48, 63, 42, + ]) + ), + Binary.fromBytes(Uint8Array.from([0, 0, 0, 0])), + ], + ], + }).decodedCall; + const res = await paraApi.tx.Sudo.sudo({ call }).signAndSubmit(alice); + return res.ok; +} + +export async function nullifyUnsigned( + paraApi: TypedApi, + signer: PolkadotSigner = alice +): Promise { + // signed and signed validation phase to 0 + const call = paraApi.tx.System.set_storage({ + items: [ + // UnsignedPhase key + [ + Binary.fromBytes( + Uint8Array.from([ + 194, 9, 245, 216, 235, 146, 6, 129, 181, 108, 100, 184, 105, 78, 167, 140, + ]) + ), + Binary.fromBytes(Uint8Array.from([0, 0, 0, 0])), + ], + ], + }).decodedCall; + const res = await paraApi.tx.Sudo.sudo({ call }).signAndSubmit(alice); + return res.ok; +} + +export async function getApis(): Promise { + const rcClient = createClient(withPolkadotSdkCompat(getWsProvider("ws://localhost:9945"))); + const rcApi = rcClient.getTypedApi(rc); + + const paraClient = createClient(withPolkadotSdkCompat(getWsProvider("ws://localhost:9946"))); + const paraApi = paraClient.getTypedApi(parachain); + + logger.info(`Connected to ${(await rcApi.constants.System.Version()).spec_name}`); + logger.info(`Connected to ${(await paraApi.constants.System.Version()).spec_name}`); + + return { rcApi, paraApi, rcClient, paraClient }; +} + +// Safely convert anything to a string so we can compare them. +export function safeJsonStringify(data: any): string { + const bigIntReplacer = (key: string, value: any): any => { + if (typeof value === "bigint") { + return value.toString(); + } + return value; + }; + + try { + return JSON.stringify(data, bigIntReplacer); + } catch (error: any) { + // Handle potential errors during stringification (e.g., circular references) + console.error("Error during JSON stringification:", error.message); + throw new Error( + "Failed to stringify data due to unsupported types or circular references." + ); + } +} 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 new file mode 100644 index 0000000000000..95e7a388f4a30 --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/example.test.ts @@ -0,0 +1,67 @@ +import { test, expect } from "bun:test"; +import { Presets } from "../src"; +import { runPresetUntilLaunched } from "../src/cmd"; +import { Chain, EventOutcome, Observe, runTest, TestCase } from "../src/test-case"; +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.skip( + `example test with preset ${PRESET}`, + async () => { + /// We run the test with our defined preset. + const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); + /// Grab PAPI Apis to both relay and parachain instance of the ZN. + const apis = await getApis(); + + // Our test is defined here. We expect a sequence of events to be observed in RC or + // Parachain. The events that we can observe are defined in `test-case.ts`'s `runTest`. In + // short, they are all of the events related to staking. + const testCase = new TestCase( + [ + Observe.on(Chain.Relay, "Session", "NewSession") + // An event can be expected to happen by a certain block + .byBlock(11) + // And it can execute a callback when it passes. + .onPass(() => { + logger.verbose("New session observed on relay chain"); + }) + // and we can check the data of the event. + .withDataCheck((x: any) => { + logger.verbose("shall we check the data? maybe", x); + return true + }), + // add more `Observe`s here + ].map((s) => s.build()), + // Passing this to true will allow events to be _interleaved_. If set to `false`, the + // above sequence of events are expected to happen in a strict order. If `true`, the + // events of each `Chain` must happen in a strict order, but intra-chain events can come + // in any order. For example, assume we have the following 4 observes in our test case: + // 1. Observe.on(Chain.Relay, "Module", "Event1") + // 2. Observe.on(Chain.Relay, "Module", "Event2") + // 3. Observe.on(Chain.Para, "Module", "Event3") + // 4. Observe.on(Chain.Para, "Module", "Event4") + // + // Without interleaving, 1 -> 4 has to be observed as-is. + // + // With interleaving, at any point in time, the first unobserved event of each chain + // type is acceptable. For example, the following is valid: + // + // 3 -> 1 -> 4 -> 2 + // + // In some sense, with `interleave = true`, we break apart the test case into two stacks + // that need to be popped in order, while in interleave = false, it is one stack. + true, + // Something to happen when the test is over. Always kill ZN, and any other processes + // you might spawn. + () => { + killZn(); + } + ); + + const outcome = await runTest(testCase, apis, paraLog); + expect(outcome).toEqual(EventOutcome.Done); + }, + { timeout: GlobalTimeout } +); 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 new file mode 100644 index 0000000000000..efc62999eebe4 --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-dot.test.ts @@ -0,0 +1,31 @@ +import { test, expect } from "bun:test"; +import { Presets } from "../src"; +import { runPresetUntilLaunched, spawnMiner } from "../src/cmd"; +import { EventOutcome, runTest, TestCase } from "../src/test-case"; +import { getApis, GlobalTimeout} from "../src/utils"; +import { commonSignedSteps } from "./common"; + +const PRESET: Presets = Presets.FakeDot; + +test( + `signed solution on ${PRESET}`, + async () => { + 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, expectedValidatorSetCount, apis), + true, + () => { + killMiner(); + killZn(); + } + ); + + const outcome = await runTest(testCase, apis, paraLog); + expect(outcome).toEqual(EventOutcome.Done); + }, + { timeout: GlobalTimeout } +); 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 new file mode 100644 index 0000000000000..ad42d1683337d --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/signed-ksm.test.ts @@ -0,0 +1,31 @@ +import { test, expect } from "bun:test"; +import { Presets } from "../src"; +import { runPresetUntilLaunched, spawnMiner } from "../src/cmd"; +import { EventOutcome, runTest, TestCase } from "../src/test-case"; +import { getApis, GlobalTimeout } from "../src/utils"; +import { commonSignedSteps } from "./common"; + +const PRESET: Presets = Presets.FakeKsm; + +test( + `signed solution on ${PRESET}`, + async () => { + 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, expectedValidatorSetCount, apis), + true, + () => { + killMiner(); + killZn(); + } + ); + + const outcome = await runTest(testCase, apis, paraLog); + expect(outcome).toEqual(EventOutcome.Done); + }, + { timeout: GlobalTimeout } +); 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 new file mode 100644 index 0000000000000..6b6bf804d7cdc --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/tests/unsigned-dev.test.ts @@ -0,0 +1,26 @@ +import { test, expect } from "bun:test"; +import { Presets } from "../src"; +import { runPresetUntilLaunched } from "../src/cmd"; +import { EventOutcome, runTest, TestCase } from "../src/test-case"; +import { getApis, GlobalTimeout} from "../src/utils"; +import { commonUnsignedSteps } from "./common"; + +const PRESET: Presets = Presets.FakeDev; + +test( + `unsigned solution on ${PRESET}`, + async () => { + const { killZn, paraLog } = await runPresetUntilLaunched(PRESET); + + const apis = await getApis(); + const steps = commonUnsignedSteps(10, 4, 4, true, apis); + + const testCase = new TestCase(steps, true, () => { + killZn(); + }); + + const outcome = await runTest(testCase, apis, paraLog); + expect(outcome).toEqual(EventOutcome.Done); + }, + { timeout: GlobalTimeout } +); 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 5184baa966b02..fd8612b3e402f 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 @@ -186,7 +186,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 new file mode 100644 index 0000000000000..884fa6248d487 --- /dev/null +++ b/substrate/frame/staking-async/runtimes/papi-tests/zn-m.toml @@ -0,0 +1,39 @@ +[relaychain] +default_command = "polkadot" +chain_spec_path = "./rc.json" + +[[relaychain.nodes]] +name = "alice" +validator = true +rpc_port = 9942 + + +[[relaychain.nodes]] +name = "bob" +validator = true +rpc_port = 9943 +args = [ + "-lruntime::system=debug,runtime::session=trace,runtime::staking-async::ah-client=trace,runtime::ah-client=debug", +] + +[[relaychain.nodes]] +name = "eve" +validator = true +rpc_port = 9944 + +[[relaychain.nodes]] +name = "dave" +validator = true +rpc_port = 9945 + +[[parachains]] +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", +] diff --git a/substrate/frame/staking-async/runtimes/parachain/bench_all.sh b/substrate/frame/staking-async/runtimes/parachain/bench_all.sh index 7b022d326245a..1c70919f5b5df 100755 --- a/substrate/frame/staking-async/runtimes/parachain/bench_all.sh +++ b/substrate/frame/staking-async/runtimes/parachain/bench_all.sh @@ -2,16 +2,24 @@ 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 +<<<<<<< HEAD LOG="runtime::multiblock-election=debug,runtime::staking-async=debug,polkadot_sdk_frame::benchmark=debug" +======= +LOG="runtime::multiblock-election=info,runtime::staking-async=info,frame::benchmark=info" +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) if [[ "${NO_COMPILE}" == "1" ]]; then echo "Skipping compilation because 'NO_COMPILE' was set" else cargo build --release -p frame-omni-bencher +<<<<<<< HEAD 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 +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) fi WASM_BLOB_PATH=../../../../../target/release/wbuild/pallet-staking-async-parachain-runtime/pallet_staking_async_parachain_runtime.compact.wasm @@ -41,6 +49,7 @@ run_benchmark() { --output "$output_file" } +<<<<<<< HEAD # run_benchmark "pallet_staking_async" "dot_size" run_benchmark "pallet_election_provider_multi_block" "dot_size" run_benchmark "pallet_election_provider_multi_block_signed" "dot_size" @@ -52,3 +61,16 @@ run_benchmark "pallet_election_provider_multi_block" "ksm_size" run_benchmark "pallet_election_provider_multi_block_signed" "ksm_size" run_benchmark "pallet_election_provider_multi_block_unsigned" "ksm_size" run_benchmark "pallet_election_provider_multi_block_verifier" "ksm_size" +======= +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_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" +run_benchmark "pallet_election_provider_multi_block_verifier" "fake-ksm" +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) 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 5e2411011cac8..67dbdfe827d17 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 @@ -108,10 +108,39 @@ pub fn get_preset(id: &PresetId) -> Option> { dev_and_testnet_params.dev_stakers = Some((4_000, 20_000)); staking_async_parachain_genesis(dev_and_testnet_params) }, +<<<<<<< HEAD "dot_size" => { dev_and_testnet_params.validator_count = 500; dev_and_testnet_params.dev_stakers = Some((2_000, 25_000)); staking_async_parachain_genesis(dev_and_testnet_params) +======= + "real-m" => { + params.validator_count = 4; + // generate no new "fake" validators. + params.dev_stakers = Some((0, 2000)); + // set expected relay validators in genesis so they are elected + params.validators = vec![ + Sr25519Keyring::AliceStash.to_account_id(), + Sr25519Keyring::BobStash.to_account_id(), + Sr25519Keyring::EveStash.to_account_id(), + Sr25519Keyring::DaveStash.to_account_id(), + ]; + staking_async_parachain_genesis(params, id.to_string()) + }, + "fake-dev" => { + // nada + staking_async_parachain_genesis(params, id.to_string()) + }, + "fake-dot" => { + params.validator_count = 600; + params.dev_stakers = Some((2_500, 25_000)); + staking_async_parachain_genesis(params, id.to_string()) + }, + "fake-ksm" => { + params.validator_count = 1_000; + params.dev_stakers = Some((4_500, 15_000)); + staking_async_parachain_genesis(params, id.to_string()) +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) }, _ => panic!("unrecognized genesis preset!"), }; diff --git a/substrate/frame/staking-async/runtimes/parachain/src/staking.rs b/substrate/frame/staking-async/runtimes/parachain/src/staking.rs index 3cb9e57e83cdc..8bcf9abcfb135 100644 --- a/substrate/frame/staking-async/runtimes/parachain/src/staking.rs +++ b/substrate/frame/staking-async/runtimes/parachain/src/staking.rs @@ -184,6 +184,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; @@ -246,6 +247,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; @@ -544,3 +548,191 @@ where UncheckedExtrinsic::new_bare(call) } } +<<<<<<< HEAD +======= + +#[cfg(test)] +mod tests { + use super::*; + use frame_election_provider_support::ElectionProvider; + use frame_support::weights::constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MILLIS}; + use pallet_election_provider_multi_block::{ + self as mb, signed::WeightInfo as _, unsigned::WeightInfo as _, + }; + use remote_externalities::{ + Builder, Mode, OfflineConfig, OnlineConfig, SnapshotConfig, Transport, + }; + use std::env::var; + + fn weight_diff(block: Weight, op: Weight) { + log::info!( + target: "runtime", + "ref_time: {:?}ms {:.4} of total", + op.ref_time() / WEIGHT_REF_TIME_PER_MILLIS, + op.ref_time() as f64 / block.ref_time() as f64 + ); + log::info!( + target: "runtime", + "proof_size: {:?}kb {:.4} of total", + op.proof_size() / WEIGHT_PROOF_SIZE_PER_KB, + op.proof_size() as f64 / block.proof_size() as f64 + ); + } + + #[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(); + let block_weight = ::BlockWeights::get().max_block; + let polkadot_signed_submission = + mb::weights::polkadot::MultiBlockSignedWeightInfo::::submit_page(); + let kusama_signed_submission = + mb::weights::kusama::MultiBlockSignedWeightInfo::::submit_page(); + + log::info!(target: "runtime", "Polkadot:"); + weight_diff(block_weight, polkadot_signed_submission); + log::info!(target: "runtime", "Kusama:"); + weight_diff(block_weight, kusama_signed_submission); + } + + #[test] + fn election_duration() { + sp_tracing::try_init_simple(); + sp_io::TestExternalities::default().execute_with(|| { + super::enable_dot_preset(false); + let duration = mb::Pallet::::average_election_duration(); + let polkadot_session = 6 * HOURS; + log::info!( + target: "runtime", + "Polkadot election duration: {:?}, session: {:?} ({} sessions)", + duration, + polkadot_session, + duration / polkadot_session + ); + }); + + sp_io::TestExternalities::default().execute_with(|| { + super::enable_ksm_preset(false); + let duration = mb::Pallet::::average_election_duration(); + let kusama_session = 1 * HOURS; + log::info!( + target: "runtime", + "Kusama election duration: {:?}, session: {:?} ({} sessions)", + duration, + kusama_session, + duration / kusama_session + ); + }); + } + + #[test] + fn max_ocw_miner_pages_as_per_weights() { + sp_tracing::try_init_simple(); + for p in 1..=32 { + log::info!( + target: "runtime", + "exec_time of polkadot miner in WASM with {} pages is {:?}ms", + p, + mb::weights::polkadot::MultiBlockUnsignedWeightInfo::::mine_solution(p).ref_time() / WEIGHT_REF_TIME_PER_MILLIS + ); + } + for p in 1..=16 { + log::info!( + target: "runtime", + "exec_time of kusama miner in WASM with {} pages is {:?}ms", + p, + mb::weights::kusama::MultiBlockUnsignedWeightInfo::::mine_solution(p).ref_time() / WEIGHT_REF_TIME_PER_MILLIS + ); + } + } + + /// Run it like: + /// + /// ```text + /// RUST_BACKTRACE=full \ + /// RUST_LOG=remote-ext=info,runtime::staking-async=debug \ + /// REMOTE_TESTS=1 \ + /// WS=ws://127.0.0.1:9999 \ + /// cargo test --release -p pallet-staking-async-parachain-runtime \ + /// --features try-runtime run_try + /// ``` + /// + /// Just replace the node with your local node. + /// + /// Pass `SNAP=polkadot` or similar to store and reuse a snapshot. + #[tokio::test] + async fn run_election_with_pages() { + if var("REMOTE_TESTS").is_err() { + return; + } + sp_tracing::try_init_simple(); + + let transport: Transport = + var("WS").unwrap_or("wss://westend-rpc.polkadot.io:443".to_string()).into(); + let maybe_state_snapshot: Option = var("SNAP").map(|s| s.into()).ok(); + + let mut ext = Builder::::default() + .mode(if let Some(state_snapshot) = maybe_state_snapshot { + Mode::OfflineOrElseOnline( + OfflineConfig { state_snapshot: state_snapshot.clone() }, + OnlineConfig { + transport, + hashed_prefixes: vec![vec![]], + state_snapshot: Some(state_snapshot), + ..Default::default() + }, + ) + } else { + Mode::Online(OnlineConfig { + hashed_prefixes: vec![vec![]], + transport, + ..Default::default() + }) + }) + .build() + .await + .unwrap(); + ext.execute_with(|| { + sp_core::crypto::set_default_ss58_version(1u8.into()); + super::enable_dot_preset(true); + + // prepare all snapshot in EPMB pallet. + mb::Pallet::::asap(); + for page in 1..=32 { + mb::unsigned::miner::OffchainWorkerMiner::::mine_solution(page, true) + .inspect(|p| log::info!(target: "runtime", "{:?}", p.score.pretty("DOT", 10))) + .unwrap(); + } + }); + } +} +>>>>>>> 05a3fb10 (Staking-Async + EPMB: Migrate operations to `poll` (#9925)) diff --git a/substrate/frame/staking-async/runtimes/parachain/zombienet-staking-runtimes.toml b/substrate/frame/staking-async/runtimes/parachain/zombienet-staking-runtimes.toml index bb360ae7f0a9b..eb9e45aa921a1 100644 --- a/substrate/frame/staking-async/runtimes/parachain/zombienet-staking-runtimes.toml +++ b/substrate/frame/staking-async/runtimes/parachain/zombienet-staking-runtimes.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/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 5951d6d3912e8..7f306574ebe35 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)] @@ -1224,6 +1225,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] @@ -1425,6 +1428,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::(); @@ -1436,9 +1463,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