Removing old transactions from the queue (#4046)

* Removing old transactions from the queue

* Addressing grumbles
This commit is contained in:
Tomasz Drwięga 2017-01-05 21:16:52 +01:00 committed by Gav Wood
parent fbc9f0d7fb
commit eb0daea9b9
3 changed files with 255 additions and 179 deletions

View File

@ -23,6 +23,7 @@ use std::cell::Cell;
use transaction::{SignedTransaction, Action}; use transaction::{SignedTransaction, Action};
use transient_hashmap::TransientHashMap; use transient_hashmap::TransientHashMap;
use miner::{TransactionQueue, TransactionImportResult, TransactionOrigin, AccountDetails}; use miner::{TransactionQueue, TransactionImportResult, TransactionOrigin, AccountDetails};
use miner::transaction_queue::QueuingInstant;
use error::{Error, TransactionError}; use error::{Error, TransactionError};
use util::{Uint, U256, H256, Address, Hashable}; use util::{Uint, U256, H256, Address, Hashable};
@ -78,6 +79,7 @@ impl BanningTransactionQueue {
pub fn add_with_banlist<F, G>( pub fn add_with_banlist<F, G>(
&mut self, &mut self,
transaction: SignedTransaction, transaction: SignedTransaction,
time: QueuingInstant,
account_details: &F, account_details: &F,
gas_estimator: &G, gas_estimator: &G,
) -> Result<TransactionImportResult, Error> where ) -> Result<TransactionImportResult, Error> where
@ -115,7 +117,7 @@ impl BanningTransactionQueue {
} }
} }
} }
self.queue.add(transaction, TransactionOrigin::External, None, account_details, gas_estimator) self.queue.add(transaction, TransactionOrigin::External, time, None, account_details, gas_estimator)
} }
/// Ban transaction with given hash. /// Ban transaction with given hash.
@ -158,7 +160,7 @@ impl BanningTransactionQueue {
Threshold::BanAfter(threshold) if count > threshold => { Threshold::BanAfter(threshold) if count > threshold => {
// Banlist the sender. // Banlist the sender.
// Remove all transactions from the queue. // Remove all transactions from the queue.
self.remove_all(address, !U256::zero()); self.cull(address, !U256::zero());
true true
}, },
_ => false _ => false
@ -263,7 +265,7 @@ mod tests {
let mut txq = queue(); let mut txq = queue();
// when // when
txq.queue().add(tx, TransactionOrigin::External, None, &default_account_details, &gas_required).unwrap(); txq.queue().add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_required).unwrap();
// then // then
// should also deref to queue // should also deref to queue
@ -279,12 +281,12 @@ mod tests {
let banlist1 = txq.ban_sender(tx.sender().unwrap()); let banlist1 = txq.ban_sender(tx.sender().unwrap());
assert!(!banlist1, "Threshold not reached yet."); assert!(!banlist1, "Threshold not reached yet.");
// Insert once // Insert once
let import1 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required).unwrap(); let import1 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required).unwrap();
assert_eq!(import1, TransactionImportResult::Current); assert_eq!(import1, TransactionImportResult::Current);
// when // when
let banlist2 = txq.ban_sender(tx.sender().unwrap()); let banlist2 = txq.ban_sender(tx.sender().unwrap());
let import2 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required); let import2 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required);
// then // then
assert!(banlist2, "Threshold should be reached - banned."); assert!(banlist2, "Threshold should be reached - banned.");
@ -303,12 +305,12 @@ mod tests {
let banlist1 = txq.ban_recipient(recipient); let banlist1 = txq.ban_recipient(recipient);
assert!(!banlist1, "Threshold not reached yet."); assert!(!banlist1, "Threshold not reached yet.");
// Insert once // Insert once
let import1 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required).unwrap(); let import1 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required).unwrap();
assert_eq!(import1, TransactionImportResult::Current); assert_eq!(import1, TransactionImportResult::Current);
// when // when
let banlist2 = txq.ban_recipient(recipient); let banlist2 = txq.ban_recipient(recipient);
let import2 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required); let import2 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required);
// then // then
assert!(banlist2, "Threshold should be reached - banned."); assert!(banlist2, "Threshold should be reached - banned.");
@ -325,12 +327,12 @@ mod tests {
let banlist1 = txq.ban_codehash(codehash); let banlist1 = txq.ban_codehash(codehash);
assert!(!banlist1, "Threshold not reached yet."); assert!(!banlist1, "Threshold not reached yet.");
// Insert once // Insert once
let import1 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required).unwrap(); let import1 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required).unwrap();
assert_eq!(import1, TransactionImportResult::Current); assert_eq!(import1, TransactionImportResult::Current);
// when // when
let banlist2 = txq.ban_codehash(codehash); let banlist2 = txq.ban_codehash(codehash);
let import2 = txq.add_with_banlist(tx.clone(), &default_account_details, &gas_required); let import2 = txq.add_with_banlist(tx.clone(), 0, &default_account_details, &gas_required);
// then // then
assert!(banlist2, "Threshold should be reached - banned."); assert!(banlist2, "Threshold should be reached - banned.");

View File

@ -417,15 +417,12 @@ impl Miner {
let block = open_block.close(); let block = open_block.close();
let fetch_account = |a: &Address| AccountDetails { let fetch_nonce = |a: &Address| chain.latest_nonce(a);
nonce: chain.latest_nonce(a),
balance: chain.latest_balance(a),
};
{ {
let mut queue = self.transaction_queue.lock(); let mut queue = self.transaction_queue.lock();
for hash in invalid_transactions { for hash in invalid_transactions {
queue.remove_invalid(&hash, &fetch_account); queue.remove_invalid(&hash, &fetch_nonce);
} }
for hash in transactions_to_penalize { for hash in transactions_to_penalize {
queue.penalize(&hash); queue.penalize(&hash);
@ -597,6 +594,8 @@ impl Miner {
let schedule = chain.latest_schedule(); let schedule = chain.latest_schedule();
let gas_required = |tx: &SignedTransaction| tx.gas_required(&schedule).into(); let gas_required = |tx: &SignedTransaction| tx.gas_required(&schedule).into();
let best_block_header = chain.best_block_header().decode(); let best_block_header = chain.best_block_header().decode();
let insertion_time = chain.chain_info().best_block_number;
transactions.into_iter() transactions.into_iter()
.map(|tx| { .map(|tx| {
if chain.transaction_block(TransactionId::Hash(tx.hash())).is_some() { if chain.transaction_block(TransactionId::Hash(tx.hash())).is_some() {
@ -618,10 +617,10 @@ impl Miner {
match origin { match origin {
TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { TransactionOrigin::Local | TransactionOrigin::RetractedBlock => {
transaction_queue.add(tx, origin, min_block, &fetch_account, &gas_required) transaction_queue.add(tx, origin, insertion_time, min_block, &fetch_account, &gas_required)
}, },
TransactionOrigin::External => { TransactionOrigin::External => {
transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required) transaction_queue.add_with_banlist(tx, insertion_time, &fetch_account, &gas_required)
} }
} }
}, },
@ -1141,8 +1140,13 @@ impl MinerService for Miner {
// ...and at the end remove the old ones // ...and at the end remove the old ones
{ {
let fetch_account = |a: &Address| AccountDetails {
nonce: chain.latest_nonce(a),
balance: chain.latest_balance(a),
};
let time = chain.chain_info().best_block_number;
let mut transaction_queue = self.transaction_queue.lock(); let mut transaction_queue = self.transaction_queue.lock();
transaction_queue.remove_old(|sender| chain.latest_nonce(sender)); transaction_queue.remove_old(&fetch_account, time);
} }
if enacted.len() > 0 { if enacted.len() > 0 {

View File

@ -51,8 +51,8 @@
//! let gas_estimator = |_tx: &SignedTransaction| 2.into(); //! let gas_estimator = |_tx: &SignedTransaction| 2.into();
//! //!
//! let mut txq = TransactionQueue::default(); //! let mut txq = TransactionQueue::default();
//! txq.add(st2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); //! txq.add(st2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
//! txq.add(st1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); //! txq.add(st1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
//! //!
//! // Check status //! // Check status
//! assert_eq!(txq.status().pending, 2); //! assert_eq!(txq.status().pending, 2);
@ -64,7 +64,7 @@
//! //!
//! // And when transaction is removed (but nonce haven't changed) //! // And when transaction is removed (but nonce haven't changed)
//! // it will move subsequent transactions to future //! // it will move subsequent transactions to future
//! txq.remove_invalid(&st1.hash(), &default_account_details); //! txq.remove_invalid(&st1.hash(), &|_| 10.into());
//! assert_eq!(txq.status().pending, 0); //! assert_eq!(txq.status().pending, 0);
//! assert_eq!(txq.status().future, 1); //! assert_eq!(txq.status().future, 1);
//! assert_eq!(txq.top_transactions().len(), 0); //! assert_eq!(txq.top_transactions().len(), 0);
@ -78,11 +78,11 @@
//! - When it's removed from `future` - all `future` transactions heights are recalculated and then //! - When it's removed from `future` - all `future` transactions heights are recalculated and then
//! we check if the transactions should go to `current` (comparing state nonce) //! 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. //! - 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. //! 3. `cull` 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 removes all transactions (either from `current` or `future`) with nonce < client nonce
//! - It moves matching `future` transactions to `current` //! - 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. //! 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. //! - Invokes `cull` with latest state nonce for all senders.
use std::ops::Deref; use std::ops::Deref;
use std::cmp::Ordering; use std::cmp::Ordering;
@ -258,16 +258,19 @@ struct VerifiedTransaction {
transaction: SignedTransaction, transaction: SignedTransaction,
/// Transaction origin. /// Transaction origin.
origin: TransactionOrigin, origin: TransactionOrigin,
/// Insertion time
insertion_time: QueuingInstant,
/// Delay until specifid block. /// Delay until specifid block.
min_block: Option<BlockNumber>, min_block: Option<BlockNumber>,
} }
impl VerifiedTransaction { impl VerifiedTransaction {
fn new(transaction: SignedTransaction, origin: TransactionOrigin, min_block: Option<BlockNumber>) -> Result<Self, Error> { fn new(transaction: SignedTransaction, origin: TransactionOrigin, time: QueuingInstant, min_block: Option<BlockNumber>) -> Result<Self, Error> {
transaction.sender()?; transaction.sender()?;
Ok(VerifiedTransaction { Ok(VerifiedTransaction {
transaction: transaction, transaction: transaction,
origin: origin, origin: origin,
insertion_time: time,
min_block: min_block, min_block: min_block,
}) })
} }
@ -283,6 +286,10 @@ impl VerifiedTransaction {
fn sender(&self) -> Address { fn sender(&self) -> Address {
self.transaction.sender().expect("Sender is verified in new; qed") self.transaction.sender().expect("Sender is verified in new; qed")
} }
fn cost(&self) -> U256 {
self.transaction.value + self.transaction.gas_price * self.transaction.gas
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -488,6 +495,10 @@ pub enum PrioritizationStrategy {
GasFactorAndGasPrice, GasFactorAndGasPrice,
} }
/// Point in time when transaction was inserted.
pub type QueuingInstant = BlockNumber;
const DEFAULT_QUEUING_PERIOD: BlockNumber = 128;
/// `TransactionQueue` implementation /// `TransactionQueue` implementation
pub struct TransactionQueue { pub struct TransactionQueue {
/// Prioritization strategy for this queue /// Prioritization strategy for this queue
@ -498,6 +509,10 @@ pub struct TransactionQueue {
tx_gas_limit: U256, tx_gas_limit: U256,
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0) /// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
gas_limit: U256, gas_limit: U256,
/// Maximal time transaction may occupy the queue.
/// When we reach `max_time_in_queue / 2^3` we re-validate
/// account balance.
max_time_in_queue: QueuingInstant,
/// Priority queue for transactions that can go to block /// Priority queue for transactions that can go to block
current: TransactionSet, current: TransactionSet,
/// Priority queue for transactions that has been received but are not yet valid to go to block /// Priority queue for transactions that has been received but are not yet valid to go to block
@ -545,6 +560,7 @@ impl TransactionQueue {
minimal_gas_price: U256::zero(), minimal_gas_price: U256::zero(),
tx_gas_limit: tx_gas_limit, tx_gas_limit: tx_gas_limit,
gas_limit: !U256::zero(), gas_limit: !U256::zero(),
max_time_in_queue: DEFAULT_QUEUING_PERIOD,
current: current, current: current,
future: future, future: future,
by_hash: HashMap::new(), by_hash: HashMap::new(),
@ -624,6 +640,7 @@ impl TransactionQueue {
&mut self, &mut self,
tx: SignedTransaction, tx: SignedTransaction,
origin: TransactionOrigin, origin: TransactionOrigin,
time: QueuingInstant,
min_block: Option<BlockNumber>, min_block: Option<BlockNumber>,
fetch_account: &F, fetch_account: &F,
gas_estimator: &G, gas_estimator: &G,
@ -635,7 +652,7 @@ impl TransactionQueue {
let hash = tx.hash(); let hash = tx.hash();
let cloned_tx = tx.clone(); let cloned_tx = tx.clone();
let result = self.add_internal(tx, origin, min_block, fetch_account, gas_estimator); let result = self.add_internal(tx, origin, time, min_block, fetch_account, gas_estimator);
match result { match result {
Ok(TransactionImportResult::Current) => { Ok(TransactionImportResult::Current) => {
self.local_transactions.mark_pending(hash); self.local_transactions.mark_pending(hash);
@ -656,7 +673,7 @@ impl TransactionQueue {
} }
result result
} else { } else {
self.add_internal(tx, origin, min_block, fetch_account, gas_estimator) self.add_internal(tx, origin, time, min_block, fetch_account, gas_estimator)
} }
} }
@ -665,6 +682,7 @@ impl TransactionQueue {
&mut self, &mut self,
tx: SignedTransaction, tx: SignedTransaction,
origin: TransactionOrigin, origin: TransactionOrigin,
time: QueuingInstant,
min_block: Option<BlockNumber>, min_block: Option<BlockNumber>,
fetch_account: &F, fetch_account: &F,
gas_estimator: &G, gas_estimator: &G,
@ -734,10 +752,10 @@ impl TransactionQueue {
// Verify signature // Verify signature
tx.check_low_s()?; tx.check_low_s()?;
let vtx = VerifiedTransaction::new(tx, origin, min_block)?; let vtx = VerifiedTransaction::new(tx, origin, time, min_block)?;
let client_account = fetch_account(&vtx.sender()); let client_account = fetch_account(&vtx.sender());
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; let cost = vtx.cost();
if client_account.balance < cost { if client_account.balance < cost {
trace!(target: "txqueue", trace!(target: "txqueue",
"Dropping transaction without sufficient balance: {:?} ({} < {})", "Dropping transaction without sufficient balance: {:?} ({} < {})",
@ -759,7 +777,7 @@ impl TransactionQueue {
/// Removes all transactions from particular sender up to (excluding) given client (state) nonce. /// Removes all transactions from particular sender up to (excluding) given client (state) nonce.
/// Client (State) Nonce = next valid nonce for this sender. /// Client (State) Nonce = next valid nonce for this sender.
pub fn remove_all(&mut self, sender: Address, client_nonce: U256) { pub fn cull(&mut self, sender: Address, client_nonce: U256) {
// Check if there is anything in current... // Check if there is anything in current...
let should_check_in_current = self.current.by_address.row(&sender) let should_check_in_current = self.current.by_address.row(&sender)
// If nonce == client_nonce nothing is changed // If nonce == client_nonce nothing is changed
@ -775,11 +793,11 @@ impl TransactionQueue {
return; return;
} }
self.remove_all_internal(sender, client_nonce); self.cull_internal(sender, client_nonce);
} }
/// Always updates future and moves transactions from current to future. /// Always updates future and moves transactions from current to future.
fn remove_all_internal(&mut self, sender: Address, client_nonce: U256) { fn cull_internal(&mut self, sender: Address, client_nonce: U256) {
// We will either move transaction to future or remove it completely // We will either move transaction to future or remove it completely
// so there will be no transactions from this sender in current // so there will be no transactions from this sender in current
self.last_nonces.remove(&sender); self.last_nonces.remove(&sender);
@ -794,16 +812,45 @@ impl TransactionQueue {
} }
/// Checks the current nonce for all transactions' senders in the queue and removes the old transactions. /// Checks the current nonce for all transactions' senders in the queue and removes the old transactions.
pub fn remove_old<F>(&mut self, fetch_nonce: F) where pub fn remove_old<F>(&mut self, fetch_account: &F, current_time: QueuingInstant) where
F: Fn(&Address) -> U256, F: Fn(&Address) -> AccountDetails,
{ {
let senders = self.current.by_address.keys() let senders = self.current.by_address.keys()
.chain(self.future.by_address.keys()) .chain(self.future.by_address.keys())
.cloned() .map(|sender| (*sender, fetch_account(sender)))
.collect::<HashSet<_>>(); .collect::<HashMap<_, _>>();
for sender in senders { for (sender, details) in senders.iter() {
self.remove_all(sender, fetch_nonce(&sender)); self.cull(*sender, details.nonce);
}
let max_time = self.max_time_in_queue;
let balance_check = max_time >> 3;
// Clear transactions occupying the queue too long
let invalid = self.by_hash.iter()
.map(|(hash, tx)| (hash, tx, current_time.saturating_sub(tx.insertion_time)))
.filter_map(|(hash, tx, time_diff)| {
if time_diff > max_time {
return Some(*hash);
}
if time_diff > balance_check {
return match senders.get(&tx.sender()) {
Some(details) if tx.cost() > details.balance => {
Some(*hash)
},
_ => None,
};
}
None
})
.collect::<Vec<_>>();
let fetch_nonce = |a: &Address| senders.get(a)
.expect("We fetch details for all senders from both current and future")
.nonce;
for hash in invalid {
self.remove_invalid(&hash, &fetch_nonce);
} }
} }
@ -851,8 +898,8 @@ impl TransactionQueue {
/// so transactions left in queue are processed according to client nonce. /// so transactions left in queue are processed according to client nonce.
/// ///
/// If gap is introduced marks subsequent transactions as future /// If gap is introduced marks subsequent transactions as future
pub fn remove_invalid<T>(&mut self, transaction_hash: &H256, fetch_account: &T) pub fn remove_invalid<T>(&mut self, transaction_hash: &H256, fetch_nonce: &T)
where T: Fn(&Address) -> AccountDetails { where T: Fn(&Address) -> U256 {
assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len());
let transaction = self.by_hash.remove(transaction_hash); let transaction = self.by_hash.remove(transaction_hash);
@ -864,7 +911,7 @@ impl TransactionQueue {
let transaction = transaction.expect("None is tested in early-exit condition above; qed"); let transaction = transaction.expect("None is tested in early-exit condition above; qed");
let sender = transaction.sender(); let sender = transaction.sender();
let nonce = transaction.nonce(); let nonce = transaction.nonce();
let current_nonce = fetch_account(&sender).nonce; let current_nonce = fetch_nonce(&sender);
trace!(target: "txqueue", "Removing invalid transaction: {:?}", transaction.hash()); trace!(target: "txqueue", "Removing invalid transaction: {:?}", transaction.hash());
@ -889,7 +936,7 @@ impl TransactionQueue {
if order.is_some() { if order.is_some() {
// This will keep consistency in queue // This will keep consistency in queue
// Moves all to future and then promotes a batch from current: // Moves all to future and then promotes a batch from current:
self.remove_all_internal(sender, current_nonce); self.cull_internal(sender, current_nonce);
assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len());
return; return;
} }
@ -1039,7 +1086,7 @@ impl TransactionQueue {
/// Finds transaction in the queue by hash (if any) /// Finds transaction in the queue by hash (if any)
pub fn find(&self, hash: &H256) -> Option<SignedTransaction> { pub fn find(&self, hash: &H256) -> Option<SignedTransaction> {
match self.by_hash.get(hash) { Some(transaction_ref) => Some(transaction_ref.transaction.clone()), None => None } self.by_hash.get(hash).map(|tx| tx.transaction.clone())
} }
/// Removes all elements (in any state) from the queue /// Removes all elements (in any state) from the queue
@ -1388,14 +1435,14 @@ mod test {
let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into()); let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into());
let sender = tx1.sender().unwrap(); let sender = tx1.sender().unwrap();
let nonce = tx1.nonce; let nonce = tx1.nonce;
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into())); assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into()));
// when // when
let tx = new_tx(123.into(), 1.into()); let tx = new_tx(123.into(), 1.into());
let res = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
// No longer the case as we don't even consider a transaction that isn't above a full // No longer the case as we don't even consider a transaction that isn't above a full
@ -1427,12 +1474,12 @@ mod test {
gas_limit: !U256::zero(), gas_limit: !U256::zero(),
}; };
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, 0, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, 0, None).unwrap();
let mut by_hash = { let mut by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, 0, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, 0, None).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -1470,12 +1517,12 @@ mod test {
// Create two transactions with same nonce // Create two transactions with same nonce
// (same hash) // (same hash)
let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into());
let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, 0, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, 0, None).unwrap();
let by_hash = { let by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, 0, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, 0, None).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -1517,10 +1564,10 @@ mod test {
gas_limit: !U256::zero(), gas_limit: !U256::zero(),
}; };
let tx = new_tx_default(); let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, 0, None).unwrap();
let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none()); assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none());
let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External, None).unwrap(); let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External, 0, None).unwrap();
let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some()); assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some());
} }
@ -1537,7 +1584,7 @@ mod test {
assert_eq!(set.gas_price_entry_limit(), 0.into()); assert_eq!(set.gas_price_entry_limit(), 0.into());
let tx = new_tx_default(); let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, 0, None).unwrap();
let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none()); assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none());
assert_eq!(set.gas_price_entry_limit(), 2.into()); assert_eq!(set.gas_price_entry_limit(), 2.into());
@ -1552,12 +1599,12 @@ mod test {
!U256::zero() }; !U256::zero() };
// First insert one transaction to future // First insert one transaction to future
let res = txq.add(tx, TransactionOrigin::External, None, &prev_nonce, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator);
assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(res.unwrap(), TransactionImportResult::Future);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// now import second transaction to current // now import second transaction to current
let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// and then there should be only one transaction in current (the one with higher gas_price) // and then there should be only one transaction in current (the one with higher gas_price)
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1577,12 +1624,12 @@ mod test {
!U256::zero() }; !U256::zero() };
// First insert one transaction to future // First insert one transaction to future
let res = txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator); let res = txq.add(tx.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator);
assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(res.unwrap(), TransactionImportResult::Future);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// now import second transaction to current // now import second transaction to current
let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1601,7 +1648,7 @@ mod test {
let tx = new_tx_default(); let tx = new_tx_default();
// when // when
let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1620,10 +1667,10 @@ mod test {
txq.set_minimal_gas_price(15.into()); txq.set_minimal_gas_price(15.into());
// when // when
let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res2 = txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res3 = txq.add(tx3, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res4 = txq.add(tx4, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -1654,10 +1701,10 @@ mod test {
txq.set_minimal_gas_price(15.into()); txq.set_minimal_gas_price(15.into());
// when // when
let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res2 = txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res3 = txq.add(tx3, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res4 = txq.add(tx4, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -1700,7 +1747,7 @@ mod test {
txq.set_gas_limit(limit); txq.set_gas_limit(limit);
// when // when
let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded {
@ -1724,7 +1771,7 @@ mod test {
}; };
// when // when
let res = txq.add(tx, TransactionOrigin::External, None, &account, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &account, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance {
@ -1744,7 +1791,7 @@ mod test {
txq.set_minimal_gas_price(tx.gas_price + U256::one()); txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when // when
let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice {
@ -1764,7 +1811,7 @@ mod test {
txq.set_minimal_gas_price(tx.gas_price + U256::one()); txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when // when
let res = txq.add(tx, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1794,7 +1841,7 @@ mod test {
rlp::decode(s.as_raw()) rlp::decode(s.as_raw())
}; };
// when // when
let res = txq.add(stx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(stx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
assert!(res.is_err()); assert!(res.is_err());
@ -1808,8 +1855,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1828,9 +1875,9 @@ mod test {
// when // when
// first insert the one with higher gas price // first insert the one with higher gas price
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then the one with lower gas price, but local // then the one with lower gas price, but local
txq.add(tx.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1847,15 +1894,15 @@ mod test {
// the second one has same nonce but higher `gas_price` // the second one has same nonce but higher `gas_price`
let (_, tx0) = new_similar_tx_pair(); let (_, tx0) = new_similar_tx_pair();
txq.add(tx0.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx0.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// the one with higher gas price is first // the one with higher gas price is first
assert_eq!(txq.top_transactions()[0], tx0); assert_eq!(txq.top_transactions()[0], tx0);
assert_eq!(txq.top_transactions()[1], tx1); assert_eq!(txq.top_transactions()[1], tx1);
// when // when
// insert second as local // insert second as local
txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
// the order should be updated // the order should be updated
@ -1874,9 +1921,9 @@ mod test {
// when // when
// first insert local one with higher gas price // first insert local one with higher gas price
txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
// then the one with lower gas price, but from retracted block // then the one with lower gas price, but from retracted block
txq.add(tx.clone(), TransactionOrigin::RetractedBlock, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::RetractedBlock, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1892,8 +1939,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1912,10 +1959,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 4); assert_eq!(txq.status().future, 4);
@ -1940,10 +1987,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
let top = txq.top_transactions(); let top = txq.top_transactions();
assert_eq!(top[0], tx1); assert_eq!(top[0], tx1);
@ -1973,10 +2020,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
let top = txq.top_transactions(); let top = txq.top_transactions();
assert_eq!(top[0], tx1); assert_eq!(top[0], tx1);
@ -2005,8 +2052,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.pending_hashes(); let top = txq.pending_hashes();
@ -2023,8 +2070,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(2.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(2.into(), 0.into());
// when // when
let res1 = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); let res2 = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
assert_eq!(res1, TransactionImportResult::Current); assert_eq!(res1, TransactionImportResult::Current);
@ -2045,8 +2092,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
let res1 = txq.add(tx.clone(), TransactionOrigin::External, Some(1), &default_account_details, &gas_estimator).unwrap(); let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, Some(1), &default_account_details, &gas_estimator).unwrap();
let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); let res2 = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
assert_eq!(res1, TransactionImportResult::Current); assert_eq!(res1, TransactionImportResult::Current);
@ -2067,12 +2114,12 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
txq.remove_all(tx.sender().unwrap(), next2_nonce); txq.cull(tx.sender().unwrap(), next2_nonce);
// should remove both transactions since they are not valid // should remove both transactions since they are not valid
// then // then
@ -2090,13 +2137,13 @@ mod test {
let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None); let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None);
let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None); let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None);
txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// when // when
txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2112,14 +2159,14 @@ mod test {
// given // given
let mut txq2 = TransactionQueue::default(); let mut txq2 = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(3.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(3.into(), 0.into());
txq2.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq2.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq2.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq2.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq2.status().pending, 1); assert_eq!(txq2.status().pending, 1);
assert_eq!(txq2.status().future, 1); assert_eq!(txq2.status().future, 1);
// when // when
txq2.remove_all(tx.sender().unwrap(), tx.nonce + U256::one()); txq2.cull(tx.sender().unwrap(), tx.nonce + U256::one());
txq2.remove_all(tx2.sender().unwrap(), tx2.nonce + U256::one()); txq2.cull(tx2.sender().unwrap(), tx2.nonce + U256::one());
// then // then
@ -2134,14 +2181,14 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default(); let tx3 = new_tx_default();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
txq.remove_invalid(&tx.hash(), &default_account_details); txq.remove_invalid(&tx.hash(), &|_| default_nonce());
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2156,8 +2203,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// add // add
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
let stats = txq.status(); let stats = txq.status();
assert_eq!(stats.pending, 2); assert_eq!(stats.pending, 2);
@ -2176,11 +2223,11 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let sender = tx.sender().unwrap(); let sender = tx.sender().unwrap();
let nonce = tx.nonce; let nonce = tx.nonce;
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
// when // when
let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator);
// then // then
let t = txq.top_transactions(); let t = txq.top_transactions();
@ -2197,14 +2244,14 @@ mod test {
txq.current.set_limit(10); txq.current.set_limit(10);
let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into()); let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into());
let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into()); let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into());
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
@ -2215,11 +2262,11 @@ mod test {
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero());
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// limited by gas // limited by gas
txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); txq.add(tx4.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap_err();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
} }
@ -2229,12 +2276,12 @@ mod test {
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
// Not accepted because of limit // Not accepted because of limit
txq.add(tx5.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); txq.add(tx5.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap_err();
txq.add(tx3.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx4.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4.clone(), TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 4); assert_eq!(txq.status().pending, 4);
} }
@ -2246,7 +2293,7 @@ mod test {
let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() }; let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() };
// when // when
let res = txq.add(tx, TransactionOrigin::External, None, &fetch_last_nonce, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, 0, None, &fetch_last_nonce, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::Old); assert_eq!(unwrap_tx_err(res), TransactionError::Old);
@ -2262,12 +2309,12 @@ mod test {
balance: !U256::zero() }; balance: !U256::zero() };
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
// when // when
let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &nonce, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &nonce, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported);
@ -2281,15 +2328,15 @@ mod test {
// given // given
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.remove_invalid(&tx1.hash(), &default_account_details); txq.remove_invalid(&tx1.hash(), &|_| default_nonce());
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2303,15 +2350,15 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default(); let tx3 = new_tx_default();
txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
let sender = tx.sender().unwrap(); let sender = tx.sender().unwrap();
txq.remove_all(sender, default_nonce() + U256::one()); txq.cull(sender, default_nonce() + U256::one());
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2333,8 +2380,8 @@ mod test {
}; };
// when // when
txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2361,10 +2408,10 @@ mod test {
}; };
// when // when
txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx0, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx0, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2376,18 +2423,16 @@ mod test {
#[test] #[test]
fn should_recalculate_height_when_removing_from_future() { fn should_recalculate_height_when_removing_from_future() {
// given // given
let previous_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce - U256::one(), balance: let previous_nonce = |a: &Address|
!U256::zero() }; AccountDetails { nonce: default_account_details(a).nonce - U256::one(), balance: !U256::zero() };
let next_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce + U256::one(), balance:
!U256::zero() };
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &previous_nonce, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, 0, None, &previous_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
txq.remove_invalid(&tx1.hash(), &next_nonce); txq.remove_invalid(&tx1.hash(), &|_| default_nonce() + 1.into());
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2414,7 +2459,7 @@ mod test {
let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() }; let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
// when // when
txq.add(tx, TransactionOrigin::External, None, &details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, 0, None, &details, &gas_estimator).unwrap();
// then // then
assert_eq!(txq.last_nonce(&from), Some(nonce)); assert_eq!(txq.last_nonce(&from), Some(nonce));
@ -2429,17 +2474,17 @@ mod test {
let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() }; let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() };
// Insert first transaction // Insert first transaction
txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, 0, None, &details1, &gas_estimator).unwrap();
// when // when
txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one()); txq.cull(tx2.sender().unwrap(), nonce2 + U256::one());
// then // then
assert!(txq.top_transactions().is_empty()); assert!(txq.top_transactions().is_empty());
} }
#[test] #[test]
fn should_return_valid_last_nonce_after_remove_all() { fn should_return_valid_last_nonce_after_cull() {
// given // given
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(4.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(4.into(), 0.into());
@ -2449,11 +2494,11 @@ mod test {
// when // when
// Insert first transaction // Insert first transaction
assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current);
// Second should go to future // Second should go to future
assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future);
// Now block is imported // Now block is imported
txq.remove_all(sender, nonce2 - U256::from(1)); txq.cull(sender, nonce2 - U256::from(1));
// tx2 should be not be promoted to current // tx2 should be not be promoted to current
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
@ -2470,9 +2515,9 @@ mod test {
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
// when // when
assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current);
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
assert_eq!(txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx2, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current);
// then // then
assert_eq!(txq.has_local_pending_transactions(), true); assert_eq!(txq.has_local_pending_transactions(), true);
@ -2487,8 +2532,8 @@ mod test {
default_account_details(a).balance }; default_account_details(a).balance };
// when // when
assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future);
assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future);
// then // then
assert_eq!(txq.future.by_priority.len(), 1); assert_eq!(txq.future.by_priority.len(), 1);
@ -2513,14 +2558,14 @@ mod test {
(tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None)) (tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None))
}; };
let sender = tx1.sender().unwrap(); let sender = tx1.sender().unwrap();
txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.future.by_priority.len(), 0); assert_eq!(txq.future.by_priority.len(), 0);
assert_eq!(txq.current.by_priority.len(), 3); assert_eq!(txq.current.by_priority.len(), 3);
// when // when
let res = txq.add(tx2_2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); let res = txq.add(tx2_2, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into());
@ -2536,8 +2581,8 @@ mod test {
let high_gas = |_: &SignedTransaction| 100_001.into(); let high_gas = |_: &SignedTransaction| 100_001.into();
// when // when
let res1 = txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &high_gas); let res2 = txq.add(tx2, TransactionOrigin::Local, 0, None, &default_account_details, &high_gas);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -2554,20 +2599,45 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let (tx3, tx4) = new_tx_pair_default(1.into(), 0.into()); let (tx3, tx4) = new_tx_pair_default(1.into(), 0.into());
let nonce1 = tx1.nonce; let next_nonce = |_: &Address|
AccountDetails { nonce: default_nonce() + U256::one(), balance: !U256::zero() };
// Insert all transactions // Insert all transactions
txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.top_transactions().len(), 4); assert_eq!(txq.top_transactions().len(), 4);
// when // when
txq.remove_old(|_| nonce1 + U256::one()); txq.remove_old(&next_nonce, 0);
// then // then
assert_eq!(txq.top_transactions().len(), 2); assert_eq!(txq.top_transactions().len(), 2);
} }
#[test]
fn should_remove_out_of_date_transactions_occupying_queue() {
// given
let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let (tx3, tx4) = new_tx_pair_default(2.into(), 0.into());
// Insert all transactions
txq.add(tx1, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, 5, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3.clone(), TransactionOrigin::External, 10, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx4, TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.top_transactions().len(), 3);
assert_eq!(txq.future_transactions().len(), 1);
// when
txq.remove_old(&default_account_details, 9 + super::DEFAULT_QUEUING_PERIOD);
// then
assert_eq!(txq.top_transactions().len(), 1);
assert_eq!(txq.future_transactions().len(), 0);
assert_eq!(txq.top_transactions(), vec![tx3]);
}
} }