Prioritizing of local transaction (#1023)

* Changing is_local flag to TransactionOrigin enum

* Prioritize local transactions
This commit is contained in:
Tomasz Drwięga 2016-05-03 16:14:33 +02:00 committed by Gav Wood
parent 8f56b21ca9
commit 1583f7d434
4 changed files with 133 additions and 85 deletions

View File

@ -56,7 +56,7 @@ mod miner;
mod external; mod external;
mod transaction_queue; mod transaction_queue;
pub use transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult}; pub use transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
pub use miner::{Miner}; pub use miner::{Miner};
pub use external::{ExternalMiner, ExternalMinerService}; pub use external::{ExternalMiner, ExternalMinerService};

View File

@ -24,7 +24,7 @@ use ethcore::block::{ClosedBlock, IsBlock};
use ethcore::error::*; use ethcore::error::*;
use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions};
use ethcore::transaction::SignedTransaction; use ethcore::transaction::SignedTransaction;
use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult}; use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
/// Keeps track of transactions using priority queue and holds currently mined block. /// Keeps track of transactions using priority queue and holds currently mined block.
pub struct Miner { pub struct Miner {
@ -305,9 +305,8 @@ impl MinerService for Miner {
Vec<Result<TransactionImportResult, Error>> Vec<Result<TransactionImportResult, Error>>
where T: Fn(&Address) -> AccountDetails { where T: Fn(&Address) -> AccountDetails {
let mut transaction_queue = self.transaction_queue.lock().unwrap(); let mut transaction_queue = self.transaction_queue.lock().unwrap();
let is_local = false;
transactions.into_iter() transactions.into_iter()
.map(|tx| transaction_queue.add(tx, &fetch_account, is_local)) .map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
.collect() .collect()
} }
@ -320,7 +319,7 @@ impl MinerService for Miner {
let imported = { let imported = {
// Be sure to release the lock before we call enable_and_prepare_sealing // Be sure to release the lock before we call enable_and_prepare_sealing
let mut transaction_queue = self.transaction_queue.lock().unwrap(); let mut transaction_queue = self.transaction_queue.lock().unwrap();
let import = transaction_queue.add(transaction, &fetch_account, true); let import = transaction_queue.add(transaction, &fetch_account, TransactionOrigin::Local);
match import { match import {
Ok(ref res) => { Ok(ref res) => {

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
// TODO [todr] - own transactions should have higher priority
//! Transaction Queue //! Transaction Queue
//! //!
//! `TransactionQueue` keeps track of all transactions seen by the node (received from other peers) and own transactions //! `TransactionQueue` keeps track of all transactions seen by the node (received from other peers) and own transactions
@ -34,7 +32,7 @@
//! use util::crypto::KeyPair; //! use util::crypto::KeyPair;
//! use util::hash::Address; //! use util::hash::Address;
//! use util::numbers::{Uint, U256}; //! use util::numbers::{Uint, U256};
//! use ethminer::{TransactionQueue, AccountDetails}; //! use ethminer::{TransactionQueue, AccountDetails, TransactionOrigin};
//! use ethcore::transaction::*; //! use ethcore::transaction::*;
//! use rustc_serialize::hex::FromHex; //! use rustc_serialize::hex::FromHex;
//! //!
@ -53,8 +51,8 @@
//! }; //! };
//! //!
//! let mut txq = TransactionQueue::new(); //! let mut txq = TransactionQueue::new();
//! txq.add(st2.clone(), &default_nonce, false).unwrap(); //! txq.add(st2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
//! txq.add(st1.clone(), &default_nonce, false).unwrap(); //! txq.add(st1.clone(), &default_nonce, TransactionOrigin::External).unwrap();
//! //!
//! // Check status //! // Check status
//! assert_eq!(txq.status().pending, 2); //! assert_eq!(txq.status().pending, 2);
@ -94,6 +92,35 @@ use util::table::*;
use ethcore::transaction::*; use ethcore::transaction::*;
use ethcore::error::{Error, TransactionError}; use ethcore::error::{Error, TransactionError};
/// Transaction origin
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TransactionOrigin {
/// Transaction coming from local RPC
Local,
/// External transaction received from network
External,
}
impl PartialOrd for TransactionOrigin {
fn partial_cmp(&self, other: &TransactionOrigin) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TransactionOrigin {
fn cmp(&self, other: &TransactionOrigin) -> Ordering {
if *other == *self {
return Ordering::Equal;
}
if *self == TransactionOrigin::Local {
Ordering::Less
} else {
Ordering::Greater
}
}
}
#[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
struct TransactionOrder { struct TransactionOrder {
@ -106,8 +133,8 @@ struct TransactionOrder {
gas_price: U256, gas_price: U256,
/// Hash to identify associated transaction /// Hash to identify associated transaction
hash: H256, hash: H256,
/// Set to true if transaction has been dispatched localy /// Origin of the transaction
is_local: bool, origin: TransactionOrigin,
} }
@ -117,7 +144,7 @@ impl TransactionOrder {
nonce_height: tx.nonce() - base_nonce, nonce_height: tx.nonce() - base_nonce,
gas_price: tx.transaction.gas_price, gas_price: tx.transaction.gas_price,
hash: tx.hash(), hash: tx.hash(),
is_local: tx.is_local, origin: tx.origin,
} }
} }
@ -138,8 +165,14 @@ impl PartialOrd for TransactionOrder {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
impl Ord for TransactionOrder { impl Ord for TransactionOrder {
fn cmp(&self, b: &TransactionOrder) -> Ordering { fn cmp(&self, b: &TransactionOrder) -> Ordering {
// Local transactions should always have priority
if self.origin != b.origin {
return self.origin.cmp(&b.origin);
}
// First check nonce_height // First check nonce_height
if self.nonce_height != b.nonce_height { if self.nonce_height != b.nonce_height {
return self.nonce_height.cmp(&b.nonce_height); return self.nonce_height.cmp(&b.nonce_height);
@ -161,15 +194,15 @@ impl Ord for TransactionOrder {
struct VerifiedTransaction { struct VerifiedTransaction {
/// Transaction /// Transaction
transaction: SignedTransaction, transaction: SignedTransaction,
/// Is it local transaction? /// transaction origin
is_local: bool, origin: TransactionOrigin,
} }
impl VerifiedTransaction { impl VerifiedTransaction {
fn new(transaction: SignedTransaction, is_local: bool) -> Result<Self, Error> { fn new(transaction: SignedTransaction, origin: TransactionOrigin) -> Result<Self, Error> {
try!(transaction.sender()); try!(transaction.sender());
Ok(VerifiedTransaction { Ok(VerifiedTransaction {
transaction: transaction, transaction: transaction,
is_local: is_local, origin: origin,
}) })
} }
@ -392,7 +425,7 @@ impl TransactionQueue {
} }
/// Add signed transaction to queue to be verified and imported /// Add signed transaction to queue to be verified and imported
pub fn add<T>(&mut self, tx: SignedTransaction, fetch_account: &T, is_local: bool) -> Result<TransactionImportResult, Error> pub fn add<T>(&mut self, tx: SignedTransaction, fetch_account: &T, origin: TransactionOrigin) -> Result<TransactionImportResult, Error>
where T: Fn(&Address) -> AccountDetails { where T: Fn(&Address) -> AccountDetails {
trace!(target: "miner", "Importing: {:?}", tx.hash()); trace!(target: "miner", "Importing: {:?}", tx.hash());
@ -421,7 +454,7 @@ impl TransactionQueue {
})); }));
} }
let vtx = try!(VerifiedTransaction::new(tx, is_local)); let vtx = try!(VerifiedTransaction::new(tx, origin));
let client_account = fetch_account(&vtx.sender()); let client_account = fetch_account(&vtx.sender());
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
@ -556,7 +589,7 @@ impl TransactionQueue {
/// Returns true if there is at least one local transaction pending /// Returns true if there is at least one local transaction pending
pub fn has_local_pending_transactions(&self) -> bool { pub fn has_local_pending_transactions(&self) -> bool {
self.current.by_priority.iter().any(|tx| tx.is_local) self.current.by_priority.iter().any(|tx| tx.origin == TransactionOrigin::Local)
} }
/// Finds transaction in the queue by hash (if any) /// Finds transaction in the queue by hash (if any)
@ -820,12 +853,12 @@ mod test {
limit: 1 limit: 1
}; };
let (tx1, tx2) = new_txs(U256::from(1)); let (tx1, tx2) = new_txs(U256::from(1));
let tx1 = VerifiedTransaction::new(tx1, false).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap();
let tx2 = VerifiedTransaction::new(tx2, false).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap();
let mut by_hash = { let mut by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), false).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), false).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -861,12 +894,12 @@ mod test {
// Create two transactions with same nonce // Create two transactions with same nonce
// (same hash) // (same hash)
let (tx1, tx2) = new_txs(U256::from(0)); let (tx1, tx2) = new_txs(U256::from(0));
let tx1 = VerifiedTransaction::new(tx1, false).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap();
let tx2 = VerifiedTransaction::new(tx2, false).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap();
let by_hash = { let by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), false).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), false).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -898,12 +931,12 @@ mod test {
!U256::zero() }; !U256::zero() };
// First insert one transaction to future // First insert one transaction to future
let res = txq.add(tx, &prev_nonce, false); let res = txq.add(tx, &prev_nonce, TransactionOrigin::External);
assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(res.unwrap(), TransactionImportResult::Future);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// now import second transaction to current // now import second transaction to current
let res = txq.add(tx2.clone(), &default_nonce, false); let res = txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External);
// and then there should be only one transaction in current (the one with higher gas_price) // and then there should be only one transaction in current (the one with higher gas_price)
assert_eq!(unwrap_tx_err(res), TransactionError::TooCheapToReplace); assert_eq!(unwrap_tx_err(res), TransactionError::TooCheapToReplace);
@ -922,7 +955,7 @@ mod test {
let tx = new_tx(); let tx = new_tx();
// when // when
let res = txq.add(tx, &default_nonce, false); let res = txq.add(tx, &default_nonce, TransactionOrigin::External);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -954,7 +987,7 @@ mod test {
txq.set_gas_limit(limit); txq.set_gas_limit(limit);
// when // when
let res = txq.add(tx, &default_nonce, false); let res = txq.add(tx, &default_nonce, TransactionOrigin::External);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded {
@ -978,7 +1011,7 @@ mod test {
}; };
// when // when
let res = txq.add(tx, &account, false); let res = txq.add(tx, &account, TransactionOrigin::External);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance {
@ -998,7 +1031,7 @@ mod test {
txq.set_minimal_gas_price(tx.gas_price + U256::one()); txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when // when
let res = txq.add(tx, &default_nonce, false); let res = txq.add(tx, &default_nonce, TransactionOrigin::External);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice {
@ -1029,7 +1062,7 @@ mod test {
decode(s.as_raw()) decode(s.as_raw())
}; };
// when // when
let res = txq.add(stx, &default_nonce, false); let res = txq.add(stx, &default_nonce, TransactionOrigin::External);
// then // then
assert!(res.is_err()); assert!(res.is_err());
@ -1043,8 +1076,8 @@ mod test {
let (tx, tx2) = new_txs(U256::from(1)); let (tx, tx2) = new_txs(U256::from(1));
// when // when
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1053,6 +1086,23 @@ mod test {
assert_eq!(top.len(), 2); assert_eq!(top.len(), 2);
} }
#[test]
fn should_prioritize_local_transactions() {
// given
let mut txq = TransactionQueue::new();
let (tx, tx2) = new_txs(U256::from(1));
// when
txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_nonce, TransactionOrigin::Local).unwrap();
// then
let top = txq.top_transactions();
assert_eq!(top[0], tx2);
assert_eq!(top[1], tx);
assert_eq!(top.len(), 2);
}
#[test] #[test]
fn should_return_pending_hashes() { fn should_return_pending_hashes() {
// given // given
@ -1061,8 +1111,8 @@ mod test {
let (tx, tx2) = new_txs(U256::from(1)); let (tx, tx2) = new_txs(U256::from(1));
// when // when
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let top = txq.pending_hashes(); let top = txq.pending_hashes();
@ -1079,8 +1129,8 @@ mod test {
let (tx, tx2) = new_txs(U256::from(2)); let (tx, tx2) = new_txs(U256::from(2));
// when // when
let res1 = txq.add(tx.clone(), &default_nonce, false).unwrap(); let res1 = txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
let res2 = txq.add(tx2.clone(), &default_nonce, false).unwrap(); let res2 = txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
// then // then
assert_eq!(res1, TransactionImportResult::Current); assert_eq!(res1, TransactionImportResult::Current);
@ -1103,8 +1153,8 @@ mod test {
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (tx, tx2) = new_txs(U256::from(1)); let (tx, tx2) = new_txs(U256::from(1));
txq.add(tx.clone(), &prev_nonce, false).unwrap(); txq.add(tx.clone(), &prev_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &prev_nonce, false).unwrap(); txq.add(tx2.clone(), &prev_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
@ -1126,13 +1176,13 @@ mod test {
let tx1 = new_unsigned_tx(U256::from(124)).sign(&secret); let tx1 = new_unsigned_tx(U256::from(124)).sign(&secret);
let tx2 = new_unsigned_tx(U256::from(125)).sign(&secret); let tx2 = new_unsigned_tx(U256::from(125)).sign(&secret);
txq.add(tx, &default_nonce, false).unwrap(); txq.add(tx, &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
txq.add(tx2, &default_nonce, false).unwrap(); txq.add(tx2, &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// when // when
txq.add(tx1, &default_nonce, false).unwrap(); txq.add(tx1, &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -1145,8 +1195,8 @@ mod test {
// given // given
let mut txq2 = TransactionQueue::new(); let mut txq2 = TransactionQueue::new();
let (tx, tx2) = new_txs(U256::from(3)); let (tx, tx2) = new_txs(U256::from(3));
txq2.add(tx.clone(), &default_nonce, false).unwrap(); txq2.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq2.add(tx2.clone(), &default_nonce, false).unwrap(); txq2.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq2.status().pending, 1); assert_eq!(txq2.status().pending, 1);
assert_eq!(txq2.status().future, 1); assert_eq!(txq2.status().future, 1);
@ -1167,10 +1217,10 @@ mod test {
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (tx, tx2) = new_txs(U256::from(1)); let (tx, tx2) = new_txs(U256::from(1));
let tx3 = new_tx(); let tx3 = new_tx();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), &default_nonce, false).unwrap(); txq.add(tx3.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
@ -1189,8 +1239,8 @@ mod test {
let (tx, tx2) = new_txs(U256::one()); let (tx, tx2) = new_txs(U256::one());
// add // add
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
let stats = txq.status(); let stats = txq.status();
assert_eq!(stats.pending, 2); assert_eq!(stats.pending, 2);
@ -1209,11 +1259,11 @@ mod test {
let (tx, tx2) = new_txs(U256::one()); let (tx, tx2) = new_txs(U256::one());
let sender = tx.sender().unwrap(); let sender = tx.sender().unwrap();
let nonce = tx.nonce; let nonce = tx.nonce;
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
// when // when
let res = txq.add(tx2.clone(), &default_nonce, false); let res = txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External);
// then // then
let t = txq.top_transactions(); let t = txq.top_transactions();
@ -1232,13 +1282,13 @@ mod test {
let (tx1, tx2) = new_txs(U256::one()); let (tx1, tx2) = new_txs(U256::one());
let sender = tx1.sender().unwrap(); let sender = tx1.sender().unwrap();
let nonce = tx1.nonce; let nonce = tx1.nonce;
txq.add(tx1.clone(), &default_nonce, false).unwrap(); txq.add(tx1.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
assert_eq!(txq.last_nonce(&sender), Some(nonce + U256::one())); assert_eq!(txq.last_nonce(&sender), Some(nonce + U256::one()));
// when // when
let res = txq.add(tx.clone(), &default_nonce, false); let res = txq.add(tx.clone(), &default_nonce, TransactionOrigin::External);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1252,14 +1302,14 @@ mod test {
txq.current.set_limit(10); txq.current.set_limit(10);
let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1)); let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1));
let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2)); let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2));
txq.add(tx1.clone(), &default_nonce, false).unwrap(); txq.add(tx1.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx3.clone(), &default_nonce, false).unwrap(); txq.add(tx3.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx4.clone(), &default_nonce, false).unwrap(); txq.add(tx4.clone(), &default_nonce, TransactionOrigin::External).unwrap();
// then // then
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
@ -1273,7 +1323,7 @@ mod test {
let fetch_last_nonce = |_a: &Address| AccountDetails{ nonce: last_nonce, balance: !U256::zero() }; let fetch_last_nonce = |_a: &Address| AccountDetails{ nonce: last_nonce, balance: !U256::zero() };
// when // when
let res = txq.add(tx, &fetch_last_nonce, false); let res = txq.add(tx, &fetch_last_nonce, TransactionOrigin::External);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::Old); assert_eq!(unwrap_tx_err(res), TransactionError::Old);
@ -1289,12 +1339,12 @@ mod test {
balance: !U256::zero() }; balance: !U256::zero() };
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (_tx1, tx2) = new_txs(U256::from(1)); let (_tx1, tx2) = new_txs(U256::from(1));
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
// when // when
let res = txq.add(tx2.clone(), &nonce, false); let res = txq.add(tx2.clone(), &nonce, TransactionOrigin::External);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported);
@ -1308,15 +1358,15 @@ mod test {
// given // given
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (tx1, tx2) = new_txs(U256::from(1)); let (tx1, tx2) = new_txs(U256::from(1));
txq.add(tx1.clone(), &default_nonce, false).unwrap(); txq.add(tx1.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.remove_invalid(&tx1.hash(), &default_nonce); txq.remove_invalid(&tx1.hash(), &default_nonce);
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx1.clone(), &default_nonce, false).unwrap(); txq.add(tx1.clone(), &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -1330,10 +1380,10 @@ mod test {
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (tx, tx2) = new_txs(U256::from(1)); let (tx, tx2) = new_txs(U256::from(1));
let tx3 = new_tx(); let tx3 = new_tx();
txq.add(tx2.clone(), &default_nonce, false).unwrap(); txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), &default_nonce, false).unwrap(); txq.add(tx3.clone(), &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx.clone(), &default_nonce, false).unwrap(); txq.add(tx.clone(), &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
@ -1360,8 +1410,8 @@ mod test {
}; };
// when // when
txq.add(tx, &default_nonce, false).unwrap(); txq.add(tx, &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2, &default_nonce, false).unwrap(); txq.add(tx2, &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -1388,10 +1438,10 @@ mod test {
}; };
// when // when
txq.add(tx1, &default_nonce, false).unwrap(); txq.add(tx1, &default_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2, &default_nonce, false).unwrap(); txq.add(tx2, &default_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx0, &default_nonce, false).unwrap(); txq.add(tx0, &default_nonce, TransactionOrigin::External).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -1409,8 +1459,8 @@ mod test {
!U256::zero() }; !U256::zero() };
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let (tx1, tx2) = new_txs(U256::one()); let (tx1, tx2) = new_txs(U256::one());
txq.add(tx1.clone(), &previous_nonce, false).unwrap(); txq.add(tx1.clone(), &previous_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2, &previous_nonce, false).unwrap(); txq.add(tx2, &previous_nonce, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
@ -1441,7 +1491,7 @@ mod test {
let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() }; let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
// when // when
txq.add(tx, &details, false).unwrap(); txq.add(tx, &details, TransactionOrigin::External).unwrap();
// then // then
assert_eq!(txq.last_nonce(&from), Some(nonce)); assert_eq!(txq.last_nonce(&from), Some(nonce));
@ -1456,7 +1506,7 @@ mod test {
let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() }; let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() };
// Insert first transaction // Insert first transaction
txq.add(tx1, &details1, false).unwrap(); txq.add(tx1, &details1, TransactionOrigin::External).unwrap();
// when // when
txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one()); txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one());
@ -1476,9 +1526,9 @@ mod test {
// when // when
// Insert first transaction // Insert first transaction
assert_eq!(txq.add(tx1, &details1, false).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, &details1, TransactionOrigin::External).unwrap(), TransactionImportResult::Current);
// Second should go to future // Second should go to future
assert_eq!(txq.add(tx2, &details1, false).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx2, &details1, TransactionOrigin::External).unwrap(), TransactionImportResult::Future);
// Now block is imported // Now block is imported
txq.remove_all(sender, nonce2 - U256::from(1)); txq.remove_all(sender, nonce2 - U256::from(1));
// tx2 should be not be promoted to current // tx2 should be not be promoted to current
@ -1497,9 +1547,9 @@ mod test {
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
// when // when
assert_eq!(txq.add(tx1, &default_nonce, false).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, &default_nonce, TransactionOrigin::External).unwrap(), TransactionImportResult::Current);
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
assert_eq!(txq.add(tx2, &default_nonce, true).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx2, &default_nonce, TransactionOrigin::Local).unwrap(), TransactionImportResult::Current);
// then // then
assert_eq!(txq.has_local_pending_transactions(), true); assert_eq!(txq.has_local_pending_transactions(), true);

View File

@ -1357,7 +1357,6 @@ impl ChainSync {
trace!(target: "sync", "Bad blocks in the queue, restarting"); trace!(target: "sync", "Bad blocks in the queue, restarting");
self.restart_on_bad_block(io); self.restart_on_bad_block(io);
} }
// TODO [todr] propagate transactions?
} }
pub fn chain_new_head(&mut self, io: &mut SyncIo) { pub fn chain_new_head(&mut self, io: &mut SyncIo) {