diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index cd2d3ba47..84981b893 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -81,6 +81,8 @@ //! 3. `remove_all` is used to inform the queue about client (state) nonce changes. //! - It removes all transactions (either from `current` or `future`) with nonce < client nonce //! - It moves matching `future` transactions to `current` +//! 4. `remove_old` is used periodically to clear the transactions if node goes out of sync +//! (in such case `remove_all` is not invoked because we are syncing the chain) use std::ops::Deref; use std::cmp::Ordering; @@ -765,6 +767,20 @@ impl TransactionQueue { assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); } + /// Checks the current nonce for all transactions' senders in the queue and removes the old transactions. + pub fn remove_old(&mut self, fetch_account: &F) where + F: Fn(&Address) -> AccountDetails, + { + let senders = self.current.by_address + .keys() + .map(|key| (*key, fetch_account(key).nonce)) + .collect::>(); + + for (sender, nonce) in senders { + self.remove_all(sender, nonce); + } + } + /// Penalize transactions from sender of transaction with given hash. /// I.e. it should change the priority of the transaction in the queue. /// @@ -2438,7 +2454,7 @@ mod test { } #[test] - fn should_reject_transactions_below_bas_gas() { + fn should_reject_transactions_below_base_gas() { // given let mut txq = TransactionQueue::default(); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); @@ -2457,4 +2473,27 @@ mod test { } + #[test] + fn should_clear_all_old_transactions() { + // given + let mut txq = TransactionQueue::default(); + let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); + let (tx3, tx4) = new_tx_pair_default(1.into(), 0.into()); + let nonce1 = tx1.nonce; + let new_details = |_a: &Address| AccountDetails { nonce: nonce1 + U256::one(), balance: !U256::zero() }; + + // Insert all transactions + txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + assert_eq!(txq.top_transactions().len(), 4); + + // when + txq.remove_old(&new_details); + + // then + assert_eq!(txq.top_transactions().len(), 2); + } + } diff --git a/util/table/src/lib.rs b/util/table/src/lib.rs index a13beab11..f65c1e171 100644 --- a/util/table/src/lib.rs +++ b/util/table/src/lib.rs @@ -18,6 +18,7 @@ use std::hash::Hash; use std::collections::HashMap; +use std::collections::hash_map::Keys; /// Structure to hold double-indexed values /// @@ -41,6 +42,11 @@ impl Table } } + /// Returns keys iterator for this Table. + pub fn keys(&self) -> Keys> { + self.map.keys() + } + /// Removes all elements from this Table pub fn clear(&mut self) { self.map.clear();