Merge branch 'master' into tx-limit-conf
Conflicts: miner/src/transaction_queue.rs
This commit is contained in:
		
						commit
						3c67ac636b
					
				| @ -62,13 +62,18 @@ pub enum ExecutionError { | |||||||
| 	Internal | 	Internal | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| /// Errors concerning transaction processing.
 | /// Errors concerning transaction processing.
 | ||||||
| pub enum TransactionError { | pub enum TransactionError { | ||||||
| 	/// Transaction is already imported to the queue
 | 	/// Transaction is already imported to the queue
 | ||||||
| 	AlreadyImported, | 	AlreadyImported, | ||||||
| 	/// Transaction is not valid anymore (state already has higher nonce)
 | 	/// Transaction is not valid anymore (state already has higher nonce)
 | ||||||
| 	Old, | 	Old, | ||||||
|  | 	/// Transaction has too low fee
 | ||||||
|  | 	/// (there is already a transaction with the same sender-nonce but higher gas price)
 | ||||||
|  | 	TooCheapToReplace, | ||||||
|  | 	/// Transaction was not imported to the queue because limit has been reached.
 | ||||||
|  | 	LimitReached, | ||||||
| 	/// Transaction's gas price is below threshold.
 | 	/// Transaction's gas price is below threshold.
 | ||||||
| 	InsufficientGasPrice { | 	InsufficientGasPrice { | ||||||
| 		/// Minimal expected gas price
 | 		/// Minimal expected gas price
 | ||||||
| @ -153,7 +158,7 @@ pub enum BlockError { | |||||||
| 	UnknownUncleParent(H256), | 	UnknownUncleParent(H256), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq)] | ||||||
| /// Import to the block queue result
 | /// Import to the block queue result
 | ||||||
| pub enum ImportError { | pub enum ImportError { | ||||||
| 	/// Already in the block chain.
 | 	/// Already in the block chain.
 | ||||||
|  | |||||||
| @ -61,7 +61,7 @@ extern crate rayon; | |||||||
| mod miner; | mod miner; | ||||||
| mod transaction_queue; | mod transaction_queue; | ||||||
| 
 | 
 | ||||||
| pub use transaction_queue::{TransactionQueue, AccountDetails}; | pub use transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult}; | ||||||
| pub use miner::{Miner}; | pub use miner::{Miner}; | ||||||
| 
 | 
 | ||||||
| use util::{H256, U256, Address, Bytes}; | use util::{H256, U256, Address, Bytes}; | ||||||
| @ -151,15 +151,6 @@ pub trait MinerService : Send + Sync { | |||||||
| 	fn sensible_gas_limit(&self) -> U256 { x!(21000) } | 	fn sensible_gas_limit(&self) -> U256 { x!(21000) } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Represents the result of importing transaction.
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub enum TransactionImportResult { |  | ||||||
| 	/// Transaction was imported to current queue.
 |  | ||||||
| 	Current, |  | ||||||
| 	/// Transaction was imported to future queue.
 |  | ||||||
| 	Future |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// Mining status
 | /// Mining status
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct MinerStatus { | pub struct MinerStatus { | ||||||
|  | |||||||
| @ -86,14 +86,12 @@ | |||||||
| 
 | 
 | ||||||
| use std::default::Default; | use std::default::Default; | ||||||
| use std::cmp::{Ordering}; | use std::cmp::{Ordering}; | ||||||
| use std::collections::{HashMap, BTreeSet}; | use std::collections::{HashMap, HashSet, BTreeSet}; | ||||||
| use util::numbers::{Uint, U256}; | use util::numbers::{Uint, U256}; | ||||||
| use util::hash::{Address, H256}; | use util::hash::{Address, H256}; | ||||||
| use util::table::*; | use util::table::*; | ||||||
| use ethcore::transaction::*; | use ethcore::transaction::*; | ||||||
| use ethcore::error::{Error, TransactionError}; | use ethcore::error::{Error, TransactionError}; | ||||||
| use super::TransactionImportResult; |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| /// Light structure used to identify transaction and it's order
 | /// Light structure used to identify transaction and it's order
 | ||||||
| @ -206,10 +204,11 @@ impl TransactionSet { | |||||||
| 	/// Remove low priority transactions if there is more then specified by given `limit`.
 | 	/// Remove low priority transactions if there is more then specified by given `limit`.
 | ||||||
| 	///
 | 	///
 | ||||||
| 	/// It drops transactions from this set but also removes associated `VerifiedTransaction`.
 | 	/// It drops transactions from this set but also removes associated `VerifiedTransaction`.
 | ||||||
| 	fn enforce_limit(&mut self, by_hash: &mut HashMap<H256, VerifiedTransaction>) { | 	/// Returns hashes of transactions removed because of limit.
 | ||||||
|  | 	fn enforce_limit(&mut self, by_hash: &mut HashMap<H256, VerifiedTransaction>) -> Option<HashSet<H256>> { | ||||||
| 		let len = self.by_priority.len(); | 		let len = self.by_priority.len(); | ||||||
| 		if len <= self.limit { | 		if len <= self.limit { | ||||||
| 			return; | 			return None; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		let to_drop : Vec<(Address, U256)> = { | 		let to_drop : Vec<(Address, U256)> = { | ||||||
| @ -222,10 +221,17 @@ impl TransactionSet { | |||||||
| 				.collect() | 				.collect() | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		for (sender, nonce) in to_drop { | 		Some(to_drop | ||||||
| 			let order = self.drop(&sender, &nonce).expect("Transaction has just been found in `by_priority`; so it is in `by_address` also."); | 			.into_iter() | ||||||
| 			by_hash.remove(&order.hash).expect("Hash found in `by_priorty` matches the one dropped; so it is included in `by_hash`"); | 			.map(|(sender, nonce)| { | ||||||
| 		} | 				let order = self.drop(&sender, &nonce) | ||||||
|  | 					.expect("Transaction has just been found in `by_priority`; so it is in `by_address` also."); | ||||||
|  | 
 | ||||||
|  | 				by_hash.remove(&order.hash) | ||||||
|  | 					.expect("Hash found in `by_priorty` matches the one dropped; so it is included in `by_hash`"); | ||||||
|  | 				order.hash | ||||||
|  | 			}) | ||||||
|  | 			.collect::<HashSet<H256>>()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Drop transaction from this set (remove from `by_priority` and `by_address`)
 | 	/// Drop transaction from this set (remove from `by_priority` and `by_address`)
 | ||||||
| @ -259,6 +265,15 @@ pub struct TransactionQueueStatus { | |||||||
| 	pub future: usize, | 	pub future: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug, PartialEq)] | ||||||
|  | /// Represents the result of importing transaction.
 | ||||||
|  | pub enum TransactionImportResult { | ||||||
|  | 	/// Transaction was imported to current queue.
 | ||||||
|  | 	Current, | ||||||
|  | 	/// Transaction was imported to future queue.
 | ||||||
|  | 	Future | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Details of account
 | /// Details of account
 | ||||||
| pub struct AccountDetails { | pub struct AccountDetails { | ||||||
| 	/// Most recent account nonce
 | 	/// Most recent account nonce
 | ||||||
| @ -601,6 +616,7 @@ impl TransactionQueue { | |||||||
| 
 | 
 | ||||||
| 		let address = tx.sender(); | 		let address = tx.sender(); | ||||||
| 		let nonce = tx.nonce(); | 		let nonce = tx.nonce(); | ||||||
|  | 		let hash = tx.hash(); | ||||||
| 
 | 
 | ||||||
| 		let next_nonce = self.last_nonces | 		let next_nonce = self.last_nonces | ||||||
| 			.get(&address) | 			.get(&address) | ||||||
| @ -610,8 +626,8 @@ impl TransactionQueue { | |||||||
| 		// Check height
 | 		// Check height
 | ||||||
| 		if nonce > next_nonce { | 		if nonce > next_nonce { | ||||||
| 			// We have a gap - put to future
 | 			// We have a gap - put to future
 | ||||||
| 			Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash); | 			try!(check_too_cheap(Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash))); | ||||||
| 			self.future.enforce_limit(&mut self.by_hash); | 			try!(check_if_removed(&hash, self.future.enforce_limit(&mut self.by_hash))); | ||||||
| 			return Ok(TransactionImportResult::Future); | 			return Ok(TransactionImportResult::Future); | ||||||
| 		} else if nonce < state_nonce { | 		} else if nonce < state_nonce { | ||||||
| 			// Droping transaction
 | 			// Droping transaction
 | ||||||
| @ -619,7 +635,7 @@ impl TransactionQueue { | |||||||
| 			return Err(TransactionError::Old); | 			return Err(TransactionError::Old); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash); | 		try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash))); | ||||||
| 		// Keep track of highest nonce stored in current
 | 		// Keep track of highest nonce stored in current
 | ||||||
| 		self.last_nonces.insert(address, nonce); | 		self.last_nonces.insert(address, nonce); | ||||||
| 		// Update nonces of transactions in future
 | 		// Update nonces of transactions in future
 | ||||||
| @ -631,10 +647,10 @@ impl TransactionQueue { | |||||||
| 		if let Some(order) = self.future.drop(&address, &nonce) { | 		if let Some(order) = self.future.drop(&address, &nonce) { | ||||||
| 			// Let's insert that transaction to current (if it has higher gas_price)
 | 			// Let's insert that transaction to current (if it has higher gas_price)
 | ||||||
| 			let future_tx = self.by_hash.remove(&order.hash).unwrap(); | 			let future_tx = self.by_hash.remove(&order.hash).unwrap(); | ||||||
| 			Self::replace_transaction(future_tx, state_nonce, &mut self.current, &mut self.by_hash); | 			try!(check_too_cheap(Self::replace_transaction(future_tx, state_nonce, &mut self.current, &mut self.by_hash))); | ||||||
| 		} | 		} | ||||||
| 		// Also enforce the limit
 | 		// Also enforce the limit
 | ||||||
| 		self.current.enforce_limit(&mut self.by_hash); | 		try!(check_if_removed(&hash, self.current.enforce_limit(&mut self.by_hash))); | ||||||
| 
 | 
 | ||||||
| 		trace!(target: "miner", "status: {:?}", self.status()); | 		trace!(target: "miner", "status: {:?}", self.status()); | ||||||
| 		Ok(TransactionImportResult::Current) | 		Ok(TransactionImportResult::Current) | ||||||
| @ -644,13 +660,17 @@ impl TransactionQueue { | |||||||
| 	///
 | 	///
 | ||||||
| 	/// If there is already transaction with same `(sender, nonce)` it will be replaced iff `gas_price` is higher.
 | 	/// If there is already transaction with same `(sender, nonce)` it will be replaced iff `gas_price` is higher.
 | ||||||
| 	/// One of the transactions is dropped from set and also removed from queue entirely (from `by_hash`).
 | 	/// One of the transactions is dropped from set and also removed from queue entirely (from `by_hash`).
 | ||||||
| 	fn replace_transaction(tx: VerifiedTransaction, base_nonce: U256, set: &mut TransactionSet, by_hash: &mut HashMap<H256, VerifiedTransaction>) { | 	///
 | ||||||
|  | 	/// Returns `true` if transaction actually got to the queue (`false` if there was already a transaction with higher
 | ||||||
|  | 	/// gas_price)
 | ||||||
|  | 	fn replace_transaction(tx: VerifiedTransaction, base_nonce: U256, set: &mut TransactionSet, by_hash: &mut HashMap<H256, VerifiedTransaction>) -> bool { | ||||||
| 		let order = TransactionOrder::for_transaction(&tx, base_nonce); | 		let order = TransactionOrder::for_transaction(&tx, base_nonce); | ||||||
| 		let hash = tx.hash(); | 		let hash = tx.hash(); | ||||||
| 		let address = tx.sender(); | 		let address = tx.sender(); | ||||||
| 		let nonce = tx.nonce(); | 		let nonce = tx.nonce(); | ||||||
| 
 | 
 | ||||||
| 		by_hash.insert(hash, tx); | 		by_hash.insert(hash, tx); | ||||||
|  | 
 | ||||||
| 		if let Some(old) = set.insert(address, nonce, order.clone()) { | 		if let Some(old) = set.insert(address, nonce, order.clone()) { | ||||||
| 			// There was already transaction in queue. Let's check which one should stay
 | 			// There was already transaction in queue. Let's check which one should stay
 | ||||||
| 			let old_fee = old.gas_price; | 			let old_fee = old.gas_price; | ||||||
| @ -660,14 +680,35 @@ impl TransactionQueue { | |||||||
| 				set.insert(address, nonce, old); | 				set.insert(address, nonce, old); | ||||||
| 				// and remove new one
 | 				// and remove new one
 | ||||||
| 				by_hash.remove(&hash); | 				by_hash.remove(&hash); | ||||||
|  | 				false | ||||||
| 			} else { | 			} else { | ||||||
| 				// Make sure we remove old transaction entirely
 | 				// Make sure we remove old transaction entirely
 | ||||||
| 				by_hash.remove(&old.hash); | 				by_hash.remove(&old.hash); | ||||||
|  | 				true | ||||||
| 			} | 			} | ||||||
|  | 		} else { | ||||||
|  | 			true | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn check_too_cheap(is_in: bool) -> Result<(), TransactionError> { | ||||||
|  | 	if !is_in { | ||||||
|  | 		Err(TransactionError::TooCheapToReplace) | ||||||
|  | 	} else { | ||||||
|  | 		Ok(()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn check_if_removed(hash: &H256, dropped: Option<HashSet<H256>>) -> Result<(), TransactionError> { | ||||||
|  | 	match dropped { | ||||||
|  | 		Some(ref dropped) if dropped.contains(hash) => { | ||||||
|  | 			Err(TransactionError::LimitReached) | ||||||
|  | 		}, | ||||||
|  | 		_ => Ok(()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
| @ -675,9 +716,17 @@ mod test { | |||||||
| 	use util::table::*; | 	use util::table::*; | ||||||
| 	use util::*; | 	use util::*; | ||||||
| 	use ethcore::transaction::*; | 	use ethcore::transaction::*; | ||||||
|  | 	use ethcore::error::{Error, TransactionError}; | ||||||
| 	use super::*; | 	use super::*; | ||||||
| 	use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; | 	use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; | ||||||
| 
 | 
 | ||||||
|  | 	fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError { | ||||||
|  | 		match err.unwrap_err() { | ||||||
|  | 			Error::Transaction(e) => e, | ||||||
|  | 			_ => panic!("Expected transaction error!"), | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	fn new_unsigned_tx(nonce: U256) -> Transaction { | 	fn new_unsigned_tx(nonce: U256) -> Transaction { | ||||||
| 		Transaction { | 		Transaction { | ||||||
| 			action: Action::Create, | 			action: Action::Create, | ||||||
| @ -719,11 +768,16 @@ mod test { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn new_txs(second_nonce: U256) -> (SignedTransaction, SignedTransaction) { | 	fn new_txs(second_nonce: U256) -> (SignedTransaction, SignedTransaction) { | ||||||
|  | 		new_txs_with_gas_price_diff(second_nonce, U256::zero()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fn new_txs_with_gas_price_diff(second_nonce: U256, gas_price: U256) -> (SignedTransaction, SignedTransaction) { | ||||||
| 		let keypair = KeyPair::create().unwrap(); | 		let keypair = KeyPair::create().unwrap(); | ||||||
| 		let secret = &keypair.secret(); | 		let secret = &keypair.secret(); | ||||||
| 		let nonce = U256::from(123); | 		let nonce = U256::from(123); | ||||||
| 		let tx = new_unsigned_tx(nonce); | 		let tx = new_unsigned_tx(nonce); | ||||||
| 		let tx2 = new_unsigned_tx(nonce + second_nonce); | 		let mut tx2 = new_unsigned_tx(nonce + second_nonce); | ||||||
|  | 		tx2.gas_price = tx2.gas_price + gas_price; | ||||||
| 
 | 
 | ||||||
| 		(tx.sign(secret), tx2.sign(secret)) | 		(tx.sign(secret), tx2.sign(secret)) | ||||||
| 	} | 	} | ||||||
| @ -816,14 +870,14 @@ mod test { | |||||||
| 
 | 
 | ||||||
| 		// First insert one transaction to future
 | 		// First insert one transaction to future
 | ||||||
| 		let res = txq.add(tx, &prev_nonce); | 		let res = txq.add(tx, &prev_nonce); | ||||||
| 		assert!(res.is_ok()); | 		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(), &default_nonce); | 		let res = txq.add(tx2.clone(), &default_nonce); | ||||||
| 
 | 
 | ||||||
| 		// 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!(res.is_ok()); | 		assert_eq!(unwrap_tx_err(res), TransactionError::TooCheapToReplace); | ||||||
| 		assert_eq!(txq.status().pending, 1); | 		assert_eq!(txq.status().pending, 1); | ||||||
| 		assert_eq!(txq.status().future, 0); | 		assert_eq!(txq.status().future, 0); | ||||||
| 		assert_eq!(txq.current.by_priority.len(), 1); | 		assert_eq!(txq.current.by_priority.len(), 1); | ||||||
| @ -842,7 +896,7 @@ mod test { | |||||||
| 		let res = txq.add(tx, &default_nonce); | 		let res = txq.add(tx, &default_nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
| 		assert!(res.is_ok()); | 		assert_eq!(res.unwrap(), TransactionImportResult::Current); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 1); | 		assert_eq!(stats.pending, 1); | ||||||
| 	} | 	} | ||||||
| @ -866,12 +920,18 @@ mod test { | |||||||
| 		// given
 | 		// given
 | ||||||
| 		let mut txq = TransactionQueue::new(); | 		let mut txq = TransactionQueue::new(); | ||||||
| 		let tx = new_tx(); | 		let tx = new_tx(); | ||||||
| 		txq.set_gas_limit(tx.gas / U256::from(2)); | 		let gas = tx.gas; | ||||||
|  | 		let limit = gas / U256::from(2); | ||||||
|  | 		txq.set_gas_limit(limit); | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx, &default_nonce).unwrap_err(); | 		let res = txq.add(tx, &default_nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { | ||||||
|  | 			limit: U256::from(55_000), // Should be 110% of set_gas_limit
 | ||||||
|  | 			got: gas, | ||||||
|  | 		}); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 0); | 		assert_eq!(stats.pending, 0); | ||||||
| 		assert_eq!(stats.future, 0); | 		assert_eq!(stats.future, 0); | ||||||
| @ -889,9 +949,13 @@ mod test { | |||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx, &account).unwrap_err(); | 		let res = txq.add(tx, &account); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { | ||||||
|  | 			balance: U256::from(1), | ||||||
|  | 			cost: U256::from(100_100), | ||||||
|  | 		}); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 0); | 		assert_eq!(stats.pending, 0); | ||||||
| 		assert_eq!(stats.future, 0); | 		assert_eq!(stats.future, 0); | ||||||
| @ -905,9 +969,13 @@ mod test { | |||||||
| 		txq.set_minimal_gas_price(tx.gas_price + U256::one()); | 		txq.set_minimal_gas_price(tx.gas_price + U256::one()); | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx, &default_nonce).unwrap_err(); | 		let res = txq.add(tx, &default_nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { | ||||||
|  | 			minimal: U256::from(2), | ||||||
|  | 			got: U256::from(1), | ||||||
|  | 		}); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 0); | 		assert_eq!(stats.pending, 0); | ||||||
| 		assert_eq!(stats.future, 0); | 		assert_eq!(stats.future, 0); | ||||||
| @ -982,10 +1050,12 @@ mod test { | |||||||
| 		let (tx, tx2) = new_txs(U256::from(2)); | 		let (tx, tx2) = new_txs(U256::from(2)); | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx.clone(), &default_nonce).unwrap(); | 		let res1 = txq.add(tx.clone(), &default_nonce).unwrap(); | ||||||
| 		txq.add(tx2.clone(), &default_nonce).unwrap(); | 		let res2 = txq.add(tx2.clone(), &default_nonce).unwrap(); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(res1, TransactionImportResult::Current); | ||||||
|  | 		assert_eq!(res2, TransactionImportResult::Future); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 1); | 		assert_eq!(stats.pending, 1); | ||||||
| 		assert_eq!(stats.future, 1); | 		assert_eq!(stats.future, 1); | ||||||
| @ -1112,10 +1182,11 @@ mod test { | |||||||
| 		assert_eq!(txq.status().pending, 1); | 		assert_eq!(txq.status().pending, 1); | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx2.clone(), &default_nonce).unwrap(); | 		let res = txq.add(tx2.clone(), &default_nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
| 		let t = txq.top_transactions(); | 		let t = txq.top_transactions(); | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::LimitReached); | ||||||
| 		assert_eq!(txq.status().pending, 1); | 		assert_eq!(txq.status().pending, 1); | ||||||
| 		assert_eq!(t.len(), 1); | 		assert_eq!(t.len(), 1); | ||||||
| 		assert_eq!(t[0], tx); | 		assert_eq!(t[0], tx); | ||||||
| @ -1125,8 +1196,8 @@ mod test { | |||||||
| 	fn should_limit_future_transactions() { | 	fn should_limit_future_transactions() { | ||||||
| 		let mut txq = TransactionQueue::with_limit(1); | 		let mut txq = TransactionQueue::with_limit(1); | ||||||
| 		txq.current.set_limit(10); | 		txq.current.set_limit(10); | ||||||
| 		let (tx1, tx2) = new_txs(U256::from(4)); | 		let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1)); | ||||||
| 		let (tx3, tx4) = new_txs(U256::from(4)); | 		let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2)); | ||||||
| 		txq.add(tx1.clone(), &default_nonce).unwrap(); | 		txq.add(tx1.clone(), &default_nonce).unwrap(); | ||||||
| 		txq.add(tx3.clone(), &default_nonce).unwrap(); | 		txq.add(tx3.clone(), &default_nonce).unwrap(); | ||||||
| 		assert_eq!(txq.status().pending, 2); | 		assert_eq!(txq.status().pending, 2); | ||||||
| @ -1148,9 +1219,10 @@ 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
 | ||||||
| 		txq.add(tx, &fetch_last_nonce).unwrap_err(); | 		let res = txq.add(tx, &fetch_last_nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::Old); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.pending, 0); | 		assert_eq!(stats.pending, 0); | ||||||
| 		assert_eq!(stats.future, 0); | 		assert_eq!(stats.future, 0); | ||||||
| @ -1168,9 +1240,10 @@ mod test { | |||||||
| 		assert_eq!(txq.status().pending, 0); | 		assert_eq!(txq.status().pending, 0); | ||||||
| 
 | 
 | ||||||
| 		// when
 | 		// when
 | ||||||
| 		txq.add(tx2.clone(), &nonce).unwrap_err(); | 		let res = txq.add(tx2.clone(), &nonce); | ||||||
| 
 | 
 | ||||||
| 		// then
 | 		// then
 | ||||||
|  | 		assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); | ||||||
| 		let stats = txq.status(); | 		let stats = txq.status(); | ||||||
| 		assert_eq!(stats.future, 1); | 		assert_eq!(stats.future, 1); | ||||||
| 		assert_eq!(stats.pending, 0); | 		assert_eq!(stats.pending, 0); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user