Introduce NetworkConfig and NetworkState

This commit is contained in:
Paul Hauner 2018-08-01 10:27:05 +10:00
parent c1d93d073d
commit ba38cef25e
7 changed files with 109 additions and 35 deletions

View File

@ -13,7 +13,6 @@ clap = "2.32.0"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "" ethereum-types = ""
futures = "0.1.23" futures = "0.1.23"
hex = "0.3.2"
libp2p-peerstore = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-peerstore = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
libp2p-core = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-core = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
libp2p-mplex = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-mplex = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
@ -21,6 +20,8 @@ libp2p-tcp-transport = { git = "https://github.com/tomaka/libp2p-rs", branch ="z
libp2p-floodsub = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-floodsub = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
libp2p-identify = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-identify = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
libp2p-kad = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" } libp2p-kad = { git = "https://github.com/tomaka/libp2p-rs", branch ="zksummit" }
# TODO: Bring pem module internal; too risky to have as external dep.
pem = "0.5.0"
rand = "0.3" rand = "0.3"
rlp = { git = "https://github.com/paritytech/parity-common" } rlp = { git = "https://github.com/paritytech/parity-common" }
slog = "^2.2.3" slog = "^2.2.3"

View File

@ -10,8 +10,10 @@ pub mod pubkeystore;
pub mod state; pub mod state;
pub mod utils; pub mod utils;
use std::path::PathBuf;
use slog::Drain; use slog::Drain;
use clap::{ App, SubCommand}; use clap::{ Arg, App, SubCommand};
use p2p::config::NetworkConfig; use p2p::config::NetworkConfig;
use p2p::floodsub; use p2p::floodsub;
use p2p::state::NetworkState; use p2p::state::NetworkState;
@ -24,17 +26,24 @@ fn main() {
let matches = App::new("Lighthouse") let matches = App::new("Lighthouse")
.version("0.0.1") .version("0.0.1")
.author("Paul H. <paul@sigmaprime.io>") .author("Sigma Prime <paul@sigmaprime.io>")
.about("Eth 2.0 Client") .about("Eth 2.0 Client")
.arg(Arg::with_name("datadir")
.value_name("DIR")
.help("Data directory for keys and databases."))
.subcommand(SubCommand::with_name("generate-keys")) .subcommand(SubCommand::with_name("generate-keys"))
.about("Generates a new set of random keys for p2p dev.") .about("Generates a new set of random keys for p2p dev.")
.get_matches(); .get_matches();
let config = NetworkConfig::default(); let mut config = NetworkConfig::default();
if let Some(dir) = matches.value_of("datadir") {
config.data_dir = PathBuf::from(dir.to_string());
}
info!(log, ""; "data_dir" => &config.data_dir.to_str());
if let Some(_) = matches.subcommand_matches("generate-keys") { if let Some(_) = matches.subcommand_matches("generate-keys") {
// keys::generate_keys(&log).expect("Failed to generate keys"); // keys::generate_keys(&log).expect("Failed to generate keys");
} else { } else {
let state = NetworkState::new(&config).expect("setup failed"); let state = NetworkState::new(config, &log).expect("setup failed");
floodsub::listen(state, &log); floodsub::listen(state, &log);
} }
info!(log, "Exiting."); info!(log, "Exiting.");

View File

@ -1,14 +1,25 @@
use std::env;
use std::path::PathBuf;
use super::libp2p_core::Multiaddr; use super::libp2p_core::Multiaddr;
#[derive(Clone)]
pub struct NetworkConfig { pub struct NetworkConfig {
pub config_dir: String, pub data_dir: PathBuf,
pub listen_multiaddr: Multiaddr, pub listen_multiaddr: Multiaddr,
} }
const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse";
impl NetworkConfig { impl NetworkConfig {
pub fn default() -> Self{ pub fn default() -> Self{
let data_dir = {
let home = env::home_dir()
.expect("Unable to determine home dir.");
home.join(DEFAULT_LIGHTHOUSE_DIR)
};
Self { Self {
config_dir: ".lighthouse".to_string(), data_dir,
listen_multiaddr: "/ip4/0.0.0.0/tcp/0" listen_multiaddr: "/ip4/0.0.0.0/tcp/0"
.parse::<Multiaddr>().unwrap() .parse::<Multiaddr>().unwrap()

View File

@ -1,7 +1,6 @@
extern crate bigint; extern crate bigint;
extern crate bytes; extern crate bytes;
extern crate futures; extern crate futures;
extern crate hex;
extern crate libp2p_peerstore; extern crate libp2p_peerstore;
extern crate libp2p_identify; extern crate libp2p_identify;
extern crate libp2p_core; extern crate libp2p_core;

View File

@ -18,26 +18,22 @@ const LOCAL_PK_FILE: &str = "local.pk";
const LOCAL_SK_FILE: &str = "local.sk"; const LOCAL_SK_FILE: &str = "local.sk";
const BOOTSTRAP_PK_FILE: &str = "bootstrap.pk"; const BOOTSTRAP_PK_FILE: &str = "bootstrap.pk";
fn get_curve() -> secp256k1::Secp256k1 { secp256k1::Secp256k1::new() }
/// Generates a new public and secret key pair and writes them to /// Generates a new public and secret key pair and writes them to
/// individual files. /// individual files.
///
/// This function should only be present during
/// early development states and should be removed.
pub fn generate_keys(config: NetworkConfig, log: &Logger) pub fn generate_keys(config: NetworkConfig, log: &Logger)
-> Result<(), IoError> -> Result<(), IoError>
{ {
// TODO: remove this method and import pem files instead
info!(log, "Generating keys..."); info!(log, "Generating keys...");
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let curve = get_curve(); let curve = secp256k1::Secp256k1::new();
let s = SecretKey::new(&curve, &mut rng); let s = SecretKey::new(&curve, &mut rng);
let p = PublicKey::from_secret_key(&curve, &s).unwrap();
let p_vec = p.serialize_vec(&curve, false);
let s_vec = &s[..]; let s_vec = &s[..];
let p_string = hex::encode(p_vec);
let s_string = hex::encode(s_vec); let s_string = hex::encode(s_vec);
let mut p_file = File::create(LOCAL_PK_FILE)?;
let mut s_file = File::create(LOCAL_SK_FILE)?; let mut s_file = File::create(LOCAL_SK_FILE)?;
info!(log, "Writing public key...");
p_file.write(p_string.as_bytes())?;
info!(log, "Writing secret key..."); info!(log, "Writing secret key...");
s_file.write(s_string.as_bytes())?; s_file.write(s_string.as_bytes())?;
Ok(()) Ok(())

View File

@ -1,7 +1,8 @@
extern crate hex;
extern crate libp2p_core; extern crate libp2p_core;
extern crate libp2p_peerstore; extern crate libp2p_peerstore;
extern crate pem;
extern crate secp256k1; extern crate secp256k1;
extern crate slog;
pub mod floodsub; pub mod floodsub;
pub mod state; pub mod state;

View File

@ -1,22 +1,26 @@
use std::io::Read; extern crate rand;
use std::io::{ Read, Write };
use std::error::Error; use std::error::Error;
use std::path::Path;
use std::fs::File; use std::fs::File;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use super::hex; use super::config::NetworkConfig;
use super::libp2p_core::Multiaddr;
use super::libp2p_peerstore::{ Peerstore, PeerAccess, PeerId };
use super::libp2p_peerstore::json_peerstore::JsonPeerstore;
use super::pem;
use super::secp256k1::Secp256k1; use super::secp256k1::Secp256k1;
use super::secp256k1::key::{ SecretKey, PublicKey }; use super::secp256k1::key::{ SecretKey, PublicKey };
use super::libp2p_core::Multiaddr; use super::slog::Logger;
use super::libp2p_peerstore::PeerId;
use super::libp2p_peerstore::json_peerstore::JsonPeerstore;
use super::config::NetworkConfig;
const PEERS_FILE: &str = "peerstore.json"; const PEERS_FILE: &str = "peerstore.json";
const LOCAL_SK_FILE: &str = "local.sk"; const LOCAL_PEM_FILE: &str = "local_peer_id.pem";
pub struct NetworkState { pub struct NetworkState {
pub config: NetworkConfig,
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub seckey: SecretKey, pub seckey: SecretKey,
pub peer_id: PeerId, pub peer_id: PeerId,
@ -25,26 +29,26 @@ pub struct NetworkState {
} }
impl NetworkState { impl NetworkState {
pub fn new(config: &NetworkConfig) -> Result <Self, Box<Error>> { pub fn new(config: NetworkConfig, log: &Logger) -> Result <Self, Box<Error>> {
let curve = Secp256k1::new(); let curve = Secp256k1::new();
let seckey = { let seckey = match
let path = Path::new(&config.config_dir).join(LOCAL_SK_FILE); NetworkState::load_secret_key_from_pem_file(&config, &curve)
let mut contents = String::new(); {
let mut file = File::open(path)?; Ok(k) => k,
file.read_to_string(&mut contents)?; _ => NetworkState::generate_new_secret_key(&config, &curve)?
let vec = hex::decode(contents)?;
SecretKey::from_slice(&curve, &vec)?
}; };
let pubkey = PublicKey::from_secret_key(&curve, &seckey)?; let pubkey = PublicKey::from_secret_key(&curve, &seckey)?;
let peer_id = PeerId::from_public_key( let peer_id = PeerId::from_public_key(
&pubkey.serialize_vec(&curve, false)); &pubkey.serialize_vec(&curve, false));
info!(log, "Loaded keys"; "peer_id" => &peer_id.to_base58());
let peer_store = { let peer_store = {
let path = Path::new(&config.config_dir).join(PEERS_FILE); let path = config.data_dir.join(PEERS_FILE);
let base = JsonPeerstore::new(path)?; let base = JsonPeerstore::new(path)?;
Arc::new(base) Arc::new(base)
}; };
let listen_multiaddr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>()?; let listen_multiaddr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>()?;
Ok(Self { Ok(Self {
config: config,
seckey, seckey,
pubkey, pubkey,
peer_id, peer_id,
@ -52,4 +56,57 @@ impl NetworkState {
peer_store, peer_store,
}) })
} }
pub fn add_peer(&mut self,
peer_id: PeerId,
multiaddr: Multiaddr,
duration_secs: u64) {
self.peer_store.peer_or_create(&peer_id)
.add_addr(multiaddr, Duration::from_secs(duration_secs));
}
// TODO: this shouldn't be hard-coded; distribute with peers json.
pub fn add_sigp_peer(&mut self) {
let peer_id = {
let b58 = "Qmajfeei87f8V5N7SQwPw3wr57M1dNcGNwhTqf72v73E7U";
b58.parse::<PeerId>().unwrap()
};
let multiaddr = {
let string = "/dns/lh.sigp.io/tcp/10101";
string.parse::<Multiaddr>().unwrap()
};
self.add_peer(peer_id, multiaddr, 3600 * 24 * 356);
}
/// Instantiate a SecretKey from a .pem file on disk.
pub fn load_secret_key_from_pem_file(config: &NetworkConfig, curve: &Secp256k1)
-> Result<SecretKey, Box<Error>>
{
let path = config.data_dir.join(LOCAL_PEM_FILE);
let mut contents = String::new();
let mut file = File::open(path)?;
file.read_to_string(&mut contents)?;
let pem_key = pem::parse(contents)?;
let key = SecretKey::from_slice(curve, &pem_key.contents)?;
Ok(key)
}
/// Generate a new SecretKey and store it on disk as a .pem file.
pub fn generate_new_secret_key(
config: &NetworkConfig,
curve: &Secp256k1)
-> Result<SecretKey, Box<Error>>
{
let mut rng = rand::thread_rng();
let sk = SecretKey::new(&curve, &mut rng);
let pem_key = pem::Pem {
tag: String::from("EC PRIVATE KEY"),
contents: sk[..].to_vec()
};
let s_string = pem::encode(&pem_key);
let path = config.data_dir.join(LOCAL_PEM_FILE);
let mut s_file = File::create(path)?;
s_file.write(s_string.as_bytes())?;
Ok(sk)
}
} }