Removing old transactions from the queue (#4046)
* Removing old transactions from the queue * Addressing grumbles
This commit is contained in:
		
							parent
							
								
									fbc9f0d7fb
								
							
						
					
					
						commit
						eb0daea9b9
					
				@ -23,6 +23,7 @@ use std::cell::Cell;
 | 
			
		||||
use transaction::{SignedTransaction, Action};
 | 
			
		||||
use transient_hashmap::TransientHashMap;
 | 
			
		||||
use miner::{TransactionQueue, TransactionImportResult, TransactionOrigin, AccountDetails};
 | 
			
		||||
use miner::transaction_queue::QueuingInstant;
 | 
			
		||||
use error::{Error, TransactionError};
 | 
			
		||||
use util::{Uint, U256, H256, Address, Hashable};
 | 
			
		||||
 | 
			
		||||
@ -78,6 +79,7 @@ impl BanningTransactionQueue {
 | 
			
		||||
	pub fn add_with_banlist<F, G>(
 | 
			
		||||
		&mut self,
 | 
			
		||||
		transaction: SignedTransaction,
 | 
			
		||||
		time: QueuingInstant,
 | 
			
		||||
		account_details: &F,
 | 
			
		||||
		gas_estimator: &G,
 | 
			
		||||
	) -> 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.
 | 
			
		||||
@ -158,7 +160,7 @@ impl BanningTransactionQueue {
 | 
			
		||||
			Threshold::BanAfter(threshold) if count > threshold => {
 | 
			
		||||
				// Banlist the sender.
 | 
			
		||||
				// Remove all transactions from the queue.
 | 
			
		||||
				self.remove_all(address, !U256::zero());
 | 
			
		||||
				self.cull(address, !U256::zero());
 | 
			
		||||
				true
 | 
			
		||||
			},
 | 
			
		||||
			_ => false
 | 
			
		||||
@ -263,7 +265,7 @@ mod tests {
 | 
			
		||||
		let mut txq = queue();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		// should also deref to queue
 | 
			
		||||
@ -279,12 +281,12 @@ mod tests {
 | 
			
		||||
		let banlist1 = txq.ban_sender(tx.sender().unwrap());
 | 
			
		||||
		assert!(!banlist1, "Threshold not reached yet.");
 | 
			
		||||
		// 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);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		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
 | 
			
		||||
		assert!(banlist2, "Threshold should be reached - banned.");
 | 
			
		||||
@ -303,12 +305,12 @@ mod tests {
 | 
			
		||||
		let banlist1 = txq.ban_recipient(recipient);
 | 
			
		||||
		assert!(!banlist1, "Threshold not reached yet.");
 | 
			
		||||
		// 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);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		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
 | 
			
		||||
		assert!(banlist2, "Threshold should be reached - banned.");
 | 
			
		||||
@ -325,12 +327,12 @@ mod tests {
 | 
			
		||||
		let banlist1 = txq.ban_codehash(codehash);
 | 
			
		||||
		assert!(!banlist1, "Threshold not reached yet.");
 | 
			
		||||
		// 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);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		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
 | 
			
		||||
		assert!(banlist2, "Threshold should be reached - banned.");
 | 
			
		||||
 | 
			
		||||
@ -417,15 +417,12 @@ impl Miner {
 | 
			
		||||
 | 
			
		||||
		let block = open_block.close();
 | 
			
		||||
 | 
			
		||||
		let fetch_account = |a: &Address| AccountDetails {
 | 
			
		||||
			nonce: chain.latest_nonce(a),
 | 
			
		||||
			balance: chain.latest_balance(a),
 | 
			
		||||
		};
 | 
			
		||||
		let fetch_nonce = |a: &Address| chain.latest_nonce(a);
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			let mut queue = self.transaction_queue.lock();
 | 
			
		||||
			for hash in invalid_transactions {
 | 
			
		||||
				queue.remove_invalid(&hash, &fetch_account);
 | 
			
		||||
				queue.remove_invalid(&hash, &fetch_nonce);
 | 
			
		||||
			}
 | 
			
		||||
			for hash in transactions_to_penalize {
 | 
			
		||||
				queue.penalize(&hash);
 | 
			
		||||
@ -597,6 +594,8 @@ impl Miner {
 | 
			
		||||
		let schedule = chain.latest_schedule();
 | 
			
		||||
		let gas_required = |tx: &SignedTransaction| tx.gas_required(&schedule).into();
 | 
			
		||||
		let best_block_header = chain.best_block_header().decode();
 | 
			
		||||
		let insertion_time = chain.chain_info().best_block_number;
 | 
			
		||||
 | 
			
		||||
		transactions.into_iter()
 | 
			
		||||
			.map(|tx| {
 | 
			
		||||
				if chain.transaction_block(TransactionId::Hash(tx.hash())).is_some() {
 | 
			
		||||
@ -618,10 +617,10 @@ impl Miner {
 | 
			
		||||
 | 
			
		||||
						match origin {
 | 
			
		||||
							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 => {
 | 
			
		||||
								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
 | 
			
		||||
		{
 | 
			
		||||
			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();
 | 
			
		||||
			transaction_queue.remove_old(|sender| chain.latest_nonce(sender));
 | 
			
		||||
			transaction_queue.remove_old(&fetch_account, time);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if enacted.len() > 0 {
 | 
			
		||||
 | 
			
		||||
@ -51,8 +51,8 @@
 | 
			
		||||
//!		let gas_estimator = |_tx: &SignedTransaction| 2.into();
 | 
			
		||||
//!
 | 
			
		||||
//!		let mut txq = TransactionQueue::default();
 | 
			
		||||
//!		txq.add(st2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
//!		txq.add(st1.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
//!
 | 
			
		||||
//!		// Check status
 | 
			
		||||
//!		assert_eq!(txq.status().pending, 2);
 | 
			
		||||
@ -64,7 +64,7 @@
 | 
			
		||||
//!
 | 
			
		||||
//!		// And when transaction is removed (but nonce haven't changed)
 | 
			
		||||
//!		// 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().future, 1);
 | 
			
		||||
//!		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
 | 
			
		||||
//!		  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.
 | 
			
		||||
//!	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 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.
 | 
			
		||||
//!		- Invokes `cull` with latest state nonce for all senders.
 | 
			
		||||
 | 
			
		||||
use std::ops::Deref;
 | 
			
		||||
use std::cmp::Ordering;
 | 
			
		||||
@ -258,16 +258,19 @@ struct VerifiedTransaction {
 | 
			
		||||
	transaction: SignedTransaction,
 | 
			
		||||
	/// Transaction origin.
 | 
			
		||||
	origin: TransactionOrigin,
 | 
			
		||||
	/// Insertion time
 | 
			
		||||
	insertion_time: QueuingInstant,
 | 
			
		||||
	/// Delay until specifid block.
 | 
			
		||||
	min_block: Option<BlockNumber>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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()?;
 | 
			
		||||
		Ok(VerifiedTransaction {
 | 
			
		||||
			transaction: transaction,
 | 
			
		||||
			origin: origin,
 | 
			
		||||
			insertion_time: time,
 | 
			
		||||
			min_block: min_block,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@ -283,6 +286,10 @@ impl VerifiedTransaction {
 | 
			
		||||
	fn sender(&self) -> Address {
 | 
			
		||||
		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)]
 | 
			
		||||
@ -488,6 +495,10 @@ pub enum PrioritizationStrategy {
 | 
			
		||||
	GasFactorAndGasPrice,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Point in time when transaction was inserted.
 | 
			
		||||
pub type QueuingInstant = BlockNumber;
 | 
			
		||||
const DEFAULT_QUEUING_PERIOD: BlockNumber = 128;
 | 
			
		||||
 | 
			
		||||
/// `TransactionQueue` implementation
 | 
			
		||||
pub struct TransactionQueue {
 | 
			
		||||
	/// Prioritization strategy for this queue
 | 
			
		||||
@ -498,6 +509,10 @@ pub struct TransactionQueue {
 | 
			
		||||
	tx_gas_limit: U256,
 | 
			
		||||
	/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
 | 
			
		||||
	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
 | 
			
		||||
	current: TransactionSet,
 | 
			
		||||
	/// 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(),
 | 
			
		||||
			tx_gas_limit: tx_gas_limit,
 | 
			
		||||
			gas_limit: !U256::zero(),
 | 
			
		||||
			max_time_in_queue: DEFAULT_QUEUING_PERIOD,
 | 
			
		||||
			current: current,
 | 
			
		||||
			future: future,
 | 
			
		||||
			by_hash: HashMap::new(),
 | 
			
		||||
@ -624,6 +640,7 @@ impl TransactionQueue {
 | 
			
		||||
		&mut self,
 | 
			
		||||
		tx: SignedTransaction,
 | 
			
		||||
		origin: TransactionOrigin,
 | 
			
		||||
		time: QueuingInstant,
 | 
			
		||||
		min_block: Option<BlockNumber>,
 | 
			
		||||
		fetch_account: &F,
 | 
			
		||||
		gas_estimator: &G,
 | 
			
		||||
@ -635,7 +652,7 @@ impl TransactionQueue {
 | 
			
		||||
			let hash = tx.hash();
 | 
			
		||||
			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 {
 | 
			
		||||
				Ok(TransactionImportResult::Current) => {
 | 
			
		||||
					self.local_transactions.mark_pending(hash);
 | 
			
		||||
@ -656,7 +673,7 @@ impl TransactionQueue {
 | 
			
		||||
			}
 | 
			
		||||
			result
 | 
			
		||||
		} 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,
 | 
			
		||||
		tx: SignedTransaction,
 | 
			
		||||
		origin: TransactionOrigin,
 | 
			
		||||
		time: QueuingInstant,
 | 
			
		||||
		min_block: Option<BlockNumber>,
 | 
			
		||||
		fetch_account: &F,
 | 
			
		||||
		gas_estimator: &G,
 | 
			
		||||
@ -734,10 +752,10 @@ impl TransactionQueue {
 | 
			
		||||
		// Verify signature
 | 
			
		||||
		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 cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
 | 
			
		||||
		let cost = vtx.cost();
 | 
			
		||||
		if client_account.balance < cost {
 | 
			
		||||
			trace!(target: "txqueue",
 | 
			
		||||
				"Dropping transaction without sufficient balance: {:?} ({} < {})",
 | 
			
		||||
@ -759,7 +777,7 @@ 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) {
 | 
			
		||||
	pub fn cull(&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
 | 
			
		||||
@ -775,11 +793,11 @@ impl TransactionQueue {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		self.remove_all_internal(sender, client_nonce);
 | 
			
		||||
		self.cull_internal(sender, client_nonce);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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
 | 
			
		||||
		// so there will be no transactions from this sender in current
 | 
			
		||||
		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.
 | 
			
		||||
	pub fn remove_old<F>(&mut self, fetch_nonce: F) where
 | 
			
		||||
		F: Fn(&Address) -> U256,
 | 
			
		||||
	pub fn remove_old<F>(&mut self, fetch_account: &F, current_time: QueuingInstant) where
 | 
			
		||||
		F: Fn(&Address) -> AccountDetails,
 | 
			
		||||
	{
 | 
			
		||||
		let senders = self.current.by_address.keys()
 | 
			
		||||
			.chain(self.future.by_address.keys())
 | 
			
		||||
			.cloned()
 | 
			
		||||
			.collect::<HashSet<_>>();
 | 
			
		||||
			.map(|sender| (*sender, fetch_account(sender)))
 | 
			
		||||
			.collect::<HashMap<_, _>>();
 | 
			
		||||
 | 
			
		||||
		for sender in senders {
 | 
			
		||||
			self.remove_all(sender, fetch_nonce(&sender));
 | 
			
		||||
		for (sender, details) in senders.iter() {
 | 
			
		||||
			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.
 | 
			
		||||
	///
 | 
			
		||||
	/// If gap is introduced marks subsequent transactions as future
 | 
			
		||||
	pub fn remove_invalid<T>(&mut self, transaction_hash: &H256, fetch_account: &T)
 | 
			
		||||
		where T: Fn(&Address) -> AccountDetails {
 | 
			
		||||
	pub fn remove_invalid<T>(&mut self, transaction_hash: &H256, fetch_nonce: &T)
 | 
			
		||||
		where T: Fn(&Address) -> U256 {
 | 
			
		||||
 | 
			
		||||
		assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len());
 | 
			
		||||
		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 sender = transaction.sender();
 | 
			
		||||
		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());
 | 
			
		||||
 | 
			
		||||
@ -889,7 +936,7 @@ impl TransactionQueue {
 | 
			
		||||
		if order.is_some() {
 | 
			
		||||
			// This will keep consistency in queue
 | 
			
		||||
			// 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());
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@ -1039,7 +1086,7 @@ impl TransactionQueue {
 | 
			
		||||
 | 
			
		||||
	/// Finds transaction in the queue by hash (if any)
 | 
			
		||||
	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
 | 
			
		||||
@ -1388,14 +1435,14 @@ mod test {
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into());
 | 
			
		||||
		let sender = tx1.sender().unwrap();
 | 
			
		||||
		let nonce = tx1.nonce;
 | 
			
		||||
		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().pending, 2);
 | 
			
		||||
		assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into()));
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		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
 | 
			
		||||
		// 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(),
 | 
			
		||||
		};
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap();
 | 
			
		||||
		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap();
 | 
			
		||||
		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, 0, None).unwrap();
 | 
			
		||||
		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, 0, None).unwrap();
 | 
			
		||||
		let mut by_hash = {
 | 
			
		||||
			let mut x = HashMap::new();
 | 
			
		||||
			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap();
 | 
			
		||||
			let tx2 = VerifiedTransaction::new(tx2.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, 0, None).unwrap();
 | 
			
		||||
			x.insert(tx1.hash(), tx1);
 | 
			
		||||
			x.insert(tx2.hash(), tx2);
 | 
			
		||||
			x
 | 
			
		||||
@ -1470,12 +1517,12 @@ mod test {
 | 
			
		||||
		// Create two transactions with same nonce
 | 
			
		||||
		// (same hash)
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into());
 | 
			
		||||
		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap();
 | 
			
		||||
		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap();
 | 
			
		||||
		let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, 0, None).unwrap();
 | 
			
		||||
		let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, 0, None).unwrap();
 | 
			
		||||
		let by_hash = {
 | 
			
		||||
			let mut x = HashMap::new();
 | 
			
		||||
			let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap();
 | 
			
		||||
			let tx2 = VerifiedTransaction::new(tx2.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, 0, None).unwrap();
 | 
			
		||||
			x.insert(tx1.hash(), tx1);
 | 
			
		||||
			x.insert(tx2.hash(), tx2);
 | 
			
		||||
			x
 | 
			
		||||
@ -1517,10 +1564,10 @@ mod test {
 | 
			
		||||
			gas_limit: !U256::zero(),
 | 
			
		||||
		};
 | 
			
		||||
		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);
 | 
			
		||||
		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);
 | 
			
		||||
		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());
 | 
			
		||||
		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);
 | 
			
		||||
		assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none());
 | 
			
		||||
		assert_eq!(set.gas_price_entry_limit(), 2.into());
 | 
			
		||||
@ -1552,12 +1599,12 @@ mod test {
 | 
			
		||||
			!U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// 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!(txq.status().future, 1);
 | 
			
		||||
 | 
			
		||||
		// 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)
 | 
			
		||||
		assert_eq!(res.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1577,12 +1624,12 @@ mod test {
 | 
			
		||||
			!U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// 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!(txq.status().future, 1);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(res.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1601,7 +1648,7 @@ mod test {
 | 
			
		||||
		let tx = new_tx_default();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(res.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1620,10 +1667,10 @@ mod test {
 | 
			
		||||
		txq.set_minimal_gas_price(15.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res4 = txq.add(tx4, 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, 0, 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, 0, None, &default_account_details, &gas_estimator);
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(res1.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1654,10 +1701,10 @@ mod test {
 | 
			
		||||
		txq.set_minimal_gas_price(15.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res4 = txq.add(tx4, 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, 0, 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, 0, None, &default_account_details, &gas_estimator);
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(res1.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1700,7 +1747,7 @@ mod test {
 | 
			
		||||
		txq.set_gas_limit(limit);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded {
 | 
			
		||||
@ -1724,7 +1771,7 @@ mod test {
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance {
 | 
			
		||||
@ -1744,7 +1791,7 @@ mod test {
 | 
			
		||||
		txq.set_minimal_gas_price(tx.gas_price + U256::one());
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice {
 | 
			
		||||
@ -1764,7 +1811,7 @@ mod test {
 | 
			
		||||
		txq.set_minimal_gas_price(tx.gas_price + U256::one());
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(res.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -1794,7 +1841,7 @@ mod test {
 | 
			
		||||
			rlp::decode(s.as_raw())
 | 
			
		||||
		};
 | 
			
		||||
		// 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
 | 
			
		||||
		assert!(res.is_err());
 | 
			
		||||
@ -1808,8 +1855,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
@ -1828,9 +1875,9 @@ mod test {
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		// 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
 | 
			
		||||
		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
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
@ -1847,15 +1894,15 @@ mod test {
 | 
			
		||||
		// the second one has same nonce but higher `gas_price`
 | 
			
		||||
		let (_, tx0) = new_similar_tx_pair();
 | 
			
		||||
 | 
			
		||||
		txq.add(tx0.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx1.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		// the one with higher gas price is first
 | 
			
		||||
		assert_eq!(txq.top_transactions()[0], tx0);
 | 
			
		||||
		assert_eq!(txq.top_transactions()[1], tx1);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		// 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
 | 
			
		||||
		// the order should be updated
 | 
			
		||||
@ -1874,9 +1921,9 @@ mod test {
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		// 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
 | 
			
		||||
		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
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
@ -1892,8 +1939,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.clone(), TransactionOrigin::Local, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
@ -1912,10 +1959,10 @@ mod test {
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
 | 
			
		||||
 | 
			
		||||
		// insert everything
 | 
			
		||||
		txq.add(txa.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(txb.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, 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, 0, None, &prev_nonce, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		assert_eq!(txq.status().future, 4);
 | 
			
		||||
 | 
			
		||||
@ -1940,10 +1987,10 @@ mod test {
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
 | 
			
		||||
 | 
			
		||||
		// insert everything
 | 
			
		||||
		txq.add(txa.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(txb.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
		assert_eq!(top[0], tx1);
 | 
			
		||||
@ -1973,10 +2020,10 @@ mod test {
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
 | 
			
		||||
 | 
			
		||||
		// insert everything
 | 
			
		||||
		txq.add(txa.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(txb.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		let top = txq.top_transactions();
 | 
			
		||||
		assert_eq!(top[0], tx1);
 | 
			
		||||
@ -2005,8 +2052,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let top = txq.pending_hashes();
 | 
			
		||||
@ -2023,8 +2070,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(2.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let res1 = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		let res2 = txq.add(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(res1, TransactionImportResult::Current);
 | 
			
		||||
@ -2045,8 +2092,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let res1 = txq.add(tx.clone(), TransactionOrigin::External, Some(1), &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(res1, TransactionImportResult::Current);
 | 
			
		||||
@ -2067,12 +2114,12 @@ mod test {
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
 | 
			
		||||
		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(tx2.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, 0, None, &prev_nonce, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().future, 2);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
@ -2090,13 +2137,13 @@ mod test {
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
		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);
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2112,14 +2159,14 @@ mod test {
 | 
			
		||||
		// given
 | 
			
		||||
		let mut txq2 = TransactionQueue::default();
 | 
			
		||||
		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(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq2.status().pending, 1);
 | 
			
		||||
		assert_eq!(txq2.status().future, 1);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq2.remove_all(tx.sender().unwrap(), tx.nonce + U256::one());
 | 
			
		||||
		txq2.remove_all(tx2.sender().unwrap(), tx2.nonce + U256::one());
 | 
			
		||||
		txq2.cull(tx.sender().unwrap(), tx.nonce + U256::one());
 | 
			
		||||
		txq2.cull(tx2.sender().unwrap(), tx2.nonce + U256::one());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
@ -2134,14 +2181,14 @@ mod test {
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
		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);
 | 
			
		||||
		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().pending, 3);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.remove_invalid(&tx.hash(), &default_account_details);
 | 
			
		||||
		txq.remove_invalid(&tx.hash(), &|_| default_nonce());
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2156,8 +2203,8 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
 | 
			
		||||
		// add
 | 
			
		||||
		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
		assert_eq!(stats.pending, 2);
 | 
			
		||||
 | 
			
		||||
@ -2176,11 +2223,11 @@ mod test {
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
		let sender = tx.sender().unwrap();
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		let t = txq.top_transactions();
 | 
			
		||||
@ -2197,14 +2244,14 @@ mod test {
 | 
			
		||||
		txq.current.set_limit(10);
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_default(4.into(), 1.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(tx3.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().pending, 2);
 | 
			
		||||
 | 
			
		||||
		// 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);
 | 
			
		||||
		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
 | 
			
		||||
		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 (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));
 | 
			
		||||
		txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx3.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx3.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		// 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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -2229,12 +2276,12 @@ mod test {
 | 
			
		||||
		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 (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(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		// Not accepted because of limit
 | 
			
		||||
		txq.add(tx5.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err();
 | 
			
		||||
		txq.add(tx3.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx4.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx5.clone(), TransactionOrigin::External, 0, None, &default_account_details, &gas_estimator).unwrap_err();
 | 
			
		||||
		txq.add(tx3.clone(), TransactionOrigin::Local, 0, 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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -2246,7 +2293,7 @@ mod test {
 | 
			
		||||
		let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(unwrap_tx_err(res), TransactionError::Old);
 | 
			
		||||
@ -2262,12 +2309,12 @@ mod test {
 | 
			
		||||
			balance: !U256::zero() };
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		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().pending, 0);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported);
 | 
			
		||||
@ -2281,15 +2328,15 @@ mod test {
 | 
			
		||||
		// given
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		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(tx2.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().pending, 2);
 | 
			
		||||
 | 
			
		||||
		// 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().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
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2303,15 +2350,15 @@ mod test {
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
 | 
			
		||||
		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);
 | 
			
		||||
		txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx.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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().pending, 3);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let sender = tx.sender().unwrap();
 | 
			
		||||
		txq.remove_all(sender, default_nonce() + U256::one());
 | 
			
		||||
		txq.cull(sender, default_nonce() + U256::one());
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2333,8 +2380,8 @@ mod test {
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2361,10 +2408,10 @@ mod test {
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		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
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2376,18 +2423,16 @@ mod test {
 | 
			
		||||
	#[test]
 | 
			
		||||
	fn should_recalculate_height_when_removing_from_future() {
 | 
			
		||||
		// given
 | 
			
		||||
		let previous_nonce = |a: &Address| 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 previous_nonce = |a: &Address|
 | 
			
		||||
			AccountDetails { nonce: default_account_details(a).nonce - U256::one(), balance: !U256::zero() };
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		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(tx2, 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, 0, None, &previous_nonce, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.status().future, 2);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.remove_invalid(&tx1.hash(), &next_nonce);
 | 
			
		||||
		txq.remove_invalid(&tx1.hash(), &|_| default_nonce() + 1.into());
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		let stats = txq.status();
 | 
			
		||||
@ -2414,7 +2459,7 @@ mod test {
 | 
			
		||||
		let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.add(tx, TransactionOrigin::External, None, &details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx, TransactionOrigin::External, 0, None, &details, &gas_estimator).unwrap();
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(txq.last_nonce(&from), Some(nonce));
 | 
			
		||||
@ -2429,17 +2474,17 @@ mod test {
 | 
			
		||||
		let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one());
 | 
			
		||||
		txq.cull(tx2.sender().unwrap(), nonce2 + U256::one());
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert!(txq.top_transactions().is_empty());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#[test]
 | 
			
		||||
	fn should_return_valid_last_nonce_after_remove_all() {
 | 
			
		||||
	fn should_return_valid_last_nonce_after_cull() {
 | 
			
		||||
		// given
 | 
			
		||||
		let mut txq = TransactionQueue::default();
 | 
			
		||||
		let (tx1, tx2) = new_tx_pair_default(4.into(), 0.into());
 | 
			
		||||
@ -2449,11 +2494,11 @@ mod test {
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		// 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
 | 
			
		||||
		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
 | 
			
		||||
		txq.remove_all(sender, nonce2 - U256::from(1));
 | 
			
		||||
		txq.cull(sender, nonce2 - U256::from(1));
 | 
			
		||||
		// tx2 should be not be promoted to current
 | 
			
		||||
		assert_eq!(txq.status().pending, 0);
 | 
			
		||||
		assert_eq!(txq.status().future, 1);
 | 
			
		||||
@ -2470,9 +2515,9 @@ mod test {
 | 
			
		||||
		assert_eq!(txq.has_local_pending_transactions(), false);
 | 
			
		||||
 | 
			
		||||
		// 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.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
 | 
			
		||||
		assert_eq!(txq.has_local_pending_transactions(), true);
 | 
			
		||||
@ -2487,8 +2532,8 @@ mod test {
 | 
			
		||||
			default_account_details(a).balance };
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		assert_eq!(txq.add(tx2, TransactionOrigin::External, 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(tx2, TransactionOrigin::External, 0, 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
 | 
			
		||||
		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))
 | 
			
		||||
		};
 | 
			
		||||
		let sender = tx1.sender().unwrap();
 | 
			
		||||
		txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx3, 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, 0, 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.current.by_priority.len(), 3);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into());
 | 
			
		||||
@ -2536,8 +2581,8 @@ mod test {
 | 
			
		||||
		let high_gas = |_: &SignedTransaction| 100_001.into();
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		let res1 = txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res2 = txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &high_gas);
 | 
			
		||||
		let res1 = txq.add(tx1, TransactionOrigin::Local, 0, None, &default_account_details, &gas_estimator);
 | 
			
		||||
		let res2 = txq.add(tx2, TransactionOrigin::Local, 0, None, &default_account_details, &high_gas);
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		assert_eq!(res1.unwrap(), TransactionImportResult::Current);
 | 
			
		||||
@ -2554,20 +2599,45 @@ mod test {
 | 
			
		||||
		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 next_nonce = |_: &Address|
 | 
			
		||||
			AccountDetails { nonce: default_nonce() + U256::one(), balance: !U256::zero() };
 | 
			
		||||
 | 
			
		||||
		// Insert all transactions
 | 
			
		||||
		txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		txq.add(tx4, 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, 0, 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, 0, None, &default_account_details, &gas_estimator).unwrap();
 | 
			
		||||
		assert_eq!(txq.top_transactions().len(), 4);
 | 
			
		||||
 | 
			
		||||
		// when
 | 
			
		||||
		txq.remove_old(|_| nonce1 + U256::one());
 | 
			
		||||
		txq.remove_old(&next_nonce, 0);
 | 
			
		||||
 | 
			
		||||
		// then
 | 
			
		||||
		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]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user