Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions utils/staking-miner/src/dry_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
let mut ext = crate::create_election_ext::<Runtime, Block>(
shared.uri.clone(),
config.at,
vec!["Staking".to_string(), "System".to_string(), "Balances".to_string()]
vec!["Staking".to_string(), "System".to_string()],
).await?;
force_create_snapshot::<Runtime>(&mut ext)?;

let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext)?;
let (raw_solution, witness) = crate::mine_with::<Runtime>(&config.solver, &mut ext, false)?;

let nonce = crate::get_account_info::<Runtime>(client, &signer.account, config.at)
.await?
Expand Down
22 changes: 16 additions & 6 deletions utils/staking-miner/src/emergency_solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! The emergency-solution command.

use crate::{prelude::*, Error, SharedConfig};
use crate::{prelude::*, EmergencySolutionConfig, Error, SharedConfig};
use codec::Encode;
use frame_election_provider_support::SequentialPhragmen;
use std::io::Write;
Expand All @@ -25,25 +25,35 @@ 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,
config: EmergencySolutionConfig,
) -> 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::<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();
let mut ready_solution = EPM::Pallet::<Runtime>::feasibility_check(raw_solution, EPM::ElectionCompute::Signed)?;

// maybe truncate.
if let Some(take) = config.take {
log::info!(target: LOG_TARGET, "truncating {} winners to {}", ready_solution.supports.len(), take);
ready_solution.supports.sort_unstable_by_key(|(_, s)| s.total);
ready_solution.supports.truncate(take);
}

// write to file and stdout.
let encoded_support = ready_solution.supports.encode();
let mut solution_file = std::fs::File::create("solution.bin")?;
let mut supports_file = std::fs::File::create("solution.supports.bin")?;
solution_file.write_all(&encoded_ready)?;
supports_file.write_all(&encoded_support)?;
log::info!(target: LOG_TARGET, "ReadySolution: size {:?} / score = {:?}", encoded_ready.len(), ready_solution.score);

log::info!(target: LOG_TARGET, "ReadySolution: size {:?} / score = {:?}", ready_solution.encoded_size(), ready_solution.score);
log::trace!(target: LOG_TARGET, "Supports: {}", sp_core::hexdisplay::HexDisplay::from(&encoded_support));

Ok(())
})
}
Expand Down
103 changes: 59 additions & 44 deletions utils/staking-miner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ enum Command {
/// 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,
EmergencySolution(EmergencySolutionConfig),
}

#[derive(Debug, Clone, StructOpt)]
Expand All @@ -291,39 +291,6 @@ enum Solvers {
},
}

/// 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.
Expand All @@ -341,16 +308,32 @@ struct MonitorConfig {
#[structopt(long, default_value = "head", possible_values = &["head", "finalized"])]
listen: String,

/// The solver algorithm to use.
#[structopt(subcommand)]
solver: Solvers,
}

#[derive(Debug, Clone, StructOpt)]
struct EmergencySolutionConfig {
/// The block hash at which scraping happens. If none is provided, the latest head is used.
#[structopt(long)]
at: Option<Hash>,

/// The solver algorithm to use.
#[structopt(subcommand)]
solver: Solvers,

/// The number of top backed winners to take. All are taken, if not provided.
take: Option<usize>,
}

#[derive(Debug, Clone, StructOpt)]
struct DryRunConfig {
/// The block hash at which scraping happens. If none is provided, the latest head is used.
#[structopt(long)]
at: Option<Hash>,

/// The solver algorithm to use.
#[structopt(subcommand)]
solver: Solvers,
}
Expand Down Expand Up @@ -407,9 +390,9 @@ async fn create_election_ext<T: EPM::Config, B: BlockT>(
.map_err(|why| Error::RemoteExternalities(why))
}

/// 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, S>(
/// Compute the election. It expects to NOT be `Phase::Off`. In other words, the snapshot must
/// exists on the given externalities.
fn mine_solution<T, S>(
ext: &mut Ext,
do_feasibility: bool,
) -> Result<(EPM::RawSolution<EPM::SolutionOf<T>>, u32), Error<T>>
Expand All @@ -434,6 +417,40 @@ where
})
}

/// Mine a solution with the given `solver`.
fn mine_with<T>(
solver: &Solvers,
ext: &mut Ext,
do_feasibility: bool,
) -> 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_solution::<
T,
SequentialPhragmen<
<T as frame_system::Config>::AccountId,
sp_runtime::Perbill,
Balancing,
>,
>(ext, do_feasibility)
},
Solvers::PhragMMS { iterations } => {
BalanceIterations::set(*iterations);
mine_solution::<
T,
PhragMMS<<T as frame_system::Config>::AccountId, sp_runtime::Perbill, Balancing>,
>(ext, do_feasibility)
},
}
}

#[allow(unused)]
fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>> {
ext.execute_with(|| {
Expand Down Expand Up @@ -474,7 +491,6 @@ fn mine_dpos<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error<T>> {

pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
client: &WsClient,
print: bool,
) -> Result<(), Error<T>> {
let linked_version = T::Version::get();
let on_chain_version = rpc_helpers::rpc::<sp_version::RuntimeVersion>(
Expand All @@ -485,10 +501,9 @@ pub(crate) async fn check_versions<T: frame_system::Config + EPM::Config>(
.await
.expect("runtime version RPC should always work; qed");

if print {
log::info!(target: LOG_TARGET, "linked version {:?}", linked_version);
log::info!(target: LOG_TARGET, "on-chain version {:?}", on_chain_version);
}
log::debug!(target: LOG_TARGET, "linked version {:?}", linked_version);
log::debug!(target: LOG_TARGET, "on-chain version {:?}", on_chain_version);

if linked_version != on_chain_version {
log::error!(
target: LOG_TARGET,
Expand Down Expand Up @@ -576,7 +591,7 @@ async fn main() {
log::info!(target: LOG_TARGET, "connected to chain {:?}", chain);

any_runtime_unit! {
check_versions::<Runtime>(&client, true).await
check_versions::<Runtime>(&client).await
};

let signer_account = any_runtime! {
Expand All @@ -595,7 +610,7 @@ async fn main() {
.map_err(|e| {
log::error!(target: LOG_TARGET, "DryRun error: {:?}", e);
}),
Command::EmergencySolution => emergency_solution_cmd(shared.clone()).await
Command::EmergencySolution(c) => emergency_solution_cmd(shared.clone(), c).await
.map_err(|e| {
log::error!(target: LOG_TARGET, "EmergencySolution error: {:?}", e);
}),
Expand Down
Loading