use clap::Parser;
use moonbeam_cli_opt::{account_key::GenerateAccountKey, EthApi, FrontierBackendType, Sealing};
use moonbeam_service::chain_spec;
use sc_cli::{Error as CliError, SubstrateCli};
use std::path::PathBuf;
use std::time::Duration;
#[cfg(feature = "lazy-loading")]
fn parse_block_hash(s: &str) -> Result<sp_core::H256, String> {
use std::str::FromStr;
sp_core::H256::from_str(s).map_err(|err| err.to_string())
}
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
#[clap(name = "export-genesis-state")]
ExportGenesisHead(ExportGenesisHeadCommand),
#[clap(name = "export-genesis-wasm")]
ExportGenesisWasm(ExportGenesisWasmCommand),
BuildSpec(BuildSpecCommand),
CheckBlock(sc_cli::CheckBlockCmd),
ExportBlocks(sc_cli::ExportBlocksCmd),
ExportState(sc_cli::ExportStateCmd),
ImportBlocks(sc_cli::ImportBlocksCmd),
PurgeChain(cumulus_client_cli::PurgeChainCmd),
Revert(sc_cli::RevertCmd),
#[clap(subcommand)]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
TryRuntime,
#[clap(subcommand)]
Key(KeyCmd),
PrecompileWasm(sc_cli::PrecompileWasmCmd),
}
#[derive(Debug, Parser)]
pub struct BuildSpecCommand {
#[clap(flatten)]
pub base: sc_cli::BuildSpecCmd,
#[clap(long, conflicts_with = "chain")]
pub accounts: Option<u32>,
#[clap(long, conflicts_with = "chain")]
pub mnemonic: Option<String>,
}
#[derive(Debug, Parser)]
pub struct ExportGenesisHeadCommand {
#[clap(value_parser)]
pub output: Option<PathBuf>,
#[clap(long)]
pub parachain_id: Option<u32>,
#[clap(short, long)]
pub raw: bool,
#[clap(long)]
pub chain: Option<String>,
}
#[derive(Debug, Parser)]
pub struct ExportGenesisWasmCommand {
#[clap(value_parser)]
pub output: Option<PathBuf>,
#[clap(short, long)]
pub raw: bool,
#[clap(long)]
pub chain: Option<String>,
}
#[derive(Debug, Parser)]
#[group(skip)]
pub struct RunCmd {
#[clap(flatten)]
pub base: cumulus_client_cli::RunCmd,
#[clap(long)]
pub dev_service: bool,
#[cfg(feature = "lazy-loading")]
#[clap(long)]
pub fork_chain_from_rpc: Option<String>,
#[cfg(feature = "lazy-loading")]
#[arg(long, value_name = "BLOCK", value_parser = parse_block_hash)]
pub block: Option<sp_core::H256>,
#[cfg(feature = "lazy-loading")]
#[clap(long, value_name = "PATH", value_parser)]
pub fork_state_overrides: Option<PathBuf>,
#[cfg(feature = "lazy-loading")]
#[clap(long, value_name = "PATH", value_parser)]
pub runtime_override: Option<PathBuf>,
#[clap(long, default_value = "instant")]
pub sealing: Sealing,
#[clap(long, value_delimiter = ',')]
pub ethapi: Vec<EthApi>,
#[clap(long, default_value = "10")]
pub ethapi_max_permits: u32,
#[clap(long, default_value = "500")]
pub ethapi_trace_max_count: u32,
#[clap(long, default_value = "300")]
pub ethapi_trace_cache_duration: u64,
#[clap(long, default_value = "300000000")]
pub eth_log_block_cache: usize,
#[clap(long, default_value = "300000000")]
pub eth_statuses_cache: usize,
#[arg(long, value_enum, ignore_case = true, default_value_t = FrontierBackendType::default())]
pub frontier_backend_type: FrontierBackendType,
#[arg(long, default_value = "100")]
pub frontier_sql_backend_pool_size: u32,
#[arg(long, default_value = "10000000")]
pub frontier_sql_backend_num_ops_timeout: u32,
#[arg(long, default_value = "4")]
pub frontier_sql_backend_thread_count: u32,
#[arg(long, default_value = "209715200")]
pub frontier_sql_backend_cache_size: u64,
#[clap(long, default_value = "20000000")]
pub tracing_raw_max_memory_usage: usize,
#[clap(long, default_value = "10000")]
pub max_past_logs: u32,
#[clap(long = "force-moonbase")]
pub force_moonbase: bool,
#[clap(long = "force-moonriver")]
pub force_moonriver: bool,
#[clap(long)]
pub parachain_id: Option<u32>,
#[clap(long, default_value = "2048")]
pub fee_history_limit: u64,
#[clap(long)]
pub no_hardware_benchmarks: bool,
#[clap(long)]
pub no_prometheus_prefix: bool,
#[clap(long, default_value = "2000", value_parser=block_authoring_duration_parser)]
pub block_authoring_duration: Duration,
}
fn block_authoring_duration_parser(s: &str) -> Result<Duration, String> {
Ok(Duration::from_millis(clap_num::number_range(
s, 250, 2_000,
)?))
}
impl RunCmd {
pub fn new_rpc_config(&self) -> moonbeam_cli_opt::RpcConfig {
moonbeam_cli_opt::RpcConfig {
ethapi: self.ethapi.clone(),
ethapi_max_permits: self.ethapi_max_permits,
ethapi_trace_max_count: self.ethapi_trace_max_count,
ethapi_trace_cache_duration: self.ethapi_trace_cache_duration,
eth_log_block_cache: self.eth_log_block_cache,
eth_statuses_cache: self.eth_statuses_cache,
fee_history_limit: self.fee_history_limit,
max_past_logs: self.max_past_logs,
relay_chain_rpc_urls: self.base.relay_chain_rpc_urls.clone(),
tracing_raw_max_memory_usage: self.tracing_raw_max_memory_usage,
frontier_backend_config: match self.frontier_backend_type {
FrontierBackendType::KeyValue => moonbeam_cli_opt::FrontierBackendConfig::KeyValue,
FrontierBackendType::Sql => moonbeam_cli_opt::FrontierBackendConfig::Sql {
pool_size: self.frontier_sql_backend_pool_size,
num_ops_timeout: self.frontier_sql_backend_num_ops_timeout,
thread_count: self.frontier_sql_backend_thread_count,
cache_size: self.frontier_sql_backend_cache_size,
},
},
no_prometheus_prefix: self.no_prometheus_prefix,
}
}
}
impl std::ops::Deref for RunCmd {
type Target = cumulus_client_cli::RunCmd;
fn deref(&self) -> &Self::Target {
&self.base
}
}
#[derive(Debug, clap::Subcommand)]
pub enum KeyCmd {
#[clap(flatten)]
BaseCli(sc_cli::KeySubcommand),
GenerateAccountKey(GenerateAccountKey),
}
impl KeyCmd {
pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), CliError> {
match self {
KeyCmd::BaseCli(cmd) => cmd.run(cli),
KeyCmd::GenerateAccountKey(cmd) => {
cmd.run();
Ok(())
}
}
}
}
#[derive(Debug, Parser)]
#[clap(
propagate_version = true,
args_conflicts_with_subcommands = true,
subcommand_negates_reqs = true
)]
pub struct Cli {
#[clap(subcommand)]
pub subcommand: Option<Subcommand>,
#[clap(flatten)]
pub run: RunCmd,
#[clap(raw = true)]
pub relaychain_args: Vec<String>,
}
#[derive(Debug)]
pub struct RelayChainCli {
pub base: polkadot_cli::RunCmd,
pub chain_id: Option<String>,
pub base_path: PathBuf,
}
impl RelayChainCli {
pub fn new<'a>(
para_config: &sc_service::Configuration,
relay_chain_args: impl Iterator<Item = &'a String>,
) -> Self {
let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
let chain_id = extension.map(|e| e.relay_chain.clone());
let base_path = para_config.base_path.path().join("polkadot");
Self {
base_path,
chain_id,
base: polkadot_cli::RunCmd::parse_from(relay_chain_args),
}
}
}