Attempt fix for addr parsing

This commit is contained in:
Paul Hauner
2019-11-23 15:20:29 +11:00
parent 466eb0420f
commit 68942318a7
4 changed files with 111 additions and 153 deletions

View File

@@ -9,14 +9,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
/* /*
* Configuration directory locations. * Configuration directory locations.
*/ */
.arg(
Arg::with_name("datadir")
.long("datadir")
.value_name("DIR")
.help("Data directory for keys and databases.")
.takes_value(true)
.global(true)
)
.arg( .arg(
Arg::with_name("network-dir") Arg::with_name("network-dir")
.long("network-dir") .long("network-dir")

View File

@@ -12,7 +12,6 @@ use reqwest::{
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use ssz::Encode; use ssz::Encode;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::net::SocketAddr;
use std::time::Duration; use std::time::Duration;
use types::{ use types::{
Attestation, BeaconBlock, BeaconState, CommitteeIndex, Epoch, EthSpec, Fork, Hash256, Attestation, BeaconBlock, BeaconState, CommitteeIndex, Epoch, EthSpec, Fork, Hash256,
@@ -36,9 +35,9 @@ pub struct RemoteBeaconNode<E: EthSpec> {
} }
impl<E: EthSpec> RemoteBeaconNode<E> { impl<E: EthSpec> RemoteBeaconNode<E> {
pub fn new(http_endpoint: SocketAddr) -> Result<Self, String> { pub fn new(http_endpoint: String) -> Result<Self, String> {
Ok(Self { Ok(Self {
http: HttpClient::new(format!("http://{}", http_endpoint.to_string())) http: HttpClient::new(http_endpoint)
.map_err(|e| format!("Unable to create http client: {:?}", e))?, .map_err(|e| format!("Unable to create http client: {:?}", e))?,
}) })
} }

View File

@@ -15,34 +15,9 @@ lazy_static! {
} }
pub fn cli_app<'a, 'b>() -> App<'a, 'b> { pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
App::new("Validator Client") App::new("validator_client")
.visible_aliases(&["v", "vc", "validator", "validator_client"]) .visible_aliases(&["v", "vc", "validator"])
.version("0.0.1") .about("Ethereum 2.0 Validator Client")
.author("Sigma Prime <contact@sigmaprime.io>")
.about("Eth 2.0 Validator Client")
.arg(
Arg::with_name("datadir")
.long("datadir")
.short("d")
.value_name("DIR")
.help("Data directory for keys and databases.")
.takes_value(true),
)
.arg(
Arg::with_name("logfile")
.long("logfile")
.value_name("logfile")
.help("File path where output will be written.")
.takes_value(true),
)
.arg(
Arg::with_name("eth2-config")
.long("eth2-config")
.short("e")
.value_name("TOML_FILE")
.help("Path to Ethereum 2.0 config and specification file (e.g., eth2_spec.toml).")
.takes_value(true),
)
.arg( .arg(
Arg::with_name("server") Arg::with_name("server")
.long("server") .long("server")

View File

@@ -69,137 +69,129 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
let log_2 = context.log.clone(); let log_2 = context.log.clone();
let log_3 = context.log.clone(); let log_3 = context.log.clone();
let http_server_addr = format!(
"http://{}:{}",
client_config.server, client_config.server_http_port
);
info!( info!(
log_1, log_1,
"Starting validator client"; "Starting validator client";
"beacon_node" => &http_server_addr,
"datadir" => format!("{:?}", client_config.data_dir), "datadir" => format!("{:?}", client_config.data_dir),
); );
format!( RemoteBeaconNode::new(http_server_addr)
"{}:{}", .map_err(|e| format!("Unable to init beacon node http client: {}", e))
client_config.server, client_config.server_http_port .into_future()
) .and_then(move |beacon_node| wait_for_node(beacon_node, log_2))
.parse() .and_then(|beacon_node| {
.map_err(|e| format!("Unable to parse server address: {:?}", e)) beacon_node
.into_future() .http
.and_then(move |http_server_addr| { .spec()
info!( .get_eth2_config()
log_1, .map(|eth2_config| (beacon_node, eth2_config))
"Beacon node connection info"; .map_err(|e| format!("Unable to read eth2 config from beacon node: {:?}", e))
"http_server" => format!("{}", http_server_addr), })
); .and_then(|(beacon_node, eth2_config)| {
beacon_node
.http
.beacon()
.get_genesis_time()
.map(|genesis_time| (beacon_node, eth2_config, genesis_time))
.map_err(|e| format!("Unable to read genesis time from beacon node: {:?}", e))
})
.and_then(move |(beacon_node, remote_eth2_config, genesis_time)| {
// Do not permit a connection to a beacon node using different spec constants.
if context.eth2_config.spec_constants != remote_eth2_config.spec_constants {
return Err(format!(
"Beacon node is using an incompatible spec. Got {}, expected {}",
remote_eth2_config.spec_constants, context.eth2_config.spec_constants
));
}
RemoteBeaconNode::new(http_server_addr) // Note: here we just assume the spec variables of the remote node. This is very useful
.map_err(|e| format!("Unable to init beacon node http client: {}", e)) // for testnets, but perhaps a security issue when it comes to mainnet.
})
.and_then(move |beacon_node| wait_for_node(beacon_node, log_2))
.and_then(|beacon_node| {
beacon_node
.http
.spec()
.get_eth2_config()
.map(|eth2_config| (beacon_node, eth2_config))
.map_err(|e| format!("Unable to read eth2 config from beacon node: {:?}", e))
})
.and_then(|(beacon_node, eth2_config)| {
beacon_node
.http
.beacon()
.get_genesis_time()
.map(|genesis_time| (beacon_node, eth2_config, genesis_time))
.map_err(|e| format!("Unable to read genesis time from beacon node: {:?}", e))
})
.and_then(move |(beacon_node, remote_eth2_config, genesis_time)| {
// Do not permit a connection to a beacon node using different spec constants.
if context.eth2_config.spec_constants != remote_eth2_config.spec_constants {
return Err(format!(
"Beacon node is using an incompatible spec. Got {}, expected {}",
remote_eth2_config.spec_constants, context.eth2_config.spec_constants
));
}
// Note: here we just assume the spec variables of the remote node. This is very useful
// for testnets, but perhaps a security issue when it comes to mainnet.
//
// A damaging attack would be for a beacon node to convince the validator client of a
// different `SLOTS_PER_EPOCH` variable. This could result in slashable messages being
// produced. We are safe from this because `SLOTS_PER_EPOCH` is a type-level constant
// for Lighthouse.
context.eth2_config = remote_eth2_config;
let slot_clock = SystemTimeSlotClock::new(
context.eth2_config.spec.genesis_slot,
Duration::from_secs(genesis_time),
Duration::from_millis(context.eth2_config.spec.milliseconds_per_slot),
);
let validator_store: ValidatorStore<T> = match &client_config.key_source {
// Load pre-existing validators from the data dir.
// //
// Use the `account_manager` to generate these files. // A damaging attack would be for a beacon node to convince the validator client of a
KeySource::Disk => ValidatorStore::load_from_disk( // different `SLOTS_PER_EPOCH` variable. This could result in slashable messages being
client_config.data_dir.clone(), // produced. We are safe from this because `SLOTS_PER_EPOCH` is a type-level constant
context.eth2_config.spec.clone(), // for Lighthouse.
log_3.clone(), context.eth2_config = remote_eth2_config;
)?,
// Generate ephemeral insecure keypairs for testing purposes. let slot_clock = SystemTimeSlotClock::new(
// context.eth2_config.spec.genesis_slot,
// Do not use in production. Duration::from_secs(genesis_time),
KeySource::TestingKeypairRange(range) => { Duration::from_millis(context.eth2_config.spec.milliseconds_per_slot),
ValidatorStore::insecure_ephemeral_validators( );
range.clone(),
let validator_store: ValidatorStore<T> = match &client_config.key_source {
// Load pre-existing validators from the data dir.
//
// Use the `account_manager` to generate these files.
KeySource::Disk => ValidatorStore::load_from_disk(
client_config.data_dir.clone(),
context.eth2_config.spec.clone(), context.eth2_config.spec.clone(),
log_3.clone(), log_3.clone(),
)? )?,
} // Generate ephemeral insecure keypairs for testing purposes.
}; //
// Do not use in production.
KeySource::TestingKeypairRange(range) => {
ValidatorStore::insecure_ephemeral_validators(
range.clone(),
context.eth2_config.spec.clone(),
log_3.clone(),
)?
}
};
info!( info!(
log_3, log_3,
"Loaded validator keypair store"; "Loaded validator keypair store";
"voting_validators" => validator_store.num_voting_validators() "voting_validators" => validator_store.num_voting_validators()
); );
let duties_service = DutiesServiceBuilder::new() let duties_service = DutiesServiceBuilder::new()
.slot_clock(slot_clock.clone()) .slot_clock(slot_clock.clone())
.validator_store(validator_store.clone()) .validator_store(validator_store.clone())
.beacon_node(beacon_node.clone()) .beacon_node(beacon_node.clone())
.runtime_context(context.service_context("duties")) .runtime_context(context.service_context("duties"))
.build()?; .build()?;
let fork_service = ForkServiceBuilder::new() let fork_service = ForkServiceBuilder::new()
.slot_clock(slot_clock.clone()) .slot_clock(slot_clock.clone())
.beacon_node(beacon_node.clone()) .beacon_node(beacon_node.clone())
.runtime_context(context.service_context("fork")) .runtime_context(context.service_context("fork"))
.build()?; .build()?;
let block_service = BlockServiceBuilder::new() let block_service = BlockServiceBuilder::new()
.duties_service(duties_service.clone()) .duties_service(duties_service.clone())
.fork_service(fork_service.clone()) .fork_service(fork_service.clone())
.slot_clock(slot_clock.clone()) .slot_clock(slot_clock.clone())
.validator_store(validator_store.clone()) .validator_store(validator_store.clone())
.beacon_node(beacon_node.clone()) .beacon_node(beacon_node.clone())
.runtime_context(context.service_context("block")) .runtime_context(context.service_context("block"))
.build()?; .build()?;
let attestation_service = AttestationServiceBuilder::new() let attestation_service = AttestationServiceBuilder::new()
.duties_service(duties_service.clone()) .duties_service(duties_service.clone())
.fork_service(fork_service.clone()) .fork_service(fork_service.clone())
.slot_clock(slot_clock) .slot_clock(slot_clock)
.validator_store(validator_store) .validator_store(validator_store)
.beacon_node(beacon_node) .beacon_node(beacon_node)
.runtime_context(context.service_context("attestation")) .runtime_context(context.service_context("attestation"))
.build()?; .build()?;
Ok(Self { Ok(Self {
context, context,
duties_service, duties_service,
fork_service, fork_service,
block_service, block_service,
attestation_service, attestation_service,
exit_signals: Arc::new(RwLock::new(vec![])), exit_signals: Arc::new(RwLock::new(vec![])),
})
}) })
})
} }
pub fn start_service(&self) -> Result<(), String> { pub fn start_service(&self) -> Result<(), String> {