Merge latest interop

This commit is contained in:
Age Manning
2019-09-05 03:03:45 +10:00
37 changed files with 1019 additions and 473 deletions

View File

@@ -1,5 +1,5 @@
use clap::ArgMatches;
use client::{BeaconChainStartMethod, ClientConfig, Eth2Config};
use client::{BeaconChainStartMethod, ClientConfig, Eth1BackendMethod, Eth2Config};
use eth2_config::{read_from_file, write_to_file};
use lighthouse_bootstrap::Bootstrapper;
use rand::{distributions::Alphanumeric, Rng};
@@ -25,6 +25,14 @@ type Config = (ClientConfig, Eth2Config);
pub fn get_configs(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
let mut builder = ConfigBuilder::new(cli_args, log)?;
if let Some(server) = cli_args.value_of("eth1-server") {
builder.set_eth1_backend_method(Eth1BackendMethod::Web3 {
server: server.into(),
})
} else {
builder.set_eth1_backend_method(Eth1BackendMethod::Interop)
}
match cli_args.subcommand() {
("testnet", Some(sub_cmd_args)) => {
process_testnet_subcommand(&mut builder, sub_cmd_args, log)?
@@ -70,11 +78,15 @@ fn process_testnet_subcommand(
builder.set_random_datadir()?;
}
if cli_args.is_present("force") {
builder.clean_datadir()?;
}
let is_bootstrap = cli_args.subcommand_name() == Some("bootstrap");
if let Some(path_string) = cli_args.value_of("eth2-config") {
if is_bootstrap {
return Err("Cannot supply --eth2-config when using bootsrap".to_string());
return Err("Cannot supply --eth2-config when using bootstrap".to_string());
}
let path = path_string
@@ -85,6 +97,18 @@ fn process_testnet_subcommand(
builder.update_spec_from_subcommand(&cli_args)?;
}
if let Some(slot_time) = cli_args.value_of("slot-time") {
if is_bootstrap {
return Err("Cannot supply --slot-time flag whilst using bootstrap.".into());
}
let slot_time = slot_time
.parse::<u64>()
.map_err(|e| format!("Unable to parse slot-time: {:?}", e))?;
builder.set_slot_time(slot_time);
}
if let Some(path_string) = cli_args.value_of("client-config") {
let path = path_string
.parse::<PathBuf>()
@@ -92,10 +116,6 @@ fn process_testnet_subcommand(
builder.load_client_config(path)?;
}
if cli_args.is_present("force") {
builder.clean_datadir()?;
}
info!(
log,
"Creating new datadir";
@@ -117,6 +137,7 @@ fn process_testnet_subcommand(
.and_then(|s| s.parse::<u16>().ok());
builder.import_bootstrap_libp2p_address(server, port)?;
builder.import_bootstrap_enr_address(server)?;
builder.import_bootstrap_eth2_config(server)?;
builder.set_beacon_chain_start_method(BeaconChainStartMethod::HttpBootstrap {
@@ -160,6 +181,32 @@ fn process_testnet_subcommand(
genesis_time,
})
}
("file", Some(cli_args)) => {
let file = cli_args
.value_of("file")
.ok_or_else(|| "No filename specified")?
.parse::<PathBuf>()
.map_err(|e| format!("Unable to parse filename: {:?}", e))?;
let format = cli_args
.value_of("format")
.ok_or_else(|| "No file format specified")?;
let start_method = match format {
"yaml" => BeaconChainStartMethod::Yaml { file },
"ssz" => BeaconChainStartMethod::Ssz { file },
"json" => BeaconChainStartMethod::Json { file },
other => return Err(format!("Unknown genesis file format: {}", other)),
};
builder.set_beacon_chain_start_method(start_method)
}
(cmd, Some(_)) => {
return Err(format!(
"Invalid valid method specified: {}. See 'testnet --help'.",
cmd
))
}
_ => return Err("No testnet method specified. See 'testnet --help'.".into()),
};
@@ -250,7 +297,12 @@ impl<'a> ConfigBuilder<'a> {
self.client_config.beacon_chain_start_method = method;
}
/// Import the libp2p address for `server` into the list of bootnodes in `self`.
/// Sets the method for starting the beacon chain.
pub fn set_eth1_backend_method(&mut self, method: Eth1BackendMethod) {
self.client_config.eth1_backend_method = method;
}
/// Import the libp2p address for `server` into the list of libp2p nodes to connect with.
///
/// If `port` is `Some`, it is used as the port for the `Multiaddr`. If `port` is `None`,
/// attempts to connect to the `server` via HTTP and retrieve it's libp2p listen port.
@@ -259,7 +311,7 @@ impl<'a> ConfigBuilder<'a> {
server: &str,
port: Option<u16>,
) -> Result<()> {
let bootstrapper = Bootstrapper::from_server_string(server.to_string())?;
let bootstrapper = Bootstrapper::connect(server.to_string(), &self.log)?;
if let Some(server_multiaddr) = bootstrapper.best_effort_multiaddr(port) {
info!(
@@ -282,6 +334,28 @@ impl<'a> ConfigBuilder<'a> {
Ok(())
}
/// Import the enr address for `server` into the list of initial enrs (boot nodes).
pub fn import_bootstrap_enr_address(&mut self, server: &str) -> Result<()> {
let bootstrapper = Bootstrapper::connect(server.to_string(), &self.log)?;
if let Ok(enr) = bootstrapper.enr() {
info!(
self.log,
"Loaded bootstrapper libp2p address";
"enr" => format!("{:?}", enr)
);
self.client_config.network.boot_nodes.push(enr);
} else {
warn!(
self.log,
"Unable to estimate a bootstrapper enr address, this node may not find any peers."
);
};
Ok(())
}
/// Set the config data_dir to be an random directory.
///
/// Useful for easily spinning up ephemeral testnets.
@@ -296,7 +370,7 @@ impl<'a> ConfigBuilder<'a> {
/// Imports an `Eth2Config` from `server`, returning an error if this fails.
pub fn import_bootstrap_eth2_config(&mut self, server: &str) -> Result<()> {
let bootstrapper = Bootstrapper::from_server_string(server.to_string())?;
let bootstrapper = Bootstrapper::connect(server.to_string(), &self.log)?;
self.update_eth2_config(bootstrapper.eth2_config()?);
@@ -307,6 +381,10 @@ impl<'a> ConfigBuilder<'a> {
self.eth2_config = eth2_config;
}
fn set_slot_time(&mut self, milliseconds_per_slot: u64) {
self.eth2_config.spec.milliseconds_per_slot = milliseconds_per_slot;
}
/// Reads the subcommand and tries to update `self.eth2_config` based up on the `--spec` flag.
///
/// Returns an error if the `--spec` flag is not present in the given `cli_args`.

View File

@@ -163,6 +163,16 @@ fn main() {
.takes_value(true),
)
/*
* Eth1 Integration
*/
.arg(
Arg::with_name("eth1-server")
.long("eth1-server")
.value_name("SERVER")
.help("Specifies the server for a web3 connection to the Eth1 chain.")
.takes_value(true)
)
/*
* Database parameters.
*/
@@ -235,6 +245,13 @@ fn main() {
backup directory.")
.conflicts_with("random-datadir")
)
.arg(
Arg::with_name("slot-time")
.long("slot-time")
.short("t")
.value_name("MILLISECONDS")
.help("Defines the slot time when creating a new testnet.")
)
/*
* `boostrap`
*
@@ -246,6 +263,7 @@ fn main() {
.arg(Arg::with_name("server")
.value_name("HTTP_SERVER")
.required(true)
.default_value("http://localhost:5052")
.help("A HTTP server, with a http:// prefix"))
.arg(Arg::with_name("libp2p-port")
.short("p")
@@ -298,9 +316,14 @@ fn main() {
*
* 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 \
a YAML state that was generated to a different spec than that specified by --spec.")
.subcommand(SubCommand::with_name("file")
.about("Creates a new datadir where the genesis state is read from YAML. May fail to parse \
a file that was generated to a different spec than that specified by --spec.")
.arg(Arg::with_name("format")
.value_name("FORMAT")
.required(true)
.possible_values(&["yaml", "ssz", "json"])
.help("The encoding of the state in the file."))
.arg(Arg::with_name("file")
.value_name("YAML_FILE")
.required(true)

View File

@@ -1,4 +1,7 @@
use client::{error, notifier, BeaconChainTypes, Client, ClientConfig, ClientType, Eth2Config};
use client::{
error, notifier, BeaconChainTypes, Client, ClientConfig, ClientType, Eth1BackendMethod,
Eth2Config,
};
use futures::sync::oneshot;
use futures::Future;
use slog::{error, info};
@@ -47,55 +50,30 @@ pub fn run_beacon_node(
"spec_constants" => &spec_constants,
);
macro_rules! run_client {
($store: ty, $eth_spec: ty) => {
run::<ClientType<$store, $eth_spec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
)
};
}
if let Eth1BackendMethod::Web3 { .. } = client_config.eth1_backend_method {
return Err("Starting from web3 backend is not supported for interop.".into());
}
match (db_type.as_str(), spec_constants.as_str()) {
("disk", "minimal") => run::<ClientType<DiskStore, MinimalEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("memory", "minimal") => run::<ClientType<MemoryStore, MinimalEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("disk", "mainnet") => run::<ClientType<DiskStore, MainnetEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("memory", "mainnet") => run::<ClientType<MemoryStore, MainnetEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("disk", "interop") => run::<ClientType<DiskStore, InteropEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("memory", "interop") => run::<ClientType<MemoryStore, InteropEthSpec>>(
&db_path,
client_config,
eth2_config,
executor,
runtime,
log,
),
("disk", "minimal") => run_client!(DiskStore, MinimalEthSpec),
("disk", "mainnet") => run_client!(DiskStore, MainnetEthSpec),
("disk", "interop") => run_client!(DiskStore, InteropEthSpec),
("memory", "minimal") => run_client!(MemoryStore, MinimalEthSpec),
("memory", "mainnet") => run_client!(MemoryStore, MainnetEthSpec),
("memory", "interop") => run_client!(MemoryStore, InteropEthSpec),
(db_type, spec) => {
error!(log, "Unknown runtime configuration"; "spec_constants" => spec, "db_type" => db_type);
Err("Unknown specification and/or db_type.".into())