From 35374ac09c7d398f0517c32de93d3cfdb1c291e3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 16:45:54 +0100 Subject: [PATCH 1/4] Start of UPnP. --- parity/main.rs | 7 ++++-- util/src/network/host.rs | 22 +++++++++++++++++++ util/src/trie/sectriedbmut.rs | 40 +++++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 43a249886..7fd8fb029 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -63,6 +63,7 @@ Options: --listen-address URL Specify the IP/port on which to listen for peers [default: 0.0.0.0:30304]. --public-address URL Specify the IP/port on which peers may connect [default: 0.0.0.0:30304]. --address URL Equivalent to --listen-address URL --public-address URL. + --upnp Use UPnP to try to figure out the correct network settings. --cache-pref-size BYTES Specify the prefered size of the blockchain cache in bytes [default: 16384]. --cache-max-size BYTES Specify the maximum size of the blockchain cache in bytes [default: 262144]. @@ -191,7 +192,7 @@ impl Informant { let sync_info = sync.status(); if let (_, &Some(ref last_cache_info), &Some(ref last_report)) = (self.chain_info.read().unwrap().deref(), self.cache_info.read().unwrap().deref(), self.report.read().unwrap().deref()) { - println!("[ {} {} ]---[ {} blk/s | {} tx/s | {} gas/s //··· {}/{} peers, {} downloaded, {}+{} queued ···// {} ({}) bl {} ({}) ex ]", + println!("[ {} {} ]---[ {} blk/s | {} tx/s | {} gas/s ··· {}/{} peers, {} downloaded, {}+{} queued ··· {} ({}) bl {} ({}) ex | {} i/c ]", chain_info.best_block_number, chain_info.best_block_hash, (report.blocks_imported - last_report.blocks_imported) / dur, @@ -207,7 +208,9 @@ impl Informant { cache_info.blocks, cache_info.blocks as isize - last_cache_info.blocks as isize, cache_info.block_details, - cache_info.block_details as isize - last_cache_info.block_details as isize + cache_info.block_details as isize - last_cache_info.block_details as isize, + + updates_per_commit() ); } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 50cf294bc..3888cdf60 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -86,6 +86,26 @@ impl NetworkConfiguration { config.public_address = SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap(); config } + + /// Conduct NAT if needed. + pub fn prepared(self) -> Self { + let listen = self.listen_address; + let public = self.public_address; + + if self.nat_enabled { + info!("Enabling NAT"); + } + + NetworkConfiguration { + listen_address: listen, + public_address: public, + nat_enabled: false, + discovery_enabled: self.discovery_enabled, + pin: self.pin, + boot_nodes: self.boot_nodes, + use_secret: self.use_secret, + } + } } // Tokens @@ -296,6 +316,8 @@ pub struct Host where Message: Send + Sync + Clone { impl Host where Message: Send + Sync + Clone { /// Create a new instance pub fn new(config: NetworkConfiguration) -> Host { + let config = config.prepared(); + let addr = config.listen_address; // Setup the server socket let tcp_listener = TcpListener::bind(&addr).unwrap(); diff --git a/util/src/trie/sectriedbmut.rs b/util/src/trie/sectriedbmut.rs index 662f6852a..5d0ef7ec3 100644 --- a/util/src/trie/sectriedbmut.rs +++ b/util/src/trie/sectriedbmut.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::sync::RwLock; +use std::cell::RefCell; use hash::*; use sha3::*; use hashdb::*; @@ -21,11 +23,26 @@ use rlp::*; use super::triedbmut::*; use super::trietraits::*; +lazy_static! { + static ref COMMIT_COUNT: RwLock = RwLock::new(0); + static ref UPDATE_COUNT: RwLock = RwLock::new(0); +} + +/// Get mean number of updates per commit so far. +pub fn updates_per_commit() -> f64 { + let cc = *COMMIT_COUNT.read().unwrap(); + if cc > 0 { + (*UPDATE_COUNT.read().unwrap() as f64) / (cc as f64) + } else { 0.0 } +} + /// A mutable `Trie` implementation which hashes keys and uses a generic `HashDB` backing database. /// /// Use it as a `Trie` or `TrieMut` trait object. You can use `raw()` to get the backing TrieDBMut object. pub struct SecTrieDBMut<'db> { - raw: TrieDBMut<'db> + raw: TrieDBMut<'db>, + /// Get number of updates done on this trie so far. + pub update_count: RefCell, } impl<'db> SecTrieDBMut<'db> { @@ -33,13 +50,13 @@ impl<'db> SecTrieDBMut<'db> { /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. pub fn new(db: &'db mut HashDB, root: &'db mut H256) -> Self { - SecTrieDBMut { raw: TrieDBMut::new(db, root) } + SecTrieDBMut { raw: TrieDBMut::new(db, root), update_count: RefCell::new(0) } } /// Create a new trie with the backing database `db` and `root` /// Panics, if `root` does not exist pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { - SecTrieDBMut { raw: TrieDBMut::from_existing(db, root) } + SecTrieDBMut { raw: TrieDBMut::from_existing(db, root), update_count: RefCell::new(0) } } /// Get the backing database. @@ -50,7 +67,9 @@ impl<'db> SecTrieDBMut<'db> { } impl<'db> Trie for SecTrieDBMut<'db> { - fn root(&self) -> &H256 { self.raw.root() } + fn root(&self) -> &H256 { + self.raw.root() + } fn contains(&self, key: &[u8]) -> bool { self.raw.contains(&key.sha3()) @@ -63,14 +82,27 @@ impl<'db> Trie for SecTrieDBMut<'db> { impl<'db> TrieMut for SecTrieDBMut<'db> { fn insert(&mut self, key: &[u8], value: &[u8]) { + *self.update_count.borrow_mut() += 1; self.raw.insert(&key.sha3(), value); } fn remove(&mut self, key: &[u8]) { + *self.update_count.borrow_mut() += 1; self.raw.remove(&key.sha3()); } } +impl<'db> Drop for SecTrieDBMut<'db> { + fn drop(&mut self) { + let uc = *self.update_count.borrow(); + if uc > 0 { + *COMMIT_COUNT.write().unwrap() += 1; + *UPDATE_COUNT.write().unwrap() += uc; + *self.update_count.borrow_mut() = 0; + } + } +} + #[test] fn sectrie_to_trie() { use memorydb::*; From 637ca97dc63ff5c62976de8b0470db13055ace7b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 18:11:10 +0100 Subject: [PATCH 2/4] Synchronous UPnP. --- parity/main.rs | 34 +++++++++++++++++----------------- util/Cargo.toml | 1 + util/src/lib.rs | 1 + util/src/network/host.rs | 25 +++++++++++++++++++++---- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index b28a3569e..385e10969 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -90,7 +90,6 @@ fn setup_log(init: &str) { builder.init().unwrap(); } - #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc, sync: Arc, url: &str) { use rpc::v1::*; @@ -107,18 +106,8 @@ fn setup_rpc_server(client: Arc, sync: Arc, url: &str) { fn setup_rpc_server(_client: Arc, _sync: Arc, _url: &str) { } -struct Configuration { - args: Args -} -impl Configuration { - fn parse() -> Self { - Configuration { - args: Args::docopt().decode().unwrap_or_else(|e| e.exit()) - } - } - - fn print_version(&self) { - println!("\ +fn print_version() { + println!("\ Parity version {} ({}-{}-{}) Copyright 2015, 2016 Ethcore (UK) Limited License GPLv3+: GNU GPL version 3 or later . @@ -127,6 +116,17 @@ There is NO WARRANTY, to the extent permitted by law. By Wood/Paronyan/Kotewicz/Drwięga/Volf.\ ", env!("CARGO_PKG_VERSION"), Target::arch(), Target::env(), Target::os()); +} + +struct Configuration { + args: Args +} + +impl Configuration { + fn parse() -> Self { + Configuration { + args: Args::docopt().decode().unwrap_or_else(|e| e.exit()) + } } fn get_spec(&self) -> Spec { @@ -179,7 +179,7 @@ fn wait_for_exit(client_service: &ClientService) { fn main() { let conf = Configuration::parse(); if conf.args.flag_version { - conf.print_version(); + print_version(); return; } @@ -191,10 +191,10 @@ fn main() { unsafe { ::fdlimit::raise_fd_limit(); } // Configure network - let init_nodes = conf.get_init_nodes(&spec); - let (listen, public) = conf.get_net_addresses(); let mut net_settings = NetworkConfiguration::new(); - net_settings.boot_nodes = init_nodes; + net_settings.nat_enabled = conf.args.flag_upnp; + net_settings.boot_nodes = conf.get_init_nodes(&spec); + let (listen, public) = conf.get_net_addresses(); net_settings.listen_address = listen; net_settings.public_address = public; diff --git a/util/Cargo.toml b/util/Cargo.toml index a123aecca..733b08701 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -29,3 +29,4 @@ serde = "0.6.7" clippy = "0.0.37" json-tests = { path = "json-tests" } target_info = "0.1.0" +igd = "0.4.2" diff --git a/util/src/lib.rs b/util/src/lib.rs index 260ef4301..bdd595014 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -100,6 +100,7 @@ extern crate crossbeam; extern crate serde; #[macro_use] extern crate log as rlog; +extern crate igd; pub mod standard; #[macro_use] diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 3888cdf60..fb1e8e1df 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::net::{SocketAddr}; +use std::net::{SocketAddr, SocketAddrV4}; use std::collections::{HashMap}; use std::hash::{Hasher}; use std::str::{FromStr}; @@ -36,6 +36,7 @@ use network::NetworkProtocolHandler; use network::node::*; use network::stats::NetworkStats; use network::error::DisconnectReason; +use igd::{PortMappingProtocol,search_gateway}; type Slab = ::slab::Slab; @@ -89,11 +90,27 @@ impl NetworkConfiguration { /// Conduct NAT if needed. pub fn prepared(self) -> Self { - let listen = self.listen_address; - let public = self.public_address; + let mut listen = self.listen_address; + let mut public = self.public_address; if self.nat_enabled { - info!("Enabling NAT"); + info!("Enabling NAT..."); + match search_gateway() { + Err(ref err) => info!("Error: {}", err), + Ok(gateway) => { + let int_addr = SocketAddrV4::from_str("127.0.0.1:30304").unwrap(); + match gateway.get_any_address(PortMappingProtocol::TCP, int_addr, 0, "Parity Node/TCP") { + Err(ref err) => { + info!("There was an error! {}", err); + }, + Ok(ext_addr) => { + info!("Local gateway: {}, External ip address: {}", gateway, ext_addr); + public = SocketAddr::V4(ext_addr); + listen = SocketAddr::V4(int_addr); + }, + } + }, + } } NetworkConfiguration { From e8aaf26ab4001bac006e99e1b1822f4b7b854cb0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 18:26:03 +0100 Subject: [PATCH 3/4] Revert printing trie insertion stats. --- parity/main.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 385e10969..7647a4bb8 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -251,7 +251,7 @@ impl Informant { let sync_info = sync.status(); if let (_, &Some(ref last_cache_info), &Some(ref last_report)) = (self.chain_info.read().unwrap().deref(), self.cache_info.read().unwrap().deref(), self.report.read().unwrap().deref()) { - println!("[ {} {} ]---[ {} blk/s | {} tx/s | {} gas/s ··· {}/{} peers, {} downloaded, {}+{} queued ··· {} ({}) bl {} ({}) ex | {} i/c ]", + println!("[ {} {} ]---[ {} blk/s | {} tx/s | {} gas/s //··· {}/{} peers, {} downloaded, {}+{} queued ···// {} ({}) bl {} ({}) ex ]", chain_info.best_block_number, chain_info.best_block_hash, (report.blocks_imported - last_report.blocks_imported) / dur, @@ -267,9 +267,7 @@ impl Informant { cache_info.blocks, cache_info.blocks as isize - last_cache_info.blocks as isize, cache_info.block_details, - cache_info.block_details as isize - last_cache_info.block_details as isize, - - updates_per_commit() + cache_info.block_details as isize - last_cache_info.block_details as isize ); } From 0e679fbee55ebafa4cc963f9033b892afcedcfb8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 18:26:39 +0100 Subject: [PATCH 4/4] Revert collecting trie stats. --- util/src/trie/sectriedbmut.rs | 40 ++++------------------------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/util/src/trie/sectriedbmut.rs b/util/src/trie/sectriedbmut.rs index 5d0ef7ec3..662f6852a 100644 --- a/util/src/trie/sectriedbmut.rs +++ b/util/src/trie/sectriedbmut.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::RwLock; -use std::cell::RefCell; use hash::*; use sha3::*; use hashdb::*; @@ -23,26 +21,11 @@ use rlp::*; use super::triedbmut::*; use super::trietraits::*; -lazy_static! { - static ref COMMIT_COUNT: RwLock = RwLock::new(0); - static ref UPDATE_COUNT: RwLock = RwLock::new(0); -} - -/// Get mean number of updates per commit so far. -pub fn updates_per_commit() -> f64 { - let cc = *COMMIT_COUNT.read().unwrap(); - if cc > 0 { - (*UPDATE_COUNT.read().unwrap() as f64) / (cc as f64) - } else { 0.0 } -} - /// A mutable `Trie` implementation which hashes keys and uses a generic `HashDB` backing database. /// /// Use it as a `Trie` or `TrieMut` trait object. You can use `raw()` to get the backing TrieDBMut object. pub struct SecTrieDBMut<'db> { - raw: TrieDBMut<'db>, - /// Get number of updates done on this trie so far. - pub update_count: RefCell, + raw: TrieDBMut<'db> } impl<'db> SecTrieDBMut<'db> { @@ -50,13 +33,13 @@ impl<'db> SecTrieDBMut<'db> { /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. pub fn new(db: &'db mut HashDB, root: &'db mut H256) -> Self { - SecTrieDBMut { raw: TrieDBMut::new(db, root), update_count: RefCell::new(0) } + SecTrieDBMut { raw: TrieDBMut::new(db, root) } } /// Create a new trie with the backing database `db` and `root` /// Panics, if `root` does not exist pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { - SecTrieDBMut { raw: TrieDBMut::from_existing(db, root), update_count: RefCell::new(0) } + SecTrieDBMut { raw: TrieDBMut::from_existing(db, root) } } /// Get the backing database. @@ -67,9 +50,7 @@ impl<'db> SecTrieDBMut<'db> { } impl<'db> Trie for SecTrieDBMut<'db> { - fn root(&self) -> &H256 { - self.raw.root() - } + fn root(&self) -> &H256 { self.raw.root() } fn contains(&self, key: &[u8]) -> bool { self.raw.contains(&key.sha3()) @@ -82,27 +63,14 @@ impl<'db> Trie for SecTrieDBMut<'db> { impl<'db> TrieMut for SecTrieDBMut<'db> { fn insert(&mut self, key: &[u8], value: &[u8]) { - *self.update_count.borrow_mut() += 1; self.raw.insert(&key.sha3(), value); } fn remove(&mut self, key: &[u8]) { - *self.update_count.borrow_mut() += 1; self.raw.remove(&key.sha3()); } } -impl<'db> Drop for SecTrieDBMut<'db> { - fn drop(&mut self) { - let uc = *self.update_count.borrow(); - if uc > 0 { - *COMMIT_COUNT.write().unwrap() += 1; - *UPDATE_COUNT.write().unwrap() += uc; - *self.update_count.borrow_mut() = 0; - } - } -} - #[test] fn sectrie_to_trie() { use memorydb::*;