diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index 27d240fed..5e73681a5 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -70,9 +70,6 @@ const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5); const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3; const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60); -/// Max number of transactions in a single packet. -const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64; - // minimum interval between updates. const UPDATE_INTERVAL: Duration = Duration::from_millis(5000); @@ -648,7 +645,7 @@ impl LightProtocol { fn propagate_transactions(&self, io: &IoContext) { if self.capabilities.read().tx_relay { return } - let ready_transactions = self.provider.ready_transactions(MAX_TRANSACTIONS_TO_PROPAGATE); + let ready_transactions = self.provider.transactions_to_propagate(); if ready_transactions.is_empty() { return } trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len()); diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index 0c9971d75..6bc6751b1 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -171,8 +171,8 @@ impl Provider for TestProvider { }) } - fn ready_transactions(&self, max_len: usize) -> Vec { - self.0.client.ready_transactions(max_len) + fn transactions_to_propagate(&self) -> Vec { + self.0.client.transactions_to_propagate() } } diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 84e7b7283..a066cefb5 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -128,7 +128,7 @@ pub trait Provider: Send + Sync { fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option; /// Provide pending transactions. - fn ready_transactions(&self, max_len: usize) -> Vec; + fn transactions_to_propagate(&self) -> Vec; /// Provide a proof-of-execution for the given transaction proof request. /// Returns a vector of all state items necessary to execute the transaction. @@ -283,8 +283,8 @@ impl Provider for T { .map(|(_, proof)| ::request::ExecutionResponse { items: proof }) } - fn ready_transactions(&self, max_len: usize) -> Vec { - BlockChainClient::ready_transactions(self, max_len) + fn transactions_to_propagate(&self) -> Vec { + BlockChainClient::transactions_to_propagate(self) .into_iter() .map(|tx| tx.pending().clone()) .collect() @@ -370,12 +370,10 @@ impl Provider for LightProvider { None } - fn ready_transactions(&self, max_len: usize) -> Vec { + fn transactions_to_propagate(&self) -> Vec { let chain_info = self.chain_info(); - let mut transactions = self.txqueue.read() - .ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp); - transactions.truncate(max_len); - transactions + self.txqueue.read() + .ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 02af5ff0a..3a7fd0d0c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::collections::{HashSet, BTreeMap, VecDeque}; +use std::cmp; use std::fmt; use std::str::FromStr; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; @@ -1945,7 +1946,25 @@ impl BlockChainClient for Client { (*self.build_last_hashes(&self.chain.read().best_block_hash())).clone() } - fn ready_transactions(&self, max_len: usize) -> Vec> { + fn transactions_to_propagate(&self) -> Vec> { + const PROPAGATE_FOR_BLOCKS: u32 = 4; + const MIN_TX_TO_PROPAGATE: usize = 256; + + let block_gas_limit = *self.best_block_header().gas_limit(); + let min_tx_gas: U256 = self.latest_schedule().tx_gas.into(); + + let max_len = if min_tx_gas.is_zero() { + usize::max_value() + } else { + cmp::max( + MIN_TX_TO_PROPAGATE, + cmp::min( + (block_gas_limit / min_tx_gas) * PROPAGATE_FOR_BLOCKS, + // never more than usize + usize::max_value().into() + ).as_u64() as usize + ) + }; self.importer.miner.ready_transactions(self, max_len, ::miner::PendingOrdering::Priority) } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 627d844ae..f729b15b7 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -807,8 +807,8 @@ impl BlockChainClient for TestBlockChainClient { self.traces.read().clone() } - fn ready_transactions(&self, max_len: usize) -> Vec> { - self.miner.ready_transactions(self, max_len, miner::PendingOrdering::Priority) + fn transactions_to_propagate(&self) -> Vec> { + self.miner.ready_transactions(self, 4096, miner::PendingOrdering::Priority) } fn signing_chain_id(&self) -> Option { None } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 3f5595f61..6ccba5e0f 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -321,8 +321,8 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get last hashes starting from best block. fn last_hashes(&self) -> LastHashes; - /// List all transactions that are allowed into the next block. - fn ready_transactions(&self, max_len: usize) -> Vec>; + /// List all ready transactions that should be propagated to other peers. + fn transactions_to_propagate(&self) -> Vec>; /// Sorted list of transaction gas prices from at least last sample_size blocks. fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus { diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 4031d30b0..24801cb57 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -316,11 +316,11 @@ fn does_not_propagate_delayed_transactions() { client.miner().import_own_transaction(&*client, tx0).unwrap(); client.miner().import_own_transaction(&*client, tx1).unwrap(); - assert_eq!(0, client.ready_transactions(10).len()); + assert_eq!(0, client.transactions_to_propagate().len()); assert_eq!(0, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len()); push_blocks_to_client(&client, 53, 2, 2); client.flush_queue(); - assert_eq!(2, client.ready_transactions(10).len()); + assert_eq!(2, client.transactions_to_propagate().len()); assert_eq!(2, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len()); } diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index ef5146f91..520226a9c 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -149,12 +149,6 @@ const MAX_NEW_HASHES: usize = 64; const MAX_NEW_BLOCK_AGE: BlockNumber = 20; // maximal packet size with transactions (cannot be greater than 16MB - protocol limitation). const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024; -// Maximal number of transactions queried from miner to propagate. -// This set is used to diff with transactions known by the peer and -// we will send a difference of length up to `MAX_TRANSACTIONS_TO_PROPAGATE`. -const MAX_TRANSACTIONS_TO_QUERY: usize = 4096; -// Maximal number of transactions in sent in single packet. -const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64; // Min number of blocks to be behind for a snapshot sync const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000; const SNAPSHOT_MIN_PEERS: usize = 3; diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index ef5e700bf..7cb145f36 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -29,11 +29,9 @@ use transaction::SignedTransaction; use super::{ random, ChainSync, + MAX_TRANSACTION_PACKET_SIZE, MAX_PEER_LAG_PROPAGATION, MAX_PEERS_PROPAGATION, - MAX_TRANSACTION_PACKET_SIZE, - MAX_TRANSACTIONS_TO_PROPAGATE, - MAX_TRANSACTIONS_TO_QUERY, MIN_PEERS_PROPAGATION, CONSENSUS_DATA_PACKET, NEW_BLOCK_HASHES_PACKET, @@ -121,7 +119,7 @@ impl SyncPropagator { return 0; } - let transactions = io.chain().ready_transactions(MAX_TRANSACTIONS_TO_QUERY); + let transactions = io.chain().transactions_to_propagate(); if transactions.is_empty() { return 0; } @@ -184,7 +182,6 @@ impl SyncPropagator { // Get hashes of all transactions to send to this peer let to_send = all_transactions_hashes.difference(&peer_info.last_sent_transactions) - .take(MAX_TRANSACTIONS_TO_PROPAGATE) .cloned() .collect::>(); if to_send.is_empty() {