From 35374ac09c7d398f0517c32de93d3cfdb1c291e3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 16:45:54 +0100 Subject: [PATCH 1/7] 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/7] 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/7] 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/7] 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::*; From 25c3e49b4f76eaac2db3bb5bcc81cd25ca291ad1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 21:21:17 +0100 Subject: [PATCH 5/7] Fix deps script. --- install-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-deps.sh b/install-deps.sh index 409f10d21..2512057b0 100755 --- a/install-deps.sh +++ b/install-deps.sh @@ -669,7 +669,7 @@ function run_installer() function build_parity() { info "Downloading Parity..." - git clone git@github.com:ethcore/parity + git clone http://github.com/ethcore/parity cd parity git submodule init git submodule update From cb09768145405b8ee0c13881757e468c01119efe Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 21:22:24 +0100 Subject: [PATCH 6/7] Fix deps script again. --- install-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-deps.sh b/install-deps.sh index 2512057b0..6b39001b1 100755 --- a/install-deps.sh +++ b/install-deps.sh @@ -669,7 +669,7 @@ function run_installer() function build_parity() { info "Downloading Parity..." - git clone http://github.com/ethcore/parity + git clone https://github.com/ethcore/parity cd parity git submodule init git submodule update From 3e49c960a0a5446e633fd61960bb2b8b73874d25 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 10 Feb 2016 21:31:21 +0100 Subject: [PATCH 7/7] Install both rocksdb deps. --- install-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-deps.sh b/install-deps.sh index 6b39001b1..28a442040 100755 --- a/install-deps.sh +++ b/install-deps.sh @@ -570,7 +570,7 @@ function run_installer() sudo apt-add-repository -y ppa:ethcore/ethcore sudo apt-get -f -y install sudo apt-get update -qq - sudo apt-get install -qq -y librocksdb-dev + sudo apt-get install -qq -y librocksdb-dev librocksdb } function linux_rocksdb_installer()