Trigger remove_old on new block

This commit is contained in:
Tomasz Drwięga
2016-12-09 15:54:13 +01:00
parent 5d054f08c3
commit cee07fef74
2 changed files with 48 additions and 54 deletions

View File

@@ -79,10 +79,10 @@
//! we check if the transactions should go to `current` (comparing state nonce)
//! - When it's removed from `current` - all transactions from this sender (`current` & `future`) are recalculated.
//! 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)
//! - 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 as convenient method to update the state nonce for all senders in the queue.
//! - Invokes `remove_all` with latest state nonce for all senders.
use std::ops::Deref;
use std::cmp::Ordering;
@@ -754,6 +754,21 @@ impl TransactionQueue {
/// Removes all transactions from particular sender up to (excluding) given client (state) nonce.
/// Client (State) Nonce = next valid nonce for this sender.
pub fn remove_all(&mut self, sender: Address, client_nonce: U256) {
// Check if there is anything in current...
let should_check_in_current = self.current.by_address.row(&sender)
// If nonce == client_nonce nothing is changed
.and_then(|by_nonce| by_nonce.keys().find(|nonce| *nonce < &client_nonce))
.map(|_| ());
// ... or future
let should_check_in_future = self.future.by_address.row(&sender)
// if nonce == client_nonce we need to promote to current
.and_then(|by_nonce| by_nonce.keys().find(|nonce| *nonce <= &client_nonce))
.map(|_| ());
if should_check_in_current.or(should_check_in_future).is_none() {
return;
}
// We will either move transaction to future or remove it completely
// so there will be no transactions from this sender in current
self.last_nonces.remove(&sender);
@@ -768,16 +783,16 @@ impl TransactionQueue {
}
/// Checks the current nonce for all transactions' senders in the queue and removes the old transactions.
pub fn remove_old<F>(&mut self, fetch_account: &F) where
F: Fn(&Address) -> AccountDetails,
pub fn remove_old<F>(&mut self, fetch_nonce: F) where
F: Fn(&Address) -> U256,
{
let senders = self.current.by_address
.keys()
.map(|key| (*key, fetch_account(key).nonce))
.collect::<Vec<_>>();
let senders = self.current.by_address.keys()
.chain(self.future.by_address.keys())
.cloned()
.collect::<HashSet<_>>();
for (sender, nonce) in senders {
self.remove_all(sender, nonce);
for sender in senders {
self.remove_all(sender, fetch_nonce(&sender));
}
}
@@ -2480,7 +2495,6 @@ mod test {
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();
@@ -2490,7 +2504,7 @@ mod test {
assert_eq!(txq.top_transactions().len(), 4);
// when
txq.remove_old(&new_details);
txq.remove_old(|_| nonce1 + U256::one());
// then
assert_eq!(txq.top_transactions().len(), 2);