lighthouse/network-libp2p/src/state.rs

120 lines
3.9 KiB
Rust
Raw Normal View History

extern crate rand;
use std::io::{ Read, Write };
2018-07-29 05:06:42 +00:00
use std::error::Error;
use std::fs::File;
2018-08-07 00:08:39 +00:00
use std::path::{ Path, PathBuf };
2018-07-29 05:06:42 +00:00
use std::sync::Arc;
use std::time::Duration;
2018-07-29 05:06:42 +00:00
use super::libp2p_core::Multiaddr;
use super::libp2p_peerstore::{ Peerstore, PeerAccess, PeerId };
2018-07-29 05:06:42 +00:00
use super::libp2p_peerstore::json_peerstore::JsonPeerstore;
use super::pem;
use super::secp256k1::Secp256k1;
use super::secp256k1::key::{ SecretKey, PublicKey };
use super::slog::Logger;
2018-07-29 05:06:42 +00:00
2018-08-07 00:08:39 +00:00
/// Location of the libp2p peerstore inside the Network base dir.
2018-07-29 05:06:42 +00:00
const PEERS_FILE: &str = "peerstore.json";
2018-08-07 00:08:39 +00:00
/// Location of the libp2p local peer secret key inside the Network base dir.
const LOCAL_PEM_FILE: &str = "local_peer_id.pem";
2018-07-29 05:06:42 +00:00
2018-08-07 00:08:39 +00:00
/// Represents the present state of a libp2p network.
2018-07-29 05:06:42 +00:00
pub struct NetworkState {
2018-08-07 00:08:39 +00:00
pub base_dir: PathBuf,
2018-07-29 05:06:42 +00:00
pub pubkey: PublicKey,
pub seckey: SecretKey,
pub peer_id: PeerId,
pub listen_multiaddr: Multiaddr,
pub peer_store: Arc<JsonPeerstore>,
}
impl NetworkState {
2018-08-07 00:08:39 +00:00
/// Create a new libp2p network state. Used to initialize
/// network service.
pub fn new(
// config: LighthouseConfig,
base_dir: &Path,
listen_port: &u16,
log: &Logger)
-> Result <Self, Box<Error>>
{
2018-07-29 05:06:42 +00:00
let curve = Secp256k1::new();
let seckey = match
2018-08-07 00:08:39 +00:00
NetworkState::load_secret_key_from_pem_file(base_dir, &curve)
{
Ok(k) => k,
2018-08-07 00:08:39 +00:00
_ => NetworkState::generate_new_secret_key(base_dir, &curve)?
2018-07-29 05:06:42 +00:00
};
let pubkey = PublicKey::from_secret_key(&curve, &seckey)?;
let peer_id = PeerId::from_public_key(
&pubkey.serialize_vec(&curve, false));
info!(log, "Loaded keys"; "peer_id" => &peer_id.to_base58());
2018-07-29 05:06:42 +00:00
let peer_store = {
2018-08-07 00:08:39 +00:00
let path = base_dir.join(PEERS_FILE);
2018-07-29 05:06:42 +00:00
let base = JsonPeerstore::new(path)?;
Arc::new(base)
};
info!(log, "Loaded peerstore"; "peer_count" => &peer_store.peers().count());
2018-08-06 23:13:24 +00:00
let listen_multiaddr =
2018-08-07 00:08:39 +00:00
NetworkState::multiaddr_on_port(&listen_port.to_string());
2018-07-29 05:06:42 +00:00
Ok(Self {
2018-08-07 00:08:39 +00:00
base_dir: PathBuf::from(base_dir),
2018-07-29 05:06:42 +00:00
seckey,
pubkey,
peer_id,
listen_multiaddr,
peer_store,
})
}
2018-08-06 23:13:24 +00:00
/// Return a TCP multiaddress on 0.0.0.0 for a given port.
pub fn multiaddr_on_port(port: &str) -> Multiaddr {
return format!("/ip4/0.0.0.0/tcp/{}", port)
.parse::<Multiaddr>().unwrap()
}
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));
}
/// Instantiate a SecretKey from a .pem file on disk.
2018-08-07 00:08:39 +00:00
pub fn load_secret_key_from_pem_file(
base_dir: &Path,
curve: &Secp256k1)
-> Result<SecretKey, Box<Error>>
{
2018-08-07 00:08:39 +00:00
let path = base_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(
2018-08-07 00:08:39 +00:00
base_dir: &Path,
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);
2018-08-07 00:08:39 +00:00
let path = base_dir.join(LOCAL_PEM_FILE);
let mut s_file = File::create(path)?;
s_file.write(s_string.as_bytes())?;
Ok(sk)
}
2018-07-29 05:06:42 +00:00
}