diff --git a/Cargo.lock b/Cargo.lock index 93fc870e5..f5ec079c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "parity" -version = "1.4.7" +version = "1.4.8" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", @@ -21,7 +21,7 @@ dependencies = [ "ethcore-rpc 1.4.0", "ethcore-signer 1.4.0", "ethcore-stratum 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "ethsync 1.4.0", "fdlimit 0.1.0", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -289,7 +289,7 @@ dependencies = [ "ethcore-ipc 1.4.0", "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "ethjson 0.1.0", "ethkey 0.2.0", "ethstore 0.1.0", @@ -336,7 +336,7 @@ dependencies = [ "ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-devtools 1.4.0", "ethcore-rpc 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "fetch 0.1.0", "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -381,7 +381,7 @@ name = "ethcore-ipc" version = "1.4.0" dependencies = [ "ethcore-devtools 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -428,7 +428,7 @@ dependencies = [ "ethcore-ipc 1.4.0", "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -439,7 +439,7 @@ name = "ethcore-logger" version = "1.4.0" dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -455,7 +455,7 @@ dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-devtools 1.4.0", "ethcore-io 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "ethcrypto 0.1.0", "ethkey 0.2.0", "igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -482,7 +482,7 @@ dependencies = [ "ethcore-devtools 1.4.0", "ethcore-io 1.4.0", "ethcore-ipc 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "ethcrypto 0.1.0", "ethjson 0.1.0", "ethkey 0.2.0", @@ -511,7 +511,7 @@ dependencies = [ "ethcore-devtools 1.4.0", "ethcore-io 1.4.0", "ethcore-rpc 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -530,7 +530,7 @@ dependencies = [ "ethcore-ipc 1.4.0", "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)", "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -541,7 +541,7 @@ dependencies = [ [[package]] name = "ethcore-util" -version = "1.4.7" +version = "1.4.8" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -590,7 +590,7 @@ dependencies = [ name = "ethjson" version = "0.1.0" dependencies = [ - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -643,7 +643,7 @@ dependencies = [ "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", "ethcore-network 1.4.0", - "ethcore-util 1.4.7", + "ethcore-util 1.4.8", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 4d31b99b7..e92030081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore client." name = "parity" -version = "1.4.7" +version = "1.4.8" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index f2e33a344..a21f58f5c 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -18,7 +18,7 @@ "ecip1010ContinueTransition": 5000000, "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff" } } }, diff --git a/ethcore/src/client/chain_notify.rs b/ethcore/src/client/chain_notify.rs index e0282d460..eb695e063 100644 --- a/ethcore/src/client/chain_notify.rs +++ b/ethcore/src/client/chain_notify.rs @@ -40,6 +40,14 @@ pub trait ChainNotify : Send + Sync { fn stop(&self) { // does nothing by default } + + /// fires when new transactions are received from a peer + fn transactions_received(&self, + _hashes: Vec, + _peer_id: usize, + ) { + // does nothing by default + } } impl IpcConfig for ChainNotify { } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 4dc3e6345..ac7d8928c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -554,10 +554,15 @@ impl Client { } /// Import transactions from the IO queue - pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize { + pub fn import_queued_transactions(&self, transactions: &[Bytes], peer_id: usize) -> usize { + trace!(target: "external_tx", "Importing queued"); let _timer = PerfTimer::new("import_queued_transactions"); self.queue_transactions.fetch_sub(transactions.len(), AtomicOrdering::SeqCst); - let txs = transactions.iter().filter_map(|bytes| UntrustedRlp::new(bytes).as_val().ok()).collect(); + let txs: Vec = transactions.iter().filter_map(|bytes| UntrustedRlp::new(bytes).as_val().ok()).collect(); + let hashes: Vec<_> = txs.iter().map(|tx| tx.hash()).collect(); + self.notify(|notify| { + notify.transactions_received(hashes.clone(), peer_id); + }); let results = self.miner.import_external_transactions(self, txs); results.len() } @@ -1164,12 +1169,14 @@ impl BlockChainClient for Client { (*self.build_last_hashes(self.chain.read().best_block_hash())).clone() } - fn queue_transactions(&self, transactions: Vec) { - if self.queue_transactions.load(AtomicOrdering::Relaxed) > MAX_TX_QUEUE_SIZE { + fn queue_transactions(&self, transactions: Vec, peer_id: usize) { + let queue_size = self.queue_transactions.load(AtomicOrdering::Relaxed); + trace!(target: "external_tx", "Queue size: {}", queue_size); + if queue_size > MAX_TX_QUEUE_SIZE { debug!("Ignoring {} transactions: queue is full", transactions.len()); } else { let len = transactions.len(); - match self.io_channel.lock().send(ClientIoMessage::NewTransactions(transactions)) { + match self.io_channel.lock().send(ClientIoMessage::NewTransactions(transactions, peer_id)) { Ok(_) => { self.queue_transactions.fetch_add(len, AtomicOrdering::SeqCst); } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 19626d434..5f4b1ccfc 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -644,7 +644,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn queue_transactions(&self, transactions: Vec) { + fn queue_transactions(&self, transactions: Vec, _peer_id: usize) { // import right here let txs = transactions.into_iter().filter_map(|bytes| UntrustedRlp::new(&bytes).as_val().ok()).collect(); self.miner.import_external_transactions(self, txs); diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 513043cf2..e67088c21 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -188,7 +188,7 @@ pub trait BlockChainClient : Sync + Send { fn last_hashes(&self) -> LastHashes; /// Queue transactions for importing. - fn queue_transactions(&self, transactions: Vec); + fn queue_transactions(&self, transactions: Vec, peer_id: usize); /// list all transactions fn pending_transactions(&self) -> Vec; @@ -267,3 +267,4 @@ pub trait MiningBlockChainClient : BlockChainClient { } impl IpcConfig for BlockChainClient { } + diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 00ba981b9..6953e9344 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -39,7 +39,7 @@ pub enum ClientIoMessage { /// A block is ready BlockVerified, /// New transaction RLPs are ready to be imported - NewTransactions(Vec), + NewTransactions(Vec, usize), /// Begin snapshot restoration BeginRestoration(ManifestData), /// Feed a state chunk to the snapshot service @@ -192,7 +192,9 @@ impl IoHandler for ClientIoHandler { match *net_message { ClientIoMessage::BlockVerified => { self.client.import_verified_blocks(); } - ClientIoMessage::NewTransactions(ref transactions) => { self.client.import_queued_transactions(transactions); } + ClientIoMessage::NewTransactions(ref transactions, peer_id) => { + self.client.import_queued_transactions(transactions, peer_id); + } ClientIoMessage::BeginRestoration(ref manifest) => { if let Err(e) = self.snapshot.init_restore(manifest.clone(), true) { warn!("Failed to initialize snapshot restoration: {}", e); diff --git a/mac/Parity.pkgproj b/mac/Parity.pkgproj index 9d36961ac..4d9b9c25e 100755 --- a/mac/Parity.pkgproj +++ b/mac/Parity.pkgproj @@ -578,7 +578,7 @@ OVERWRITE_PERMISSIONS VERSION - 1.4.7 + 1.4.8 UUID 2DCD5B81-7BAF-4DA1-9251-6274B089FD36 diff --git a/nsis/installer.nsi b/nsis/installer.nsi index b8bf8e836..991a9476c 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -4,13 +4,13 @@ !define WND_TITLE "Parity" !define WAIT_MS 5000 !define SYNC_TERM 0x00100001 - + !define APPNAME "Parity" !define COMPANYNAME "Ethcore" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 !define VERSIONMINOR 4 -!define VERSIONBUILD 7 +!define VERSIONBUILD 8 !define ARGS "--warp" !define FIRST_START_ARGS "ui --warp --mode=passive" @@ -90,7 +90,7 @@ section "install" # Files added here should be removed by the uninstaller (see section "uninstall") file /oname=parity.exe ..\target\release\parity.exe file /oname=ptray.exe ..\windows\ptray\x64\Release\ptray.exe - + file "logo.ico" file vc_redist.x64.exe diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index e0f811fc0..b4fc1ae74 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -74,7 +74,7 @@ impl SyncProvider for TestSyncProvider { PeerInfo { id: Some("node1".to_owned()), client_version: "Parity/1".to_owned(), - capabilities: vec!["eth/62".to_owned(), "eth/63".to_owned()], + capabilities: vec!["eth/62".to_owned(), "eth/63".to_owned()], remote_address: "127.0.0.1:7777".to_owned(), local_address: "127.0.0.1:8888".to_owned(), eth_version: 62, @@ -84,7 +84,7 @@ impl SyncProvider for TestSyncProvider { PeerInfo { id: None, client_version: "Parity/2".to_owned(), - capabilities: vec!["eth/63".to_owned(), "eth/64".to_owned()], + capabilities: vec!["eth/63".to_owned(), "eth/64".to_owned()], remote_address: "Handshake".to_owned(), local_address: "127.0.0.1:3333".to_owned(), eth_version: 64, diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index b5c8187c7..0713b339d 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -355,3 +355,4 @@ fn rpc_parity_next_nonce() { assert_eq!(io1.handle_request_sync(&request), Some(response1.to_owned())); assert_eq!(io2.handle_request_sync(&request), Some(response2.to_owned())); } + diff --git a/sync/src/api.rs b/sync/src/api.rs index 1a33bc727..64e2c6806 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -73,7 +73,7 @@ pub trait SyncProvider: Send + Sync { /// Get peers information fn peers(&self) -> Vec; - + /// Get the enode if available. fn enode(&self) -> Option; } @@ -233,6 +233,10 @@ impl ChainNotify for EthSync { fn stop(&self) { self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e)); } + + fn transactions_received(&self, hashes: Vec, peer_id: PeerId) { + self.handler.sync.write().transactions_received(hashes, peer_id); + } } impl IpcConfig for ManageNetwork { } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 71a097c88..4b5edf1cf 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -438,6 +438,13 @@ impl ChainSync { .collect() } + /// Updates transactions were received by a peer + pub fn transactions_received(&mut self, hashes: Vec, peer_id: PeerId) { + if let Some(mut peer_info) = self.peers.get_mut(&peer_id) { + peer_info.last_sent_transactions.extend(&hashes); + } + } + /// Abort all sync activity pub fn abort(&mut self, io: &mut SyncIo) { self.reset_and_continue(io); @@ -1422,7 +1429,7 @@ impl ChainSync { } let mut item_count = r.item_count(); - trace!(target: "sync", "{} -> Transactions ({} entries)", peer_id, item_count); + trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count); item_count = min(item_count, MAX_TX_TO_IMPORT); let mut transactions = Vec::with_capacity(item_count); for i in 0 .. item_count { @@ -1434,7 +1441,7 @@ impl ChainSync { let tx = rlp.as_raw().to_vec(); transactions.push(tx); } - io.chain().queue_transactions(transactions); + io.chain().queue_transactions(transactions, peer_id); Ok(()) } @@ -1935,7 +1942,7 @@ impl ChainSync { // Send all transactions if peer_info.last_sent_transactions.is_empty() { peer_info.last_sent_transactions = all_transactions_hashes.clone(); - return Some((*peer_id, all_transactions_rlp.clone())); + return Some((*peer_id, all_transactions_hashes.len(), all_transactions_rlp.clone())); } // Get hashes of all transactions to send to this peer @@ -1953,20 +1960,22 @@ impl ChainSync { } peer_info.last_sent_transactions = all_transactions_hashes.clone(); - Some((*peer_id, packet.out())) + Some((*peer_id, to_send.len(), packet.out())) }) .collect::>(); // Send RLPs - let sent = lucky_peers.len(); - if sent > 0 { - for (peer_id, rlp) in lucky_peers { + let peers = lucky_peers.len(); + if peers > 0 { + let mut max_sent = 0; + for (peer_id, sent, rlp) in lucky_peers { self.send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp); + trace!(target: "sync", "{:02} <- Transactions ({} entries)", peer_id, sent); + max_sent = max(max_sent, sent); } - - trace!(target: "sync", "Sent up to {} transactions to {} peers.", transactions.len(), sent); + debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, peers); } - sent + peers } fn propagate_latest_blocks(&mut self, io: &mut SyncIo, sealed: &[H256]) { @@ -1986,7 +1995,6 @@ impl ChainSync { trace!(target: "sync", "Sent sealed block to all peers"); }; } - self.propagate_new_transactions(io); self.last_sent_block_number = chain_info.best_block_number; } @@ -1999,7 +2007,9 @@ impl ChainSync { /// called when block is imported to chain - propagates the blocks and updates transactions sent to peers pub fn chain_new_blocks(&mut self, io: &mut SyncIo, _imported: &[H256], invalid: &[H256], enacted: &[H256], _retracted: &[H256], sealed: &[H256]) { let queue_info = io.chain().queue_info(); - if !self.status().is_syncing(queue_info) || !sealed.is_empty() { + let is_syncing = self.status().is_syncing(queue_info); + + if !is_syncing || !sealed.is_empty() { trace!(target: "sync", "Propagating blocks, state={:?}", self.state); self.propagate_latest_blocks(io, sealed); } @@ -2008,7 +2018,7 @@ impl ChainSync { self.restart(io); } - if !enacted.is_empty() { + if !is_syncing && !enacted.is_empty() { // Select random peers to re-broadcast transactions to. let mut random = random::new(); let len = self.peers.len(); @@ -2358,7 +2368,7 @@ mod tests { } #[test] - fn should_not_propagate_transactions_again_after_new_block() { + fn does_not_propagate_new_transactions_after_new_block() { let mut client = TestBlockChainClient::new(); client.add_blocks(100, EachBlockWith::Uncle); client.insert_transaction_to_queue(); @@ -2367,6 +2377,8 @@ mod tests { let ss = TestSnapshotService::new(); let mut io = TestIo::new(&mut client, &ss, &mut queue, None); let peer_count = sync.propagate_new_transactions(&mut io); + // New block import should not trigger propagation. + // (we only propagate on timeout) sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[]); // Try to propagate same transactions for the second time let peer_count2 = sync.propagate_new_transactions(&mut io); diff --git a/util/Cargo.toml b/util/Cargo.toml index c55ba6ddf..dd40c2830 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore utility library" homepage = "http://ethcore.io" license = "GPL-3.0" name = "ethcore-util" -version = "1.4.7" +version = "1.4.8" authors = ["Ethcore "] build = "build.rs"