From b00a21f39a5211531f0cf27ee51d264122097735 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Tue, 15 Jan 2019 22:25:31 +0100 Subject: [PATCH] backports for stable 2.2.7 (#10163) * version: bump stable to 2.2.7 * version: mark 2.2 track stable * version: mark update critical on all networks * version: commit cargo lock * Ping nodes from discovery (#10167) * snap: fix path in script (#10157) * snap: fix path in script * debug, revert me * fix * necromancer awk magic * awk necromancy and path fixing * working track selection * Fix _cannot recursively call into `Core`_ issue (#10144) * Change igd to github:maufl/rust-igd * Run `igd::search_gateway_from_timeout` from own thread * Handle the case for contract creation on an empty but exist account with storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas * version: bump fork blocks for kovan and foundation (#10186) * pull constantinople on ethereum network (#10189) * ethcore: pull constantinople on ethereum network * version: mark update as critical * ethcore: remove constantinople alltogether from chain spec * version: revert fork block for ethereum --- Cargo.lock | 12 +-- Cargo.toml | 2 +- ethcore/res/ethereum/foundation.json | 12 +-- ethcore/res/ethereum/tests | 2 +- .../res/ethereum/tests-issues/currents.json | 44 +-------- ethcore/src/externalities.rs | 7 +- ethcore/src/state/account.rs | 5 + ethcore/src/state/mod.rs | 7 ++ scripts/gitlab/publish-snap.sh | 8 +- util/network-devp2p/src/discovery.rs | 93 +++++++++++++++---- util/network-devp2p/src/ip_utils.rs | 66 +++++++------ util/version/Cargo.toml | 8 +- 12 files changed, 152 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78cacab58..1a75dd40f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2210,7 +2210,7 @@ version = "1.12.0" dependencies = [ "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-ethereum 2.2.6", + "parity-ethereum 2.2.7", ] [[package]] @@ -2226,7 +2226,7 @@ dependencies = [ [[package]] name = "parity-ethereum" -version = "2.2.6" +version = "2.2.7" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2275,7 +2275,7 @@ dependencies = [ "parity-rpc-client 1.4.0", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.2.6", + "parity-version 2.2.7", "parity-whisper 0.1.0", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2430,7 +2430,7 @@ dependencies = [ "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.2.6", + "parity-version 2.2.7", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2527,7 +2527,7 @@ dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.12.0", "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-version 2.2.6", + "parity-version 2.2.7", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2537,7 +2537,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "2.2.6" +version = "2.2.7" dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 630f947a0..891eeba63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "Parity Ethereum client" name = "parity-ethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "2.2.6" +version = "2.2.7" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 82edec89c..0408e9772 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -9,8 +9,7 @@ "durationLimit": "0xd", "blockReward": { "0x0": "0x4563918244f40000", - "0x42ae50": "0x29a2241af62c0000", - "0x6c0840": "0x1bc16d674ec80000" + "0x42ae50": "0x29a2241af62c0000" }, "homesteadTransition": "0x118c30", "daoHardforkTransition": "0x1d4c00", @@ -135,8 +134,7 @@ ], "eip100bTransition": "0x42ae50", "difficultyBombDelays": { - "0x42ae50": "0x2dc6c0", - "0x6c0840": "0x1e8480" + "0x42ae50": "0x2dc6c0" } } } @@ -161,11 +159,7 @@ "eip140Transition": "0x42ae50", "eip211Transition": "0x42ae50", "eip214Transition": "0x42ae50", - "eip658Transition": "0x42ae50", - "eip145Transition": "0x6c0840", - "eip1014Transition": "0x6c0840", - "eip1052Transition": "0x6c0840", - "eip1283Transition": "0x6c0840" + "eip658Transition": "0x42ae50" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index 2cd62aeec..420f44347 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit 2cd62aeec11da29766b30d500f2b9a96f1f28cf0 +Subproject commit 420f443477caa8516f1f9ee8122fafc3415c0f34 diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json index 2ece034d0..d4d3f5e3a 100644 --- a/ethcore/res/ethereum/tests-issues/currents.json +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -1,42 +1,4 @@ -{ "block": - [ - { - "reference": "None", - "comment": "This failing test is deemed skippable. Could not happen on a mainnet.", - "failing": "GeneralStateTest_stCreate2", - "subtests": ["RevertInCreateInInitCreate2_d0g0v0_Constantinople"] - }, - { - "reference": "None", - "comment": "This failing test is deemed skippable. Could not happen on a mainnet.", - "failing": "GeneralStateTest_stRevertTest", - "subtests": ["RevertInCreateInInit_d0g0v0_Constantinople"] - } - ], - "state": - [ - { - "reference": "None", - "comment": "This failing test is deemed skippable. Could not happen on a mainnet.", - "failing": "stCreate2Test", - "subtests": { - "RevertInCreateInInitCreate2": { - "subnumbers": ["1"], - "chain": "Constantinople (test)" - } - } - }, - { - "reference": "None", - "comment": "This failing test is deemed skippable. Could not happen on a mainnet.", - "failing": "stRevertTest", - "subtests": { - "RevertInCreateInInit": { - "subnumbers": ["1"], - "chain": "Constantinople (test)" - } - } - } - - ] +{ + "block": [], + "state": [] } diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 778ef5cc7..e447ee9d9 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -116,7 +116,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> where T: Tracer, V: VMTracer, B: StateBackend { fn initial_storage_at(&self, key: &H256) -> vm::Result { - self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) + if self.state.is_base_storage_root_unchanged(&self.origin_info.address)? { + self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) + } else { + warn!(target: "externalities", "Detected existing account {:#x} where a forced contract creation happened.", self.origin_info.address); + Ok(H256::zero()) + } } fn storage_at(&self, key: &H256) -> vm::Result { diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index 160152fc7..1d61bb31b 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -447,6 +447,11 @@ impl Account { } } + /// Whether the base storage root of this account is unchanged. + pub fn is_base_storage_root_unchanged(&self) -> bool { + self.original_storage_cache.is_none() + } + /// Storage root where the account changes are based upon. pub fn base_storage_root(&self) -> H256 { self.storage_root diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index e9ef64af8..f6d681abe 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -539,6 +539,13 @@ impl State { |a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce())) } + /// Whether the base storage root of an account remains unchanged. + pub fn is_base_storage_root_unchanged(&self, a: &Address) -> TrieResult { + Ok(self.ensure_cached(a, RequireCache::None, true, + |a| a.as_ref().map(|account| account.is_base_storage_root_unchanged()))? + .unwrap_or(true)) + } + /// Get the storage root of account `a`. pub fn storage_root(&self, a: &Address) -> TrieResult> { self.ensure_cached(a, RequireCache::None, true, diff --git a/scripts/gitlab/publish-snap.sh b/scripts/gitlab/publish-snap.sh index a664341e8..f001bbff0 100755 --- a/scripts/gitlab/publish-snap.sh +++ b/scripts/gitlab/publish-snap.sh @@ -3,13 +3,17 @@ set -e # fail on any error set -u # treat unset variables as error -TRACK=`awk -F '=' '/^track/ {print $2}' ./util/version/Cargo.toml` +# some necromancy: +# gsub(/"/, "", $2) deletes "qoutes" +# gsub(/ /, "", $2) deletes whitespaces +TRACK=`awk -F '=' '/^track/ {gsub(/"/, "", $2); gsub(/ /, "", $2); print $2}' ./util/version/Cargo.toml` +echo Track is: $TRACK case ${TRACK} in nightly) export GRADE="devel" CHANNEL="edge";; beta) export GRADE="stable" CHANNEL="beta";; stable) export GRADE="stable" CHANNEL="stable";; - *) echo "No release" exit 0;; + *) echo "No release" && exit 0;; esac SNAP_PACKAGE="parity_"$VERSION"_"$BUILD_ARCH".snap" diff --git a/util/network-devp2p/src/discovery.rs b/util/network-devp2p/src/discovery.rs index abf6cf4d0..fd5af2764 100644 --- a/util/network-devp2p/src/discovery.rs +++ b/util/network-devp2p/src/discovery.rs @@ -53,12 +53,15 @@ const REQUEST_BACKOFF: [Duration; 4] = [ Duration::from_secs(64) ]; +const NODE_LAST_SEEN_TIMEOUT: Duration = Duration::from_secs(24*60*60); + #[derive(Clone, Debug)] pub struct NodeEntry { pub id: NodeId, pub endpoint: NodeEndpoint, } +#[derive(Debug)] pub struct BucketEntry { pub address: NodeEntry, pub id_hash: H256, @@ -89,6 +92,12 @@ struct FindNodeRequest { answered: bool, } +#[derive(Clone, Copy)] +enum PingReason { + Default, + FromDiscoveryRequest(NodeId) +} + struct PingRequest { // Time when the request was sent sent_at: Instant, @@ -99,8 +108,10 @@ struct PingRequest { // The hash Parity used to respond with (until rev 01f825b0e1f1c4c420197b51fc801cbe89284b29) #[deprecated()] deprecated_echo_hash: H256, + reason: PingReason } +#[derive(Debug)] pub struct NodeBucket { nodes: VecDeque, //sorted by last active } @@ -178,7 +189,7 @@ impl<'a> Discovery<'a> { if self.node_buckets[dist].nodes.iter().any(|n| n.id_hash == id_hash) { return; } - self.try_ping(e); + self.try_ping(e, PingReason::Default); } } @@ -221,7 +232,7 @@ impl<'a> Discovery<'a> { } else { None } }; if let Some(node) = ping { - self.try_ping(node); + self.try_ping(node, PingReason::Default); } Some(TableUpdates { added: added_map, removed: HashSet::new() }) } @@ -244,7 +255,7 @@ impl<'a> Discovery<'a> { fn update_new_nodes(&mut self) { while self.in_flight_pings.len() < MAX_NODES_PING { match self.adding_nodes.pop() { - Some(next) => self.try_ping(next), + Some(next) => self.try_ping(next, PingReason::Default), None => break, } } @@ -298,7 +309,7 @@ impl<'a> Discovery<'a> { None // a and b are equal, so log distance is -inf } - fn try_ping(&mut self, node: NodeEntry) { + fn try_ping(&mut self, node: NodeEntry, reason: PingReason) { if !self.is_allowed(&node) { trace!(target: "discovery", "Node {:?} not allowed", node); return; @@ -313,7 +324,7 @@ impl<'a> Discovery<'a> { } if self.in_flight_pings.len() < MAX_NODES_PING { - self.ping(&node) + self.ping(&node, reason) .unwrap_or_else(|e| { warn!(target: "discovery", "Error sending Ping packet: {:?}", e); }); @@ -322,7 +333,7 @@ impl<'a> Discovery<'a> { } } - fn ping(&mut self, node: &NodeEntry) -> Result<(), Error> { + fn ping(&mut self, node: &NodeEntry, reason: PingReason) -> Result<(), Error> { let mut rlp = RlpStream::new_list(4); rlp.append(&PROTOCOL_VERSION); self.public_endpoint.to_rlp_list(&mut rlp); @@ -336,6 +347,7 @@ impl<'a> Discovery<'a> { node: node.clone(), echo_hash: hash, deprecated_echo_hash: old_parity_hash, + reason: reason }); trace!(target: "discovery", "Sent Ping to {:?} ; node_id={:#x}", &node.endpoint, node.id); @@ -515,7 +527,7 @@ impl<'a> Discovery<'a> { if request.deprecated_echo_hash == echo_hash { trace!(target: "discovery", "Got Pong from an old parity-ethereum version."); } - Some(request.node.clone()) + Some((request.node.clone(), request.reason.clone())) } }; @@ -529,7 +541,10 @@ impl<'a> Discovery<'a> { }, }; - if let Some(node) = expected_node { + if let Some((node, ping_reason)) = expected_node { + if let PingReason::FromDiscoveryRequest(target) = ping_reason { + self.respond_with_discovery(target, &node)?; + } Ok(self.update_node(node)) } else { debug!(target: "discovery", "Got unexpected Pong from {:?} ; request not found", &from); @@ -537,21 +552,59 @@ impl<'a> Discovery<'a> { } } - fn on_find_node(&mut self, rlp: &Rlp, _node: &NodeId, from: &SocketAddr) -> Result, Error> { + fn on_find_node(&mut self, rlp: &Rlp, node_id: &NodeId, from: &SocketAddr) -> Result, Error> { trace!(target: "discovery", "Got FindNode from {:?}", &from); let target: NodeId = rlp.val_at(0)?; let timestamp: u64 = rlp.val_at(1)?; self.check_timestamp(timestamp)?; + + let node = NodeEntry { + id: node_id.clone(), + endpoint: NodeEndpoint { + address: *from, + udp_port: from.port() + } + }; + + if self.is_a_valid_known_node(&node) { + self.respond_with_discovery(target, &node)?; + } else { + // Make sure the request source is actually there and responds to pings before actually responding + self.try_ping(node, PingReason::FromDiscoveryRequest(target)); + } + Ok(None) + } + + fn is_a_valid_known_node(&self, node: &NodeEntry) -> bool { + let id_hash = keccak(node.id); + let dist = match Discovery::distance(&self.id_hash, &id_hash) { + Some(dist) => dist, + None => { + debug!(target: "discovery", "Got an incoming discovery request from self: {:?}", node); + return false; + } + }; + + let bucket = &self.node_buckets[dist]; + if let Some(known_node) = bucket.nodes.iter().find(|n| n.address.id == node.id) { + debug!(target: "discovery", "Found a known node in a bucket when processing discovery: {:?}/{:?}", known_node, node); + (known_node.address.endpoint == node.endpoint) && (known_node.last_seen.elapsed() < NODE_LAST_SEEN_TIMEOUT) + } else { + false + } + } + + fn respond_with_discovery(&mut self, target: NodeId, node: &NodeEntry) -> Result<(), Error> { let nearest = self.nearest_node_entries(&target); if nearest.is_empty() { - return Ok(None); + return Ok(()); } let mut packets = Discovery::prepare_neighbours_packets(&nearest); for p in packets.drain(..) { - self.send_packet(PACKET_NEIGHBOURS, from, &p)?; + self.send_packet(PACKET_NEIGHBOURS, &node.endpoint.address, &p)?; } - trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &from); - Ok(None) + trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &node.endpoint); + Ok(()) } fn prepare_neighbours_packets(nearest: &[NodeEntry]) -> Vec { @@ -827,7 +880,7 @@ mod tests { } // After 4 discovery rounds, the first one should have learned about the rest. - for _round in 0 .. 4 { + for _round in 0 .. 5 { discovery_handlers[0].round(); let mut continue_loop = true; @@ -835,9 +888,9 @@ mod tests { continue_loop = false; // Process all queued messages. - for i in 0 .. 5 { - let src = discovery_handlers[i].public_endpoint.address.clone(); - while let Some(datagram) = discovery_handlers[i].dequeue_send() { + for i in 0 .. 20 { + let src = discovery_handlers[i%5].public_endpoint.address.clone(); + while let Some(datagram) = discovery_handlers[i%5].dequeue_send() { let dest = discovery_handlers.iter_mut() .find(|disc| datagram.address == disc.public_endpoint.address) .unwrap(); @@ -929,14 +982,14 @@ mod tests { let mut discovery = Discovery { request_backoff: &request_backoff, ..discovery }; for _ in 0..2 { - discovery.ping(&node_entries[101]).unwrap(); + discovery.ping(&node_entries[101], PingReason::Default).unwrap(); let num_nodes = total_bucket_nodes(&discovery.node_buckets); discovery.check_expired(Instant::now() + PING_TIMEOUT); let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets); assert_eq!(removed, 0); } - discovery.ping(&node_entries[101]).unwrap(); + discovery.ping(&node_entries[101], PingReason::Default).unwrap(); let num_nodes = total_bucket_nodes(&discovery.node_buckets); discovery.check_expired(Instant::now() + PING_TIMEOUT); let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets); @@ -1123,7 +1176,7 @@ mod tests { let mut discovery1 = Discovery::new(&key1, ep1.clone(), IpFilter::default()); let mut discovery2 = Discovery::new(&key2, ep2.clone(), IpFilter::default()); - discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }).unwrap(); + discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }, PingReason::Default).unwrap(); let ping_data = discovery1.dequeue_send().unwrap(); assert!(!discovery1.any_sends_queued()); let data = &ping_data.payload[(32 + 65)..]; diff --git a/util/network-devp2p/src/ip_utils.rs b/util/network-devp2p/src/ip_utils.rs index cde0c8c6b..bb454ab7a 100644 --- a/util/network-devp2p/src/ip_utils.rs +++ b/util/network-devp2p/src/ip_utils.rs @@ -40,7 +40,7 @@ pub trait SocketAddrExt { fn is_documentation_s(&self) -> bool { false } fn is_global_multicast(&self) -> bool { false } fn is_other_multicast(&self) -> bool { false } - + fn is_reserved(&self) -> bool; fn is_usable_public(&self) -> bool; fn is_usable_private(&self) -> bool; @@ -50,38 +50,38 @@ pub trait SocketAddrExt { impl SocketAddrExt for Ipv4Addr { fn is_global_s(&self) -> bool { - !self.is_private() && - !self.is_loopback() && + !self.is_private() && + !self.is_loopback() && !self.is_link_local() && - !self.is_broadcast() && + !self.is_broadcast() && !self.is_documentation() } - // Used for communications between a service provider and its subscribers when using a carrier-grade NAT + // Used for communications between a service provider and its subscribers when using a carrier-grade NAT // see: https://en.wikipedia.org/wiki/Reserved_IP_addresses fn is_shared_space(&self) -> bool { - *self >= Ipv4Addr::new(100, 64, 0, 0) && + *self >= Ipv4Addr::new(100, 64, 0, 0) && *self <= Ipv4Addr::new(100, 127, 255, 255) } // Used for the IANA IPv4 Special Purpose Address Registry // see: https://en.wikipedia.org/wiki/Reserved_IP_addresses fn is_special_purpose(&self) -> bool { - *self >= Ipv4Addr::new(192, 0, 0, 0) && + *self >= Ipv4Addr::new(192, 0, 0, 0) && *self <= Ipv4Addr::new(192, 0, 0, 255) } // Used for testing of inter-network communications between two separate subnets // see: https://en.wikipedia.org/wiki/Reserved_IP_addresses fn is_benchmarking(&self) -> bool { - *self >= Ipv4Addr::new(198, 18, 0, 0) && + *self >= Ipv4Addr::new(198, 18, 0, 0) && *self <= Ipv4Addr::new(198, 19, 255, 255) } // Reserved for future use // see: https://en.wikipedia.org/wiki/Reserved_IP_addresses fn is_future_use(&self) -> bool { - *self >= Ipv4Addr::new(240, 0, 0, 0) && + *self >= Ipv4Addr::new(240, 0, 0, 0) && *self <= Ipv4Addr::new(255, 255, 255, 254) } @@ -102,7 +102,7 @@ impl SocketAddrExt for Ipv4Addr { !self.is_reserved() && !self.is_private() } - + fn is_usable_private(&self) -> bool { self.is_private() } @@ -118,7 +118,7 @@ impl SocketAddrExt for Ipv4Addr { impl SocketAddrExt for Ipv6Addr { fn is_global_s(&self) -> bool { self.is_global_multicast() || - (!self.is_loopback() && + (!self.is_loopback() && !self.is_unique_local_s() && !self.is_unicast_link_local_s() && !self.is_documentation_s() && @@ -134,7 +134,7 @@ impl SocketAddrExt for Ipv6Addr { fn is_unicast_link_local_s(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } - + // reserved for documentation (2001:db8::/32). fn is_documentation_s(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) @@ -160,7 +160,7 @@ impl SocketAddrExt for Ipv6Addr { !self.is_reserved() && !self.is_unique_local_s() } - + fn is_usable_private(&self) -> bool { self.is_unique_local_s() } @@ -194,7 +194,7 @@ impl SocketAddrExt for IpAddr { IpAddr::V6(ref ip) => ip.is_usable_public(), } } - + fn is_usable_private(&self) -> bool { match *self { IpAddr::V4(ref ip) => ip.is_usable_private(), @@ -308,7 +308,15 @@ pub fn select_public_address(port: u16) -> SocketAddr { pub fn map_external_address(local: &NodeEndpoint) -> Option { if let SocketAddr::V4(ref local_addr) = local.address { - match search_gateway_from_timeout(*local_addr.ip(), Duration::new(5, 0)) { + let local_ip = *local_addr.ip(); + let search_gateway_child = ::std::thread::spawn(move || { + search_gateway_from_timeout(local_ip, Duration::new(5, 0)) + }); + let gateway_result = match search_gateway_child.join() { + Err(_) => return None, + Ok(gateway_result) => gateway_result, + }; + match gateway_result { Err(ref err) => debug!("Gateway search error: {}", err), Ok(gateway) => { match gateway.get_external_ip() { @@ -425,32 +433,32 @@ fn ipv4_future_use() { fn ipv4_usable_public() { assert!(!Ipv4Addr::new(0,0,0,0).is_usable_public()); // unspecified assert!(Ipv4Addr::new(0,0,0,1).is_usable_public()); - + assert!(Ipv4Addr::new(9,255,255,255).is_usable_public()); assert!(!Ipv4Addr::new(10,0,0,0).is_usable_public()); // private intra-network assert!(!Ipv4Addr::new(10,255,255,255).is_usable_public()); // private intra-network assert!(Ipv4Addr::new(11,0,0,0).is_usable_public()); - + assert!(Ipv4Addr::new(100, 63, 255, 255).is_usable_public()); - assert!(!Ipv4Addr::new(100, 64, 0, 0).is_usable_public()); // shared space + assert!(!Ipv4Addr::new(100, 64, 0, 0).is_usable_public()); // shared space assert!(!Ipv4Addr::new(100, 127, 255, 255).is_usable_public()); // shared space assert!(Ipv4Addr::new(100, 128, 0, 0).is_usable_public()); - + assert!(Ipv4Addr::new(126,255,255,255).is_usable_public()); assert!(!Ipv4Addr::new(127,0,0,0).is_usable_public()); // loopback assert!(!Ipv4Addr::new(127,255,255,255).is_usable_public()); // loopback assert!(Ipv4Addr::new(128,0,0,0).is_usable_public()); - + assert!(Ipv4Addr::new(169,253,255,255).is_usable_public()); assert!(!Ipv4Addr::new(169,254,0,0).is_usable_public()); // link-local assert!(!Ipv4Addr::new(169,254,255,255).is_usable_public()); // link-local assert!(Ipv4Addr::new(169,255,0,0).is_usable_public()); - + assert!(Ipv4Addr::new(172,15,255,255).is_usable_public()); assert!(!Ipv4Addr::new(172,16,0,0).is_usable_public()); // private intra-network assert!(!Ipv4Addr::new(172,31,255,255).is_usable_public()); // private intra-network assert!(Ipv4Addr::new(172,32,255,255).is_usable_public()); - + assert!(Ipv4Addr::new(191,255,255,255).is_usable_public()); assert!(!Ipv4Addr::new(192,0,0,0).is_usable_public()); // special purpose assert!(!Ipv4Addr::new(192,0,0,255).is_usable_public()); // special purpose @@ -458,19 +466,19 @@ fn ipv4_usable_public() { assert!(Ipv4Addr::new(192,0,1,255).is_usable_public()); assert!(!Ipv4Addr::new(192,0,2,0).is_usable_public()); // documentation - assert!(!Ipv4Addr::new(192,0,2,255).is_usable_public()); // documentation + assert!(!Ipv4Addr::new(192,0,2,255).is_usable_public()); // documentation assert!(Ipv4Addr::new(192,0,3,0).is_usable_public()); - + assert!(Ipv4Addr::new(192,167,255,255).is_usable_public()); assert!(!Ipv4Addr::new(192,168,0,0).is_usable_public()); // private intra-network assert!(!Ipv4Addr::new(192,168,255,255).is_usable_public()); // private intra-network assert!(Ipv4Addr::new(192,169,0,0).is_usable_public()); - + assert!(Ipv4Addr::new(198,17,255,255).is_usable_public()); assert!(!Ipv4Addr::new(198,18,0,0).is_usable_public()); // benchmarking assert!(!Ipv4Addr::new(198,19,255,255).is_usable_public()); // benchmarking assert!(Ipv4Addr::new(198,20,0,0).is_usable_public()); - + assert!(Ipv4Addr::new(198,51,99,255).is_usable_public()); assert!(!Ipv4Addr::new(198,51,100,0).is_usable_public()); // documentation assert!(!Ipv4Addr::new(198,51,100,255).is_usable_public()); // documentation @@ -485,7 +493,7 @@ fn ipv4_usable_public() { assert!(!Ipv4Addr::new(224,0,0,0).is_usable_public()); // multicast assert!(!Ipv4Addr::new(239, 255, 255, 255).is_usable_public()); // multicast assert!(!Ipv4Addr::new(240, 0, 0, 0).is_usable_public()); // future use - assert!(!Ipv4Addr::new(255, 255, 255, 254).is_usable_public()); // future use + assert!(!Ipv4Addr::new(255, 255, 255, 254).is_usable_public()); // future use assert!(!Ipv4Addr::new(255, 255, 255, 255).is_usable_public()); // limited broadcast } @@ -495,12 +503,12 @@ fn ipv4_usable_private() { assert!(Ipv4Addr::new(10,0,0,0).is_usable_private()); // private intra-network assert!(Ipv4Addr::new(10,255,255,255).is_usable_private()); // private intra-network assert!(!Ipv4Addr::new(11,0,0,0).is_usable_private()); - + assert!(!Ipv4Addr::new(172,15,255,255).is_usable_private()); assert!(Ipv4Addr::new(172,16,0,0).is_usable_private()); // private intra-network assert!(Ipv4Addr::new(172,31,255,255).is_usable_private()); // private intra-network assert!(!Ipv4Addr::new(172,32,255,255).is_usable_private()); - + assert!(!Ipv4Addr::new(192,167,255,255).is_usable_private()); assert!(Ipv4Addr::new(192,168,0,0).is_usable_private()); // private intra-network assert!(Ipv4Addr::new(192,168,255,255).is_usable_private()); // private intra-network diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index 7a82825f0..db8451632 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -3,22 +3,22 @@ [package] name = "parity-version" # NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION) -version = "2.2.6" +version = "2.2.7" authors = ["Parity Technologies "] build = "build.rs" [package.metadata] # This versions track. Should be changed to `stable` or `beta` when on respective branches. # Used by auto-updater and for Parity version string. -track = "beta" +track = "stable" # Network specific settings, used ONLY by auto-updater. # Latest supported fork blocks. # Indicates a critical release in this track (i.e. consensus issue). [package.metadata.networks] -foundation = { forkBlock = 4370000, critical = false } +foundation = { forkBlock = 4370000, critical = true } ropsten = { forkBlock = 4230000, critical = false } -kovan = { forkBlock = 6600000, critical = true } +kovan = { forkBlock = 9200000, critical = true } [dependencies] parity-bytes = "0.1"