From 713eb8c642a09f59ae973a1cc46781df44fd4c90 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 00:38:45 +0200 Subject: [PATCH 01/26] Refactoring opts out --- utils/staking-miner/Cargo.toml | 2 +- utils/staking-miner/src/dry_run.rs | 3 +- utils/staking-miner/src/macros.rs | 109 +++++++++++++ utils/staking-miner/src/main.rs | 253 +---------------------------- utils/staking-miner/src/opts.rs | 252 ++++++++++++++++++++++++++++ 5 files changed, 369 insertions(+), 250 deletions(-) create mode 100644 utils/staking-miner/src/macros.rs create mode 100644 utils/staking-miner/src/opts.rs diff --git a/utils/staking-miner/Cargo.toml b/utils/staking-miner/Cargo.toml index 24e5231614e3..92625f6604f0 100644 --- a/utils/staking-miner/Cargo.toml +++ b/utils/staking-miner/Cargo.toml @@ -43,4 +43,4 @@ westend-runtime = { path = "../../runtime/westend" } sub-tokens = { git = "https://github.com/paritytech/substrate-debug-kit", branch = "master" } [dev-dependencies] -assert_cmd = "2.0.2" +assert_cmd = "2.0.4" diff --git a/utils/staking-miner/src/dry_run.rs b/utils/staking-miner/src/dry_run.rs index 19be1c4474f7..e9a13cda77ab 100644 --- a/utils/staking-miner/src/dry_run.rs +++ b/utils/staking-miner/src/dry_run.rs @@ -16,11 +16,12 @@ //! The dry-run command. -use crate::{prelude::*, rpc::*, signer::Signer, DryRunConfig, Error, SharedRpcClient}; +use crate::{prelude::*, rpc::*, signer::Signer, Error, SharedRpcClient}; use codec::Encode; use frame_support::traits::Currency; use sp_core::Bytes; use sp_npos_elections::ElectionScore; +use crate::opts::DryRunConfig; /// Forcefully create the snapshot. This can be used to compute the election at anytime. fn force_create_snapshot(ext: &mut Ext) -> Result<(), Error> { diff --git a/utils/staking-miner/src/macros.rs b/utils/staking-miner/src/macros.rs new file mode 100644 index 000000000000..bb6eb47dea0c --- /dev/null +++ b/utils/staking-miner/src/macros.rs @@ -0,0 +1,109 @@ +// NOTE: this is no longer used extensively, most of the per-runtime stuff us delegated to +// `construct_runtime_prelude` and macro's the import directly from it. A part of the code is also +// still generic over `T`. My hope is to still make everything generic over a `Runtime`, but sadly +// that is not currently possible as each runtime has its unique `Call`, and all Calls are not +// sharing any generic trait. In other words, to create the `UncheckedExtrinsic` of each chain, you +// need the concrete `Call` of that chain as well. +#[macro_export] +macro_rules! any_runtime { + ($($code:tt)*) => { + unsafe { + match $crate::RUNTIME { + $crate::AnyRuntime::Polkadot => { + #[allow(unused)] + use $crate::polkadot_runtime_exports::*; + $($code)* + }, + $crate::AnyRuntime::Kusama => { + #[allow(unused)] + use $crate::kusama_runtime_exports::*; + $($code)* + }, + $crate::AnyRuntime::Westend => { + #[allow(unused)] + use $crate::westend_runtime_exports::*; + $($code)* + } + } + } + } +} + +/// Same as [`any_runtime`], but instead of returning a `Result`, this simply returns `()`. Useful +/// for situations where the result is not useful and un-ergonomic to handle. +#[macro_export] +macro_rules! any_runtime_unit { + ($($code:tt)*) => { + unsafe { + match $crate::RUNTIME { + $crate::AnyRuntime::Polkadot => { + #[allow(unused)] + use $crate::polkadot_runtime_exports::*; + let _ = $($code)*; + }, + $crate::AnyRuntime::Kusama => { + #[allow(unused)] + use $crate::kusama_runtime_exports::*; + let _ = $($code)*; + }, + $crate::AnyRuntime::Westend => { + #[allow(unused)] + use $crate::westend_runtime_exports::*; + let _ = $($code)*; + } + } + } + } +} + +macro_rules! construct_runtime_prelude { + ($runtime:ident) => { paste::paste! { + #[allow(unused_import)] + pub(crate) mod [<$runtime _runtime_exports>] { + pub(crate) use crate::prelude::EPM; + pub(crate) use [<$runtime _runtime>]::*; + pub(crate) use crate::monitor::[] as monitor_cmd; + pub(crate) use crate::dry_run::[] as dry_run_cmd; + pub(crate) use crate::emergency_solution::[] as emergency_solution_cmd; + pub(crate) use private::{[] as create_uxt}; + + mod private { + use super::*; + pub(crate) fn []( + raw_solution: EPM::RawSolution>, + signer: crate::signer::Signer, + nonce: crate::prelude::Index, + tip: crate::prelude::Balance, + era: sp_runtime::generic::Era, + ) -> UncheckedExtrinsic { + use codec::Encode as _; + use sp_core::Pair as _; + use sp_runtime::traits::StaticLookup as _; + + let crate::signer::Signer { account, pair, .. } = signer; + + let local_call = EPMCall::::submit { raw_solution: Box::new(raw_solution) }; + let call: Call = as std::convert::TryInto>::try_into(local_call) + .expect("election provider pallet must exist in the runtime, thus \ + inner call can be converted, qed." + ); + + let extra: SignedExtra = crate::[](nonce, tip, era); + let raw_payload = SignedPayload::new(call, extra).expect("creating signed payload infallible; qed."); + let signature = raw_payload.using_encoded(|payload| { + pair.sign(payload) + }); + let (call, extra, _) = raw_payload.deconstruct(); + let address = ::Lookup::unlookup(account); + let extrinsic = UncheckedExtrinsic::new_signed(call, address, signature.into(), extra); + log::debug!( + target: crate::LOG_TARGET, "constructed extrinsic {} with length {}", + sp_core::hexdisplay::HexDisplay::from(&extrinsic.encode()), + extrinsic.encode().len(), + ); + extrinsic + } + } + }} + }; +} diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 5a515c9de296..481f26817626 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -31,15 +31,15 @@ mod dry_run; mod emergency_solution; mod monitor; +mod opts; mod prelude; mod rpc; mod signer; -use std::str::FromStr; - pub(crate) use prelude::*; pub(crate) use signer::get_account_info; +use crate::opts::*; use clap::Parser; use frame_election_provider_support::NposSolver; use frame_support::traits::Get; @@ -49,8 +49,8 @@ use rpc::{RpcApiClient, SharedRpcClient}; use sp_npos_elections::BalancingConfig; use sp_runtime::{traits::Block as BlockT, DeserializeOwned, Perbill}; use tracing_subscriber::{fmt, EnvFilter}; - use std::{ops::Deref, sync::Arc}; +use tracing_subscriber::{fmt, EnvFilter}; pub(crate) enum AnyRuntime { Polkadot, @@ -278,70 +278,6 @@ impl std::fmt::Display for Error { } } -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -enum Command { - /// Monitor for the phase being signed, then compute. - Monitor(MonitorConfig), - /// Just compute a solution now, and don't submit it. - DryRun(DryRunConfig), - /// Provide a solution that can be submitted to the chain as an emergency response. - EmergencySolution(EmergencySolutionConfig), -} - -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -enum Solver { - SeqPhragmen { - #[clap(long, default_value = "10")] - iterations: usize, - }, - PhragMMS { - #[clap(long, default_value = "10")] - iterations: usize, - }, -} - -/// Submission strategy to use. -#[derive(Debug, Copy, Clone)] -#[cfg_attr(test, derive(PartialEq))] -enum SubmissionStrategy { - // Only submit if at the time, we are the best. - IfLeading, - // Always submit. - Always, - // Submit if we are leading, or if the solution that's leading is more that the given `Perbill` - // better than us. This helps detect obviously fake solutions and still combat them. - ClaimBetterThan(Perbill), -} - -/// Custom `impl` to parse `SubmissionStrategy` from CLI. -/// -/// Possible options: -/// * --submission-strategy if-leading: only submit if leading -/// * --submission-strategy always: always submit -/// * --submission-strategy "percent-better ": submit if submission is `n` percent better. -/// -impl FromStr for SubmissionStrategy { - type Err = String; - - fn from_str(s: &str) -> Result { - let s = s.trim(); - - let res = if s == "if-leading" { - Self::IfLeading - } else if s == "always" { - Self::Always - } else if s.starts_with("percent-better ") { - let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; - Self::ClaimBetterThan(Perbill::from_percent(percent)) - } else { - return Err(s.into()) - }; - Ok(res) - } -} - frame_support::parameter_types! { /// Number of balancing iterations for a solution algorithm. Set based on the [`Solvers`] CLI /// config. @@ -349,87 +285,6 @@ frame_support::parameter_types! { pub static Balancing: Option = Some( BalancingConfig { iterations: BalanceIterations::get(), tolerance: 0 } ); } -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -struct MonitorConfig { - /// They type of event to listen to. - /// - /// Typically, finalized is safer and there is no chance of anything going wrong, but it can be - /// slower. It is recommended to use finalized, if the duration of the signed phase is longer - /// than the the finality delay. - #[clap(long, default_value = "head", possible_values = &["head", "finalized"])] - listen: String, - - /// The solver algorithm to use. - #[clap(subcommand)] - solver: Solver, - - /// Submission strategy to use. - /// - /// Possible options: - /// - /// `--submission-strategy if-leading`: only submit if leading. - /// - /// `--submission-strategy always`: always submit. - /// - /// `--submission-strategy "percent-better "`: submit if the submission is `n` percent better. - #[clap(long, parse(try_from_str), default_value = "if-leading")] - submission_strategy: SubmissionStrategy, -} - -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -struct EmergencySolutionConfig { - /// The block hash at which scraping happens. If none is provided, the latest head is used. - #[clap(long)] - at: Option, - - /// The solver algorithm to use. - #[clap(subcommand)] - solver: Solver, - - /// The number of top backed winners to take. All are taken, if not provided. - take: Option, -} - -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -struct DryRunConfig { - /// The block hash at which scraping happens. If none is provided, the latest head is used. - #[clap(long)] - at: Option, - - /// The solver algorithm to use. - #[clap(subcommand)] - solver: Solver, - - /// Force create a new snapshot, else expect one to exist onchain. - #[clap(long)] - force_snapshot: bool, -} - -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -#[clap(author, version, about)] -struct Opt { - /// The `ws` node to connect to. - #[clap(long, short, default_value = DEFAULT_URI, env = "URI")] - uri: String, - - /// The path to a file containing the seed of the account. If the file is not found, the seed is - /// used as-is. - /// - /// Can also be provided via the `SEED` environment variable. - /// - /// WARNING: Don't use an account with a large stash for this. Based on how the bot is - /// configured, it might re-try and lose funds through transaction fees/deposits. - #[clap(long, short, env = "SEED")] - seed_or_path: String, - - #[clap(subcommand)] - command: Command, -} - /// Build the Ext at hash with all the data of `ElectionProviderMultiPhase` and any additional /// pallets. async fn create_election_ext( @@ -528,7 +383,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return + return; } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -639,7 +494,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return + return; }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); @@ -696,102 +551,4 @@ mod tests { assert_eq!(polkadot_version.spec_name, "polkadot".into()); assert_eq!(kusama_version.spec_name, "kusama".into()); } - - #[test] - fn cli_monitor_works() { - let opt = Opt::try_parse_from([ - env!("CARGO_PKG_NAME"), - "--uri", - "hi", - "--seed-or-path", - "//Alice", - "monitor", - "--listen", - "head", - "seq-phragmen", - ]) - .unwrap(); - - assert_eq!( - opt, - Opt { - uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), - command: Command::Monitor(MonitorConfig { - listen: "head".to_string(), - solver: Solver::SeqPhragmen { iterations: 10 }, - submission_strategy: SubmissionStrategy::IfLeading, - }), - } - ); - } - - #[test] - fn cli_dry_run_works() { - let opt = Opt::try_parse_from([ - env!("CARGO_PKG_NAME"), - "--uri", - "hi", - "--seed-or-path", - "//Alice", - "dry-run", - "phrag-mms", - ]) - .unwrap(); - - assert_eq!( - opt, - Opt { - uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), - command: Command::DryRun(DryRunConfig { - at: None, - solver: Solver::PhragMMS { iterations: 10 }, - force_snapshot: false, - }), - } - ); - } - - #[test] - fn cli_emergency_works() { - let opt = Opt::try_parse_from([ - env!("CARGO_PKG_NAME"), - "--uri", - "hi", - "--seed-or-path", - "//Alice", - "emergency-solution", - "99", - "phrag-mms", - "--iterations", - "1337", - ]) - .unwrap(); - - assert_eq!( - opt, - Opt { - uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), - command: Command::EmergencySolution(EmergencySolutionConfig { - take: Some(99), - at: None, - solver: Solver::PhragMMS { iterations: 1337 } - }), - } - ); - } - - #[test] - fn submission_strategy_from_str_works() { - use std::str::FromStr; - - assert_eq!(SubmissionStrategy::from_str("if-leading"), Ok(SubmissionStrategy::IfLeading)); - assert_eq!(SubmissionStrategy::from_str("always"), Ok(SubmissionStrategy::Always)); - assert_eq!( - SubmissionStrategy::from_str(" percent-better 99 "), - Ok(SubmissionStrategy::ClaimBetterThan(Perbill::from_percent(99))) - ); - } } diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs new file mode 100644 index 000000000000..3bcdcd0146a3 --- /dev/null +++ b/utils/staking-miner/src/opts.rs @@ -0,0 +1,252 @@ +use crate::prelude::*; +use clap::Parser; +use sp_runtime::Perbill; +use std::str::FromStr; + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) struct MonitorConfig { + /// They type of event to listen to. + /// + /// Typically, finalized is safer and there is no chance of anything going wrong, but it can be + /// slower. It is recommended to use finalized, if the duration of the signed phase is longer + /// than the the finality delay. + #[clap(long, default_value = "head", possible_values = &["head", "finalized"])] + pub listen: String, + + /// The solver algorithm to use. + #[clap(subcommand)] + pub solver: Solver, + + /// Submission strategy to use. + /// + /// Possible options: + /// + /// `--submission-strategy if-leading`: only submit if leading. + /// + /// `--submission-strategy always`: always submit. + /// + /// `--submission-strategy "percent-better "`: submit if the submission is `n` percent better. + #[clap(long, parse(try_from_str), default_value = "if-leading")] + pub submission_strategy: SubmissionStrategy, +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) struct EmergencySolutionConfig { + /// The block hash at which scraping happens. If none is provided, the latest head is used. + #[clap(long)] + pub at: Option, + + /// The solver algorithm to use. + #[clap(subcommand)] + pub solver: Solver, + + /// The number of top backed winners to take. All are taken, if not provided. + pub take: Option, +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) struct DryRunConfig { + /// The block hash at which scraping happens. If none is provided, the latest head is used. + #[clap(long)] + pub at: Option, + + /// The solver algorithm to use. + #[clap(subcommand)] + pub solver: Solver, + + /// Force create a new snapshot, else expect one to exist onchain. + #[clap(long)] + pub force_snapshot: bool, +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +#[clap(author, version, about)] +pub(crate) struct Opt { + /// The `ws` node to connect to. + #[clap(long, short, default_value = DEFAULT_URI, env = "URI")] + pub uri: String, + + /// The path to a file containing the seed of the account. If the file is not found, the seed is + /// used as-is. + /// + /// Can also be provided via the `SEED` environment variable. + /// + /// WARNING: Don't use an account with a large stash for this. Based on how the bot is + /// configured, it might re-try and lose funds through transaction fees/deposits. + #[clap(long, short, env = "SEED")] + pub seed_or_path: String, + + #[clap(subcommand)] + pub command: Command, +} + +/// Submission strategy to use. +#[derive(Debug, Copy, Clone)] +#[cfg_attr(test, derive(PartialEq))] +pub enum SubmissionStrategy { + // Only submit if at the time, we are the best. + IfLeading, + // Always submit. + Always, + // Submit if we are leading, or if the solution that's leading is more that the given `Perbill` + // better than us. This helps detect obviously fake solutions and still combat them. + ClaimBetterThan(Perbill), +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) enum Command { + /// Monitor for the phase being signed, then compute. + Monitor(MonitorConfig), + /// Just compute a solution now, and don't submit it. + DryRun(DryRunConfig), + /// Provide a solution that can be submitted to the chain as an emergency response. + EmergencySolution(EmergencySolutionConfig), +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) enum Solver { + SeqPhragmen { + #[clap(long, default_value = "10")] + iterations: usize, + }, + PhragMMS { + #[clap(long, default_value = "10")] + iterations: usize, + }, +} + +/// Custom `impl` to parse `SubmissionStrategy` from CLI. +/// +/// Possible options: +/// * --submission-strategy if-leading: only submit if leading +/// * --submission-strategy always: always submit +/// * --submission-strategy "percent-better ": submit if submission is `n` percent better. +/// +impl FromStr for SubmissionStrategy { + type Err = String; + + fn from_str(s: &str) -> Result { + let s = s.trim(); + + let res = if s == "if-leading" { + Self::IfLeading + } else if s == "always" { + Self::Always + } else if s.starts_with("percent-better ") { + let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; + Self::ClaimBetterThan(Perbill::from_percent(percent)) + } else { + return Err(s.into()); + }; + Ok(res) + } +} + +#[cfg(test)] +mod test_super { + use super::*; + + #[test] + fn cli_monitor_works() { + let opt = Opt::try_parse_from([ + env!("CARGO_PKG_NAME"), + "--uri", + "hi", + "--seed-or-path", + "//Alice", + "monitor", + "--listen", + "head", + "seq-phragmen", + ]) + .unwrap(); + + assert_eq!( + opt, + Opt { + uri: "hi".to_string(), + seed_or_path: "//Alice".to_string(), + command: Command::Monitor(MonitorConfig { + listen: "head".to_string(), + solver: Solver::SeqPhragmen { iterations: 10 }, + submission_strategy: SubmissionStrategy::IfLeading, + }), + } + ); + } + + #[test] + fn cli_dry_run_works() { + let opt = Opt::try_parse_from([ + env!("CARGO_PKG_NAME"), + "--uri", + "hi", + "--seed-or-path", + "//Alice", + "dry-run", + "phrag-mms", + ]) + .unwrap(); + + assert_eq!( + opt, + Opt { + uri: "hi".to_string(), + seed_or_path: "//Alice".to_string(), + command: Command::DryRun(DryRunConfig { + at: None, + solver: Solver::PhragMMS { iterations: 10 }, + force_snapshot: false, + }), + } + ); + } + + #[test] + fn cli_emergency_works() { + let opt = Opt::try_parse_from([ + env!("CARGO_PKG_NAME"), + "--uri", + "hi", + "--seed-or-path", + "//Alice", + "emergency-solution", + "99", + "phrag-mms", + "--iterations", + "1337", + ]) + .unwrap(); + + assert_eq!( + opt, + Opt { + uri: "hi".to_string(), + seed_or_path: "//Alice".to_string(), + command: Command::EmergencySolution(EmergencySolutionConfig { + take: Some(99), + at: None, + solver: Solver::PhragMMS { iterations: 1337 } + }), + } + ); + } + + #[test] + fn submission_strategy_from_str_works() { + use std::str::FromStr; + + assert_eq!(SubmissionStrategy::from_str("if-leading"), Ok(SubmissionStrategy::IfLeading)); + assert_eq!(SubmissionStrategy::from_str("always"), Ok(SubmissionStrategy::Always)); + assert_eq!( + SubmissionStrategy::from_str(" percent-better 99 "), + Ok(SubmissionStrategy::ClaimBetterThan(Perbill::from_percent(99))) + ); + } +} From 69ff865b88a5144ec79d5eb910f144906ac6fb0e Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:02:39 +0200 Subject: [PATCH 02/26] Implement info command fix #5560 --- utils/staking-miner/src/info.rs | 11 ++++ utils/staking-miner/src/main.rs | 43 ++++++++++----- utils/staking-miner/src/opts.rs | 93 ++++++++++++++++++++------------- 3 files changed, 97 insertions(+), 50 deletions(-) create mode 100644 utils/staking-miner/src/info.rs diff --git a/utils/staking-miner/src/info.rs b/utils/staking-miner/src/info.rs new file mode 100644 index 000000000000..f3bb6d349612 --- /dev/null +++ b/utils/staking-miner/src/info.rs @@ -0,0 +1,11 @@ +#[derive(Debug, serde::Serialize)] +pub(crate) struct Info { + pub spec_name: String, + pub spec_version: u32, +} + +impl Info { + pub fn new(spec_name: String, spec_version: u32) -> Self { + Self { spec_name, spec_version } + } +} diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 481f26817626..809f346c1b37 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -30,6 +30,7 @@ mod dry_run; mod emergency_solution; +mod info; mod monitor; mod opts; mod prelude; @@ -43,6 +44,7 @@ use crate::opts::*; use clap::Parser; use frame_election_provider_support::NposSolver; use frame_support::traits::Get; +use info::*; use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; use remote_externalities::{Builder, Mode, OnlineConfig}; use rpc::{RpcApiClient, SharedRpcClient}; @@ -437,7 +439,7 @@ pub(crate) async fn check_versions( async fn main() { fmt().with_env_filter(EnvFilter::from_default_env()).init(); - let Opt { uri, seed_or_path, command } = Opt::parse(); + let Opt { uri, command } = Opt::parse(); log::debug!(target: LOG_TARGET, "attempting to connect to {:?}", uri); let rpc = loop { @@ -503,26 +505,41 @@ async fn main() { check_versions::(&rpc).await }; - let signer_account = any_runtime! { - signer::signer_uri_from_string::(&seed_or_path, &rpc) - .await - .expect("Provided account is invalid, terminating.") - }; - let outcome = any_runtime! { match command { - Command::Monitor(cmd) => monitor_cmd(rpc, cmd, signer_account).await + Command::Monitor(monitor_config) => + { + let signer_account = any_runtime! { + signer::signer_uri_from_string::(&monitor_config.seed_or_path , &rpc) + .await + .expect("Provided account is invalid, terminating.") + }; + monitor_cmd(rpc, monitor_config, signer_account).await .map_err(|e| { log::error!(target: LOG_TARGET, "Monitor error: {:?}", e); - }), - Command::DryRun(cmd) => dry_run_cmd(rpc, cmd, signer_account).await + })}, + Command::DryRun(dryrun_config) => { + let signer_account = any_runtime! { + signer::signer_uri_from_string::(&dryrun_config.seed_or_path , &rpc) + .await + .expect("Provided account is invalid, terminating.") + }; + dry_run_cmd(rpc, dryrun_config, signer_account).await .map_err(|e| { log::error!(target: LOG_TARGET, "DryRun error: {:?}", e); - }), - Command::EmergencySolution(cmd) => emergency_solution_cmd(rpc, cmd).await + })}, + Command::EmergencySolution(emergency_solution_config) => { + emergency_solution_cmd(rpc, emergency_solution_config).await .map_err(|e| { log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e); - }), + })}, + Command::Info(_info_opts) => { + let runtime_version: RuntimeVersion = rpc.runtime_version(None).await.expect("runtime_version infallible; qed."); + let info = Info::new(runtime_version.spec_name.to_string(), runtime_version.spec_version); + let info = serde_json::to_string_pretty(&info).expect("Failed serializing infos"); + println!("{}", info); + Ok(()) + } } }; log::info!(target: LOG_TARGET, "round of execution finished. outcome = {:?}", outcome); diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 3bcdcd0146a3..49f0ebc30521 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -3,9 +3,47 @@ use clap::Parser; use sp_runtime::Perbill; use std::str::FromStr; +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +#[clap(author, version, about)] +pub(crate) struct Opt { + /// The `ws` node to connect to. + #[clap(long, short, default_value = DEFAULT_URI, env = "URI")] + pub uri: String, + + #[clap(subcommand)] + pub command: Command, +} + +#[derive(Debug, Clone, Parser)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) enum Command { + /// Monitor for the phase being signed, then compute. + Monitor(MonitorConfig), + + /// Just compute a solution now, and don't submit it. + DryRun(DryRunConfig), + + /// Provide a solution that can be submitted to the chain as an emergency response. + EmergencySolution(EmergencySolutionConfig), + + /// Return information about the current version + Info(InfoOpts), +} + #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] pub(crate) struct MonitorConfig { + /// The path to a file containing the seed of the account. If the file is not found, the seed is + /// used as-is. + /// + /// Can also be provided via the `SEED` environment variable. + /// + /// WARNING: Don't use an account with a large stash for this. Based on how the bot is + /// configured, it might re-try and lose funds through transaction fees/deposits. + #[clap(long, short, env = "SEED")] + pub seed_or_path: String, + /// They type of event to listen to. /// /// Typically, finalized is safer and there is no chance of anything going wrong, but it can be @@ -33,7 +71,17 @@ pub(crate) struct MonitorConfig { #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] -pub(crate) struct EmergencySolutionConfig { +pub(crate) struct DryRunConfig { + /// The path to a file containing the seed of the account. If the file is not found, the seed is + /// used as-is. + /// + /// Can also be provided via the `SEED` environment variable. + /// + /// WARNING: Don't use an account with a large stash for this. Based on how the bot is + /// configured, it might re-try and lose funds through transaction fees/deposits. + #[clap(long, short, env = "SEED")] + pub seed_or_path: String, + /// The block hash at which scraping happens. If none is provided, the latest head is used. #[clap(long)] pub at: Option, @@ -42,13 +90,14 @@ pub(crate) struct EmergencySolutionConfig { #[clap(subcommand)] pub solver: Solver, - /// The number of top backed winners to take. All are taken, if not provided. - pub take: Option, + /// Force create a new snapshot, else expect one to exist onchain. + #[clap(long)] + pub force_snapshot: bool, } #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] -pub(crate) struct DryRunConfig { +pub(crate) struct EmergencySolutionConfig { /// The block hash at which scraping happens. If none is provided, the latest head is used. #[clap(long)] pub at: Option, @@ -57,32 +106,13 @@ pub(crate) struct DryRunConfig { #[clap(subcommand)] pub solver: Solver, - /// Force create a new snapshot, else expect one to exist onchain. - #[clap(long)] - pub force_snapshot: bool, + /// The number of top backed winners to take. All are taken, if not provided. + pub take: Option, } #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] -#[clap(author, version, about)] -pub(crate) struct Opt { - /// The `ws` node to connect to. - #[clap(long, short, default_value = DEFAULT_URI, env = "URI")] - pub uri: String, - - /// The path to a file containing the seed of the account. If the file is not found, the seed is - /// used as-is. - /// - /// Can also be provided via the `SEED` environment variable. - /// - /// WARNING: Don't use an account with a large stash for this. Based on how the bot is - /// configured, it might re-try and lose funds through transaction fees/deposits. - #[clap(long, short, env = "SEED")] - pub seed_or_path: String, - - #[clap(subcommand)] - pub command: Command, -} +pub(crate) struct InfoOpts {} /// Submission strategy to use. #[derive(Debug, Copy, Clone)] @@ -97,17 +127,6 @@ pub enum SubmissionStrategy { ClaimBetterThan(Perbill), } -#[derive(Debug, Clone, Parser)] -#[cfg_attr(test, derive(PartialEq))] -pub(crate) enum Command { - /// Monitor for the phase being signed, then compute. - Monitor(MonitorConfig), - /// Just compute a solution now, and don't submit it. - DryRun(DryRunConfig), - /// Provide a solution that can be submitted to the chain as an emergency response. - EmergencySolution(EmergencySolutionConfig), -} - #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] pub(crate) enum Solver { From acfe01434ba93acacb4e0a5f22edbbbcbc1e88a4 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:33:57 +0200 Subject: [PATCH 03/26] fmt --- utils/staking-miner/src/dry_run.rs | 3 +-- utils/staking-miner/src/main.rs | 4 ++-- utils/staking-miner/src/opts.rs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/utils/staking-miner/src/dry_run.rs b/utils/staking-miner/src/dry_run.rs index e9a13cda77ab..8b105d70eb3b 100644 --- a/utils/staking-miner/src/dry_run.rs +++ b/utils/staking-miner/src/dry_run.rs @@ -16,12 +16,11 @@ //! The dry-run command. -use crate::{prelude::*, rpc::*, signer::Signer, Error, SharedRpcClient}; +use crate::{opts::DryRunConfig, prelude::*, rpc::*, signer::Signer, Error, SharedRpcClient}; use codec::Encode; use frame_support::traits::Currency; use sp_core::Bytes; use sp_npos_elections::ElectionScore; -use crate::opts::DryRunConfig; /// Forcefully create the snapshot. This can be used to compute the election at anytime. fn force_create_snapshot(ext: &mut Ext) -> Result<(), Error> { diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 809f346c1b37..e66869534268 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -385,7 +385,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return; + return } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -496,7 +496,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return; + return }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 49f0ebc30521..5927e302aa02 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -161,7 +161,7 @@ impl FromStr for SubmissionStrategy { let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { - return Err(s.into()); + return Err(s.into()) }; Ok(res) } From b5ccaddbd4fb234be1830dd08aac2b1afeb64e44 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:36:37 +0200 Subject: [PATCH 04/26] remove useless change --- utils/staking-miner/src/macros.rs | 109 ------------------------------ 1 file changed, 109 deletions(-) delete mode 100644 utils/staking-miner/src/macros.rs diff --git a/utils/staking-miner/src/macros.rs b/utils/staking-miner/src/macros.rs deleted file mode 100644 index bb6eb47dea0c..000000000000 --- a/utils/staking-miner/src/macros.rs +++ /dev/null @@ -1,109 +0,0 @@ -// NOTE: this is no longer used extensively, most of the per-runtime stuff us delegated to -// `construct_runtime_prelude` and macro's the import directly from it. A part of the code is also -// still generic over `T`. My hope is to still make everything generic over a `Runtime`, but sadly -// that is not currently possible as each runtime has its unique `Call`, and all Calls are not -// sharing any generic trait. In other words, to create the `UncheckedExtrinsic` of each chain, you -// need the concrete `Call` of that chain as well. -#[macro_export] -macro_rules! any_runtime { - ($($code:tt)*) => { - unsafe { - match $crate::RUNTIME { - $crate::AnyRuntime::Polkadot => { - #[allow(unused)] - use $crate::polkadot_runtime_exports::*; - $($code)* - }, - $crate::AnyRuntime::Kusama => { - #[allow(unused)] - use $crate::kusama_runtime_exports::*; - $($code)* - }, - $crate::AnyRuntime::Westend => { - #[allow(unused)] - use $crate::westend_runtime_exports::*; - $($code)* - } - } - } - } -} - -/// Same as [`any_runtime`], but instead of returning a `Result`, this simply returns `()`. Useful -/// for situations where the result is not useful and un-ergonomic to handle. -#[macro_export] -macro_rules! any_runtime_unit { - ($($code:tt)*) => { - unsafe { - match $crate::RUNTIME { - $crate::AnyRuntime::Polkadot => { - #[allow(unused)] - use $crate::polkadot_runtime_exports::*; - let _ = $($code)*; - }, - $crate::AnyRuntime::Kusama => { - #[allow(unused)] - use $crate::kusama_runtime_exports::*; - let _ = $($code)*; - }, - $crate::AnyRuntime::Westend => { - #[allow(unused)] - use $crate::westend_runtime_exports::*; - let _ = $($code)*; - } - } - } - } -} - -macro_rules! construct_runtime_prelude { - ($runtime:ident) => { paste::paste! { - #[allow(unused_import)] - pub(crate) mod [<$runtime _runtime_exports>] { - pub(crate) use crate::prelude::EPM; - pub(crate) use [<$runtime _runtime>]::*; - pub(crate) use crate::monitor::[] as monitor_cmd; - pub(crate) use crate::dry_run::[] as dry_run_cmd; - pub(crate) use crate::emergency_solution::[] as emergency_solution_cmd; - pub(crate) use private::{[] as create_uxt}; - - mod private { - use super::*; - pub(crate) fn []( - raw_solution: EPM::RawSolution>, - signer: crate::signer::Signer, - nonce: crate::prelude::Index, - tip: crate::prelude::Balance, - era: sp_runtime::generic::Era, - ) -> UncheckedExtrinsic { - use codec::Encode as _; - use sp_core::Pair as _; - use sp_runtime::traits::StaticLookup as _; - - let crate::signer::Signer { account, pair, .. } = signer; - - let local_call = EPMCall::::submit { raw_solution: Box::new(raw_solution) }; - let call: Call = as std::convert::TryInto>::try_into(local_call) - .expect("election provider pallet must exist in the runtime, thus \ - inner call can be converted, qed." - ); - - let extra: SignedExtra = crate::[](nonce, tip, era); - let raw_payload = SignedPayload::new(call, extra).expect("creating signed payload infallible; qed."); - let signature = raw_payload.using_encoded(|payload| { - pair.sign(payload) - }); - let (call, extra, _) = raw_payload.deconstruct(); - let address = ::Lookup::unlookup(account); - let extrinsic = UncheckedExtrinsic::new_signed(call, address, signature.into(), extra); - log::debug!( - target: crate::LOG_TARGET, "constructed extrinsic {} with length {}", - sp_core::hexdisplay::HexDisplay::from(&extrinsic.encode()), - extrinsic.encode().len(), - ); - extrinsic - } - } - }} - }; -} From e870aeaa117c88942b295852313c07b21d641124 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:38:55 +0200 Subject: [PATCH 05/26] Remove unnecessary brackets --- utils/staking-miner/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index e66869534268..66f2049acfd6 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -385,7 +385,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return + return; } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -496,7 +496,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return + return; }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); @@ -528,11 +528,11 @@ async fn main() { .map_err(|e| { log::error!(target: LOG_TARGET, "DryRun error: {:?}", e); })}, - Command::EmergencySolution(emergency_solution_config) => { + Command::EmergencySolution(emergency_solution_config) => emergency_solution_cmd(rpc, emergency_solution_config).await .map_err(|e| { log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e); - })}, + }), Command::Info(_info_opts) => { let runtime_version: RuntimeVersion = rpc.runtime_version(None).await.expect("runtime_version infallible; qed."); let info = Info::new(runtime_version.spec_name.to_string(), runtime_version.spec_version); From d87d5833a53a68136b1fd284168c91745189f320 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:46:47 +0200 Subject: [PATCH 06/26] Fix and add tests --- utils/staking-miner/src/opts.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 5927e302aa02..3974baebd51b 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -161,7 +161,7 @@ impl FromStr for SubmissionStrategy { let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { - return Err(s.into()) + return Err(s.into()); }; Ok(res) } @@ -177,9 +177,9 @@ mod test_super { env!("CARGO_PKG_NAME"), "--uri", "hi", + "monitor", "--seed-or-path", "//Alice", - "monitor", "--listen", "head", "seq-phragmen", @@ -190,8 +190,8 @@ mod test_super { opt, Opt { uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), command: Command::Monitor(MonitorConfig { + seed_or_path: "//Alice".to_string(), listen: "head".to_string(), solver: Solver::SeqPhragmen { iterations: 10 }, submission_strategy: SubmissionStrategy::IfLeading, @@ -206,9 +206,9 @@ mod test_super { env!("CARGO_PKG_NAME"), "--uri", "hi", + "dry-run", "--seed-or-path", "//Alice", - "dry-run", "phrag-mms", ]) .unwrap(); @@ -217,8 +217,8 @@ mod test_super { opt, Opt { uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), command: Command::DryRun(DryRunConfig { + seed_or_path: "//Alice".to_string(), at: None, solver: Solver::PhragMMS { iterations: 10 }, force_snapshot: false, @@ -233,8 +233,6 @@ mod test_super { env!("CARGO_PKG_NAME"), "--uri", "hi", - "--seed-or-path", - "//Alice", "emergency-solution", "99", "phrag-mms", @@ -247,7 +245,6 @@ mod test_super { opt, Opt { uri: "hi".to_string(), - seed_or_path: "//Alice".to_string(), command: Command::EmergencySolution(EmergencySolutionConfig { take: Some(99), at: None, @@ -257,6 +254,13 @@ mod test_super { ); } + #[test] + fn cli_info_works() { + let opt = Opt::try_parse_from([env!("CARGO_PKG_NAME"), "--uri", "hi", "info"]).unwrap(); + + assert_eq!(opt, Opt { uri: "hi".to_string(), command: Command::Info(InfoOpts {}) }); + } + #[test] fn submission_strategy_from_str_works() { use std::str::FromStr; From cc34f7f94e8c3621fbca20667304b89dd29ef980 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:48:12 +0200 Subject: [PATCH 07/26] fmt --- utils/staking-miner/src/main.rs | 4 ++-- utils/staking-miner/src/opts.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 66f2049acfd6..cf191ad38d32 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -385,7 +385,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return; + return } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -496,7 +496,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return; + return }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 3974baebd51b..8ac0fccf1aaa 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -161,7 +161,7 @@ impl FromStr for SubmissionStrategy { let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { - return Err(s.into()); + return Err(s.into()) }; Ok(res) } From 1124d053660df8be285229abecaf7f0f9838c59c Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Fri, 20 May 2022 18:52:01 +0200 Subject: [PATCH 08/26] Promote the uri flag to global --- utils/staking-miner/src/opts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 8ac0fccf1aaa..67e7153f3aae 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -8,7 +8,7 @@ use std::str::FromStr; #[clap(author, version, about)] pub(crate) struct Opt { /// The `ws` node to connect to. - #[clap(long, short, default_value = DEFAULT_URI, env = "URI")] + #[clap(long, short, default_value = DEFAULT_URI, env = "URI", global = true)] pub uri: String, #[clap(subcommand)] From e6c093cabed64fceac619fb9bc6edf1c94b8ccae Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sun, 5 Jun 2022 17:33:50 +0100 Subject: [PATCH 09/26] Ignore lint identity ops --- runtime/kusama/constants/src/lib.rs | 1 + utils/staking-miner/src/dry_run.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/kusama/constants/src/lib.rs b/runtime/kusama/constants/src/lib.rs index 00e429cff568..f2cbee0a52c7 100644 --- a/runtime/kusama/constants/src/lib.rs +++ b/runtime/kusama/constants/src/lib.rs @@ -15,6 +15,7 @@ // along with Polkadot. If not, see . #![cfg_attr(not(feature = "std"), no_std)] +#[allow(identity_op)] pub mod weights; diff --git a/utils/staking-miner/src/dry_run.rs b/utils/staking-miner/src/dry_run.rs index 8b105d70eb3b..970f50c50398 100644 --- a/utils/staking-miner/src/dry_run.rs +++ b/utils/staking-miner/src/dry_run.rs @@ -77,7 +77,7 @@ async fn print_info( ); }); - let info = rpc.payment_query_info(&extrinsic, None).await; + let info = rpc.payment_query_info(extrinsic, None).await; log::info!( target: LOG_TARGET, From d1b774643432faab2349aea54830ca7ba442e3e4 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sun, 5 Jun 2022 17:37:47 +0100 Subject: [PATCH 10/26] fmt --- runtime/kusama/constants/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/kusama/constants/src/lib.rs b/runtime/kusama/constants/src/lib.rs index f2cbee0a52c7..d88e642dcd40 100644 --- a/runtime/kusama/constants/src/lib.rs +++ b/runtime/kusama/constants/src/lib.rs @@ -16,7 +16,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #[allow(identity_op)] - pub mod weights; /// Money matters. From 15ad5dc9a5b1fd2ef62c54bc94ecbff44eda21e6 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sun, 5 Jun 2022 17:42:38 +0100 Subject: [PATCH 11/26] Reverse adding #[allow(identity_op)] --- runtime/kusama/constants/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/kusama/constants/src/lib.rs b/runtime/kusama/constants/src/lib.rs index d88e642dcd40..00e429cff568 100644 --- a/runtime/kusama/constants/src/lib.rs +++ b/runtime/kusama/constants/src/lib.rs @@ -15,7 +15,7 @@ // along with Polkadot. If not, see . #![cfg_attr(not(feature = "std"), no_std)] -#[allow(identity_op)] + pub mod weights; /// Money matters. From 825613dd1fd5680de91aaa5ec21313f7ade8b18e Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sun, 5 Jun 2022 18:27:09 +0100 Subject: [PATCH 12/26] Typo --- utils/staking-miner/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/staking-miner/README.md b/utils/staking-miner/README.md index 2190443003e7..599217e7e134 100644 --- a/utils/staking-miner/README.md +++ b/utils/staking-miner/README.md @@ -28,7 +28,7 @@ There are 2 options to build a staking-miner Docker image: ### Building the injected image First build the binary as documented [above](#building). -You may then inject the binary into a Docker base image usingfrom the root of the Polkadot repository: +You may then inject the binary into a Docker base image from the root of the Polkadot repository: ``` docker build -t staking-miner -f scripts/ci/dockerfiles/staking-miner/staking-miner_injected.Dockerfile target/release ``` From 5ab43e5fc3ba390b551b8aad4c1f82286b4c052c Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Mon, 6 Jun 2022 14:40:29 +0100 Subject: [PATCH 13/26] Add cli test for the info command --- utils/staking-miner/tests/cli.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/utils/staking-miner/tests/cli.rs b/utils/staking-miner/tests/cli.rs index 46f5cf0cb0b2..0d6393f2040f 100644 --- a/utils/staking-miner/tests/cli.rs +++ b/utils/staking-miner/tests/cli.rs @@ -1,4 +1,5 @@ use assert_cmd::{cargo::cargo_bin, Command}; +use serde_json::{Result, Value}; #[test] fn cli_version_works() { @@ -10,3 +11,20 @@ fn cli_version_works() { assert_eq!(version, format!("{} {}", crate_name, env!("CARGO_PKG_VERSION"))); } + +#[test] +fn cli_info_works() { + let crate_name = env!("CARGO_PKG_NAME"); + let output = Command::new(cargo_bin(crate_name)) + .arg("info") + .env("RUST_LOG", "none") + .output() + .unwrap(); + + assert!(output.status.success(), "command returned with non-success exit code"); + let info = String::from_utf8_lossy(&output.stdout).trim().to_owned(); + let v: Result = serde_json::from_str(&info); + let v = v.unwrap(); + assert!(!v["spec_name"].to_string().is_empty()); + assert!(!v["version"].to_string().is_empty()); +} From bda111a63659937681528aef0cae787f7ba57df0 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Mon, 6 Jun 2022 14:55:31 +0100 Subject: [PATCH 14/26] Add licende headers and fix some grumbles --- utils/staking-miner/src/info.rs | 22 +++++++++++++++++++++- utils/staking-miner/src/main.rs | 4 ++-- utils/staking-miner/src/opts.rs | 16 ++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/utils/staking-miner/src/info.rs b/utils/staking-miner/src/info.rs index f3bb6d349612..5662c20be3f3 100644 --- a/utils/staking-miner/src/info.rs +++ b/utils/staking-miner/src/info.rs @@ -1,3 +1,21 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use sp_version::RuntimeVersion; + #[derive(Debug, serde::Serialize)] pub(crate) struct Info { pub spec_name: String, @@ -5,7 +23,9 @@ pub(crate) struct Info { } impl Info { - pub fn new(spec_name: String, spec_version: u32) -> Self { + pub fn new(runtime_version: &RuntimeVersion) -> Self { + let spec_name = runtime_version.spec_name.to_string(); + let spec_version = runtime_version.spec_version; Self { spec_name, spec_version } } } diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index cf191ad38d32..17b7afdd3748 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -535,8 +535,8 @@ async fn main() { }), Command::Info(_info_opts) => { let runtime_version: RuntimeVersion = rpc.runtime_version(None).await.expect("runtime_version infallible; qed."); - let info = Info::new(runtime_version.spec_name.to_string(), runtime_version.spec_version); - let info = serde_json::to_string_pretty(&info).expect("Failed serializing infos"); + let info = Info::new(&runtime_version); + let info = serde_json::to_string_pretty(&info).expect("Failed serializing version info"); println!("{}", info); Ok(()) } diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 67e7153f3aae..d96a613b7bb0 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -1,3 +1,19 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + use crate::prelude::*; use clap::Parser; use sp_runtime::Perbill; From 1f998ef736d7310e0a60f2dc8fb43f513fe8f09b Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Tue, 21 Jun 2022 21:41:19 +0200 Subject: [PATCH 15/26] Add retrieval of the linked version and make the json output optional --- utils/staking-miner/src/dry_run.rs | 2 +- utils/staking-miner/src/info.rs | 31 ----------- utils/staking-miner/src/main.rs | 30 +++++++---- utils/staking-miner/src/opts.rs | 5 +- utils/staking-miner/src/runtime_versions.rs | 58 +++++++++++++++++++++ 5 files changed, 82 insertions(+), 44 deletions(-) delete mode 100644 utils/staking-miner/src/info.rs create mode 100644 utils/staking-miner/src/runtime_versions.rs diff --git a/utils/staking-miner/src/dry_run.rs b/utils/staking-miner/src/dry_run.rs index 970f50c50398..8b105d70eb3b 100644 --- a/utils/staking-miner/src/dry_run.rs +++ b/utils/staking-miner/src/dry_run.rs @@ -77,7 +77,7 @@ async fn print_info( ); }); - let info = rpc.payment_query_info(extrinsic, None).await; + let info = rpc.payment_query_info(&extrinsic, None).await; log::info!( target: LOG_TARGET, diff --git a/utils/staking-miner/src/info.rs b/utils/staking-miner/src/info.rs deleted file mode 100644 index 5662c20be3f3..000000000000 --- a/utils/staking-miner/src/info.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -use sp_version::RuntimeVersion; - -#[derive(Debug, serde::Serialize)] -pub(crate) struct Info { - pub spec_name: String, - pub spec_version: u32, -} - -impl Info { - pub fn new(runtime_version: &RuntimeVersion) -> Self { - let spec_name = runtime_version.spec_name.to_string(); - let spec_version = runtime_version.spec_version; - Self { spec_name, spec_version } - } -} diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 17b7afdd3748..846230b041f9 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -30,11 +30,11 @@ mod dry_run; mod emergency_solution; -mod info; mod monitor; mod opts; mod prelude; mod rpc; +mod runtime_versions; mod signer; pub(crate) use prelude::*; @@ -44,15 +44,14 @@ use crate::opts::*; use clap::Parser; use frame_election_provider_support::NposSolver; use frame_support::traits::Get; -use info::*; use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; use remote_externalities::{Builder, Mode, OnlineConfig}; use rpc::{RpcApiClient, SharedRpcClient}; use sp_npos_elections::BalancingConfig; use sp_runtime::{traits::Block as BlockT, DeserializeOwned, Perbill}; -use tracing_subscriber::{fmt, EnvFilter}; use std::{ops::Deref, sync::Arc}; use tracing_subscriber::{fmt, EnvFilter}; +use tracing_subscriber::{fmt, EnvFilter}; pub(crate) enum AnyRuntime { Polkadot, @@ -64,7 +63,6 @@ pub(crate) static mut RUNTIME: AnyRuntime = AnyRuntime::Polkadot; macro_rules! construct_runtime_prelude { ($runtime:ident) => { paste::paste! { - #[allow(unused_import)] pub(crate) mod [<$runtime _runtime_exports>] { pub(crate) use crate::prelude::EPM; pub(crate) use [<$runtime _runtime>]::*; @@ -385,7 +383,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return + return; } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -496,7 +494,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return + return; }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); @@ -533,11 +531,21 @@ async fn main() { .map_err(|e| { log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e); }), - Command::Info(_info_opts) => { - let runtime_version: RuntimeVersion = rpc.runtime_version(None).await.expect("runtime_version infallible; qed."); - let info = Info::new(&runtime_version); - let info = serde_json::to_string_pretty(&info).expect("Failed serializing version info"); - println!("{}", info); + Command::Info(info_opts) => { + let remote_runtime_version = rpc.runtime_version(None).await.expect("runtime_version infallible; qed."); + + let builtin_version = any_runtime! { + Version::get() + }; + + let versions = RuntimeVersions::new(&remote_runtime_version, &builtin_version); + + if !info_opts.json { + println!("{}", versions); + } else { + let versions = serde_json::to_string_pretty(&versions).expect("Failed serializing version info"); + println!("{}", versions); + } Ok(()) } } diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index d96a613b7bb0..8c8bd99eeb30 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -128,7 +128,10 @@ pub(crate) struct EmergencySolutionConfig { #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] -pub(crate) struct InfoOpts {} +pub(crate) struct InfoOpts { + #[clap(long, short)] + pub json: bool, +} /// Submission strategy to use. #[derive(Debug, Copy, Clone)] diff --git a/utils/staking-miner/src/runtime_versions.rs b/utils/staking-miner/src/runtime_versions.rs new file mode 100644 index 000000000000..47701560ef2e --- /dev/null +++ b/utils/staking-miner/src/runtime_versions.rs @@ -0,0 +1,58 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use sp_version::RuntimeVersion; +use std::fmt; + +#[derive(Debug, serde::Serialize)] +pub(crate) struct SimpleRuntimeVersion { + pub spec_name: String, + pub spec_version: u32, +} + +impl fmt::Display for SimpleRuntimeVersion { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln!(f, "{} v{}", self.spec_name, self.spec_version) + } +} + +impl From<&RuntimeVersion> for SimpleRuntimeVersion { + fn from(r: &RuntimeVersion) -> Self { + Self { spec_name: r.spec_name.to_string(), spec_version: r.spec_version } + } +} + +#[derive(Debug, serde::Serialize)] +pub(crate) struct RuntimeVersions { + pub builtin: SimpleRuntimeVersion, + pub remote: SimpleRuntimeVersion, +} + +impl RuntimeVersions { + pub fn new( + remote_runtime_version: &RuntimeVersion, + builtin_runtime_version: &RuntimeVersion, + ) -> Self { + Self { remote: remote_runtime_version.into(), builtin: builtin_runtime_version.into() } + } +} + +impl fmt::Display for RuntimeVersions { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let _ = write!(f, "- builtin: {}", self.builtin); + write!(f, "- remote : {}", self.remote) + } +} From 6200a7b2d8b797f47ed340ee3a3faa602a06696d Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Tue, 21 Jun 2022 22:07:56 +0200 Subject: [PATCH 16/26] Cleanup --- utils/staking-miner/src/main.rs | 2 +- utils/staking-miner/src/opts.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 846230b041f9..a87833a99b3b 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -48,7 +48,7 @@ use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; use remote_externalities::{Builder, Mode, OnlineConfig}; use rpc::{RpcApiClient, SharedRpcClient}; use sp_npos_elections::BalancingConfig; -use sp_runtime::{traits::Block as BlockT, DeserializeOwned, Perbill}; +use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; use std::{ops::Deref, sync::Arc}; use tracing_subscriber::{fmt, EnvFilter}; use tracing_subscriber::{fmt, EnvFilter}; diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 8c8bd99eeb30..9f53da38a0e4 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -129,6 +129,7 @@ pub(crate) struct EmergencySolutionConfig { #[derive(Debug, Clone, Parser)] #[cfg_attr(test, derive(PartialEq))] pub(crate) struct InfoOpts { + /// Serialize the output as json #[clap(long, short)] pub json: bool, } From d1ed2d3451b82e3f69a85a916f8c8f9f022188fe Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Tue, 21 Jun 2022 22:21:14 +0200 Subject: [PATCH 17/26] Fix tests --- utils/staking-miner/src/opts.rs | 5 ++++- utils/staking-miner/tests/cli.rs | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 9f53da38a0e4..bcbc120907e7 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -278,7 +278,10 @@ mod test_super { fn cli_info_works() { let opt = Opt::try_parse_from([env!("CARGO_PKG_NAME"), "--uri", "hi", "info"]).unwrap(); - assert_eq!(opt, Opt { uri: "hi".to_string(), command: Command::Info(InfoOpts {}) }); + assert_eq!( + opt, + Opt { uri: "hi".to_string(), command: Command::Info(InfoOpts { json: true }) } + ); } #[test] diff --git a/utils/staking-miner/tests/cli.rs b/utils/staking-miner/tests/cli.rs index 0d6393f2040f..ebd5380f047b 100644 --- a/utils/staking-miner/tests/cli.rs +++ b/utils/staking-miner/tests/cli.rs @@ -17,6 +17,7 @@ fn cli_info_works() { let crate_name = env!("CARGO_PKG_NAME"); let output = Command::new(cargo_bin(crate_name)) .arg("info") + .arg("--json") .env("RUST_LOG", "none") .output() .unwrap(); @@ -25,6 +26,8 @@ fn cli_info_works() { let info = String::from_utf8_lossy(&output.stdout).trim().to_owned(); let v: Result = serde_json::from_str(&info); let v = v.unwrap(); - assert!(!v["spec_name"].to_string().is_empty()); - assert!(!v["version"].to_string().is_empty()); + assert!(!v["builtin"].to_string().is_empty()); + assert!(!v["builtin"]["spec_name"].to_string().is_empty()); + assert!(!v["builtin"]["spec_version"].to_string().is_empty()); + assert!(!v["remote"].to_string().is_empty()); } From a3783aeffad151a05d6a1aba38463431f363a723 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 00:35:54 +0200 Subject: [PATCH 18/26] Keep it generic and renamed builtin into linked --- utils/staking-miner/src/main.rs | 1 - utils/staking-miner/src/runtime_versions.rs | 53 +++++++++++++-------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index a87833a99b3b..3479bc6146f2 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -51,7 +51,6 @@ use sp_npos_elections::BalancingConfig; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; use std::{ops::Deref, sync::Arc}; use tracing_subscriber::{fmt, EnvFilter}; -use tracing_subscriber::{fmt, EnvFilter}; pub(crate) enum AnyRuntime { Polkadot, diff --git a/utils/staking-miner/src/runtime_versions.rs b/utils/staking-miner/src/runtime_versions.rs index 47701560ef2e..37063d0d2d7d 100644 --- a/utils/staking-miner/src/runtime_versions.rs +++ b/utils/staking-miner/src/runtime_versions.rs @@ -18,41 +18,56 @@ use sp_version::RuntimeVersion; use std::fmt; #[derive(Debug, serde::Serialize)] -pub(crate) struct SimpleRuntimeVersion { - pub spec_name: String, - pub spec_version: u32, -} +pub(crate) struct RuntimeWrapper<'a>(pub &'a RuntimeVersion); -impl fmt::Display for SimpleRuntimeVersion { +impl<'a> fmt::Display for RuntimeWrapper<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "{} v{}", self.spec_name, self.spec_version) + let width = 16; + + writeln!( + f, + r#" impl_name : {impl_name:>width$} + spec_name : {spec_name:>width$} + spec_version : {spec_version:>width$} + transaction_version : {transaction_version:>width$} + impl_version : {impl_version:>width$} + authoringVersion : {authoring_version:>width$} + state_version : {state_version:>width$}"#, + spec_name = self.0.spec_name.to_string(), + impl_name = self.0.impl_name.to_string(), + spec_version = self.0.spec_version, + impl_version = self.0.impl_version, + authoring_version = self.0.authoring_version, + transaction_version = self.0.transaction_version, + state_version = self.0.state_version, + ) } } -impl From<&RuntimeVersion> for SimpleRuntimeVersion { - fn from(r: &RuntimeVersion) -> Self { - Self { spec_name: r.spec_name.to_string(), spec_version: r.spec_version } +impl<'a> From<&'a RuntimeVersion> for RuntimeWrapper<'a> { + fn from(r: &'a RuntimeVersion) -> Self { + RuntimeWrapper(r) } } #[derive(Debug, serde::Serialize)] -pub(crate) struct RuntimeVersions { - pub builtin: SimpleRuntimeVersion, - pub remote: SimpleRuntimeVersion, +pub(crate) struct RuntimeVersions<'a> { + pub linked: RuntimeWrapper<'a>, + pub remote: RuntimeWrapper<'a>, } -impl RuntimeVersions { +impl<'a> RuntimeVersions<'a> { pub fn new( - remote_runtime_version: &RuntimeVersion, - builtin_runtime_version: &RuntimeVersion, + remote_runtime_version: &'a RuntimeVersion, + linked_runtime_version: &'a RuntimeVersion, ) -> Self { - Self { remote: remote_runtime_version.into(), builtin: builtin_runtime_version.into() } + Self { remote: remote_runtime_version.into(), linked: linked_runtime_version.into() } } } -impl fmt::Display for RuntimeVersions { +impl<'a> fmt::Display for RuntimeVersions<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let _ = write!(f, "- builtin: {}", self.builtin); - write!(f, "- remote : {}", self.remote) + let _ = write!(f, "- linked:\n{}", self.linked); + write!(f, "- remote :\n{}", self.remote) } } From 4a38ea60756d0a991c547624c260c773717d75d3 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 00:51:17 +0200 Subject: [PATCH 19/26] Rebase master --- utils/staking-miner/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 3479bc6146f2..7303ad833389 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -47,6 +47,7 @@ use frame_support::traits::Get; use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; use remote_externalities::{Builder, Mode, OnlineConfig}; use rpc::{RpcApiClient, SharedRpcClient}; +use runtime_versions::RuntimeVersions; use sp_npos_elections::BalancingConfig; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; use std::{ops::Deref, sync::Arc}; @@ -382,7 +383,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { voters.into_iter().for_each(|(who, stake, targets)| { if targets.is_empty() { println!("target = {:?}", (who, stake, targets)); - return; + return } let share: u128 = (stake as u128) / (targets.len() as u128); for target in targets { @@ -493,7 +494,7 @@ async fn main() { }, _ => { eprintln!("unexpected chain: {:?}", chain); - return; + return }, } log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); From 94b16e8dc40ed04c443dee28d31b5401260dd533 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 09:49:23 +0200 Subject: [PATCH 20/26] Add runtimes compatibility information --- utils/staking-miner/src/runtime_versions.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/utils/staking-miner/src/runtime_versions.rs b/utils/staking-miner/src/runtime_versions.rs index 37063d0d2d7d..1a473d076f5a 100644 --- a/utils/staking-miner/src/runtime_versions.rs +++ b/utils/staking-miner/src/runtime_versions.rs @@ -52,8 +52,15 @@ impl<'a> From<&'a RuntimeVersion> for RuntimeWrapper<'a> { #[derive(Debug, serde::Serialize)] pub(crate) struct RuntimeVersions<'a> { + /// The `RuntimeVersion` linked in the staking-miner pub linked: RuntimeWrapper<'a>, + + /// The `RuntimeVersion` reported by the node we connect to via RPC pub remote: RuntimeWrapper<'a>, + + /// This bool reports whether both remote and linked `RuntimeVersion` are compatible + /// and if the staking-miner is expected to work properly against the remote runtime + compatible: bool, } impl<'a> RuntimeVersions<'a> { @@ -61,13 +68,23 @@ impl<'a> RuntimeVersions<'a> { remote_runtime_version: &'a RuntimeVersion, linked_runtime_version: &'a RuntimeVersion, ) -> Self { - Self { remote: remote_runtime_version.into(), linked: linked_runtime_version.into() } + Self { + remote: remote_runtime_version.into(), + linked: linked_runtime_version.into(), + compatible: are_runtimes_compatible(remote_runtime_version, linked_runtime_version), + } } } +/// Check whether runtimes are compatible. Currently we only support equality. +fn are_runtimes_compatible(r1: &RuntimeVersion, r2: &RuntimeVersion) -> bool { + r1 == r2 +} + impl<'a> fmt::Display for RuntimeVersions<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let _ = write!(f, "- linked:\n{}", self.linked); - write!(f, "- remote :\n{}", self.remote) + let _ = write!(f, "- remote :\n{}", self.remote); + write!(f, "Compatibles: {}", if self.compatible { "YES" } else { "NO" }) } } From 9f421eb14c9ddce6be49bd633ba35e99b725121c Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 13:00:46 +0200 Subject: [PATCH 21/26] Silence erroneous warning about unsafe --- utils/staking-miner/src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 7303ad833389..1f847022deb0 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -28,6 +28,10 @@ //! development. It is intended to run this bot with a `restart = true` way, so that it reports it //! crash, but resumes work thereafter. +// Silence erroneous warning about unsafe not being required whereas it is +// see https://github.com/rust-lang/rust/issues/49112 +#![allow(unused_unsafe)] + mod dry_run; mod emergency_solution; mod monitor; @@ -52,7 +56,6 @@ use sp_npos_elections::BalancingConfig; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; use std::{ops::Deref, sync::Arc}; use tracing_subscriber::{fmt, EnvFilter}; - pub(crate) enum AnyRuntime { Polkadot, Kusama, @@ -178,9 +181,11 @@ construct_runtime_prelude!(westend); // that is not currently possible as each runtime has its unique `Call`, and all Calls are not // sharing any generic trait. In other words, to create the `UncheckedExtrinsic` of each chain, you // need the concrete `Call` of that chain as well. + #[macro_export] macro_rules! any_runtime { ($($code:tt)*) => { + unsafe { match $crate::RUNTIME { $crate::AnyRuntime::Polkadot => { @@ -208,6 +213,7 @@ macro_rules! any_runtime { #[macro_export] macro_rules! any_runtime_unit { ($($code:tt)*) => { + #[allow(unused_unsafe)] unsafe { match $crate::RUNTIME { $crate::AnyRuntime::Polkadot => { From bcd461a5da786b43a70843023420a36b5edf4b7f Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 13:04:08 +0200 Subject: [PATCH 22/26] Cleanup --- utils/staking-miner/src/main.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 1f847022deb0..fd1281e2ec59 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -181,11 +181,9 @@ construct_runtime_prelude!(westend); // that is not currently possible as each runtime has its unique `Call`, and all Calls are not // sharing any generic trait. In other words, to create the `UncheckedExtrinsic` of each chain, you // need the concrete `Call` of that chain as well. - #[macro_export] macro_rules! any_runtime { ($($code:tt)*) => { - unsafe { match $crate::RUNTIME { $crate::AnyRuntime::Polkadot => { @@ -213,7 +211,6 @@ macro_rules! any_runtime { #[macro_export] macro_rules! any_runtime_unit { ($($code:tt)*) => { - #[allow(unused_unsafe)] unsafe { match $crate::RUNTIME { $crate::AnyRuntime::Polkadot => { From d8d1423b7f55bf2631db4a5bce08674873b46699 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Wed, 22 Jun 2022 13:09:13 +0200 Subject: [PATCH 23/26] Fix spellcheck --- utils/staking-miner/src/runtime_versions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/staking-miner/src/runtime_versions.rs b/utils/staking-miner/src/runtime_versions.rs index 1a473d076f5a..2bdc73521fdf 100644 --- a/utils/staking-miner/src/runtime_versions.rs +++ b/utils/staking-miner/src/runtime_versions.rs @@ -58,7 +58,7 @@ pub(crate) struct RuntimeVersions<'a> { /// The `RuntimeVersion` reported by the node we connect to via RPC pub remote: RuntimeWrapper<'a>, - /// This bool reports whether both remote and linked `RuntimeVersion` are compatible + /// This `bool` reports whether both remote and linked `RuntimeVersion` are compatible /// and if the staking-miner is expected to work properly against the remote runtime compatible: bool, } From e59cfa2bc3afa51e7d3cc4abddde7621d79bc90f Mon Sep 17 00:00:00 2001 From: Chevdor Date: Wed, 22 Jun 2022 15:47:19 +0200 Subject: [PATCH 24/26] Update utils/staking-miner/src/runtime_versions.rs Co-authored-by: Niklas Adolfsson --- utils/staking-miner/src/runtime_versions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/staking-miner/src/runtime_versions.rs b/utils/staking-miner/src/runtime_versions.rs index 2bdc73521fdf..20e4bd435a63 100644 --- a/utils/staking-miner/src/runtime_versions.rs +++ b/utils/staking-miner/src/runtime_versions.rs @@ -85,6 +85,6 @@ impl<'a> fmt::Display for RuntimeVersions<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let _ = write!(f, "- linked:\n{}", self.linked); let _ = write!(f, "- remote :\n{}", self.remote); - write!(f, "Compatibles: {}", if self.compatible { "YES" } else { "NO" }) + write!(f, "Compatible: {}", if self.compatible { "YES" } else { "NO" }) } } From ed4f9b66f680e88199b00dc7d7195728a3c4ce4e Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sat, 25 Jun 2022 13:44:55 +0200 Subject: [PATCH 25/26] Fix test --- utils/staking-miner/src/opts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index bcbc120907e7..b96a8218b451 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -181,7 +181,7 @@ impl FromStr for SubmissionStrategy { let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { - return Err(s.into()) + return Err(s.into()); }; Ok(res) } @@ -280,7 +280,7 @@ mod test_super { assert_eq!( opt, - Opt { uri: "hi".to_string(), command: Command::Info(InfoOpts { json: true }) } + Opt { uri: "hi".to_string(), command: Command::Info(InfoOpts { json: false }) } ); } From d7d154058af76edf01b7ff027e6e0459c5578715 Mon Sep 17 00:00:00 2001 From: Wilfried Kopp Date: Sat, 25 Jun 2022 13:46:06 +0200 Subject: [PATCH 26/26] fmt --- utils/staking-miner/src/opts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index b96a8218b451..63425b89a105 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -181,7 +181,7 @@ impl FromStr for SubmissionStrategy { let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { - return Err(s.into()); + return Err(s.into()) }; Ok(res) }