mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Allow staking miner to use different election algorithms (#3752)
* WIP * Dry run cmd working * Monitor cmd works * Configure balance with parameter type * Comments * cleannnn * Add balancing to PhragMMS * Move OffchainRanomBalancing to common * DRY mine_unchecked over config.solver * FMT * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Improve docs for any_runtime_unit! * Some cleanup * fmt * Correct capitilaztion * Improve version mismatch log * Revert "Improve version mismatch log" This reverts commit 57570403f654f1efa4307956cda2de6f0c64f70a. * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Remove Balancing struct and use Balancing Parameter type instead * update Substrate Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: parity-processbot <>
This commit is contained in:
Generated
+164
-170
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
|
||||
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
|
||||
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -90,6 +91,7 @@ std = [
|
||||
"libsecp256k1/std",
|
||||
"runtime-parachains/std",
|
||||
"xcm/std",
|
||||
"sp-npos-elections/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"libsecp256k1/hmac",
|
||||
|
||||
@@ -55,3 +55,30 @@ impl pallet_election_provider_multi_phase::BenchmarkingConfig for BenchmarkConfi
|
||||
const MINER_MAXIMUM_VOTERS: u32 = 15_000;
|
||||
const MAXIMUM_TARGETS: u32 = 2000;
|
||||
}
|
||||
|
||||
/// Maximum number of iterations for balancing that will be executed in the embedded miner of
|
||||
/// pallet-election-provider-multi-phase.
|
||||
pub const MINER_MAX_ITERATIONS: u32 = 10;
|
||||
|
||||
/// A source of random balance for the NPoS Solver, which is meant to be run by the OCW election
|
||||
/// miner.
|
||||
pub struct OffchainRandomBalancing;
|
||||
impl frame_support::pallet_prelude::Get<Option<(usize, sp_npos_elections::ExtendedBalance)>>
|
||||
for OffchainRandomBalancing
|
||||
{
|
||||
fn get() -> Option<(usize, sp_npos_elections::ExtendedBalance)> {
|
||||
use sp_runtime::{codec::Decode, traits::TrailingZeroInput};
|
||||
let iters = match MINER_MAX_ITERATIONS {
|
||||
0 => 0,
|
||||
max @ _ => {
|
||||
let seed = sp_io::offchain::random_seed();
|
||||
let random = <u32>::decode(&mut TrailingZeroInput::new(&seed))
|
||||
.expect("input is padded with zeroes; qed") %
|
||||
max.saturating_add(1);
|
||||
random as usize
|
||||
},
|
||||
};
|
||||
|
||||
Some((iters, 0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,6 @@ parameter_types! {
|
||||
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||
|
||||
// miner configs
|
||||
pub const MinerMaxIterations: u32 = 10;
|
||||
pub OffchainRepeat: BlockNumber = 5;
|
||||
}
|
||||
|
||||
@@ -384,7 +383,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type RewardHandler = (); // nothing to do upon rewards
|
||||
type SignedPhase = SignedPhase;
|
||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||
type MinerMaxIterations = MinerMaxIterations;
|
||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||
type OffchainRepeat = OffchainRepeat;
|
||||
@@ -393,6 +391,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type Solution = NposCompactSolution24;
|
||||
type OnChainAccuracy = Perbill;
|
||||
type Fallback = Fallback;
|
||||
type Solver = frame_election_provider_support::SequentialPhragmen<
|
||||
AccountId,
|
||||
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
|
||||
runtime_common::elections::OffchainRandomBalancing,
|
||||
>;
|
||||
type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||
type ForceOrigin = EnsureOneOf<
|
||||
AccountId,
|
||||
|
||||
@@ -362,7 +362,6 @@ parameter_types! {
|
||||
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||
|
||||
// miner configs
|
||||
pub const MinerMaxIterations: u32 = 10;
|
||||
pub OffchainRepeat: BlockNumber = 5;
|
||||
}
|
||||
|
||||
@@ -390,7 +389,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type SlashHandler = (); // burn slashes
|
||||
type RewardHandler = (); // nothing to do upon rewards
|
||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||
type MinerMaxIterations = MinerMaxIterations;
|
||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||
type OffchainRepeat = OffchainRepeat;
|
||||
@@ -399,6 +397,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type OnChainAccuracy = Perbill;
|
||||
type Solution = NposCompactSolution16;
|
||||
type Fallback = Fallback;
|
||||
type Solver = frame_election_provider_support::SequentialPhragmen<
|
||||
AccountId,
|
||||
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
|
||||
runtime_common::elections::OffchainRandomBalancing,
|
||||
>;
|
||||
type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||
type ForceOrigin = EnsureOneOf<
|
||||
AccountId,
|
||||
|
||||
@@ -342,7 +342,6 @@ parameter_types! {
|
||||
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||
|
||||
// miner configs
|
||||
pub const MinerMaxIterations: u32 = 10;
|
||||
pub OffchainRepeat: BlockNumber = 5;
|
||||
}
|
||||
|
||||
@@ -370,7 +369,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type SlashHandler = (); // burn slashes
|
||||
type RewardHandler = (); // nothing to do upon rewards
|
||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||
type MinerMaxIterations = MinerMaxIterations;
|
||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||
type OffchainRepeat = OffchainRepeat;
|
||||
@@ -379,6 +377,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
||||
type OnChainAccuracy = Perbill;
|
||||
type Solution = NposCompactSolution16;
|
||||
type Fallback = Fallback;
|
||||
type Solver = frame_election_provider_support::SequentialPhragmen<
|
||||
AccountId,
|
||||
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
|
||||
runtime_common::elections::OffchainRandomBalancing,
|
||||
>;
|
||||
type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>;
|
||||
|
||||
@@ -22,11 +22,13 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-election-provider-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -23,7 +23,7 @@ use codec::Encode;
|
||||
use frame_support::traits::Currency;
|
||||
|
||||
/// Forcefully create the snapshot. This can be used to compute the election at anytime.
|
||||
fn force_create_snapshot<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error> {
|
||||
fn force_create_snapshot<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>> {
|
||||
ext.execute_with(|| {
|
||||
if <EPM::Snapshot<T>>::exists() {
|
||||
log::info!(target: LOG_TARGET, "snapshot already exists.");
|
||||
@@ -112,7 +112,7 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||
shared: SharedConfig,
|
||||
config: DryRunConfig,
|
||||
signer: Signer,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||
use $crate::[<$runtime _runtime_exports>]::*;
|
||||
let mut ext = crate::create_election_ext::<Runtime, Block>(
|
||||
shared.uri.clone(),
|
||||
@@ -121,7 +121,8 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||
).await?;
|
||||
force_create_snapshot::<Runtime>(&mut ext)?;
|
||||
|
||||
let (raw_solution, witness) = crate::mine_unchecked::<Runtime>(&mut ext, config.iterations, false)?;
|
||||
let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext)?;
|
||||
|
||||
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, config.at)
|
||||
.await?
|
||||
.map(|i| i.nonce)
|
||||
@@ -148,7 +149,9 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||
});
|
||||
log::info!(target: LOG_TARGET, "dispatch result is {:?}", dispatch_result);
|
||||
|
||||
let outcome = rpc_decode::<sp_runtime::ApplyExtrinsicResult>(client, "system_dryRun", params!{ bytes }).await?;
|
||||
let outcome = rpc_decode::<sp_runtime::ApplyExtrinsicResult>(client, "system_dryRun", params!{ bytes })
|
||||
.await
|
||||
.map_err::<Error<Runtime>, _>(Into::into)?;
|
||||
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", outcome);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -18,20 +18,22 @@
|
||||
|
||||
use crate::{prelude::*, Error, SharedConfig};
|
||||
use codec::Encode;
|
||||
use frame_election_provider_support::SequentialPhragmen;
|
||||
use std::io::Write;
|
||||
|
||||
macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||
/// Execute the emergency-solution command.
|
||||
pub(crate) async fn [<emergency_solution_cmd_ $runtime>](
|
||||
shared: SharedConfig,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||
use $crate::[<$runtime _runtime_exports>]::*;
|
||||
let mut ext = crate::create_election_ext::<Runtime, Block>(shared.uri.clone(), None, vec![]).await?;
|
||||
ext.execute_with(|| {
|
||||
assert!(EPM::Pallet::<Runtime>::current_phase().is_emergency());
|
||||
// NOTE: this internally calls feasibility_check, but we just re-do it here as an easy way
|
||||
// to get a `ReadySolution`.
|
||||
let (raw_solution, _) = <EPM::Pallet<Runtime>>::mine_solution(50)?;
|
||||
let (raw_solution, _) =
|
||||
<EPM::Pallet<Runtime>>::mine_solution::<SequentialPhragmen<AccountId, sp_runtime::Perbill>>()?;
|
||||
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
|
||||
let ready_solution = EPM::Pallet::<Runtime>::feasibility_check(raw_solution, EPM::ElectionCompute::Signed)?;
|
||||
let encoded_ready = ready_solution.encode();
|
||||
|
||||
@@ -38,9 +38,11 @@ mod signer;
|
||||
pub(crate) use prelude::*;
|
||||
pub(crate) use signer::get_account_info;
|
||||
|
||||
use frame_election_provider_support::NposSolver;
|
||||
use frame_support::traits::Get;
|
||||
use jsonrpsee_ws_client::{WsClient, WsClientBuilder};
|
||||
use remote_externalities::{Builder, Mode, OnlineConfig};
|
||||
use sp_npos_elections::ExtendedBalance;
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use structopt::StructOpt;
|
||||
|
||||
@@ -193,15 +195,43 @@ macro_rules! any_runtime {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum Error {
|
||||
/// 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)*;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(frame_support::DebugNoBound, thiserror::Error)]
|
||||
enum Error<T: EPM::Config> {
|
||||
Io(#[from] std::io::Error),
|
||||
Jsonrpsee(#[from] jsonrpsee_ws_client::types::Error),
|
||||
JsonRpsee(#[from] jsonrpsee_ws_client::types::Error),
|
||||
RpcHelperError(#[from] rpc_helpers::RpcHelperError),
|
||||
Codec(#[from] codec::Error),
|
||||
Crypto(sp_core::crypto::SecretStringError),
|
||||
RemoteExternalities(&'static str),
|
||||
PalletMiner(EPM::unsigned::MinerError),
|
||||
PalletElection(EPM::ElectionError),
|
||||
PalletMiner(EPM::unsigned::MinerError<T>),
|
||||
PalletElection(EPM::ElectionError<T>),
|
||||
PalletFeasibility(EPM::FeasibilityError),
|
||||
AccountDoesNotExists,
|
||||
IncorrectPhase,
|
||||
@@ -209,33 +239,33 @@ enum Error {
|
||||
VersionMismatch,
|
||||
}
|
||||
|
||||
impl From<sp_core::crypto::SecretStringError> for Error {
|
||||
fn from(e: sp_core::crypto::SecretStringError) -> Error {
|
||||
impl<T: EPM::Config> From<sp_core::crypto::SecretStringError> for Error<T> {
|
||||
fn from(e: sp_core::crypto::SecretStringError) -> Error<T> {
|
||||
Error::Crypto(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EPM::unsigned::MinerError> for Error {
|
||||
fn from(e: EPM::unsigned::MinerError) -> Error {
|
||||
impl<T: EPM::Config> From<EPM::unsigned::MinerError<T>> for Error<T> {
|
||||
fn from(e: EPM::unsigned::MinerError<T>) -> Error<T> {
|
||||
Error::PalletMiner(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EPM::ElectionError> for Error {
|
||||
fn from(e: EPM::ElectionError) -> Error {
|
||||
impl<T: EPM::Config> From<EPM::ElectionError<T>> for Error<T> {
|
||||
fn from(e: EPM::ElectionError<T>) -> Error<T> {
|
||||
Error::PalletElection(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EPM::FeasibilityError> for Error {
|
||||
fn from(e: EPM::FeasibilityError) -> Error {
|
||||
impl<T: EPM::Config> From<EPM::FeasibilityError> for Error<T> {
|
||||
fn from(e: EPM::FeasibilityError) -> Error<T> {
|
||||
Error::PalletFeasibility(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
impl<T: EPM::Config> std::fmt::Display for Error<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
<Error as std::fmt::Debug>::fmt(self, f)
|
||||
<Error<T> as std::fmt::Debug>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +279,58 @@ enum Command {
|
||||
EmergencySolution,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
enum Solvers {
|
||||
SeqPhragmen {
|
||||
#[structopt(long, default_value = "10")]
|
||||
iterations: usize,
|
||||
},
|
||||
PhragMMS {
|
||||
#[structopt(long, default_value = "10")]
|
||||
iterations: usize,
|
||||
},
|
||||
}
|
||||
|
||||
/// Mine a solution with the given `solver`.
|
||||
fn mine_with<T>(
|
||||
solver: &Solvers,
|
||||
ext: &mut Ext,
|
||||
) -> Result<(EPM::RawSolution<EPM::SolutionOf<T>>, u32), Error<T>>
|
||||
where
|
||||
T: EPM::Config,
|
||||
T::Solver: NposSolver<Error = sp_npos_elections::Error>,
|
||||
{
|
||||
use frame_election_provider_support::{PhragMMS, SequentialPhragmen};
|
||||
|
||||
match solver {
|
||||
Solvers::SeqPhragmen { iterations } => {
|
||||
BalanceIterations::set(*iterations);
|
||||
mine_unchecked::<
|
||||
T,
|
||||
SequentialPhragmen<
|
||||
<T as frame_system::Config>::AccountId,
|
||||
sp_runtime::Perbill,
|
||||
Balancing,
|
||||
>,
|
||||
>(ext, false)
|
||||
},
|
||||
Solvers::PhragMMS { iterations } => {
|
||||
BalanceIterations::set(*iterations);
|
||||
mine_unchecked::<
|
||||
T,
|
||||
PhragMMS<<T as frame_system::Config>::AccountId, sp_runtime::Perbill, Balancing>,
|
||||
>(ext, false)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::parameter_types! {
|
||||
/// Number of balancing iterations for a solution algorithm. Set based on the [`Solvers`] CLI
|
||||
/// config.
|
||||
pub static BalanceIterations: usize = 10;
|
||||
pub static Balancing: Option<(usize, ExtendedBalance)> = Some((BalanceIterations::get(), 0));
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
struct MonitorConfig {
|
||||
/// They type of event to listen to.
|
||||
@@ -259,8 +341,8 @@ struct MonitorConfig {
|
||||
#[structopt(long, default_value = "head", possible_values = &["head", "finalized"])]
|
||||
listen: String,
|
||||
|
||||
#[structopt(long, short, default_value = "10")]
|
||||
iterations: usize,
|
||||
#[structopt(subcommand)]
|
||||
solver: Solvers,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
@@ -269,8 +351,8 @@ struct DryRunConfig {
|
||||
#[structopt(long)]
|
||||
at: Option<Hash>,
|
||||
|
||||
#[structopt(long, short, default_value = "10")]
|
||||
iterations: usize,
|
||||
#[structopt(subcommand)]
|
||||
solver: Solvers,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
@@ -303,7 +385,7 @@ async fn create_election_ext<T: EPM::Config, B: BlockT>(
|
||||
uri: String,
|
||||
at: Option<B::Hash>,
|
||||
additional: Vec<String>,
|
||||
) -> Result<Ext, Error> {
|
||||
) -> Result<Ext, Error<T>> {
|
||||
use frame_support::{storage::generator::StorageMap, traits::PalletInfo};
|
||||
use sp_core::hashing::twox_128;
|
||||
|
||||
@@ -327,13 +409,20 @@ async fn create_election_ext<T: EPM::Config, B: BlockT>(
|
||||
|
||||
/// Compute the election at the given block number. It expects to NOT be `Phase::Off`. In other
|
||||
/// words, the snapshot must exists on the given externalities.
|
||||
fn mine_unchecked<T: EPM::Config>(
|
||||
fn mine_unchecked<T, S>(
|
||||
ext: &mut Ext,
|
||||
iterations: usize,
|
||||
do_feasibility: bool,
|
||||
) -> Result<(EPM::RawSolution<EPM::SolutionOf<T>>, u32), Error> {
|
||||
) -> Result<(EPM::RawSolution<EPM::SolutionOf<T>>, u32), Error<T>>
|
||||
where
|
||||
T: EPM::Config,
|
||||
S: NposSolver<
|
||||
Error = <<T as EPM::Config>::Solver as NposSolver>::Error,
|
||||
AccountId = <<T as EPM::Config>::Solver as NposSolver>::AccountId,
|
||||
>,
|
||||
{
|
||||
ext.execute_with(|| {
|
||||
let (solution, _) = <EPM::Pallet<T>>::mine_solution(iterations)?;
|
||||
let (solution, _) =
|
||||
<EPM::Pallet<T>>::mine_solution::<S>().map_err::<Error<T>, _>(Into::into)?;
|
||||
if do_feasibility {
|
||||
let _ = <EPM::Pallet<T>>::feasibility_check(
|
||||
solution.clone(),
|
||||
@@ -346,7 +435,7 @@ fn mine_unchecked<T: EPM::Config>(
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error> {
|
||||
fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>> {
|
||||
ext.execute_with(|| {
|
||||
use std::collections::BTreeMap;
|
||||
use EPM::RoundSnapshot;
|
||||
@@ -383,10 +472,10 @@ fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error> {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn check_versions<T: frame_system::Config>(
|
||||
pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
|
||||
client: &WsClient,
|
||||
print: bool,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<T>> {
|
||||
let linked_version = T::Version::get();
|
||||
let on_chain_version = rpc_helpers::rpc::<sp_version::RuntimeVersion>(
|
||||
client,
|
||||
@@ -486,7 +575,7 @@ async fn main() {
|
||||
}
|
||||
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);
|
||||
|
||||
let _ = any_runtime! {
|
||||
any_runtime_unit! {
|
||||
check_versions::<Runtime>(&client, true).await
|
||||
};
|
||||
|
||||
@@ -498,9 +587,18 @@ async fn main() {
|
||||
|
||||
let outcome = any_runtime! {
|
||||
match command.clone() {
|
||||
Command::Monitor(c) => monitor_cmd(&client, shared, c, signer_account).await,
|
||||
Command::DryRun(c) => dry_run_cmd(&client, shared, c, signer_account).await,
|
||||
Command::EmergencySolution => emergency_solution_cmd(shared.clone()).await,
|
||||
Command::Monitor(c) => monitor_cmd(&client, shared, c, signer_account).await
|
||||
.map_err(|e| {
|
||||
log::error!(target: LOG_TARGET, "Monitor error: {:?}", e);
|
||||
}),
|
||||
Command::DryRun(c) => dry_run_cmd(&client, shared, c, signer_account).await
|
||||
.map_err(|e| {
|
||||
log::error!(target: LOG_TARGET, "DryRun error: {:?}", e);
|
||||
}),
|
||||
Command::EmergencySolution => emergency_solution_cmd(shared.clone()).await
|
||||
.map_err(|e| {
|
||||
log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e);
|
||||
}),
|
||||
}
|
||||
};
|
||||
log::info!(target: LOG_TARGET, "round of execution finished. outcome = {:?}", outcome);
|
||||
|
||||
@@ -30,10 +30,11 @@ use sc_transaction_pool_api::TransactionStatus;
|
||||
async fn ensure_signed_phase<T: EPM::Config, B: BlockT>(
|
||||
client: &WsClient,
|
||||
at: B::Hash,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<T>> {
|
||||
let key = sp_core::storage::StorageKey(EPM::CurrentPhase::<T>::hashed_key().to_vec());
|
||||
let phase = get_storage::<EPM::Phase<BlockNumber>>(client, params! {key, at})
|
||||
.await?
|
||||
.await
|
||||
.map_err::<Error<T>, _>(Into::into)?
|
||||
.unwrap_or_default();
|
||||
|
||||
if phase.is_signed() {
|
||||
@@ -50,7 +51,7 @@ async fn ensure_no_previous_solution<
|
||||
>(
|
||||
ext: &mut Ext,
|
||||
us: &AccountId,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<T>> {
|
||||
use EPM::signed::SignedSubmissions;
|
||||
ext.execute_with(|| {
|
||||
if <SignedSubmissions<T>>::get().iter().any(|ss| &ss.who == us) {
|
||||
@@ -68,7 +69,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
||||
shared: SharedConfig,
|
||||
config: MonitorConfig,
|
||||
signer: Signer,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||
use $crate::[<$runtime _runtime_exports>]::*;
|
||||
let (sub, unsub) = if config.listen == "head" {
|
||||
("chain_subscribeNewHeads", "chain_unsubscribeNewHeads")
|
||||
@@ -109,7 +110,8 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
||||
continue;
|
||||
}
|
||||
|
||||
let (raw_solution, witness) = crate::mine_unchecked::<Runtime>(&mut ext, config.iterations, true)?;
|
||||
let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext)?;
|
||||
|
||||
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
|
||||
|
||||
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, Some(hash))
|
||||
@@ -149,8 +151,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
||||
TransactionStatus::InBlock(hash) => {
|
||||
log::info!(target: LOG_TARGET, "included at {:?}", hash);
|
||||
let key = frame_support::storage::storage_prefix(b"System", b"Events");
|
||||
let events =get_storage::<
|
||||
Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>
|
||||
let events = get_storage::<Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>,
|
||||
>(client, params!{ key, hash }).await?.unwrap_or_default();
|
||||
log::info!(target: LOG_TARGET, "events at inclusion {:?}", events);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,18 @@ use super::*;
|
||||
use jsonrpsee_ws_client::types::traits::Client;
|
||||
pub(crate) use jsonrpsee_ws_client::types::v2::params::JsonRpcParams;
|
||||
|
||||
#[derive(frame_support::DebugNoBound, thiserror::Error)]
|
||||
pub(crate) enum RpcHelperError {
|
||||
JsonRpsee(#[from] jsonrpsee_ws_client::types::Error),
|
||||
Codec(#[from] codec::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RpcHelperError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
<RpcHelperError as std::fmt::Debug>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! params {
|
||||
($($param:expr),*) => {
|
||||
@@ -41,8 +53,11 @@ pub(crate) async fn rpc<'a, Ret: serde::de::DeserializeOwned>(
|
||||
client: &WsClient,
|
||||
method: &'a str,
|
||||
params: JsonRpcParams<'a>,
|
||||
) -> Result<Ret, Error> {
|
||||
client.request::<Ret>(method, params).await.map_err(Into::into)
|
||||
) -> Result<Ret, RpcHelperError> {
|
||||
client
|
||||
.request::<Ret>(method, params)
|
||||
.await
|
||||
.map_err::<RpcHelperError, _>(Into::into)
|
||||
}
|
||||
|
||||
/// Make the rpc request, decode the outcome into `Dec`. Don't use for storage, it will fail for
|
||||
@@ -51,57 +66,26 @@ pub(crate) async fn rpc_decode<'a, Dec: codec::Decode>(
|
||||
client: &WsClient,
|
||||
method: &'a str,
|
||||
params: JsonRpcParams<'a>,
|
||||
) -> Result<Dec, Error> {
|
||||
let bytes = rpc::<sp_core::Bytes>(client, method, params).await?;
|
||||
<Dec as codec::Decode>::decode(&mut &*bytes.0).map_err(Into::into)
|
||||
) -> Result<Dec, RpcHelperError> {
|
||||
let bytes = rpc::<sp_core::Bytes>(client, method, params)
|
||||
.await
|
||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||
<Dec as codec::Decode>::decode(&mut &*bytes.0).map_err::<RpcHelperError, _>(Into::into)
|
||||
}
|
||||
|
||||
/// Get the storage item.
|
||||
pub(crate) async fn get_storage<'a, T: codec::Decode>(
|
||||
client: &WsClient,
|
||||
params: JsonRpcParams<'a>,
|
||||
) -> Result<Option<T>, Error> {
|
||||
let maybe_bytes = rpc::<Option<sp_core::Bytes>>(client, "state_getStorage", params).await?;
|
||||
) -> Result<Option<T>, RpcHelperError> {
|
||||
let maybe_bytes = rpc::<Option<sp_core::Bytes>>(client, "state_getStorage", params)
|
||||
.await
|
||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||
if let Some(bytes) = maybe_bytes {
|
||||
let decoded = <T as codec::Decode>::decode(&mut &*bytes.0)?;
|
||||
let decoded = <T as codec::Decode>::decode(&mut &*bytes.0)
|
||||
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||
Ok(Some(decoded))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
use codec::{EncodeLike, FullCodec};
|
||||
use frame_support::storage::{StorageMap, StorageValue};
|
||||
#[allow(unused)]
|
||||
pub(crate) async fn get_storage_value_frame_v2<'a, V: StorageValue<T>, T: FullCodec, Hash>(
|
||||
client: &WsClient,
|
||||
maybe_at: Option<Hash>,
|
||||
) -> Result<Option<V::Query>, Error>
|
||||
where
|
||||
V::Query: codec::Decode,
|
||||
Hash: serde::Serialize,
|
||||
{
|
||||
let key = <V as StorageValue<T>>::hashed_key();
|
||||
get_storage::<V::Query>(client, params! { key, maybe_at }).await
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) async fn get_storage_map_frame_v2<
|
||||
'a,
|
||||
Hash,
|
||||
KeyArg: EncodeLike<K>,
|
||||
K: FullCodec,
|
||||
T: FullCodec,
|
||||
M: StorageMap<K, T>,
|
||||
>(
|
||||
client: &WsClient,
|
||||
key: KeyArg,
|
||||
maybe_at: Option<Hash>,
|
||||
) -> Result<Option<M::Query>, Error>
|
||||
where
|
||||
M::Query: codec::Decode,
|
||||
Hash: serde::Serialize,
|
||||
{
|
||||
let key = <M as StorageMap<K, T>>::hashed_key_for(key);
|
||||
get_storage::<M::Query>(client, params! { key, maybe_at }).await
|
||||
}
|
||||
|
||||
@@ -34,11 +34,11 @@ pub(crate) struct Signer {
|
||||
pub(crate) pair: Pair,
|
||||
}
|
||||
|
||||
pub(crate) async fn get_account_info<T: frame_system::Config>(
|
||||
pub(crate) async fn get_account_info<T: frame_system::Config + EPM::Config>(
|
||||
client: &WsClient,
|
||||
who: &T::AccountId,
|
||||
maybe_at: Option<T::Hash>,
|
||||
) -> Result<Option<frame_system::AccountInfo<Index, T::AccountData>>, Error> {
|
||||
) -> Result<Option<frame_system::AccountInfo<Index, T::AccountData>>, Error<T>> {
|
||||
rpc_helpers::get_storage::<frame_system::AccountInfo<Index, T::AccountData>>(
|
||||
client,
|
||||
crate::params! {
|
||||
@@ -47,6 +47,7 @@ pub(crate) async fn get_account_info<T: frame_system::Config>(
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Read the signer account's URI
|
||||
@@ -55,18 +56,18 @@ pub(crate) async fn signer_uri_from_string<
|
||||
AccountId = AccountId,
|
||||
Index = Index,
|
||||
AccountData = pallet_balances::AccountData<Balance>,
|
||||
>,
|
||||
> + EPM::Config,
|
||||
>(
|
||||
seed: &str,
|
||||
client: &WsClient,
|
||||
) -> Result<Signer, Error> {
|
||||
) -> Result<Signer, Error<T>> {
|
||||
let seed = seed.trim();
|
||||
|
||||
let pair = Pair::from_string(seed, None)?;
|
||||
let account = T::AccountId::from(pair.public());
|
||||
let _info = get_account_info::<T>(client, &account, None)
|
||||
.await?
|
||||
.ok_or(Error::AccountDoesNotExists)?;
|
||||
.ok_or(Error::<T>::AccountDoesNotExists)?;
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"loaded account {:?}, free: {:?}, info: {:?}",
|
||||
|
||||
Reference in New Issue
Block a user