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-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-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-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-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 }
|
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
@@ -90,6 +91,7 @@ std = [
|
|||||||
"libsecp256k1/std",
|
"libsecp256k1/std",
|
||||||
"runtime-parachains/std",
|
"runtime-parachains/std",
|
||||||
"xcm/std",
|
"xcm/std",
|
||||||
|
"sp-npos-elections/std",
|
||||||
]
|
]
|
||||||
runtime-benchmarks = [
|
runtime-benchmarks = [
|
||||||
"libsecp256k1/hmac",
|
"libsecp256k1/hmac",
|
||||||
|
|||||||
@@ -55,3 +55,30 @@ impl pallet_election_provider_multi_phase::BenchmarkingConfig for BenchmarkConfi
|
|||||||
const MINER_MAXIMUM_VOTERS: u32 = 15_000;
|
const MINER_MAXIMUM_VOTERS: u32 = 15_000;
|
||||||
const MAXIMUM_TARGETS: u32 = 2000;
|
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);
|
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||||
|
|
||||||
// miner configs
|
// miner configs
|
||||||
pub const MinerMaxIterations: u32 = 10;
|
|
||||||
pub OffchainRepeat: BlockNumber = 5;
|
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 RewardHandler = (); // nothing to do upon rewards
|
||||||
type SignedPhase = SignedPhase;
|
type SignedPhase = SignedPhase;
|
||||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||||
type MinerMaxIterations = MinerMaxIterations;
|
|
||||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||||
type OffchainRepeat = OffchainRepeat;
|
type OffchainRepeat = OffchainRepeat;
|
||||||
@@ -393,6 +391,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
|||||||
type Solution = NposCompactSolution24;
|
type Solution = NposCompactSolution24;
|
||||||
type OnChainAccuracy = Perbill;
|
type OnChainAccuracy = Perbill;
|
||||||
type Fallback = Fallback;
|
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 BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||||
type ForceOrigin = EnsureOneOf<
|
type ForceOrigin = EnsureOneOf<
|
||||||
AccountId,
|
AccountId,
|
||||||
|
|||||||
@@ -362,7 +362,6 @@ parameter_types! {
|
|||||||
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||||
|
|
||||||
// miner configs
|
// miner configs
|
||||||
pub const MinerMaxIterations: u32 = 10;
|
|
||||||
pub OffchainRepeat: BlockNumber = 5;
|
pub OffchainRepeat: BlockNumber = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +389,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
|||||||
type SlashHandler = (); // burn slashes
|
type SlashHandler = (); // burn slashes
|
||||||
type RewardHandler = (); // nothing to do upon rewards
|
type RewardHandler = (); // nothing to do upon rewards
|
||||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||||
type MinerMaxIterations = MinerMaxIterations;
|
|
||||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||||
type OffchainRepeat = OffchainRepeat;
|
type OffchainRepeat = OffchainRepeat;
|
||||||
@@ -399,6 +397,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
|||||||
type OnChainAccuracy = Perbill;
|
type OnChainAccuracy = Perbill;
|
||||||
type Solution = NposCompactSolution16;
|
type Solution = NposCompactSolution16;
|
||||||
type Fallback = Fallback;
|
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 BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||||
type ForceOrigin = EnsureOneOf<
|
type ForceOrigin = EnsureOneOf<
|
||||||
AccountId,
|
AccountId,
|
||||||
|
|||||||
@@ -342,7 +342,6 @@ parameter_types! {
|
|||||||
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
|
||||||
|
|
||||||
// miner configs
|
// miner configs
|
||||||
pub const MinerMaxIterations: u32 = 10;
|
|
||||||
pub OffchainRepeat: BlockNumber = 5;
|
pub OffchainRepeat: BlockNumber = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +369,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
|||||||
type SlashHandler = (); // burn slashes
|
type SlashHandler = (); // burn slashes
|
||||||
type RewardHandler = (); // nothing to do upon rewards
|
type RewardHandler = (); // nothing to do upon rewards
|
||||||
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
type SolutionImprovementThreshold = SolutionImprovementThreshold;
|
||||||
type MinerMaxIterations = MinerMaxIterations;
|
|
||||||
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
|
||||||
type MinerMaxLength = OffchainSolutionLengthLimit;
|
type MinerMaxLength = OffchainSolutionLengthLimit;
|
||||||
type OffchainRepeat = OffchainRepeat;
|
type OffchainRepeat = OffchainRepeat;
|
||||||
@@ -379,6 +377,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
|
|||||||
type OnChainAccuracy = Perbill;
|
type OnChainAccuracy = Perbill;
|
||||||
type Solution = NposCompactSolution16;
|
type Solution = NposCompactSolution16;
|
||||||
type Fallback = Fallback;
|
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 BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
|
||||||
type ForceOrigin = EnsureRoot<AccountId>;
|
type ForceOrigin = EnsureRoot<AccountId>;
|
||||||
type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>;
|
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-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
sp-io = { 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-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" }
|
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
|
||||||
|
|
||||||
frame-system = { 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-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-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
pallet-staking = { 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" }
|
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use codec::Encode;
|
|||||||
use frame_support::traits::Currency;
|
use frame_support::traits::Currency;
|
||||||
|
|
||||||
/// Forcefully create the snapshot. This can be used to compute the election at anytime.
|
/// 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(|| {
|
ext.execute_with(|| {
|
||||||
if <EPM::Snapshot<T>>::exists() {
|
if <EPM::Snapshot<T>>::exists() {
|
||||||
log::info!(target: LOG_TARGET, "snapshot already 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,
|
shared: SharedConfig,
|
||||||
config: DryRunConfig,
|
config: DryRunConfig,
|
||||||
signer: Signer,
|
signer: Signer,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
let mut ext = crate::create_election_ext::<Runtime, Block>(
|
let mut ext = crate::create_election_ext::<Runtime, Block>(
|
||||||
shared.uri.clone(),
|
shared.uri.clone(),
|
||||||
@@ -121,7 +121,8 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
|
|||||||
).await?;
|
).await?;
|
||||||
force_create_snapshot::<Runtime>(&mut ext)?;
|
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)
|
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, config.at)
|
||||||
.await?
|
.await?
|
||||||
.map(|i| i.nonce)
|
.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);
|
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);
|
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", outcome);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,20 +18,22 @@
|
|||||||
|
|
||||||
use crate::{prelude::*, Error, SharedConfig};
|
use crate::{prelude::*, Error, SharedConfig};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
|
use frame_election_provider_support::SequentialPhragmen;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! {
|
macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! {
|
||||||
/// Execute the emergency-solution command.
|
/// Execute the emergency-solution command.
|
||||||
pub(crate) async fn [<emergency_solution_cmd_ $runtime>](
|
pub(crate) async fn [<emergency_solution_cmd_ $runtime>](
|
||||||
shared: SharedConfig,
|
shared: SharedConfig,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
let mut ext = crate::create_election_ext::<Runtime, Block>(shared.uri.clone(), None, vec![]).await?;
|
let mut ext = crate::create_election_ext::<Runtime, Block>(shared.uri.clone(), None, vec![]).await?;
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
assert!(EPM::Pallet::<Runtime>::current_phase().is_emergency());
|
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
|
// NOTE: this internally calls feasibility_check, but we just re-do it here as an easy way
|
||||||
// to get a `ReadySolution`.
|
// 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);
|
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 ready_solution = EPM::Pallet::<Runtime>::feasibility_check(raw_solution, EPM::ElectionCompute::Signed)?;
|
||||||
let encoded_ready = ready_solution.encode();
|
let encoded_ready = ready_solution.encode();
|
||||||
|
|||||||
@@ -38,9 +38,11 @@ mod signer;
|
|||||||
pub(crate) use prelude::*;
|
pub(crate) use prelude::*;
|
||||||
pub(crate) use signer::get_account_info;
|
pub(crate) use signer::get_account_info;
|
||||||
|
|
||||||
|
use frame_election_provider_support::NposSolver;
|
||||||
use frame_support::traits::Get;
|
use frame_support::traits::Get;
|
||||||
use jsonrpsee_ws_client::{WsClient, WsClientBuilder};
|
use jsonrpsee_ws_client::{WsClient, WsClientBuilder};
|
||||||
use remote_externalities::{Builder, Mode, OnlineConfig};
|
use remote_externalities::{Builder, Mode, OnlineConfig};
|
||||||
|
use sp_npos_elections::ExtendedBalance;
|
||||||
use sp_runtime::traits::Block as BlockT;
|
use sp_runtime::traits::Block as BlockT;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
@@ -193,15 +195,43 @@ macro_rules! any_runtime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
/// Same as [`any_runtime`], but instead of returning a `Result`, this simply returns `()`. Useful
|
||||||
enum Error {
|
/// 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),
|
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),
|
Codec(#[from] codec::Error),
|
||||||
Crypto(sp_core::crypto::SecretStringError),
|
Crypto(sp_core::crypto::SecretStringError),
|
||||||
RemoteExternalities(&'static str),
|
RemoteExternalities(&'static str),
|
||||||
PalletMiner(EPM::unsigned::MinerError),
|
PalletMiner(EPM::unsigned::MinerError<T>),
|
||||||
PalletElection(EPM::ElectionError),
|
PalletElection(EPM::ElectionError<T>),
|
||||||
PalletFeasibility(EPM::FeasibilityError),
|
PalletFeasibility(EPM::FeasibilityError),
|
||||||
AccountDoesNotExists,
|
AccountDoesNotExists,
|
||||||
IncorrectPhase,
|
IncorrectPhase,
|
||||||
@@ -209,33 +239,33 @@ enum Error {
|
|||||||
VersionMismatch,
|
VersionMismatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<sp_core::crypto::SecretStringError> for Error {
|
impl<T: EPM::Config> From<sp_core::crypto::SecretStringError> for Error<T> {
|
||||||
fn from(e: sp_core::crypto::SecretStringError) -> Error {
|
fn from(e: sp_core::crypto::SecretStringError) -> Error<T> {
|
||||||
Error::Crypto(e)
|
Error::Crypto(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EPM::unsigned::MinerError> for Error {
|
impl<T: EPM::Config> From<EPM::unsigned::MinerError<T>> for Error<T> {
|
||||||
fn from(e: EPM::unsigned::MinerError) -> Error {
|
fn from(e: EPM::unsigned::MinerError<T>) -> Error<T> {
|
||||||
Error::PalletMiner(e)
|
Error::PalletMiner(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EPM::ElectionError> for Error {
|
impl<T: EPM::Config> From<EPM::ElectionError<T>> for Error<T> {
|
||||||
fn from(e: EPM::ElectionError) -> Error {
|
fn from(e: EPM::ElectionError<T>) -> Error<T> {
|
||||||
Error::PalletElection(e)
|
Error::PalletElection(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EPM::FeasibilityError> for Error {
|
impl<T: EPM::Config> From<EPM::FeasibilityError> for Error<T> {
|
||||||
fn from(e: EPM::FeasibilityError) -> Error {
|
fn from(e: EPM::FeasibilityError) -> Error<T> {
|
||||||
Error::PalletFeasibility(e)
|
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 {
|
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,
|
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)]
|
#[derive(Debug, Clone, StructOpt)]
|
||||||
struct MonitorConfig {
|
struct MonitorConfig {
|
||||||
/// They type of event to listen to.
|
/// They type of event to listen to.
|
||||||
@@ -259,8 +341,8 @@ struct MonitorConfig {
|
|||||||
#[structopt(long, default_value = "head", possible_values = &["head", "finalized"])]
|
#[structopt(long, default_value = "head", possible_values = &["head", "finalized"])]
|
||||||
listen: String,
|
listen: String,
|
||||||
|
|
||||||
#[structopt(long, short, default_value = "10")]
|
#[structopt(subcommand)]
|
||||||
iterations: usize,
|
solver: Solvers,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, StructOpt)]
|
#[derive(Debug, Clone, StructOpt)]
|
||||||
@@ -269,8 +351,8 @@ struct DryRunConfig {
|
|||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
at: Option<Hash>,
|
at: Option<Hash>,
|
||||||
|
|
||||||
#[structopt(long, short, default_value = "10")]
|
#[structopt(subcommand)]
|
||||||
iterations: usize,
|
solver: Solvers,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, StructOpt)]
|
#[derive(Debug, Clone, StructOpt)]
|
||||||
@@ -303,7 +385,7 @@ async fn create_election_ext<T: EPM::Config, B: BlockT>(
|
|||||||
uri: String,
|
uri: String,
|
||||||
at: Option<B::Hash>,
|
at: Option<B::Hash>,
|
||||||
additional: Vec<String>,
|
additional: Vec<String>,
|
||||||
) -> Result<Ext, Error> {
|
) -> Result<Ext, Error<T>> {
|
||||||
use frame_support::{storage::generator::StorageMap, traits::PalletInfo};
|
use frame_support::{storage::generator::StorageMap, traits::PalletInfo};
|
||||||
use sp_core::hashing::twox_128;
|
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
|
/// 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.
|
/// words, the snapshot must exists on the given externalities.
|
||||||
fn mine_unchecked<T: EPM::Config>(
|
fn mine_unchecked<T, S>(
|
||||||
ext: &mut Ext,
|
ext: &mut Ext,
|
||||||
iterations: usize,
|
|
||||||
do_feasibility: bool,
|
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(|| {
|
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 {
|
if do_feasibility {
|
||||||
let _ = <EPM::Pallet<T>>::feasibility_check(
|
let _ = <EPM::Pallet<T>>::feasibility_check(
|
||||||
solution.clone(),
|
solution.clone(),
|
||||||
@@ -346,7 +435,7 @@ fn mine_unchecked<T: EPM::Config>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[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(|| {
|
ext.execute_with(|| {
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use EPM::RoundSnapshot;
|
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,
|
client: &WsClient,
|
||||||
print: bool,
|
print: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<T>> {
|
||||||
let linked_version = T::Version::get();
|
let linked_version = T::Version::get();
|
||||||
let on_chain_version = rpc_helpers::rpc::<sp_version::RuntimeVersion>(
|
let on_chain_version = rpc_helpers::rpc::<sp_version::RuntimeVersion>(
|
||||||
client,
|
client,
|
||||||
@@ -486,7 +575,7 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);
|
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);
|
||||||
|
|
||||||
let _ = any_runtime! {
|
any_runtime_unit! {
|
||||||
check_versions::<Runtime>(&client, true).await
|
check_versions::<Runtime>(&client, true).await
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -498,9 +587,18 @@ async fn main() {
|
|||||||
|
|
||||||
let outcome = any_runtime! {
|
let outcome = any_runtime! {
|
||||||
match command.clone() {
|
match command.clone() {
|
||||||
Command::Monitor(c) => monitor_cmd(&client, shared, c, signer_account).await,
|
Command::Monitor(c) => monitor_cmd(&client, shared, c, signer_account).await
|
||||||
Command::DryRun(c) => dry_run_cmd(&client, shared, c, signer_account).await,
|
.map_err(|e| {
|
||||||
Command::EmergencySolution => emergency_solution_cmd(shared.clone()).await,
|
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);
|
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>(
|
async fn ensure_signed_phase<T: EPM::Config, B: BlockT>(
|
||||||
client: &WsClient,
|
client: &WsClient,
|
||||||
at: B::Hash,
|
at: B::Hash,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<T>> {
|
||||||
let key = sp_core::storage::StorageKey(EPM::CurrentPhase::<T>::hashed_key().to_vec());
|
let key = sp_core::storage::StorageKey(EPM::CurrentPhase::<T>::hashed_key().to_vec());
|
||||||
let phase = get_storage::<EPM::Phase<BlockNumber>>(client, params! {key, at})
|
let phase = get_storage::<EPM::Phase<BlockNumber>>(client, params! {key, at})
|
||||||
.await?
|
.await
|
||||||
|
.map_err::<Error<T>, _>(Into::into)?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if phase.is_signed() {
|
if phase.is_signed() {
|
||||||
@@ -50,7 +51,7 @@ async fn ensure_no_previous_solution<
|
|||||||
>(
|
>(
|
||||||
ext: &mut Ext,
|
ext: &mut Ext,
|
||||||
us: &AccountId,
|
us: &AccountId,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<T>> {
|
||||||
use EPM::signed::SignedSubmissions;
|
use EPM::signed::SignedSubmissions;
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
if <SignedSubmissions<T>>::get().iter().any(|ss| &ss.who == us) {
|
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,
|
shared: SharedConfig,
|
||||||
config: MonitorConfig,
|
config: MonitorConfig,
|
||||||
signer: Signer,
|
signer: Signer,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error<$crate::[<$runtime _runtime_exports>]::Runtime>> {
|
||||||
use $crate::[<$runtime _runtime_exports>]::*;
|
use $crate::[<$runtime _runtime_exports>]::*;
|
||||||
let (sub, unsub) = if config.listen == "head" {
|
let (sub, unsub) = if config.listen == "head" {
|
||||||
("chain_subscribeNewHeads", "chain_unsubscribeNewHeads")
|
("chain_subscribeNewHeads", "chain_unsubscribeNewHeads")
|
||||||
@@ -109,7 +110,8 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! {
|
|||||||
continue;
|
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);
|
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
|
||||||
|
|
||||||
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, Some(hash))
|
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) => {
|
TransactionStatus::InBlock(hash) => {
|
||||||
log::info!(target: LOG_TARGET, "included at {:?}", hash);
|
log::info!(target: LOG_TARGET, "included at {:?}", hash);
|
||||||
let key = frame_support::storage::storage_prefix(b"System", b"Events");
|
let key = frame_support::storage::storage_prefix(b"System", b"Events");
|
||||||
let events =get_storage::<
|
let events = get_storage::<Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>,
|
||||||
Vec<frame_system::EventRecord<Event, <Block as BlockT>::Hash>>
|
|
||||||
>(client, params!{ key, hash }).await?.unwrap_or_default();
|
>(client, params!{ key, hash }).await?.unwrap_or_default();
|
||||||
log::info!(target: LOG_TARGET, "events at inclusion {:?}", events);
|
log::info!(target: LOG_TARGET, "events at inclusion {:?}", events);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,18 @@ use super::*;
|
|||||||
use jsonrpsee_ws_client::types::traits::Client;
|
use jsonrpsee_ws_client::types::traits::Client;
|
||||||
pub(crate) use jsonrpsee_ws_client::types::v2::params::JsonRpcParams;
|
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_export]
|
||||||
macro_rules! params {
|
macro_rules! params {
|
||||||
($($param:expr),*) => {
|
($($param:expr),*) => {
|
||||||
@@ -41,8 +53,11 @@ pub(crate) async fn rpc<'a, Ret: serde::de::DeserializeOwned>(
|
|||||||
client: &WsClient,
|
client: &WsClient,
|
||||||
method: &'a str,
|
method: &'a str,
|
||||||
params: JsonRpcParams<'a>,
|
params: JsonRpcParams<'a>,
|
||||||
) -> Result<Ret, Error> {
|
) -> Result<Ret, RpcHelperError> {
|
||||||
client.request::<Ret>(method, params).await.map_err(Into::into)
|
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
|
/// 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,
|
client: &WsClient,
|
||||||
method: &'a str,
|
method: &'a str,
|
||||||
params: JsonRpcParams<'a>,
|
params: JsonRpcParams<'a>,
|
||||||
) -> Result<Dec, Error> {
|
) -> Result<Dec, RpcHelperError> {
|
||||||
let bytes = rpc::<sp_core::Bytes>(client, method, params).await?;
|
let bytes = rpc::<sp_core::Bytes>(client, method, params)
|
||||||
<Dec as codec::Decode>::decode(&mut &*bytes.0).map_err(Into::into)
|
.await
|
||||||
|
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||||
|
<Dec as codec::Decode>::decode(&mut &*bytes.0).map_err::<RpcHelperError, _>(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the storage item.
|
/// Get the storage item.
|
||||||
pub(crate) async fn get_storage<'a, T: codec::Decode>(
|
pub(crate) async fn get_storage<'a, T: codec::Decode>(
|
||||||
client: &WsClient,
|
client: &WsClient,
|
||||||
params: JsonRpcParams<'a>,
|
params: JsonRpcParams<'a>,
|
||||||
) -> Result<Option<T>, Error> {
|
) -> Result<Option<T>, RpcHelperError> {
|
||||||
let maybe_bytes = rpc::<Option<sp_core::Bytes>>(client, "state_getStorage", params).await?;
|
let maybe_bytes = rpc::<Option<sp_core::Bytes>>(client, "state_getStorage", params)
|
||||||
|
.await
|
||||||
|
.map_err::<RpcHelperError, _>(Into::into)?;
|
||||||
if let Some(bytes) = maybe_bytes {
|
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))
|
Ok(Some(decoded))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
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) 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,
|
client: &WsClient,
|
||||||
who: &T::AccountId,
|
who: &T::AccountId,
|
||||||
maybe_at: Option<T::Hash>,
|
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>>(
|
rpc_helpers::get_storage::<frame_system::AccountInfo<Index, T::AccountData>>(
|
||||||
client,
|
client,
|
||||||
crate::params! {
|
crate::params! {
|
||||||
@@ -47,26 +47,27 @@ pub(crate) async fn get_account_info<T: frame_system::Config>(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the signer account's URI
|
/// Read the signer account's URI
|
||||||
pub(crate) async fn signer_uri_from_string<
|
pub(crate) async fn signer_uri_from_string<
|
||||||
T: frame_system::Config<
|
T: frame_system::Config<
|
||||||
AccountId = AccountId,
|
AccountId = AccountId,
|
||||||
Index = Index,
|
Index = Index,
|
||||||
AccountData = pallet_balances::AccountData<Balance>,
|
AccountData = pallet_balances::AccountData<Balance>,
|
||||||
>,
|
> + EPM::Config,
|
||||||
>(
|
>(
|
||||||
seed: &str,
|
seed: &str,
|
||||||
client: &WsClient,
|
client: &WsClient,
|
||||||
) -> Result<Signer, Error> {
|
) -> Result<Signer, Error<T>> {
|
||||||
let seed = seed.trim();
|
let seed = seed.trim();
|
||||||
|
|
||||||
let pair = Pair::from_string(seed, None)?;
|
let pair = Pair::from_string(seed, None)?;
|
||||||
let account = T::AccountId::from(pair.public());
|
let account = T::AccountId::from(pair.public());
|
||||||
let _info = get_account_info::<T>(client, &account, None)
|
let _info = get_account_info::<T>(client, &account, None)
|
||||||
.await?
|
.await?
|
||||||
.ok_or(Error::AccountDoesNotExists)?;
|
.ok_or(Error::<T>::AccountDoesNotExists)?;
|
||||||
log::info!(
|
log::info!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"loaded account {:?}, free: {:?}, info: {:?}",
|
"loaded account {:?}, free: {:?}, info: {:?}",
|
||||||
|
|||||||
Reference in New Issue
Block a user