Add whiteblock script, CLI options to support it

This commit is contained in:
Paul Hauner
2019-09-10 12:13:54 -04:00
parent 5de80f2799
commit 8c5a8034b6
16 changed files with 342 additions and 28 deletions

View File

@@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
clap = "2.32.0"
hex = "0.3"
#SigP repository
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "d4851ea3b564266aeb9d83d10148b972721999db" }
enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "d4851ea3b564266aeb9d83d10148b972721999db", features = ["serde"] }

View File

@@ -40,6 +40,12 @@ pub struct Config {
/// Target number of connected peers.
pub max_peers: usize,
/// A secp256k1 secret key, as bytes in ASCII-encoded hex.
///
/// With or without `0x` prefix.
#[serde(skip)]
pub secret_key_hex: Option<String>,
/// Gossipsub configuration parameters.
#[serde(skip)]
pub gs_config: GossipsubConfig,
@@ -70,6 +76,7 @@ impl Default for Config {
discovery_address: "127.0.0.1".parse().expect("valid ip address"),
discovery_port: 9000,
max_peers: 10,
secret_key_hex: None,
// Note: The topics by default are sent as plain strings. Hashes are an optional
// parameter.
gs_config: GossipsubConfigBuilder::new()
@@ -158,6 +165,10 @@ impl Config {
.map_err(|_| format!("Invalid discovery port: {}", disc_port_str))?;
}
if let Some(p2p_priv_key) = args.value_of("p2p-priv-key") {
self.secret_key_hex = Some(p2p_priv_key.to_string());
}
Ok(())
}
}

View File

@@ -42,16 +42,22 @@ impl Service {
pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result<Self> {
trace!(log, "Libp2p Service starting");
let local_keypair = if let Some(hex_bytes) = &config.secret_key_hex {
keypair_from_hex(hex_bytes)?
} else {
load_private_key(&config, &log)
};
// load the private key from CLI flag, disk or generate a new one
let local_private_key = load_private_key(&config, &log);
let local_peer_id = PeerId::from(local_private_key.public());
// let local_private_key = load_private_key(&config, &log);
let local_peer_id = PeerId::from(local_keypair.public());
info!(log, "Libp2p Service"; "peer_id" => format!("{:?}", local_peer_id));
let mut swarm = {
// Set up the transport - tcp/ws with secio and mplex/yamux
let transport = build_transport(local_private_key.clone());
let transport = build_transport(local_keypair.clone());
// Lighthouse network behaviour
let behaviour = Behaviour::new(&local_private_key, &config, &log)?;
let behaviour = Behaviour::new(&local_keypair, &config, &log)?;
Swarm::new(transport, behaviour, local_peer_id.clone())
};
@@ -246,6 +252,27 @@ pub enum Libp2pEvent {
},
}
fn keypair_from_hex(hex_bytes: &str) -> error::Result<Keypair> {
let hex_bytes = if hex_bytes.starts_with("0x") {
hex_bytes[2..].to_string()
} else {
hex_bytes.to_string()
};
hex::decode(&hex_bytes)
.map_err(|e| format!("Failed to parse p2p secret key bytes: {:?}", e).into())
.and_then(keypair_from_bytes)
}
fn keypair_from_bytes(mut bytes: Vec<u8>) -> error::Result<Keypair> {
libp2p::core::identity::secp256k1::SecretKey::from_bytes(&mut bytes)
.map(|secret| {
let keypair: libp2p::core::identity::secp256k1::Keypair = secret.into();
Keypair::Secp256k1(keypair)
})
.map_err(|e| format!("Unable to parse p2p secret key: {:?}", e).into())
}
/// Loads a private key from disk. If this fails, a new key is
/// generated and is then saved to disk.
///

View File

@@ -13,7 +13,7 @@ pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
type Result<T> = std::result::Result<T, String>;
type Config = (ClientConfig, Eth2Config);
type Config = (ClientConfig, Eth2Config, Logger);
/// Gets the fully-initialized global client and eth2 configuration objects.
///
@@ -22,8 +22,10 @@ type Config = (ClientConfig, Eth2Config);
/// 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> {
let mut builder = ConfigBuilder::new(cli_args, log)?;
pub fn get_configs(cli_args: &ArgMatches, core_log: Logger) -> Result<Config> {
let log = core_log.clone();
let mut builder = ConfigBuilder::new(cli_args, core_log)?;
if let Some(server) = cli_args.value_of("eth1-server") {
builder.set_eth1_backend_method(Eth1BackendMethod::Web3 {
@@ -35,7 +37,7 @@ pub fn get_configs(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
match cli_args.subcommand() {
("testnet", Some(sub_cmd_args)) => {
process_testnet_subcommand(&mut builder, sub_cmd_args, log)?
process_testnet_subcommand(&mut builder, sub_cmd_args, &log)?
}
// No sub-command assumes a resume operation.
_ => {
@@ -216,15 +218,15 @@ fn process_testnet_subcommand(
}
/// Allows for building a set of configurations based upon `clap` arguments.
struct ConfigBuilder<'a> {
log: &'a Logger,
struct ConfigBuilder {
log: Logger,
eth2_config: Eth2Config,
client_config: ClientConfig,
}
impl<'a> ConfigBuilder<'a> {
impl ConfigBuilder {
/// Create a new builder with default settings.
pub fn new(cli_args: &'a ArgMatches, log: &'a Logger) -> Result<Self> {
pub fn new(cli_args: &ArgMatches, log: Logger) -> Result<Self> {
// Read the `--datadir` flag.
//
// If it's not present, try and find the home directory (`~`) and push the default data
@@ -539,8 +541,7 @@ impl<'a> ConfigBuilder<'a> {
/// cli_args).
pub fn build(mut self, cli_args: &ArgMatches) -> Result<Config> {
self.eth2_config.apply_cli_args(cli_args)?;
self.client_config
.apply_cli_args(cli_args, &mut self.log.clone())?;
self.client_config.apply_cli_args(cli_args, &mut self.log)?;
if let Some(bump) = cli_args.value_of("port-bump") {
let bump = bump
@@ -561,7 +562,7 @@ impl<'a> ConfigBuilder<'a> {
return Err("Specification constant mismatch".into());
}
Ok((self.client_config, self.eth2_config))
Ok((self.client_config, self.eth2_config, self.log))
}
}

View File

@@ -116,6 +116,13 @@ fn main() {
.help("One or more comma-delimited multiaddrs to manually connect to a libp2p peer without an ENR.")
.takes_value(true),
)
.arg(
Arg::with_name("p2p-priv-key")
.long("p2p-priv-key")
.value_name("HEX")
.help("A secp256k1 secret key, represented as ASCII-encoded hex bytes (with or without 0x prefix).")
.takes_value(true),
)
/*
* gRPC parameters.
*/
@@ -355,13 +362,15 @@ fn main() {
"Ethereum 2.0 is pre-release. This software is experimental."
);
let log_clone = log.clone();
// Load the process-wide configuration.
//
// May load this from disk or create a new configuration, depending on the CLI flags supplied.
let (client_config, eth2_config) = match get_configs(&matches, &log) {
let (client_config, eth2_config, log) = match get_configs(&matches, log) {
Ok(configs) => configs,
Err(e) => {
crit!(log, "Failed to load configuration"; "error" => e);
crit!(log_clone, "Failed to load configuration. Exiting"; "error" => e);
return;
}
};