Allow bootstrapper to scrape libp2p address
This commit is contained in:
parent
4678524659
commit
ce37f95861
@ -28,3 +28,4 @@ dirs = "1.0.3"
|
|||||||
exit-future = "0.1.3"
|
exit-future = "0.1.3"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
reqwest = "0.9"
|
reqwest = "0.9"
|
||||||
|
url = "1.2"
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use eth2_libp2p::Enr;
|
use eth2_libp2p::{Enr, Multiaddr};
|
||||||
use reqwest::{Error as HttpError, Url};
|
use reqwest::{Error as HttpError, Url};
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
use types::{BeaconBlock, BeaconState, Checkpoint, EthSpec, Slot};
|
use types::{BeaconBlock, BeaconState, Checkpoint, EthSpec, Slot};
|
||||||
|
use url::Host;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
@ -25,10 +27,22 @@ impl Bootstrapper {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn server_ipv4_addr(&self) -> Option<Ipv4Addr> {
|
||||||
|
match self.url.host()? {
|
||||||
|
Host::Ipv4(addr) => Some(addr),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enr(&self) -> Result<Enr, String> {
|
pub fn enr(&self) -> Result<Enr, String> {
|
||||||
get_enr(self.url.clone()).map_err(|e| format!("Unable to get ENR: {:?}", e))
|
get_enr(self.url.clone()).map_err(|e| format!("Unable to get ENR: {:?}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn listen_addresses(&self) -> Result<Vec<Multiaddr>, String> {
|
||||||
|
get_listen_addresses(self.url.clone())
|
||||||
|
.map_err(|e| format!("Unable to get listen addresses: {:?}", e))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn genesis<T: EthSpec>(&self) -> Result<(BeaconState<T>, BeaconBlock<T>), String> {
|
pub fn genesis<T: EthSpec>(&self) -> Result<(BeaconState<T>, BeaconBlock<T>), String> {
|
||||||
let genesis_slot = Slot::new(0);
|
let genesis_slot = Slot::new(0);
|
||||||
|
|
||||||
@ -124,3 +138,16 @@ fn get_enr(mut url: Url) -> Result<Enr, Error> {
|
|||||||
.json()
|
.json()
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_listen_addresses(mut url: Url) -> Result<Vec<Multiaddr>, Error> {
|
||||||
|
url.path_segments_mut()
|
||||||
|
.map(|mut url| {
|
||||||
|
url.push("node").push("network").push("listen_addresses");
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::UrlCannotBeBase)?;
|
||||||
|
|
||||||
|
reqwest::get(url)?
|
||||||
|
.error_for_status()?
|
||||||
|
.json()
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::Eth2Config;
|
use crate::{Bootstrapper, Eth2Config};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
|
use eth2_libp2p::multiaddr::{Multiaddr, Protocol};
|
||||||
use network::NetworkConfig;
|
use network::NetworkConfig;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use slog::{info, o, Drain};
|
use slog::{info, o, warn, Drain};
|
||||||
use std::fs::{self, OpenOptions};
|
use std::fs::{self, OpenOptions};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@ -149,6 +150,43 @@ impl Config {
|
|||||||
self.update_logger(log)?;
|
self.update_logger(log)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If the `--bootstrap` flag is provided, overwrite the default configuration.
|
||||||
|
if let Some(server) = args.value_of("bootstrap") {
|
||||||
|
do_bootstrapping(self, server.to_string(), &log)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_bootstrapping(config: &mut Config, server: String, log: &slog::Logger) -> Result<(), String> {
|
||||||
|
// Set the genesis state source.
|
||||||
|
config.genesis_state = GenesisState::HttpBootstrap {
|
||||||
|
server: server.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bootstrapper = Bootstrapper::from_server_string(server.to_string())?;
|
||||||
|
|
||||||
|
config.network.boot_nodes.push(bootstrapper.enr()?);
|
||||||
|
|
||||||
|
if let Some(server_ip) = bootstrapper.server_ipv4_addr() {
|
||||||
|
let server_multiaddr: Multiaddr = bootstrapper
|
||||||
|
.listen_addresses()?
|
||||||
|
.first()
|
||||||
|
.ok_or_else(|| "Bootstrap peer returned an empty list of listen addresses")?
|
||||||
|
// Iterate through the components of the Multiaddr, replacing any Ipv4 address with the
|
||||||
|
// server address.
|
||||||
|
.iter()
|
||||||
|
.map(|protocol| match protocol {
|
||||||
|
Protocol::Ip4(_) => Protocol::Ip4(server_ip),
|
||||||
|
_ => protocol,
|
||||||
|
})
|
||||||
|
.collect::<Multiaddr>();
|
||||||
|
|
||||||
|
config.network.libp2p_nodes.push(server_multiaddr);
|
||||||
|
} else {
|
||||||
|
warn!(log, "Unable to determine bootstrap server Ipv4 address. Unable to add server as libp2p peer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -23,7 +23,7 @@ pub use libp2p::multiaddr;
|
|||||||
pub use libp2p::Multiaddr;
|
pub use libp2p::Multiaddr;
|
||||||
pub use libp2p::{
|
pub use libp2p::{
|
||||||
gossipsub::{GossipsubConfig, GossipsubConfigBuilder},
|
gossipsub::{GossipsubConfig, GossipsubConfigBuilder},
|
||||||
PeerId,
|
PeerId, Swarm,
|
||||||
};
|
};
|
||||||
pub use rpc::RPCEvent;
|
pub use rpc::RPCEvent;
|
||||||
pub use service::Libp2pEvent;
|
pub use service::Libp2pEvent;
|
||||||
|
@ -5,7 +5,7 @@ use beacon_chain::{BeaconChain, BeaconChainTypes};
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use eth2_libp2p::Service as LibP2PService;
|
use eth2_libp2p::Service as LibP2PService;
|
||||||
use eth2_libp2p::Topic;
|
use eth2_libp2p::Topic;
|
||||||
use eth2_libp2p::{Enr, Libp2pEvent, PeerId};
|
use eth2_libp2p::{Enr, Libp2pEvent, Multiaddr, PeerId, Swarm};
|
||||||
use eth2_libp2p::{PubsubMessage, RPCEvent};
|
use eth2_libp2p::{PubsubMessage, RPCEvent};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
@ -64,6 +64,8 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
|
|||||||
Ok((Arc::new(network_service), network_send))
|
Ok((Arc::new(network_service), network_send))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the local ENR from the underlying Discv5 behaviour that external peers may connect
|
||||||
|
/// to.
|
||||||
pub fn local_enr(&self) -> Enr {
|
pub fn local_enr(&self) -> Enr {
|
||||||
self.libp2p_service
|
self.libp2p_service
|
||||||
.lock()
|
.lock()
|
||||||
@ -73,10 +75,19 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
|
|||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the list of `Multiaddr` that the underlying libp2p instance is listening on.
|
||||||
|
pub fn listen_multiaddrs(&self) -> Vec<Multiaddr> {
|
||||||
|
Swarm::listeners(&self.libp2p_service.lock().swarm)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of libp2p connected peers.
|
||||||
pub fn connected_peers(&self) -> usize {
|
pub fn connected_peers(&self) -> usize {
|
||||||
self.libp2p_service.lock().swarm.connected_peers()
|
self.libp2p_service.lock().swarm.connected_peers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the set of `PeerId` that are connected via libp2p.
|
||||||
pub fn connected_peer_set(&self) -> Vec<PeerId> {
|
pub fn connected_peer_set(&self) -> Vec<PeerId> {
|
||||||
self.libp2p_service
|
self.libp2p_service
|
||||||
.lock()
|
.lock()
|
||||||
@ -88,6 +99,7 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides a reference to the underlying libp2p service.
|
||||||
pub fn libp2p_service(&self) -> Arc<Mutex<LibP2PService>> {
|
pub fn libp2p_service(&self) -> Arc<Mutex<LibP2PService>> {
|
||||||
self.libp2p_service.clone()
|
self.libp2p_service.clone()
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,9 @@ pub fn start_server<T: BeaconChainTypes + Clone + Send + Sync + 'static>(
|
|||||||
(&Method::GET, "/node/network/enr") => network::get_enr::<T>(req),
|
(&Method::GET, "/node/network/enr") => network::get_enr::<T>(req),
|
||||||
(&Method::GET, "/node/network/peer_count") => network::get_peer_count::<T>(req),
|
(&Method::GET, "/node/network/peer_count") => network::get_peer_count::<T>(req),
|
||||||
(&Method::GET, "/node/network/peers") => network::get_peer_list::<T>(req),
|
(&Method::GET, "/node/network/peers") => network::get_peer_list::<T>(req),
|
||||||
|
(&Method::GET, "/node/network/listen_addresses") => {
|
||||||
|
network::get_listen_addresses::<T>(req)
|
||||||
|
}
|
||||||
(&Method::GET, "/spec") => spec::get_spec::<T>(req),
|
(&Method::GET, "/spec") => spec::get_spec::<T>(req),
|
||||||
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
||||||
_ => Err(ApiError::MethodNotAllowed(path.clone())),
|
_ => Err(ApiError::MethodNotAllowed(path.clone())),
|
||||||
|
@ -1,9 +1,28 @@
|
|||||||
use crate::{success_response, ApiError, ApiResult, NetworkService};
|
use crate::{success_response, ApiError, ApiResult, NetworkService};
|
||||||
use beacon_chain::BeaconChainTypes;
|
use beacon_chain::BeaconChainTypes;
|
||||||
use eth2_libp2p::{Enr, PeerId};
|
use eth2_libp2p::{Enr, Multiaddr, PeerId};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// HTTP handle to return the list of libp2p multiaddr the client is listening on.
|
||||||
|
///
|
||||||
|
/// Returns a list of `Multiaddr`, serialized according to their `serde` impl.
|
||||||
|
pub fn get_listen_addresses<T: BeaconChainTypes + Send + Sync + 'static>(
|
||||||
|
req: Request<Body>,
|
||||||
|
) -> ApiResult {
|
||||||
|
let network = req
|
||||||
|
.extensions()
|
||||||
|
.get::<Arc<NetworkService<T>>>()
|
||||||
|
.ok_or_else(|| ApiError::ServerError("NetworkService extension missing".to_string()))?;
|
||||||
|
|
||||||
|
let multiaddresses: Vec<Multiaddr> = network.listen_multiaddrs();
|
||||||
|
|
||||||
|
Ok(success_response(Body::from(
|
||||||
|
serde_json::to_string(&multiaddresses)
|
||||||
|
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Enr: {:?}", e)))?,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
/// HTTP handle to return the Discv5 ENR from the client's libp2p service.
|
/// HTTP handle to return the Discv5 ENR from the client's libp2p service.
|
||||||
///
|
///
|
||||||
/// ENR is encoded as base64 string.
|
/// ENR is encoded as base64 string.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod run;
|
mod run;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use client::{Bootstrapper, ClientConfig, Eth2Config, GenesisState};
|
use client::{ClientConfig, Eth2Config};
|
||||||
use env_logger::{Builder, Env};
|
use env_logger::{Builder, Env};
|
||||||
use eth2_config::{read_from_file, write_to_file};
|
use eth2_config::{read_from_file, write_to_file};
|
||||||
use slog::{crit, o, warn, Drain, Level};
|
use slog::{crit, o, warn, Drain, Level};
|
||||||
@ -298,32 +298,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the `--bootstrap` flag is provided, overwrite the default configuration.
|
|
||||||
if let Some(server) = matches.value_of("bootstrap") {
|
|
||||||
// Set the genesis state source.
|
|
||||||
client_config.genesis_state = GenesisState::HttpBootstrap {
|
|
||||||
server: server.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let bootstrapper = match Bootstrapper::from_server_string(server.to_string()) {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => {
|
|
||||||
crit!(log, "Failed to load bootstrapper"; "error" => format!("{:?}", e));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let enr = match bootstrapper.enr() {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => {
|
|
||||||
crit!(log, "Failed to read ENR from bootstrap server"; "error" => format!("{:?}", e));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
client_config.network.boot_nodes.push(enr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let eth2_config_path = data_dir.join(ETH2_CONFIG_FILENAME);
|
let eth2_config_path = data_dir.join(ETH2_CONFIG_FILENAME);
|
||||||
|
|
||||||
// Initialise the `Eth2Config`.
|
// Initialise the `Eth2Config`.
|
||||||
|
Loading…
Reference in New Issue
Block a user