From abf768fff51ff1adeaa26399f88803b61c32f644 Mon Sep 17 00:00:00 2001 From: Paolo La Camera Date: Fri, 30 May 2025 15:10:39 +0200 Subject: [PATCH 1/2] static config: Add support for AH and staking-async chains - Deprecated `asset-hub-next`, replaced by `staking-async-parachain` and `staking-async-rc` in https://github.com/paritytech/polkadot-sdk/pull/8422 - Add support for statemint, statemine, westmint AH chains, without dropping the polkadot / kusama / westend RC variants until we deprecate the legacy `monitor` path and rely only on EPMB For the time being, static miner's config for StakingAsync is a copy-paste of Westend one but will evolve independently. As a separate topic (see #994), a partial / complete removal of the static configuration per chain will be tackled. --- src/macros.rs | 8 ++-- src/opt.rs | 10 +++-- src/static_types/legacy.rs | 65 +++++++++++++++++++++++++++++++++ src/static_types/multi_block.rs | 37 +++++++++++++++++++ tests/common.rs | 2 +- 5 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 1003af907..1d0a83a3f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -53,9 +53,9 @@ macro_rules! for_legacy_runtime { use $crate::static_types::legacy::westend::MinerConfig; $($code)* }, - $crate::opt::Chain::AssetHubNext => { + $crate::opt::Chain::StakingAsync => { #[allow(unused)] - use $crate::static_types::legacy::westend::MinerConfig; + use $crate::static_types::legacy::staking_async::MinerConfig; $($code)* } $crate::opt::Chain::SubstrateNode => { @@ -87,9 +87,9 @@ macro_rules! for_multi_block_runtime { use $crate::static_types::multi_block::westend::MinerConfig; $($code)* }, - $crate::opt::Chain::AssetHubNext => { + $crate::opt::Chain::StakingAsync => { #[allow(unused)] - use $crate::static_types::multi_block::westend::MinerConfig; + use $crate::static_types::multi_block::staking_async::MinerConfig; $($code)* } $crate::opt::Chain::SubstrateNode => { diff --git a/src/opt.rs b/src/opt.rs index 3bca51d14..0e1d4fb7c 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -51,7 +51,7 @@ pub enum Chain { Kusama, Polkadot, SubstrateNode, - AssetHubNext, + StakingAsync, } impl fmt::Display for Chain { @@ -61,7 +61,7 @@ impl fmt::Display for Chain { Self::Kusama => "kusama", Self::Westend => "westend", Self::SubstrateNode => "node", - Self::AssetHubNext => "asset-hub-next", + Self::StakingAsync => "staking-async", }; write!(f, "{}", chain) } @@ -73,9 +73,13 @@ impl std::str::FromStr for Chain { fn from_str(s: &str) -> Result { match s { "polkadot" => Ok(Self::Polkadot), + "statemint" => Ok(Self::Polkadot), // Polkadot AH "kusama" => Ok(Self::Kusama), + "statemine" => Ok(Self::Kusama), // Kusama AH "westend" => Ok(Self::Westend), - "asset-hub-next" => Ok(Self::AssetHubNext), + "westmint" => Ok(Self::Westend), // Westend AH + "staking-async-parachain" => Ok(Self::StakingAsync), + "staking-async-rc" => Ok(Self::StakingAsync), "node" => Ok(Self::SubstrateNode), chain => Err(Error::InvalidChain(chain.to_string())), } diff --git a/src/static_types/legacy.rs b/src/static_types/legacy.rs index bd3f89aed..b23320cc0 100644 --- a/src/static_types/legacy.rs +++ b/src/static_types/legacy.rs @@ -314,3 +314,68 @@ pub mod kusama { } } } + +/// This is used to test against staking-async runtimes from the SDK. +pub mod staking_async { + use super::*; + + // SYNC + frame_election_provider_support::generate_solution_type!( + #[compact] + pub struct NposSolution16::< + VoterIndex = u32, + TargetIndex = u16, + Accuracy = sp_runtime::PerU16, + MaxVoters = ConstU32::<22500> + >(16) + ); + + #[derive(Debug)] + pub struct MinerConfig; + impl pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig { + type AccountId = AccountId; + type MaxLength = MaxLength; + type MaxWeight = MaxWeight; + type MaxVotesPerVoter = MaxVotesPerVoter; + type MaxBackersPerWinner = ConstU32<22500>; + type Solution = NposSolution16; + type MaxWinners = MaxWinners; + + fn solution_weight( + voters: u32, + targets: u32, + active_voters: u32, + desired_targets: u32, + ) -> Weight { + let Some(votes) = dynamic::mock_votes( + active_voters, + desired_targets + .try_into() + .expect("Desired targets < u16::MAX"), + ) else { + return Weight::MAX; + }; + + // Mock a RawSolution to get the correct weight without having to do the heavy work. + let raw = RawSolution { + solution: NposSolution16 { + votes1: votes, + ..Default::default() + }, + ..Default::default() + }; + + if raw.solution.voter_count() != active_voters as usize + || raw.solution.unique_targets().len() != desired_targets as usize + { + return Weight::MAX; + } + + futures::executor::block_on(dynamic::runtime_api_solution_weight( + raw, + SolutionOrSnapshotSize { voters, targets }, + )) + .expect("solution_weight should work") + } + } +} diff --git a/src/static_types/multi_block.rs b/src/static_types/multi_block.rs index 634a45c65..aec2a33d3 100644 --- a/src/static_types/multi_block.rs +++ b/src/static_types/multi_block.rs @@ -157,3 +157,40 @@ pub mod westend { type Hash = Hash; } } + +/// This is used to test against staking-async runtimes from the SDK. +pub mod staking_async { + use super::*; + use frame_election_provider_support::SequentialPhragmen; + + // TODO: validate config https://github.com/paritytech/polkadot-staking-miner/issues/994 + frame_election_provider_support::generate_solution_type!( + #[compact] + pub struct NposSolution16::< + VoterIndex = u32, + TargetIndex = u16, + Accuracy = PerU16, + MaxVoters = ConstU32::<22500> + >(16) + ); + + #[derive(Debug)] + pub struct MinerConfig; + + // TODO: validate config https://github.com/paritytech/polkadot-staking-miner/issues/994 + impl multi_block::unsigned::miner::MinerConfig for MinerConfig { + type AccountId = AccountId; + type Solution = NposSolution16; + // TODO: make it configurable via CLI https://github.com/paritytech/polkadot-staking-miner/issues/989 + type Solver = SequentialPhragmen; + type Pages = Pages; + type MaxVotesPerVoter = ConstU32<16>; + type MaxWinnersPerPage = MaxWinnersPerPage; + type MaxBackersPerWinner = MaxBackersPerWinner; + type MaxBackersPerWinnerFinal = ConstU32<{ u32::MAX }>; + type VoterSnapshotPerBlock = VoterSnapshotPerBlock; + type TargetSnapshotPerBlock = TargetSnapshotPerBlock; + type MaxLength = MaxLength; + type Hash = Hash; + } +} diff --git a/tests/common.rs b/tests/common.rs index e2d328218..3d58c3287 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -84,7 +84,7 @@ pub fn run_polkadot_node(chain: Chain) -> (KillChildOnDrop, String) { Chain::Kusama => "chainspecs/kusama-dev.json", Chain::Westend => "westend-dev", Chain::SubstrateNode => "dev", - Chain::AssetHubNext => panic!("AssetHubNext is not supported"), + Chain::StakingAsync => panic!("StakingAsync is not supported"), }; let mut node_cmd = KillChildOnDrop( From 94bba45bc8b559efdc7c691787a3cdca77284579 Mon Sep 17 00:00:00 2001 From: Paolo La Camera Date: Mon, 2 Jun 2025 14:15:31 +0200 Subject: [PATCH 2/2] Remove staking-async support from legacy This change removes staking-async runtime support from the legacy monitor code path, replacing it with appropriate error messages for unsupported cases. --- src/macros.rs | 4 +-- src/main.rs | 11 +++++++ src/opt.rs | 4 ++- src/static_types/legacy.rs | 65 -------------------------------------- 4 files changed, 15 insertions(+), 69 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 1d0a83a3f..7f542b273 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -54,9 +54,7 @@ macro_rules! for_legacy_runtime { $($code)* }, $crate::opt::Chain::StakingAsync => { - #[allow(unused)] - use $crate::static_types::legacy::staking_async::MinerConfig; - $($code)* + panic!("StakingAsync is not supported in legacy monitor"); } $crate::opt::Chain::SubstrateNode => { #[allow(unused)] diff --git a/src/main.rs b/src/main.rs index fce675642..64f74e47d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -459,4 +459,15 @@ mod tests { ) ); } + + #[test] + #[should_panic(expected = "StakingAsync is not supported in legacy monitor")] + fn for_legacy_runtime_panics_on_staking_async() { + use crate::opt::Chain; + let chain = Chain::StakingAsync; + macros::for_legacy_runtime!(chain, { + // This block should never be executed + let _ = (); + }); + } } diff --git a/src/opt.rs b/src/opt.rs index 0e1d4fb7c..ef891e609 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -79,7 +79,9 @@ impl std::str::FromStr for Chain { "westend" => Ok(Self::Westend), "westmint" => Ok(Self::Westend), // Westend AH "staking-async-parachain" => Ok(Self::StakingAsync), - "staking-async-rc" => Ok(Self::StakingAsync), + "staking-async-rc" => { + unimplemented!("multi-block mining is not supported on relay chains") + } "node" => Ok(Self::SubstrateNode), chain => Err(Error::InvalidChain(chain.to_string())), } diff --git a/src/static_types/legacy.rs b/src/static_types/legacy.rs index b23320cc0..bd3f89aed 100644 --- a/src/static_types/legacy.rs +++ b/src/static_types/legacy.rs @@ -314,68 +314,3 @@ pub mod kusama { } } } - -/// This is used to test against staking-async runtimes from the SDK. -pub mod staking_async { - use super::*; - - // SYNC - frame_election_provider_support::generate_solution_type!( - #[compact] - pub struct NposSolution16::< - VoterIndex = u32, - TargetIndex = u16, - Accuracy = sp_runtime::PerU16, - MaxVoters = ConstU32::<22500> - >(16) - ); - - #[derive(Debug)] - pub struct MinerConfig; - impl pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig { - type AccountId = AccountId; - type MaxLength = MaxLength; - type MaxWeight = MaxWeight; - type MaxVotesPerVoter = MaxVotesPerVoter; - type MaxBackersPerWinner = ConstU32<22500>; - type Solution = NposSolution16; - type MaxWinners = MaxWinners; - - fn solution_weight( - voters: u32, - targets: u32, - active_voters: u32, - desired_targets: u32, - ) -> Weight { - let Some(votes) = dynamic::mock_votes( - active_voters, - desired_targets - .try_into() - .expect("Desired targets < u16::MAX"), - ) else { - return Weight::MAX; - }; - - // Mock a RawSolution to get the correct weight without having to do the heavy work. - let raw = RawSolution { - solution: NposSolution16 { - votes1: votes, - ..Default::default() - }, - ..Default::default() - }; - - if raw.solution.voter_count() != active_voters as usize - || raw.solution.unique_targets().len() != desired_targets as usize - { - return Weight::MAX; - } - - futures::executor::block_on(dynamic::runtime_api_solution_weight( - raw, - SolutionOrSnapshotSize { voters, targets }, - )) - .expect("solution_weight should work") - } - } -}