From bd684e37323a76d34ad7ae90f00f52d899d8ff60 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 2 Feb 2016 12:12:32 +0100 Subject: [PATCH 01/13] Check for parent on queue import --- ethcore/src/block_queue.rs | 32 +++++++++++++++++++++++++++----- ethcore/src/client.rs | 15 +++++++++++++-- ethcore/src/error.rs | 10 ++++++---- sync/src/chain.rs | 8 ++++++++ 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index dabe047e9..1c0cc41ae 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -9,6 +9,7 @@ use engine::Engine; use views::*; use header::*; use service::*; +use client::BlockStatus; /// Block queue status #[derive(Debug)] @@ -41,7 +42,7 @@ pub struct BlockQueue { deleting: Arc, ready_signal: Arc, empty: Arc, - processing: HashSet + processing: RwLock> } struct UnVerifiedBlock { @@ -106,7 +107,7 @@ impl BlockQueue { verification: verification.clone(), verifiers: verifiers, deleting: deleting.clone(), - processing: HashSet::new(), + processing: RwLock::new(HashSet::new()), empty: empty.clone(), } } @@ -196,11 +197,22 @@ impl BlockQueue { } } + /// Check if the block is currently in the queue + pub fn block_status(&self, hash: &H256) -> BlockStatus { + if self.processing.read().unwrap().contains(&hash) { + return BlockStatus::Queued; + } + if self.verification.lock().unwrap().bad.contains(&hash) { + return BlockStatus::Bad; + } + BlockStatus::Unknown + } + /// Add a block to the queue. pub fn import_block(&mut self, bytes: Bytes) -> ImportResult { let header = BlockView::new(&bytes).header(); let h = header.hash(); - if self.processing.contains(&h) { + if self.processing.read().unwrap().contains(&h) { return Err(ImportError::AlreadyQueued); } { @@ -217,7 +229,7 @@ impl BlockQueue { match verify_block_basic(&header, &bytes, self.engine.deref().deref()) { Ok(()) => { - self.processing.insert(h.clone()); + self.processing.write().unwrap().insert(h.clone()); self.verification.lock().unwrap().unverified.push_back(UnVerifiedBlock { header: header, bytes: bytes }); self.more_to_verify.notify_all(); Ok(h) @@ -235,10 +247,12 @@ impl BlockQueue { let mut verification_lock = self.verification.lock().unwrap(); let mut verification = verification_lock.deref_mut(); verification.bad.insert(hash.clone()); + self.processing.write().unwrap().remove(&hash); let mut new_verified = VecDeque::new(); for block in verification.verified.drain(..) { if verification.bad.contains(&block.header.parent_hash) { verification.bad.insert(block.header.hash()); + self.processing.write().unwrap().remove(&block.header.hash()); } else { new_verified.push_back(block); @@ -247,6 +261,15 @@ impl BlockQueue { verification.verified = new_verified; } + /// Mark given block as processed + pub fn mark_as_good(&mut self, hashes: &[H256]) { + let mut processing = self.processing.write().unwrap(); + for h in hashes { + processing.remove(&h); + } + //TODO: reward peers + } + /// Removes up to `max` verified blocks from the queue pub fn drain(&mut self, max: usize) -> Vec { let mut verification = self.verification.lock().unwrap(); @@ -254,7 +277,6 @@ impl BlockQueue { let mut result = Vec::with_capacity(count); for _ in 0..count { let block = verification.verified.pop_front().unwrap(); - self.processing.remove(&block.header.hash()); result.push(block); } self.ready_signal.reset(); diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 1a59aefc5..f9b992fc5 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -15,7 +15,7 @@ use verification::*; use block::*; /// General block status -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum BlockStatus { /// Part of the blockchain. InChain, @@ -204,6 +204,7 @@ impl Client { let mut bad = HashSet::new(); let _import_lock = self.import_lock.lock(); let blocks = self.block_queue.write().unwrap().drain(128); + let mut good_blocks = Vec::with_capacity(128); for block in blocks { if bad.contains(&block.header.parent_hash) { self.block_queue.write().unwrap().mark_as_bad(&block.header.hash()); @@ -256,6 +257,8 @@ impl Client { break; } + good_blocks.push(header.hash().clone()); + self.chain.write().unwrap().insert_block(&block.bytes); //TODO: err here? let ancient = if header.number() >= HISTORY { Some(header.number() - HISTORY) } else { None }; match result.drain().commit(header.number(), &header.hash(), ancient.map(|n|(n, self.chain.read().unwrap().block_hash(n).unwrap()))) { @@ -269,6 +272,7 @@ impl Client { trace!(target: "client", "Imported #{} ({})", header.number(), header.hash()); ret += 1; } + self.block_queue.write().unwrap().mark_as_good(&good_blocks); ret } @@ -318,7 +322,11 @@ impl BlockChainClient for Client { } fn block_status(&self, hash: &H256) -> BlockStatus { - if self.chain.read().unwrap().is_known(&hash) { BlockStatus::InChain } else { BlockStatus::Unknown } + if self.chain.read().unwrap().is_known(&hash) { + BlockStatus::InChain + } else { + self.block_queue.read().unwrap().block_status(hash) + } } fn block_total_difficulty(&self, hash: &H256) -> Option { @@ -365,6 +373,9 @@ impl BlockChainClient for Client { if self.chain.read().unwrap().is_known(&header.hash()) { return Err(ImportError::AlreadyInChain); } + if self.block_status(&header.parent_hash) == BlockStatus::Unknown { + return Err(ImportError::UnknownParent); + } self.block_queue.write().unwrap().import_block(bytes) } diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 4ca988679..96a362025 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -130,14 +130,16 @@ pub enum BlockError { } #[derive(Debug)] -/// TODO [arkpar] Please document me +/// Import to the block queue result pub enum ImportError { - /// TODO [arkpar] Please document me + /// Bad block detected Bad(Option), - /// TODO [arkpar] Please document me + /// Already in the block chain AlreadyInChain, - /// TODO [arkpar] Please document me + /// Already in the block queue AlreadyQueued, + /// Unknown parent + UnknownParent, } impl From for ImportError { diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 13158f95a..dcc5c52e3 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -408,6 +408,7 @@ impl ChainSync { trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); let header_view = HeaderView::new(header_rlp.as_raw()); // TODO: Decompose block and add to self.headers and self.bodies instead + let mut unknown = false; if header_view.number() == From::from(self.last_imported_block + 1) { match io.chain().import_block(block_rlp.as_raw().to_vec()) { Err(ImportError::AlreadyInChain) => { @@ -416,6 +417,10 @@ impl ChainSync { Err(ImportError::AlreadyQueued) => { trace!(target: "sync", "New block already queued {:?}", h); }, + Err(ImportError::UnknownParent) => { + unknown = true; + trace!(target: "sync", "New block with unknown parent {:?}", h); + }, Ok(_) => { trace!(target: "sync", "New block queued {:?}", h); }, @@ -426,6 +431,9 @@ impl ChainSync { }; } else { + unknown = true; + } + if unknown { trace!(target: "sync", "New block unknown {:?}", h); //TODO: handle too many unknown blocks let difficulty: U256 = try!(r.val_at(1)); From 3f8fdfaea70e978926e96b02dad7c1f09bbfaefe Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 14:33:02 +0100 Subject: [PATCH 02/13] Deploying artifacts for releases --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2663d0d8e..7d5ef19eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ script: - cargo build --release --verbose ${FEATURES} - cargo test --release --verbose ${FEATURES} ${TARGETS} - cargo bench --no-run ${FEATURES} ${TARGETS} +- zip -j target/release/parity parity-${TRAVIS_TAG}.zip after_success: | wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && @@ -53,3 +54,12 @@ env: global: - secure: 3sUjNi9mhdL5h1GTm8LONnDN/SYvUHT+WSkMl93h3nYiLCQXk8eZaPS98AS7oOaTsfW4UvnwckVFCFl49ttInsv4cd/TkAxmrJHe6kPyS9/4NWUdmP8BjicbBvL/ioSdXMECMEYzPDLV+I3KhtC2LcB6ceDEl/XwMOJlzbGf7RbtcXGVQgMLqSYY1YKjQA4vbT5nFgIS/sZu3Z9yFgN0GafnihKcizqoHhdJjs/zxmX+qJepnC6o3V6KcFnS7QHhM1JOr85twE6S422UlvNaEb5ovwLPqmOl5+fA+6shbx4AxFTY6E9Iors+OVY/JliFhrqOdCt0i2P1FUHN4kbGZQkf0rphN/ZOI2uKNFTOyXiPvppfo/ZemKmcqkwkqP9+lf5QqYmtE6hsAYagxn49xJZILl8tAYbdqxF5gxa+TEVrfsBFtz/Sv3q8QhKQNPAmjEcKyMatyEreLUIFEpFTGIco8jN4eXeSoLRdJ+Z75ihttfQWhNfUDgNL30iQLy0AgFSsh/cyb5M8y9lxrGDzDTogvaiKGwr/V45sPkcXWCkmOgMdINqBB6ZtdL3bGHdyjmYj+y3btjf3aP11k++BL0fXIaKn25aS/p/9iyGb1FyGCM03o4ZRQ3YhTOvfMRfRGf6nWbaMx9upv8o5ShSdysewhrnh3082r7u896ny1Ho= - secure: 0/FeVvFl3AhBW0TCPoujY9zOAYoUNMlAz3XjC04vlc4Ksfx0lGU3KFi97LlALxMWV0lfwQc7ixSe2vTgQVQuLVSU9XEW40fQgEjJlmLca2RcRx1kfzJDypuWSiCME7MWmLPH0ac4COdTDS1z5WGggv5YB7GQPCzFvcmOOaPYtF29ngCtkyB2HmNkY/W3omHFEk7Si6bsmOSHZiOAhivPl6ixnGpFyTEKPyraMMqPIj5rbEGkzgeLTiXf2ur143n/tnSr8tmP1MfQi9yS8/ONidMqnxUeuLkeNnb82zj9pVJhVXq0xF44WXJ8Za1jm0ByiTakgqpm8Juk822qjvtNulJ1XZW/fyZQZaN1dy3uq5Ud3W8wS9M7VIVl8CoXozzDpIsdPeUAtkAxeHBsZqL1vAH2yC1YJA7HPySMYzCjYqkJ2r62xYk0gXmNXphfU+F/X/rHzHsTMJPONJ54HQwu12m7zVlKIYBGHgEXg/HAM/g4ljUzl6WWR/nHH/tQM8ND/8FpHluJSZJWacq/1QNhVdTq2x6cqws2fs5A7nVpccR9+6RRgYgv6+YS2LxvFzByuZveGGoKif+uMECXN876j40araUqU528Yz9i8bHJlnM3coRBndaLNWByLcUyXCB9r9IUosUu41rr+L2mVzkSDm0GicuNCzqvzYQ9Q6QY4uQ= + +deploy: + provider: releases + api_key: + secure: ATorsRujvWN9y4bZlUdp2I0hvh3pKkpkrr/oyQyt8ZssE7ORx1+lYgTdYocHyx53uBrGFjRQbSCvdDsrs8c1v2Dh2872TmMQMWgLaeeS6bPiNw7WkJuH1hvvTNAiFCfuT9nnntFvMuKcUpBHQ1eeuEU + skip_cleanup: true + file: parity-${TRAVIS_TAG}.zip + on: + tags: true From 25c87d000441be215911cd00df96b12da937160f Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 14:43:55 +0100 Subject: [PATCH 03/13] Including OS_NAME in artifact --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d5ef19eb..37d9eafee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ matrix: fast_finish: true include: - rust: nightly - env: FEATURES="--features ethcore/json-tests" KCOV_FEATURES="" TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity" + env: FEATURES="--features ethcore/json-tests" KCOV_FEATURES="" TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity" ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" cache: apt: true directories: @@ -30,7 +30,7 @@ script: - cargo build --release --verbose ${FEATURES} - cargo test --release --verbose ${FEATURES} ${TARGETS} - cargo bench --no-run ${FEATURES} ${TARGETS} -- zip -j target/release/parity parity-${TRAVIS_TAG}.zip +- zip -j target/release/parity parity${ARCHIVE_SUFFIX}.zip after_success: | wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && @@ -60,6 +60,6 @@ deploy: api_key: secure: ATorsRujvWN9y4bZlUdp2I0hvh3pKkpkrr/oyQyt8ZssE7ORx1+lYgTdYocHyx53uBrGFjRQbSCvdDsrs8c1v2Dh2872TmMQMWgLaeeS6bPiNw7WkJuH1hvvTNAiFCfuT9nnntFvMuKcUpBHQ1eeuEU skip_cleanup: true - file: parity-${TRAVIS_TAG}.zip + file: parity${ARCHIVE_SUFFIX}.zip on: tags: true From ce0cc11c56db7981ca9a04ac3403ce817d38a426 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 2 Feb 2016 14:54:46 +0100 Subject: [PATCH 04/13] Peer sync timeouts --- sync/Cargo.toml | 1 + sync/src/chain.rs | 17 +++++++++++++++++ sync/src/io.rs | 6 ++++++ sync/src/lib.rs | 9 ++++++++- sync/src/tests.rs | 3 +++ util/src/network/error.rs | 20 ++++++++++---------- util/src/network/host.rs | 27 ++++++++++++++++++++++++++- util/src/network/service.rs | 2 +- util/src/network/session.rs | 3 ++- 9 files changed, 74 insertions(+), 14 deletions(-) diff --git a/sync/Cargo.toml b/sync/Cargo.toml index c3ae470fd..5f098bc26 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -13,4 +13,5 @@ ethcore = { path = ".." } clippy = "0.0.37" log = "0.3" env_logger = "0.3" +time = "0.1.34" diff --git a/sync/src/chain.rs b/sync/src/chain.rs index dcc5c52e3..9752a5013 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -22,6 +22,7 @@ use range_collection::{RangeCollection, ToUsize, FromUsize}; use ethcore::error::*; use ethcore::block::Block; use io::SyncIo; +use time; impl ToUsize for BlockNumber { fn to_usize(&self) -> usize { @@ -61,6 +62,8 @@ const RECEIPTS_PACKET: u8 = 0x10; const NETWORK_ID: U256 = ONE_U256; //TODO: get this from parent +const CONNECTION_TIMEOUT_SEC: f64 = 30f64; + struct Header { /// Header data data: Bytes, @@ -138,6 +141,8 @@ struct PeerInfo { asking: PeerAsking, /// A set of block numbers being requested asking_blocks: Vec, + /// Request timestamp + ask_time: f64, } /// Blockchain sync handler. @@ -250,6 +255,7 @@ impl ChainSync { genesis: try!(r.val_at(4)), asking: PeerAsking::Nothing, asking_blocks: Vec::new(), + ask_time: 0f64, }; trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest, peer.genesis); @@ -803,6 +809,7 @@ impl ChainSync { Ok(_) => { let mut peer = self.peers.get_mut(&peer_id).unwrap(); peer.asking = asking; + peer.ask_time = time::precise_time_s(); } } } @@ -977,6 +984,16 @@ impl ChainSync { }) } + /// Handle peer timeouts + pub fn maintain_peers(&self, io: &mut SyncIo) { + let tick = time::precise_time_s(); + for (peer_id, peer) in &self.peers { + if peer.asking != PeerAsking::Nothing && (tick - peer.ask_time) > CONNECTION_TIMEOUT_SEC { + io.disconnect_peer(*peer_id); + } + } + } + /// Maintain other peers. Send out any new blocks and transactions pub fn _maintain_sync(&mut self, _io: &mut SyncIo) { } diff --git a/sync/src/io.rs b/sync/src/io.rs index 4425a2555..8f415f582 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -9,6 +9,8 @@ use ethcore::service::SyncMessage; pub trait SyncIo { /// Disable a peer fn disable_peer(&mut self, peer_id: PeerId); + /// Disconnect peer + fn disconnect_peer(&mut self, peer_id: PeerId); /// Respond to current request with a packet. Can be called from an IO handler for incoming packet. fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), UtilError>; /// Send a packet to a peer. @@ -42,6 +44,10 @@ impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> { self.network.disable_peer(peer_id); } + fn disconnect_peer(&mut self, peer_id: PeerId) { + self.network.disconnect_peer(peer_id); + } + fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), UtilError>{ self.network.respond(packet_id, data) } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 09f3eb521..40b67dc5b 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -33,11 +33,13 @@ extern crate log; extern crate ethcore_util as util; extern crate ethcore; extern crate env_logger; +extern crate time; use std::ops::*; use std::sync::*; use ethcore::client::Client; use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, PeerId}; +use util::io::TimerToken; use chain::ChainSync; use ethcore::service::SyncMessage; use io::NetSyncIo; @@ -87,7 +89,8 @@ impl EthSync { } impl NetworkProtocolHandler for EthSync { - fn initialize(&self, _io: &NetworkContext) { + fn initialize(&self, io: &NetworkContext) { + io.register_timer(0, 1000).expect("Error registering sync timer"); } fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { @@ -101,6 +104,10 @@ impl NetworkProtocolHandler for EthSync { fn disconnected(&self, io: &NetworkContext, peer: &PeerId) { self.sync.write().unwrap().on_peer_aborting(&mut NetSyncIo::new(io, self.chain.deref()), *peer); } + + fn timeout(&self, io: &NetworkContext, _timer: TimerToken) { + self.sync.write().unwrap().maintain_peers(&mut NetSyncIo::new(io, self.chain.deref())); + } } diff --git a/sync/src/tests.rs b/sync/src/tests.rs index 41516ef60..5b796e6f1 100644 --- a/sync/src/tests.rs +++ b/sync/src/tests.rs @@ -209,6 +209,9 @@ impl<'p> SyncIo for TestIo<'p> { fn disable_peer(&mut self, _peer_id: PeerId) { } + fn disconnect_peer(&mut self, _peer_id: PeerId) { + } + fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { self.queue.push_back(TestPacket { data: data, diff --git a/util/src/network/error.rs b/util/src/network/error.rs index b9dfdc892..f03e128e6 100644 --- a/util/src/network/error.rs +++ b/util/src/network/error.rs @@ -5,17 +5,17 @@ use rlp::*; pub enum DisconnectReason { DisconnectRequested, - //TCPError, - //BadProtocol, + _TCPError, + _BadProtocol, UselessPeer, - //TooManyPeers, - //DuplicatePeer, - //IncompatibleProtocol, - //NullIdentity, - //ClientQuit, - //UnexpectedIdentity, - //LocalIdentity, - //PingTimeout, + _TooManyPeers, + _DuplicatePeer, + _IncompatibleProtocol, + _NullIdentity, + _ClientQuit, + _UnexpectedIdentity, + _LocalIdentity, + _PingTimeout, } #[derive(Debug)] diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 95b1e3668..5e44c5854 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -18,6 +18,7 @@ use io::*; use network::NetworkProtocolHandler; use network::node::*; use network::stats::NetworkStats; +use network::error::DisconnectReason; type Slab = ::slab::Slab; @@ -107,6 +108,11 @@ pub enum NetworkIoMessage where Message: Send + Sync + Clone { /// Timer delay in milliseconds. delay: u64, }, + /// Disconnect a peer + Disconnect { + /// Peer Id + peer: PeerId, + }, /// User message User(Message), } @@ -180,8 +186,16 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone } /// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected. - pub fn disable_peer(&self, _peer: PeerId) { + pub fn disable_peer(&self, peer: PeerId) { //TODO: remove capability, disconnect if no capabilities left + self.disconnect_peer(peer); + } + + /// Disconnect peer. Reconnect can be attempted later. + pub fn disconnect_peer(&self, peer: PeerId) { + self.io.message(NetworkIoMessage::Disconnect { + peer: peer, + }); } /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. @@ -683,6 +697,17 @@ impl IoHandler> for Host where Messa self.timers.write().unwrap().insert(handler_token, ProtocolTimer { protocol: protocol, token: *token }); io.register_timer(handler_token, *delay).expect("Error registering timer"); }, + NetworkIoMessage::Disconnect { + ref peer, + } => { + if let Some(connection) = self.connections.read().unwrap().get(*peer).cloned() { + match *connection.lock().unwrap().deref_mut() { + ConnectionEntry::Handshake(_) => {}, + ConnectionEntry::Session(ref mut s) => { s.disconnect(DisconnectReason::DisconnectRequested); } + } + } + self.kill_connection(*peer, io); + }, NetworkIoMessage::User(ref message) => { for (p, h) in self.handlers.read().unwrap().iter() { h.message(&NetworkContext::new(io, p, None, self.connections.clone()), &message); diff --git a/util/src/network/service.rs b/util/src/network/service.rs index cbf400872..41a23cda6 100644 --- a/util/src/network/service.rs +++ b/util/src/network/service.rs @@ -21,7 +21,7 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat let host = Arc::new(Host::new(config)); let stats = host.stats().clone(); let host_info = host.client_version(); - info!("NetworkService::start(): id={:?}", host.client_id()); + info!("Host ID={:?}", host.client_id()); try!(io_service.register_handler(host)); Ok(NetworkService { io_service: io_service, diff --git a/util/src/network/session.rs b/util/src/network/session.rs index fb385b487..20a9c9a48 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -263,7 +263,8 @@ impl Session { self.send(try!(Session::prepare(PACKET_PONG))) } - fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { + /// Disconnect this session + pub fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { let mut rlp = RlpStream::new(); rlp.append(&(PACKET_DISCONNECT as u32)); rlp.begin_list(1); From 8f12989785503d49fa49b053d04d88060f0daba4 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 15:01:18 +0100 Subject: [PATCH 05/13] Changing packaging to tar.gz --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 37d9eafee..d1cefa6ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ script: - cargo build --release --verbose ${FEATURES} - cargo test --release --verbose ${FEATURES} ${TARGETS} - cargo bench --no-run ${FEATURES} ${TARGETS} -- zip -j target/release/parity parity${ARCHIVE_SUFFIX}.zip +- tar cvzf parity${ARCHIVE_SUFFIX}.tar.gz -C target/release parity after_success: | wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && @@ -60,6 +60,6 @@ deploy: api_key: secure: ATorsRujvWN9y4bZlUdp2I0hvh3pKkpkrr/oyQyt8ZssE7ORx1+lYgTdYocHyx53uBrGFjRQbSCvdDsrs8c1v2Dh2872TmMQMWgLaeeS6bPiNw7WkJuH1hvvTNAiFCfuT9nnntFvMuKcUpBHQ1eeuEU skip_cleanup: true - file: parity${ARCHIVE_SUFFIX}.zip + file: parity${ARCHIVE_SUFFIX}.tar.gz on: tags: true From 8ea7331d2b667e717ea16f4774e69674111f53af Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 16:13:42 +0100 Subject: [PATCH 06/13] Building beta-* and stable-* tags --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d1cefa6ba..899174b5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ language: rust branches: only: - master + - /^beta-.*$/ + - /^stable-.*$/ matrix: fast_finish: true include: From 1260a4c36d516c63c67cb6f9056f9c0ed5611102 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 17:37:37 +0100 Subject: [PATCH 07/13] Replacing secure token for deployment --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 899174b5a..fff7c94ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,7 +60,7 @@ env: deploy: provider: releases api_key: - secure: ATorsRujvWN9y4bZlUdp2I0hvh3pKkpkrr/oyQyt8ZssE7ORx1+lYgTdYocHyx53uBrGFjRQbSCvdDsrs8c1v2Dh2872TmMQMWgLaeeS6bPiNw7WkJuH1hvvTNAiFCfuT9nnntFvMuKcUpBHQ1eeuEU + secure: 3sUjNi9mhdL5h1GTm8LONnDN/SYvUHT+WSkMl93h3nYiLCQXk8eZaPS98AS7oOaTsfW4UvnwckVFCFl49ttInsv4cd/TkAxmrJHe6kPyS9/4NWUdmP8BjicbBvL/ioSdXMECMEYzPDLV+I3KhtC2LcB6ceDEl/XwMOJlzbGf7RbtcXGVQgMLqSYY1YKjQA4vbT5nFgIS/sZu3Z9yFgN0GafnihKcizqoHhdJjs/zxmX+qJepnC6o3V6KcFnS7QHhM1JOr85twE6S422UlvNaEb5ovwLPqmOl5+fA+6shbx4AxFTY6E9Iors+OVY/JliFhrqOdCt0i2P1FUHN4kbGZQkf0rphN/ZOI2uKNFTOyXiPvppfo/ZemKmcqkwkqP9+lf5QqYmtE6hsAYagxn49xJZILl8tAYbdqxF5gxa+TEVrfsBFtz/Sv3q8QhKQNPAmjEcKyMatyEreLUIFEpFTGIco8jN4eXeSoLRdJ+Z75ihttfQWhNfUDgNL30iQLy0AgFSsh/cyb5M8y9lxrGDzDTogvaiKGwr/V45sPkcXWCkmOgMdINqBB6ZtdL3bGHdyjmYj+y3btjf3aP11k++BL0fXIaKn25aS/p/9iyGb1FyGCM03o4ZRQ3YhTOvfMRfRGf6nWbaMx9upv8o5ShSdysewhrnh3082r7u896ny1Ho= skip_cleanup: true file: parity${ARCHIVE_SUFFIX}.tar.gz on: From 366f9fe8f21a0789c27e57760f3a2142222156c6 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 18:02:58 +0100 Subject: [PATCH 08/13] Couple of tests for EVM --- ethcore/src/evm/evm.rs | 19 +-- ethcore/src/evm/factory.rs | 6 +- ethcore/src/evm/interpreter.rs | 3 +- ethcore/src/evm/tests.rs | 301 +++++++++++++++++++++++++++++++-- 4 files changed, 302 insertions(+), 27 deletions(-) diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index b90ea5f97..c30bedfaa 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -15,31 +15,30 @@ pub enum Error { /// `BadJumpDestination` is returned when execution tried to move /// to position that wasn't marked with JUMPDEST instruction BadJumpDestination { - /// TODO [Tomusdrw] Please document me + /// Position the code tried to jump to. destination: usize }, /// `BadInstructions` is returned when given instruction is not supported BadInstruction { - /// TODO [Tomusdrw] Please document me + /// Unrecognized opcode instruction: u8, }, /// `StackUnderflow` when there is not enough stack elements to execute instruction - /// First parameter says how many elements were needed and the second how many were actually on Stack StackUnderflow { - /// TODO [Tomusdrw] Please document me + /// Invoked instruction instruction: &'static str, - /// TODO [Tomusdrw] Please document me + /// How many stack elements was requested by instruction wanted: usize, - /// TODO [Tomusdrw] Please document me + /// How many elements were on stack on_stack: usize }, /// When execution would exceed defined Stack Limit OutOfStack { - /// TODO [Tomusdrw] Please document me + /// Invoked instruction instruction: &'static str, - /// TODO [Tomusdrw] Please document me - wanted: usize, - /// TODO [Tomusdrw] Please document me + /// How many stack elements instruction wanted to push + wanted: usize, + /// What was the stack limit limit: usize }, /// Returned on evm internal error. Should never be ignored during development. diff --git a/ethcore/src/evm/factory.rs b/ethcore/src/evm/factory.rs index 9f76d25ec..591826960 100644 --- a/ethcore/src/evm/factory.rs +++ b/ethcore/src/evm/factory.rs @@ -3,11 +3,11 @@ use std::fmt; use evm::Evm; #[derive(Clone)] -/// TODO [Tomusdrw] Please document me +/// Type of EVM to use. pub enum VMType { - /// TODO [Tomusdrw] Please document me + /// JIT EVM Jit, - /// TODO [Tomusdrw] Please document me + /// RUST EVM Interpreter } diff --git a/ethcore/src/evm/interpreter.rs b/ethcore/src/evm/interpreter.rs index f55b94adb..6516d9946 100644 --- a/ethcore/src/evm/interpreter.rs +++ b/ethcore/src/evm/interpreter.rs @@ -1,11 +1,10 @@ ///! Rust VM implementation use common::*; -use evm; use super::instructions as instructions; use super::instructions::Instruction; use std::marker::Copy; -use evm::{MessageCallResult, ContractCreateResult}; +use evm::{self, MessageCallResult, ContractCreateResult}; #[cfg(not(feature = "evm-debug"))] macro_rules! evm_debug { diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index d448ccb3a..bf0480f47 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -150,7 +150,7 @@ fn test_add(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_988)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap()); + assert_store(&ext, 0, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); } evm_test!{test_sha3: test_sha3_jit, test_sha3_int} @@ -170,7 +170,7 @@ fn test_sha3(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_961)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap()); + assert_store(&ext, 0, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); } evm_test!{test_address: test_address_jit, test_address_int} @@ -190,7 +190,7 @@ fn test_address(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"); } evm_test!{test_origin: test_origin_jit, test_origin_int} @@ -212,7 +212,7 @@ fn test_origin(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()); + assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681"); } // TODO [todr] Fails with Signal 11 on JIT @@ -235,7 +235,7 @@ fn test_sender(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()); + assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681"); } evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int} @@ -270,7 +270,7 @@ fn test_extcodecopy(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_935)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("6005600055000000000000000000000000000000000000000000000000000000").unwrap()); + assert_store(&ext, 0, "6005600055000000000000000000000000000000000000000000000000000000"); } evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int} @@ -369,7 +369,7 @@ fn test_calldataload(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_991)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap()); + assert_store(&ext, 0, "23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23"); } @@ -390,7 +390,7 @@ fn test_author(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"); } evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int} @@ -410,7 +410,7 @@ fn test_timestamp(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234"); } evm_test!{test_number: test_number_jit, test_number_int} @@ -430,7 +430,7 @@ fn test_number(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234"); } evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int} @@ -450,7 +450,7 @@ fn test_difficulty(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234"); } evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int} @@ -470,6 +470,283 @@ fn test_gas_limit(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_995)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234"); +} + +evm_test!{test_mul: test_mul_jit, test_mul_int} +fn test_mul(factory: super::Factory) { + let code = "65012365124623626543219002600055".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383"); + assert_eq!(gas_left, U256::from(79_983)); +} + +evm_test!{test_sub: test_sub_jit, test_sub_int} +fn test_sub(factory: super::Factory) { + let code = "65012365124623626543219003600055".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302"); + assert_eq!(gas_left, U256::from(79_985)); +} + +evm_test!{test_div: test_div_jit, test_div_int} +fn test_div(factory: super::Factory) { + let code = "65012365124623626543219004600055".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac"); + assert_eq!(gas_left, U256::from(79_983)); +} + +evm_test!{test_div_zero: test_div_zero_jit, test_div_zero_int} +fn test_div_zero(factory: super::Factory) { + let code = "6501236512462360009004600055".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_eq!(gas_left, U256::from(94_983)); +} + +evm_test!{test_mod: test_mod_jit, test_mod_int} +fn test_mod(factory: super::Factory) { + let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_eq!(gas_left, U256::from(74_966)); +} + +evm_test!{test_smod: test_smod_jit, test_smod_int} +fn test_smod(factory: super::Factory) { + let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_eq!(gas_left, U256::from(74_966)); +} + +evm_test!{test_sdiv: test_sdiv_jit, test_sdiv_int} +fn test_sdiv(factory: super::Factory) { + let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_eq!(gas_left, U256::from(74_966)); +} + +evm_test!{test_exp: test_exp_jit, test_exp_int} +fn test_exp(factory: super::Factory) { + let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000012365124623"); + assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_eq!(gas_left, U256::from(39_923)); +} + +evm_test!{test_comparison: test_comparison_jit, test_comparison_int} +fn test_comparison(factory: super::Factory) { + let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_eq!(gas_left, U256::from(49_952)); +} + +evm_test!{test_signed_comparison: test_signed_comparison_jit, test_signed_comparison_int} +fn test_signed_comparison(factory: super::Factory) { + let code = "60106000036010818112600055136001556010601060000381811260025513600355".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_eq!(gas_left, U256::from(49_940)); +} + +evm_test!{test_bitops: test_bitops_jit, test_bitops_int} +fn test_bitops(factory: super::Factory) { + let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(150_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0"); + assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000fff"); + assert_store(&ext, 2, "0000000000000000000000000000000000000000000000000000000000000f0f"); + assert_store(&ext, 3, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_store(&ext, 4, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_store(&ext, 5, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert_eq!(gas_left, U256::from(44_937)); +} + +evm_test!{test_addmod_mulmod: test_addmod_mulmod_jit, test_addmod_mulmod_int} +fn test_addmod_mulmod(factory: super::Factory) { + let code = "60ff60f060108282820860005509600155600060f0601082828208196002550919600355".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001"); + assert_store(&ext, 1, "000000000000000000000000000000000000000000000000000000000000000f"); + assert_store(&ext, 2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert_store(&ext, 3, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert_eq!(gas_left, U256::from(19_914)); +} + +evm_test!{test_byte: test_byte_jit, test_byte_int} +fn test_byte(factory: super::Factory) { + let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); + assert_store(&ext, 1, "00000000000000000000000000000000000000000000000000000000000000ff"); + assert_eq!(gas_left, U256::from(74_976)); +} + +evm_test!{test_signextend: test_signextend_jit, test_signextend_int} +fn test_signextend(factory: super::Factory) { + let code = "610fff60020b60005560ff60200b600155".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff"); + assert_store(&ext, 1, "00000000000000000000000000000000000000000000000000000000000000ff"); + assert_eq!(gas_left, U256::from(59_972)); +} + +fn assert_store(ext: &FakeExt, pos: u64, val: &str) { + assert_eq!(ext.store.get(&H256::from(pos)).unwrap(), &H256::from_str(val).unwrap()); } From 270c6c18975196498fc41850cc79e82edba414b0 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Tue, 2 Feb 2016 18:16:24 +0100 Subject: [PATCH 09/13] Adding pop & badinstruction tests --- ethcore/src/evm/tests.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index bf0480f47..292a0d869 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -746,6 +746,44 @@ fn test_signextend(factory: super::Factory) { assert_eq!(gas_left, U256::from(59_972)); } + +evm_test!{test_badinstruction: test_badinstruction_jit, test_badinstruction_int} +fn test_badinstruction(factory: super::Factory) { + let code = "af".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let err = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap_err() + }; + + match err { + evm::Error::BadInstruction { instruction: 0xaf } => (), + _ => assert!(false, "Expected bad instruction") + } +} +evm_test!{test_pop: test_pop_jit, test_pop_int} +fn test_pop(factory: super::Factory) { + let code = "60f060aa50600055".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(code); + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = factory.create(); + vm.exec(params, &mut ext).unwrap() + }; + + assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0"); + assert_eq!(gas_left, U256::from(79_989)); +} + fn assert_store(ext: &FakeExt, pos: u64, val: &str) { assert_eq!(ext.store.get(&H256::from(pos)).unwrap(), &H256::from_str(val).unwrap()); } From 77794bc4b3be702b72e70c9144e59fee15efe891 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 2 Feb 2016 19:40:45 +0100 Subject: [PATCH 10/13] Add installation dependencies script. --- install-deps.sh | 466 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100755 install-deps.sh diff --git a/install-deps.sh b/install-deps.sh new file mode 100755 index 000000000..b10d373b7 --- /dev/null +++ b/install-deps.sh @@ -0,0 +1,466 @@ +#!/usr/bin/env bash + +function run_installer() +{ + ####### Init vars + + HOMEBREW_PREFIX=/usr/local + HOMEBREW_CACHE=/Library/Caches/Homebrew + HOMEBREW_REPO=https://github.com/Homebrew/homebrew + OSX_REQUIERED_VERSION="10.7.0" + + + declare OS_TYPE + declare OSX_VERSION + declare GIT_PATH + declare RUBY_PATH + declare BREW_PATH + declare INSTALL_FILES="" + + errorMessages="" + isOsVersion=false + isGit=false + isRuby=false + isBrew=false + canContinue=true + depCount=0 + depFound=0 + + + + ####### Setup colors + + red=`tput setaf 1` + green=`tput setaf 2` + yellow=`tput setaf 3` + blue=`tput setaf 4` + magenta=`tput setaf 5` + cyan=`tput setaf 6` + white=`tput setaf 7` + b=`tput bold` + u=`tput sgr 0 1` + ul=`tput smul` + xl=`tput rmul` + stou=`tput smso` + xtou=`tput rmso` + dim=`tput dim` + reverse=`tput rev` + reset=`tput sgr0` + + + function head() { + echo "${blue}${b}==>${white} $1${reset}" + } + + function info() { + echo "${blue}${b}==>${reset} $1" + } + + function successHeading() { + echo "${green}${b}==> $1${reset}" + } + + function success() { + echo "${green}${b}==>${reset}${green} $1${reset}" + } + + function error() { + echo "${red}==> ${u}${b}${red}$1${reset}" + } + + function smallError() { + echo "${red}==>${reset} $1" + } + + function green() { + echo "${green}$1${reset}" + } + + function red() { + echo "${red}$1${reset}" + } + + function check() { + echo "${green}${bold} ✓${reset} $1${reset}" + } + + function uncheck() { + echo "${red}${bold} ✘${reset} $1${reset}" + } + + + + ####### Setup methods + + function wait_for_user() { + while : + do + read -p "${blue}==>${reset} $1 [Y/n] " imp + case $imp in + [yY] ) echo; break ;; + '' ) echo; break ;; + [nN] ) abortInstall "${red}==>${reset} Process stopped by user. To resume the install run the one-liner command again." ;; + * ) echo "Unrecognized option provided. Please provide either 'Y' or 'N'"; + esac + done + } + + + + function exe() { + echo "\$ $@"; "$@" + } + + function detectOS() { + if [[ "$OSTYPE" == "linux-gnu" ]] + then + OS_TYPE="linux" + get_linux_dependencies + elif [[ "$OSTYPE" == "darwin"* ]] + then + OS_TYPE="osx" + get_osx_dependencies + else + OS_TYPE="win" + abortInstall "${red}==>${reset} ${b}OS not supported:${reset} parity one-liner currently support OS X and Linux.\nFor instructions on installing parity on other platforms please visit ${u}${blue}http://ethcore.io/${reset}" + fi + + echo + + if [[ $depCount == $depFound ]] + then + green "Found all dependencies ($depFound/$depCount)" + else + if [[ $canContinue == true ]] + then + red "Some dependencies are missing ($depFound/$depCount)" + elif [[ $canContinue == false && $depFound == 0 ]] + then + red "All dependencies are missing and cannot be auto-installed ($depFound/$depCount)" + abortInstall "$errorMessages"; + elif [[ $canContinue == false ]] + then + red "Some dependencies which cannot be auto-installed are missing ($depFound/$depCount)" + abortInstall "$errorMessages"; + fi + fi + } + + function get_osx_dependencies() + { + macos_version + find_git + find_ruby + find_brew + } + + function macos_version() + { + declare -a reqVersion + declare -a localVersion + + depCount=$((depCount+1)) + OSX_VERSION=`/usr/bin/sw_vers -productVersion 2>/dev/null` + + if [ -z "$OSX_VERSION" ] + then + uncheck "OS X version not supported 🔥" + isOsVersion=false + canContinue=false + else + IFS='.' read -a localVersion <<< "$OSX_VERSION" + IFS='.' read -a reqVersion <<< "$OSX_REQUIERED_VERSION" + + if (( ${reqVersion[0]} <= ${localVersion[0]} )) && (( ${reqVersion[1]} <= ${localVersion[1]} )) + then + check "OS X Version ${OSX_VERSION}" + isOsVersion=true + depFound=$((depFound+1)) + return + else + uncheck "OS X version not supported" + isOsVersion=false + canContinue=false + fi + fi + + errorMessages+="${red}==>${reset} ${b}Mac OS version too old:${reset} eth requires OS X version ${red}$OSX_REQUIERED_VERSION${reset} at least in order to run.\n" + errorMessages+=" Please update the OS and reload the install process.\n" + } + + function find_eth() + { + ETH_PATH=`which eth 2>/dev/null` + + if [[ -f $ETH_PATH ]] + then + check "Found eth: $ETH_PATH" + echo "$($ETH_PATH -V)" + isEth=true + else + uncheck "Eth is missing" + isEth=false + fi + } + + function find_git() + { + depCount=$((depCount+1)) + + GIT_PATH=`which git 2>/dev/null` + + if [[ -f $GIT_PATH ]] + then + check "$($GIT_PATH --version)" + isGit=true + depFound=$((depFound+1)) + else + uncheck "Git is missing" + isGit=false + fi + } + + function find_ruby() + { + depCount=$((depCount+1)) + + RUBY_PATH=`which ruby 2>/dev/null` + + if [[ -f $RUBY_PATH ]] + then + RUBY_VERSION=`ruby -e "print RUBY_VERSION"` + check "Ruby ${RUBY_VERSION}" + isRuby=true + depFound=$((depFound+1)) + else + uncheck "Ruby is missing 🔥" + isRuby=false + canContinue=false + errorMessages+="${red}==>${reset} ${b}Couldn't find Ruby:${reset} Brew requires Ruby which could not be found.\n" + errorMessages+=" Please install Ruby using these instructions ${u}${blue}https://www.ruby-lang.org/en/documentation/installation/${reset}.\n" + fi + } + + function find_brew() + { + BREW_PATH=`which brew 2>/dev/null` + + if [[ -f $BREW_PATH ]] + then + check "$($BREW_PATH -v)" + isBrew=true + depFound=$((depFound+1)) + else + uncheck "Homebrew is missing" + isBrew=false + + INSTALL_FILES+="${blue}${dim}==> Homebrew:${reset}\n" + INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/bin/brew\n" + INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/Library\n" + INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/share/man/man1/brew.1\n" + fi + + depCount=$((depCount+1)) + } + + function install_brew() + { + if [[ $isBrew == false ]] + then + head "Installing Homebrew" + + if [[ $isRuby == true ]] + then + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + else + cd /usr + + if [[ ! -d $HOMEBREW_PREFIX ]] + then + sudo mkdir $HOMEBREW_PREFIX + sudo chmod g+rwx $HOMEBREW_PREFIX + fi + + if [[ ! -d $HOMEBREW_CACHE ]] + then + sudo mkdir $HOMEBREW_CACHE + sudo chmod g+rwx $HOMEBREW_CACHE + fi + + DEVELOPER_DIR=`/usr/bin/xcode-select -print-path 2>/dev/null` + + if [[ ! $(ls -A $DEVELOPER_DIR) || ! -f $DEVELOPER_DIR/usr/bin/git ]] + then + info "Installing the Command Line Tools (expect a GUI popup):" + sudo /usr/bin/xcode-select --install + + echo "Press any key when the installation has completed" + fi + + cd $HOMEBREW_PREFIX + + bash -o pipefail -c "curl -fsSL ${HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1" + fi + + find_brew + echo + + if [[ $isBrew == false ]] + then + abortInstall "Couldn't install brew" + fi + fi + } + + function osx_installer() + { + osx_dependency_installer + + info "Updating brew" + exe brew update + echo + + info "Installing rocksdb" + exe brew install rocksdb + info "Installing multirust" + exe brew install multirust + sudo multirust update nightly + sudo multirust default nightly + echo + } + + function osx_dependency_installer() + { + if [[ $isGit == false ]]; + then + echo "Installing Git" + fi + + if [[ $isRuby == false ]]; + then + echo "Installing Ruby" + fi + + if [[ $isBrew == false ]]; + then + install_brew + fi + } + + function get_linux_dependencies() + { + find_apt + } + + function find_apt() + { + APT_PATH=`which apt-get 2>/dev/null` + + if [[ -f $APT_PATH ]] + then + check "apt-get" + echo "$($APT_PATH -v)" + isApt=true + else + uncheck "apt-get is missing" + isApt=false + fi + } + function linux_rocksdb_installer() + { + oldpwd=`pwd` + cd /tmp + exe git clone --branch v4.1 --depth=1 https://github.com/facebook/rocksdb.git + cd rocksdb + exe make shared_lib + sudo cp -a librocksdb.so* /usr/lib + sudo ldconfig + cd /tmp + rm -rf /tmp/rocksdb + cd $oldpwd + } + + function linux_installer() + { + info "Installing git" + sudo apt-get install -q -y git + echo + + info "Installing rocksdb" + linux_rocksdb_installer + echo + + info "Installing multirust" + curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes + sudo multirust update nightly + sudo multirust default nightly + echo + } + + function install() + { + echo + head "Installing Parity build dependencies" + + if [[ $OS_TYPE == "osx" ]] + then + osx_installer + elif [[ $OS_TYPE == "linux" ]] + then + linux_installer + fi + } + + function verify_installation() + { + info "Verifying installation" +# find_eth + +# if [[ $isEth == false ]] +# then +# abortInstall +# fi + } + + function abortInstall() + { + echo + error "Installation failed" + echo -e "$1" + echo + exit 0 + } + + function finish() + { +# echo +# successHeading "Installation successful!" +# head "Next steps" +# info "Run ${cyan}\`\`${reset} to get started.${reset}" +# echo + exit 0 + } + + # Check dependencies + head "Checking OS dependencies" + detectOS + + echo + head "In addition to the parity build dependencies, this script will install:" + echo "$INSTALL_FILES" + echo + + # Prompt user to continue or abort + wait_for_user "${b}OK,${reset} let's go!" + + # Install dependencies and eth + install + + # Check installation + verify_installation + + # Display goodby message + finish +} + +run_installer \ No newline at end of file From 05e86ca63c69ca52ce5f35d3f8345b4deeff55fb Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 2 Feb 2016 20:58:12 +0100 Subject: [PATCH 11/13] Peers keep-alive --- util/src/network/connection.rs | 6 ++++ util/src/network/error.rs | 2 +- util/src/network/host.rs | 16 ++++++++++ util/src/network/session.rs | 58 ++++++++++++++++++++++++++++------ 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index 7ed8c3c18..d7bfe5284 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -207,6 +207,12 @@ pub struct EncryptedConnection { } impl EncryptedConnection { + + /// Get socket token + pub fn token(&self) -> StreamToken { + self.connection.token + } + /// Create an encrypted connection out of the handshake. Consumes a handshake object. pub fn new(mut handshake: Handshake) -> Result { let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_public)); diff --git a/util/src/network/error.rs b/util/src/network/error.rs index f03e128e6..78f015c37 100644 --- a/util/src/network/error.rs +++ b/util/src/network/error.rs @@ -15,7 +15,7 @@ pub enum DisconnectReason _ClientQuit, _UnexpectedIdentity, _LocalIdentity, - _PingTimeout, + PingTimeout, } #[derive(Debug)] diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 7fe4937e4..01df8bc41 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -346,6 +346,7 @@ impl Host where Message: Send + Sync + Clone { } fn maintain_network(&self, io: &IoContext>) { + self.keep_alive(io); self.connect_peers(io); } @@ -357,6 +358,21 @@ impl Host where Message: Send + Sync + Clone { self.connections.read().unwrap().iter().any(|e| match *e.lock().unwrap().deref() { ConnectionEntry::Handshake(ref h) => h.id.eq(&id), _ => false }) } + fn keep_alive(&self, io: &IoContext>) { + let mut to_kill = Vec::new(); + for e in self.connections.write().unwrap().iter_mut() { + if let ConnectionEntry::Session(ref mut s) = *e.lock().unwrap().deref_mut() { + if !s.keep_alive() { + s.disconnect(DisconnectReason::PingTimeout); + to_kill.push(s.token()); + } + } + } + for p in to_kill { + self.kill_connection(p, io); + } + } + fn connect_peers(&self, io: &IoContext>) { struct NodeInfo { id: NodeId, diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 20a9c9a48..41e8e9c5d 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -4,10 +4,14 @@ use rlp::*; use network::connection::{EncryptedConnection, Packet}; use network::handshake::Handshake; use error::*; -use io::{IoContext}; +use io::{IoContext, StreamToken}; use network::error::{NetworkError, DisconnectReason}; use network::host::*; use network::node::NodeId; +use time; + +const PING_TIMEOUT_SEC: u64 = 30; +const PING_INTERVAL_SEC: u64 = 30; /// Peer session over encrypted connection. /// When created waits for Hello packet exchange and signals ready state. @@ -19,6 +23,8 @@ pub struct Session { connection: EncryptedConnection, /// Session ready flag. Set after successfull Hello packet exchange had_hello: bool, + ping_time_ns: u64, + pong_time_ns: Option, } /// Structure used to report various session events. @@ -47,6 +53,8 @@ pub struct SessionInfo { pub protocol_version: u32, /// Peer protocol capabilities capabilities: Vec, + /// Peer ping delay in milliseconds + pub ping_ms: Option, } #[derive(Debug, PartialEq, Eq)] @@ -95,10 +103,13 @@ impl Session { client_version: String::new(), protocol_version: 0, capabilities: Vec::new(), + ping_ms: None, }, + ping_time_ns: 0, + pong_time_ns: None, }; try!(session.write_hello(host)); - try!(session.write_ping()); + try!(session.send_ping()); Ok(session) } @@ -141,7 +152,7 @@ impl Session { while protocol != self.info.capabilities[i].protocol { i += 1; if i == self.info.capabilities.len() { - debug!(target: "net", "Unkown protocol: {:?}", protocol); + debug!(target: "net", "Unknown protocol: {:?}", protocol); return Ok(()) } } @@ -152,6 +163,26 @@ impl Session { self.connection.send_packet(&rlp.out()) } + /// Keep this session alive. Returns false if ping timeout happened + pub fn keep_alive(&mut self) -> bool { + let timed_out = if let Some(pong) = self.pong_time_ns { + pong - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000 + } else { + time::precise_time_ns() - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000 + }; + + if !timed_out && time::precise_time_ns() - self.ping_time_ns > PING_INTERVAL_SEC * 1000_000_000 { + if let Err(e) = self.send_ping() { + debug!("Error sending ping message: {:?}", e); + } + } + !timed_out + } + + pub fn token(&self) -> StreamToken { + self.connection.token() + } + fn read_packet(&mut self, packet: Packet, host: &HostInfo) -> Result { if packet.data.len() < 2 { return Err(From::from(NetworkError::BadProtocol)); @@ -168,7 +199,12 @@ impl Session { }, PACKET_DISCONNECT => Err(From::from(NetworkError::Disconnect(DisconnectReason::DisconnectRequested))), PACKET_PING => { - try!(self.write_pong()); + try!(self.send_pong()); + Ok(SessionData::None) + }, + PACKET_PONG => { + self.pong_time_ns = Some(time::precise_time_ns()); + self.info.ping_ms = Some((self.pong_time_ns.unwrap() - self.ping_time_ns) / 1000_000); Ok(SessionData::None) }, PACKET_GET_PEERS => Ok(SessionData::None), //TODO; @@ -178,7 +214,7 @@ impl Session { while packet_id < self.info.capabilities[i].id_offset { i += 1; if i == self.info.capabilities.len() { - debug!(target: "net", "Unkown packet: {:?}", packet_id); + debug!(target: "net", "Unknown packet: {:?}", packet_id); return Ok(SessionData::None) } } @@ -189,7 +225,7 @@ impl Session { Ok(SessionData::Packet { data: packet.data, protocol: protocol, packet_id: pid } ) }, _ => { - debug!(target: "net", "Unkown packet: {:?}", packet_id); + debug!(target: "net", "Unknown packet: {:?}", packet_id); Ok(SessionData::None) } } @@ -255,11 +291,15 @@ impl Session { Ok(()) } - fn write_ping(&mut self) -> Result<(), UtilError> { - self.send(try!(Session::prepare(PACKET_PING))) + /// Senf ping packet + pub fn send_ping(&mut self) -> Result<(), UtilError> { + try!(self.send(try!(Session::prepare(PACKET_PING)))); + self.ping_time_ns = time::precise_time_ns(); + self.pong_time_ns = None; + Ok(()) } - fn write_pong(&mut self) -> Result<(), UtilError> { + fn send_pong(&mut self) -> Result<(), UtilError> { self.send(try!(Session::prepare(PACKET_PONG))) } From 6e717c017fa8f8cf01f4cf1c39b7a00109cde008 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 2 Feb 2016 21:06:21 +0100 Subject: [PATCH 12/13] Fixed queue test --- ethcore/src/block_queue.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index 1c0cc41ae..1fe31ba19 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -316,6 +316,7 @@ mod tests { use block_queue::*; use tests::helpers::*; use error::*; + use views::*; fn get_test_queue() -> BlockQueue { let spec = get_test_spec(); @@ -361,11 +362,14 @@ mod tests { #[test] fn returns_ok_for_drained_duplicates() { let mut queue = get_test_queue(); - if let Err(e) = queue.import_block(get_good_dummy_block()) { + let block = get_good_dummy_block(); + let hash = BlockView::new(&block).header().hash().clone(); + if let Err(e) = queue.import_block(block) { panic!("error importing block that is valid by definition({:?})", e); } queue.flush(); queue.drain(10); + queue.mark_as_good(&[ hash ]); if let Err(e) = queue.import_block(get_good_dummy_block()) { panic!("error importing block that has already been drained ({:?})", e); From da52fee2b3c0f0fffe065690264740e25939ca2d Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 2 Feb 2016 21:10:16 +0100 Subject: [PATCH 13/13] Simplified Disconnect struct --- util/src/network/host.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 01df8bc41..5a572dcae 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -110,10 +110,7 @@ pub enum NetworkIoMessage where Message: Send + Sync + Clone { delay: u64, }, /// Disconnect a peer - Disconnect { - /// Peer Id - peer: PeerId, - }, + Disconnect(PeerId), /// User message User(Message), } @@ -194,9 +191,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone /// Disconnect peer. Reconnect can be attempted later. pub fn disconnect_peer(&self, peer: PeerId) { - self.io.message(NetworkIoMessage::Disconnect { - peer: peer, - }); + self.io.message(NetworkIoMessage::Disconnect(peer)); } /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. @@ -714,9 +709,7 @@ impl IoHandler> for Host where Messa self.timers.write().unwrap().insert(handler_token, ProtocolTimer { protocol: protocol, token: *token }); io.register_timer(handler_token, *delay).expect("Error registering timer"); }, - NetworkIoMessage::Disconnect { - ref peer, - } => { + NetworkIoMessage::Disconnect(ref peer) => { if let Some(connection) = self.connections.read().unwrap().get(*peer).cloned() { match *connection.lock().unwrap().deref_mut() { ConnectionEntry::Handshake(_) => {},