Improve and extend CLI interface
This commit is contained in:
parent
6ba093d14f
commit
5f0509be50
@ -158,12 +158,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
genesis_state_root,
|
genesis_state_root,
|
||||||
));
|
));
|
||||||
|
|
||||||
info!(log, "BeaconChain init";
|
|
||||||
"genesis_validator_count" => genesis_state.validators.len(),
|
|
||||||
"genesis_state_root" => format!("{}", genesis_state_root),
|
|
||||||
"genesis_block_root" => format!("{}", genesis_block_root),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Slot clock
|
// Slot clock
|
||||||
let slot_clock = T::SlotClock::from_eth2_genesis(
|
let slot_clock = T::SlotClock::from_eth2_genesis(
|
||||||
spec.genesis_slot,
|
spec.genesis_slot,
|
||||||
@ -172,6 +166,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
)
|
)
|
||||||
.ok_or_else(|| Error::SlotClockDidNotStart)?;
|
.ok_or_else(|| Error::SlotClockDidNotStart)?;
|
||||||
|
|
||||||
|
info!(log, "Beacon chain initialized from genesis";
|
||||||
|
"validator_count" => genesis_state.validators.len(),
|
||||||
|
"state_root" => format!("{}", genesis_state_root),
|
||||||
|
"block_root" => format!("{}", genesis_block_root),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
spec,
|
spec,
|
||||||
slot_clock,
|
slot_clock,
|
||||||
@ -211,6 +211,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
|
|
||||||
let op_pool = p.op_pool.into_operation_pool(state, &spec);
|
let op_pool = p.op_pool.into_operation_pool(state, &spec);
|
||||||
|
|
||||||
|
info!(log, "Beacon chain initialized from store";
|
||||||
|
"head_root" => format!("{}", p.canonical_head.beacon_block_root),
|
||||||
|
"head_epoch" => format!("{}", p.canonical_head.beacon_block.slot.epoch(T::EthSpec::slots_per_epoch())),
|
||||||
|
"finalized_root" => format!("{}", last_finalized_root),
|
||||||
|
"finalized_epoch" => format!("{}", last_finalized_block.slot.epoch(T::EthSpec::slots_per_epoch())),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(Some(BeaconChain {
|
Ok(Some(BeaconChain {
|
||||||
spec,
|
spec,
|
||||||
slot_clock,
|
slot_clock,
|
||||||
|
@ -82,34 +82,70 @@ where
|
|||||||
|
|
||||||
let beacon_chain_builder = match &client_config.beacon_chain_start_method {
|
let beacon_chain_builder = match &client_config.beacon_chain_start_method {
|
||||||
BeaconChainStartMethod::Resume => {
|
BeaconChainStartMethod::Resume => {
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"Starting beacon chain";
|
||||||
|
"method" => "resume"
|
||||||
|
);
|
||||||
BeaconChainBuilder::from_store(spec.clone(), log.clone())
|
BeaconChainBuilder::from_store(spec.clone(), log.clone())
|
||||||
}
|
}
|
||||||
BeaconChainStartMethod::Mainnet => {
|
BeaconChainStartMethod::Mainnet => {
|
||||||
crit!(log, "No mainnet beacon chain startup specification.");
|
crit!(log, "No mainnet beacon chain startup specification.");
|
||||||
return Err("Mainnet is not yet specified. We're working on it.".into());
|
return Err("Mainnet launch is not yet announced.".into());
|
||||||
}
|
}
|
||||||
BeaconChainStartMethod::RecentGenesis {
|
BeaconChainStartMethod::RecentGenesis {
|
||||||
validator_count,
|
validator_count,
|
||||||
minutes,
|
minutes,
|
||||||
} => BeaconChainBuilder::recent_genesis(
|
} => {
|
||||||
*validator_count,
|
info!(
|
||||||
*minutes,
|
log,
|
||||||
spec.clone(),
|
"Starting beacon chain";
|
||||||
log.clone(),
|
"validator_count" => validator_count,
|
||||||
)?,
|
"minutes" => minutes,
|
||||||
|
"method" => "recent"
|
||||||
|
);
|
||||||
|
BeaconChainBuilder::recent_genesis(
|
||||||
|
*validator_count,
|
||||||
|
*minutes,
|
||||||
|
spec.clone(),
|
||||||
|
log.clone(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
BeaconChainStartMethod::Generated {
|
BeaconChainStartMethod::Generated {
|
||||||
validator_count,
|
validator_count,
|
||||||
genesis_time,
|
genesis_time,
|
||||||
} => BeaconChainBuilder::quick_start(
|
} => {
|
||||||
*genesis_time,
|
info!(
|
||||||
*validator_count,
|
log,
|
||||||
spec.clone(),
|
"Starting beacon chain";
|
||||||
log.clone(),
|
"validator_count" => validator_count,
|
||||||
)?,
|
"genesis_time" => genesis_time,
|
||||||
|
"method" => "quick"
|
||||||
|
);
|
||||||
|
BeaconChainBuilder::quick_start(
|
||||||
|
*genesis_time,
|
||||||
|
*validator_count,
|
||||||
|
spec.clone(),
|
||||||
|
log.clone(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
BeaconChainStartMethod::Yaml { file } => {
|
BeaconChainStartMethod::Yaml { file } => {
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"Starting beacon chain";
|
||||||
|
"file" => format!("{:?}", file),
|
||||||
|
"method" => "yaml"
|
||||||
|
);
|
||||||
BeaconChainBuilder::yaml_state(file, spec.clone(), log.clone())?
|
BeaconChainBuilder::yaml_state(file, spec.clone(), log.clone())?
|
||||||
}
|
}
|
||||||
BeaconChainStartMethod::HttpBootstrap { server, .. } => {
|
BeaconChainStartMethod::HttpBootstrap { server, port } => {
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"Starting beacon chain";
|
||||||
|
"port" => port,
|
||||||
|
"server" => server,
|
||||||
|
"method" => "bootstrap"
|
||||||
|
);
|
||||||
BeaconChainBuilder::http_bootstrap(server, spec.clone(), log.clone())?
|
BeaconChainBuilder::http_bootstrap(server, spec.clone(), log.clone())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -124,26 +160,6 @@ where
|
|||||||
panic!("Cannot start client before genesis!")
|
panic!("Cannot start client before genesis!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block starting the client until we have caught the state up to the current slot.
|
|
||||||
//
|
|
||||||
// If we don't block here we create an initial scenario where we're unable to process any
|
|
||||||
// blocks and we're basically useless.
|
|
||||||
{
|
|
||||||
let state_slot = beacon_chain.head().beacon_state.slot;
|
|
||||||
let wall_clock_slot = beacon_chain
|
|
||||||
.slot()
|
|
||||||
.expect("Cannot start client before genesis");
|
|
||||||
let slots_since_genesis = beacon_chain.slots_since_genesis().unwrap();
|
|
||||||
info!(
|
|
||||||
log,
|
|
||||||
"BeaconState cache init";
|
|
||||||
"state_slot" => state_slot,
|
|
||||||
"wall_clock_slot" => wall_clock_slot,
|
|
||||||
"slots_since_genesis" => slots_since_genesis,
|
|
||||||
"catchup_distance" => wall_clock_slot - state_slot,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let network_config = &client_config.network;
|
let network_config = &client_config.network;
|
||||||
let (network, network_send) =
|
let (network, network_send) =
|
||||||
NetworkService::new(beacon_chain.clone(), network_config, executor, log.clone())?;
|
NetworkService::new(beacon_chain.clone(), network_config, executor, log.clone())?;
|
||||||
|
@ -15,6 +15,12 @@ type Result<T> = std::result::Result<T, String>;
|
|||||||
type Config = (ClientConfig, Eth2Config);
|
type Config = (ClientConfig, Eth2Config);
|
||||||
|
|
||||||
/// Gets the fully-initialized global client and eth2 configuration objects.
|
/// Gets the fully-initialized global client and eth2 configuration objects.
|
||||||
|
///
|
||||||
|
/// The top-level `clap` arguments should be provied as `cli_args`.
|
||||||
|
///
|
||||||
|
/// The output of this function depends primarily upon the given `cli_args`, however it's behaviour
|
||||||
|
/// may be influenced by other external services like the contents of the file system or the
|
||||||
|
/// response of some remote server.
|
||||||
pub fn get_configs(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
|
pub fn get_configs(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
|
||||||
let mut builder = ConfigBuilder::new(cli_args, log)?;
|
let mut builder = ConfigBuilder::new(cli_args, log)?;
|
||||||
|
|
||||||
@ -95,7 +101,7 @@ fn process_testnet_subcommand(
|
|||||||
"path" => format!("{:?}", builder.data_dir)
|
"path" => format!("{:?}", builder.data_dir)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start matching on the second subcommand (e.g., `testnet bootstrap ...`)
|
// Start matching on the second subcommand (e.g., `testnet bootstrap ...`).
|
||||||
match cli_args.subcommand() {
|
match cli_args.subcommand() {
|
||||||
("bootstrap", Some(cli_args)) => {
|
("bootstrap", Some(cli_args)) => {
|
||||||
let server = cli_args
|
let server = cli_args
|
||||||
@ -131,6 +137,24 @@ fn process_testnet_subcommand(
|
|||||||
minutes,
|
minutes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
("quick", Some(cli_args)) => {
|
||||||
|
let validator_count = cli_args
|
||||||
|
.value_of("validator_count")
|
||||||
|
.ok_or_else(|| "No validator_count specified")?
|
||||||
|
.parse::<usize>()
|
||||||
|
.map_err(|e| format!("Unable to parse validator_count: {:?}", e))?;
|
||||||
|
|
||||||
|
let genesis_time = cli_args
|
||||||
|
.value_of("genesis_time")
|
||||||
|
.ok_or_else(|| "No genesis time supplied")?
|
||||||
|
.parse::<u64>()
|
||||||
|
.map_err(|e| format!("Unable to parse genesis time: {:?}", e))?;
|
||||||
|
|
||||||
|
builder.set_beacon_chain_start_method(BeaconChainStartMethod::Generated {
|
||||||
|
validator_count,
|
||||||
|
genesis_time,
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => return Err("No testnet method specified. See 'testnet --help'.".into()),
|
_ => return Err("No testnet method specified. See 'testnet --help'.".into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -420,6 +444,18 @@ impl<'a> ConfigBuilder<'a> {
|
|||||||
self.client_config
|
self.client_config
|
||||||
.apply_cli_args(cli_args, &mut self.log.clone())?;
|
.apply_cli_args(cli_args, &mut self.log.clone())?;
|
||||||
|
|
||||||
|
if let Some(bump) = cli_args.value_of("port-bump") {
|
||||||
|
let bump = bump
|
||||||
|
.parse::<u16>()
|
||||||
|
.map_err(|e| format!("Unable to parse port bump: {}", e))?;
|
||||||
|
|
||||||
|
self.client_config.network.libp2p_port += bump;
|
||||||
|
self.client_config.network.discovery_port += bump;
|
||||||
|
self.client_config.rpc.port += bump;
|
||||||
|
self.client_config.rpc.port += bump;
|
||||||
|
self.client_config.rest_api.port += bump;
|
||||||
|
}
|
||||||
|
|
||||||
if self.eth2_config.spec_constants != self.client_config.spec_constants {
|
if self.eth2_config.spec_constants != self.client_config.spec_constants {
|
||||||
crit!(self.log, "Specification constants do not match.";
|
crit!(self.log, "Specification constants do not match.";
|
||||||
"client_config" => format!("{}", self.client_config.spec_constants),
|
"client_config" => format!("{}", self.client_config.spec_constants),
|
||||||
|
@ -48,18 +48,29 @@ fn main() {
|
|||||||
/*
|
/*
|
||||||
* Network parameters.
|
* Network parameters.
|
||||||
*/
|
*/
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("port-bump")
|
||||||
|
.long("port-bump")
|
||||||
|
.short("b")
|
||||||
|
.value_name("INCREMENT")
|
||||||
|
.help("Sets all listening TCP/UDP ports to default values, but with each port increased by \
|
||||||
|
INCREMENT. Useful when starting multiple nodes on a single machine. Using increments \
|
||||||
|
in multiples of 10 is recommended.")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("listen-address")
|
Arg::with_name("listen-address")
|
||||||
.long("listen-address")
|
.long("listen-address")
|
||||||
.value_name("ADDRESS")
|
.value_name("ADDRESS")
|
||||||
.help("The address lighthouse will listen for UDP and TCP connections. (default 127.0.0.1).")
|
.help("The address lighthouse will listen for UDP and TCP connections. (default 127.0.0.1).")
|
||||||
.takes_value(true),
|
.takes_value(true)
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("port")
|
Arg::with_name("port")
|
||||||
.long("port")
|
.long("port")
|
||||||
.value_name("PORT")
|
.value_name("PORT")
|
||||||
.help("The TCP/UDP port to listen on. The UDP port can be modified by the --discovery-port flag.")
|
.help("The TCP/UDP port to listen on. The UDP port can be modified by the --discovery-port flag.")
|
||||||
|
.conflicts_with("port-bump")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -81,6 +92,7 @@ fn main() {
|
|||||||
.long("disc-port")
|
.long("disc-port")
|
||||||
.value_name("PORT")
|
.value_name("PORT")
|
||||||
.help("The discovery UDP port.")
|
.help("The discovery UDP port.")
|
||||||
|
.conflicts_with("port-bump")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -125,6 +137,7 @@ fn main() {
|
|||||||
Arg::with_name("rpc-port")
|
Arg::with_name("rpc-port")
|
||||||
.long("rpc-port")
|
.long("rpc-port")
|
||||||
.help("Listen port for RPC endpoint.")
|
.help("Listen port for RPC endpoint.")
|
||||||
|
.conflicts_with("port-bump")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
/* Client related arguments */
|
/* Client related arguments */
|
||||||
@ -147,6 +160,7 @@ fn main() {
|
|||||||
.long("api-port")
|
.long("api-port")
|
||||||
.value_name("APIPORT")
|
.value_name("APIPORT")
|
||||||
.help("Set the listen TCP port for the RESTful HTTP API server.")
|
.help("Set the listen TCP port for the RESTful HTTP API server.")
|
||||||
|
.conflicts_with("port-bump")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -230,8 +244,6 @@ fn main() {
|
|||||||
.conflicts_with("random-datadir")
|
.conflicts_with("random-datadir")
|
||||||
)
|
)
|
||||||
/*
|
/*
|
||||||
* Testnet sub-commands.
|
|
||||||
*
|
|
||||||
* `boostrap`
|
* `boostrap`
|
||||||
*
|
*
|
||||||
* Start a new node by downloading genesis and network info from another node via the
|
* Start a new node by downloading genesis and network info from another node via the
|
||||||
@ -272,7 +284,29 @@ fn main() {
|
|||||||
.default_value("15")
|
.default_value("15")
|
||||||
.help("The maximum number of minutes that will have elapsed before genesis"))
|
.help("The maximum number of minutes that will have elapsed before genesis"))
|
||||||
)
|
)
|
||||||
.subcommand(SubCommand::with_name("yaml-genesis-state")
|
/*
|
||||||
|
* `quick`
|
||||||
|
*
|
||||||
|
* Start a new node, specifying the number of validators and genesis time
|
||||||
|
*/
|
||||||
|
.subcommand(SubCommand::with_name("quick")
|
||||||
|
.about("Creates a new genesis state from the specified validator count and genesis time. \
|
||||||
|
Compatible with the `quick-start genesis` defined in the eth2.0-pm repo.")
|
||||||
|
.arg(Arg::with_name("validator_count")
|
||||||
|
.value_name("VALIDATOR_COUNT")
|
||||||
|
.required(true)
|
||||||
|
.help("The number of validators in the genesis state"))
|
||||||
|
.arg(Arg::with_name("genesis_time")
|
||||||
|
.value_name("UNIX_EPOCH_SECONDS")
|
||||||
|
.required(true)
|
||||||
|
.help("The genesis time for the given state."))
|
||||||
|
)
|
||||||
|
/*
|
||||||
|
* `yaml`
|
||||||
|
*
|
||||||
|
* Start a new node, using a genesis state loaded from a YAML file
|
||||||
|
*/
|
||||||
|
.subcommand(SubCommand::with_name("yaml")
|
||||||
.about("Creates a new datadir where the genesis state is read from YAML. Will fail to parse \
|
.about("Creates a new datadir where the genesis state is read from YAML. Will fail to parse \
|
||||||
a YAML state that was generated to a different spec than that specified by --spec.")
|
a YAML state that was generated to a different spec than that specified by --spec.")
|
||||||
.arg(Arg::with_name("file")
|
.arg(Arg::with_name("file")
|
||||||
|
@ -41,11 +41,10 @@ pub fn run_beacon_node(
|
|||||||
|
|
||||||
info!(
|
info!(
|
||||||
log,
|
log,
|
||||||
"BeaconNode init";
|
"Starting beacon node";
|
||||||
"p2p_listen_address" => format!("{:?}", &other_client_config.network.listen_address),
|
"p2p_listen_address" => format!("{}", &other_client_config.network.listen_address),
|
||||||
"network_dir" => format!("{:?}", other_client_config.network.network_dir),
|
|
||||||
"spec_constants" => &spec_constants,
|
|
||||||
"db_type" => &other_client_config.db_type,
|
"db_type" => &other_client_config.db_type,
|
||||||
|
"spec_constants" => &spec_constants,
|
||||||
);
|
);
|
||||||
|
|
||||||
match (db_type.as_str(), spec_constants.as_str()) {
|
match (db_type.as_str(), spec_constants.as_str()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user