diff --git a/util/network-devp2p/src/discovery.rs b/util/network-devp2p/src/discovery.rs index 6ce269f0b2c..22f24be5b86 100644 --- a/util/network-devp2p/src/discovery.rs +++ b/util/network-devp2p/src/discovery.rs @@ -941,7 +941,7 @@ mod tests { fn ping_queue() { let key = Random.generate(); let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40445").unwrap(), udp_port: 40445 }; - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); let mut discovery = Discovery::new(&key, ep.clone(), enr, IpFilter::default()); for i in 1..(MAX_NODES_PING+1) { @@ -966,7 +966,7 @@ mod tests { address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 41000 + i), udp_port: 41000 + i, }; - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); Discovery::new(&key, ep, enr, IpFilter::default()) }) .collect::>(); @@ -1014,7 +1014,7 @@ mod tests { fn removes_expired() { let key = Random.generate(); let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40447 }; - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); let discovery = Discovery::new(&key, ep.clone(), enr, IpFilter::default()); let mut discovery = Discovery { request_backoff: &[], ..discovery }; @@ -1107,7 +1107,7 @@ mod tests { let key = Random.generate(); let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40447").unwrap(), udp_port: 40447 }; - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); let mut discovery = Discovery::new(&key, ep.clone(), enr, IpFilter::default()); for _ in 0..(16 + 10) { @@ -1165,7 +1165,7 @@ mod tests { let key = Secret::from_str(secret_hex) .and_then(|secret| KeyPair::from_secret(secret)) .unwrap(); - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); let mut discovery = Discovery::new(&key, ep.clone(), enr, IpFilter::default()); discovery.init_node_list(node_entries.clone()); @@ -1211,7 +1211,7 @@ mod tests { fn packets() { let key = Random.generate(); let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40449").unwrap(), udp_port: 40449 }; - let enr = EnrManager::new(key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); + let enr = EnrManager::new(None, key.secret().clone(), 0).unwrap().with_node_endpoint(&ep).into_enr(); let mut discovery = Discovery::new(&key, ep.clone(), enr, IpFilter::default()); discovery.check_timestamps = false; let from = SocketAddr::from_str("99.99.99.99:40445").unwrap(); @@ -1281,8 +1281,8 @@ mod tests { let ep1 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40344").unwrap(), udp_port: 40344 }; let ep2 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40345").unwrap(), udp_port: 40345 }; let ep3 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40346").unwrap(), udp_port: 40345 }; - let enr1 = EnrManager::new(key1.secret().clone(), 0).unwrap().with_node_endpoint(&ep1).into_enr(); - let enr2 = EnrManager::new(key2.secret().clone(), 0).unwrap().with_node_endpoint(&ep2).into_enr(); + let enr1 = EnrManager::new(None, key1.secret().clone(), 0).unwrap().with_node_endpoint(&ep1).into_enr(); + let enr2 = EnrManager::new(None, key2.secret().clone(), 0).unwrap().with_node_endpoint(&ep2).into_enr(); let mut discovery1 = Discovery::new(&key1, ep1.clone(), enr1, IpFilter::default()); let mut discovery2 = Discovery::new(&key2, ep2.clone(), enr2, IpFilter::default()); diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 2db330827df..9571ddba1c1 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -305,12 +305,14 @@ impl Host { let mut enr = None; if !key_created { if let Some(path) = &config.config_path { - if let Some(data) = load(Path::new(&path)) { - enr = EnrManager::load(keys.secret().clone(), data); - } + enr = EnrManager::load(path.as_str(), keys.secret().clone()); } } - let enr = enr.unwrap_or_else(|| EnrManager::new(keys.secret().clone(), 0).expect("keys.secret() is a valid secp256k1 secret; Enr does not fail given valid secp256k1 secret; qed")); + let enr = enr.unwrap_or_else(|| EnrManager::new( + config.config_path.as_ref().map(|v| v.into()), + keys.secret().clone(), + 0) + .expect("keys.secret() is a valid secp256k1 secret; Enr does not fail given valid secp256k1 secret; qed")); let path = config.net_config_path.clone(); // Setup the server socket let tcp_listener = TcpListener::bind(&listen_address)?; diff --git a/util/network-devp2p/src/node_record.rs b/util/network-devp2p/src/node_record.rs index 64efa9df827..f505c789d37 100644 --- a/util/network-devp2p/src/node_record.rs +++ b/util/network-devp2p/src/node_record.rs @@ -1,6 +1,7 @@ use log::*; use parity_crypto::publickey::Secret; -use crate::{persistence::DiskEntity, node_table::NodeEndpoint}; +use std::path::PathBuf; +use crate::{persistence::{save, load, DiskEntity}, node_table::NodeEndpoint}; pub type Enr = enr::Enr; @@ -9,18 +10,32 @@ const ENR_VERSION: &str = "v4"; pub struct EnrManager { secret: secp256k1::SecretKey, inner: Enr, + path: Option, } impl EnrManager { - pub fn new(key: Secret, seq: u64) -> Option { + fn save(&mut self) { + if let Some(path) = &self.path { + save(path, &self.inner); + } + } + + pub fn new(path: Option, key: Secret, seq: u64) -> Option { let secret = key.to_secp256k1_secret().ok()?; let mut b = enr::EnrBuilder::new(ENR_VERSION); b.seq(seq); let inner = b.build(&secret).ok()?; - Some(Self { secret, inner }) + let mut this = Self { secret, inner, path }; + this.save(); + Some(this) } - pub fn load(key: Secret, inner: Enr) -> Option { + pub fn load

(path: P, key: Secret) -> Option + where + PathBuf: From

+ { + let path = PathBuf::from(path); + let inner = load::(&path)?; let secret = key.to_secp256k1_secret().ok()?; let public = secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &secret); @@ -28,7 +43,7 @@ impl EnrManager { warn!("ENR does not match the provided key"); return None; } - Some(Self { secret, inner }) + Some(Self { secret, inner, path: Some(path) }) } #[cfg(test)] @@ -45,6 +60,7 @@ impl EnrManager { self.inner.set_udp(endpoint.udp_port, &self.secret).expect(ENR_PROOF); // We just wrap here, unlikely to be a problem in our lifetimes unless the user sets seq high enough on purpose. self.inner.set_seq(seq.wrapping_add(1), &self.secret).expect(ENR_PROOF); + self.save(); } pub fn as_enr(&self) -> &Enr { @@ -69,3 +85,26 @@ impl DiskEntity for Enr { Ok(s.parse()?) } } + +#[cfg(test)] +mod tests { + #[test] + fn save_load() { + use super::*; + use ethereum_types::H256; + use std::net::SocketAddr; + use tempfile::TempDir; + + let tempdir = TempDir::new().unwrap(); + let key = Secret::from(H256::random()); + + let mut enr = EnrManager::new(Some(tempdir.path().into()), key.clone(), 0).unwrap(); + assert_eq!(*enr.as_enr(), EnrManager::load(tempdir.path(), key.clone()).unwrap().into_enr()); + let endpoint = NodeEndpoint { + address: SocketAddr::from((rand::random::<[u8; 4]>(), rand::random())), + udp_port: rand::random(), + }; + enr.set_node_endpoint(&endpoint); + assert_eq!(*enr.as_enr(), EnrManager::load(tempdir.path(), key).unwrap().into_enr()); + } +}