New Transaction Queue implementation (#8074)
* Implementation of Verifier, Scoring and Ready. * Queue in progress. * TransactionPool. * Prepare for txpool release. * Miner refactor [WiP] * WiP reworking miner. * Make it compile. * Add some docs. * Split blockchain access to a separate file. * Work on miner API. * Fix ethcore tests. * Refactor miner interface for sealing/work packages. * Implement next nonce. * RPC compiles. * Implement couple of missing methdods for RPC. * Add transaction queue listeners. * Compiles! * Clean-up and parallelize. * Get rid of RefCell in header. * Revert "Get rid of RefCell in header." This reverts commit 0f2424c9b7319a786e1565ea2a8a6d801a21b4fb. * Override Sync requirement. * Fix status display. * Unify logging. * Extract some cheap checks. * Measurements and optimizations. * Fix scoring bug, heap size of bug and add cache * Disable tx queueing and parallel verification. * Make ethcore and ethcore-miner compile again. * Make RPC compile again. * Bunch of txpool tests. * Migrate transaction queue tests. * Nonce Cap * Nonce cap cache and tests. * Remove stale future transactions from the queue. * Optimize scoring and write some tests. * Simple penalization. * Clean up and support for different scoring algorithms. * Add CLI parameters for the new queue. * Remove banning queue. * Disable debug build. * Change per_sender limit to be 1% instead of 5% * Avoid cloning when propagating transactions. * Remove old todo. * Post-review fixes. * Fix miner options default. * Implement back ready transactions for light client. * Get rid of from_pending_block * Pass rejection reason. * Add more details to drop. * Rollback heap size of. * Avoid cloning hashes when propagating and include more details on rejection. * Fix tests. * Introduce nonces cache. * Remove uneccessary hashes allocation. * Lower the mem limit. * Re-enable parallel verification. * Add miner log. Don't check the type if not below min_gas_price. * Add more traces, fix disabling miner. * Fix creating pending blocks twice on AuRa authorities. * Fix tests. * re-use pending blocks in AuRa * Use reseal_min_period to prevent too frequent update_sealing. * Fix log to contain hash not sender. * Optimize local transactions. * Fix aura tests. * Update locks comments. * Get rid of unsafe Sync impl. * Review fixes. * Remove excessive matches. * Fix compilation errors. * Use new pool in private transactions. * Fix private-tx test. * Fix secret store tests. * Actually use gas_floor_target * Fix config tests. * Fix pool tests. * Address grumbles.
This commit is contained in:
committed by
Marek Kotewicz
parent
03b96a7c0a
commit
1cd93e4ceb
@@ -21,11 +21,12 @@ use ethereum_types::U256;
|
||||
use {scoring, Scoring, Ready, Readiness, Address as Sender};
|
||||
use super::{Transaction, SharedTransaction};
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DummyScoring;
|
||||
|
||||
impl Scoring<Transaction> for DummyScoring {
|
||||
type Score = U256;
|
||||
type Event = ();
|
||||
|
||||
fn compare(&self, old: &Transaction, new: &Transaction) -> cmp::Ordering {
|
||||
old.nonce.cmp(&new.nonce)
|
||||
@@ -43,9 +44,17 @@ impl Scoring<Transaction> for DummyScoring {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_scores(&self, txs: &[SharedTransaction], scores: &mut [Self::Score], _change: scoring::Change) {
|
||||
for i in 0..txs.len() {
|
||||
scores[i] = txs[i].gas_price;
|
||||
fn update_scores(&self, txs: &[SharedTransaction], scores: &mut [Self::Score], change: scoring::Change) {
|
||||
if let scoring::Change::Event(_) = change {
|
||||
// In case of event reset all scores to 0
|
||||
for i in 0..txs.len() {
|
||||
scores[i] = 0.into();
|
||||
}
|
||||
} else {
|
||||
// Set to a gas price otherwise
|
||||
for i in 0..txs.len() {
|
||||
scores[i] = txs[i].gas_price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ fn should_reject_if_above_count() {
|
||||
let tx2 = b.tx().nonce(1).new();
|
||||
let hash = *tx2.hash();
|
||||
txq.import(tx1).unwrap();
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash));
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into()));
|
||||
assert_eq!(txq.light_status().transaction_count, 1);
|
||||
|
||||
txq.clear();
|
||||
@@ -151,7 +151,7 @@ fn should_reject_if_above_mem_usage() {
|
||||
let tx2 = b.tx().nonce(2).mem_usage(2).new();
|
||||
let hash = *tx2.hash();
|
||||
txq.import(tx1).unwrap();
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash));
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into()));
|
||||
assert_eq!(txq.light_status().transaction_count, 1);
|
||||
|
||||
txq.clear();
|
||||
@@ -177,7 +177,7 @@ fn should_reject_if_above_sender_count() {
|
||||
let tx2 = b.tx().nonce(2).new();
|
||||
let hash = *tx2.hash();
|
||||
txq.import(tx1).unwrap();
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash));
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into()));
|
||||
assert_eq!(txq.light_status().transaction_count, 1);
|
||||
|
||||
txq.clear();
|
||||
@@ -188,7 +188,7 @@ fn should_reject_if_above_sender_count() {
|
||||
let hash = *tx2.hash();
|
||||
txq.import(tx1).unwrap();
|
||||
// This results in error because we also compare nonces
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash));
|
||||
assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into()));
|
||||
assert_eq!(txq.light_status().transaction_count, 1);
|
||||
}
|
||||
|
||||
@@ -249,6 +249,66 @@ fn should_construct_pending() {
|
||||
assert_eq!(pending.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_update_scoring_correctly() {
|
||||
// given
|
||||
let b = TransactionBuilder::default();
|
||||
let mut txq = TestPool::default();
|
||||
|
||||
let tx0 = txq.import(b.tx().nonce(0).gas_price(5).new()).unwrap();
|
||||
let tx1 = txq.import(b.tx().nonce(1).gas_price(5).new()).unwrap();
|
||||
let tx2 = txq.import(b.tx().nonce(2).new()).unwrap();
|
||||
// this transaction doesn't get to the block despite high gas price
|
||||
// because of block gas limit and simplistic ordering algorithm.
|
||||
txq.import(b.tx().nonce(3).gas_price(4).new()).unwrap();
|
||||
//gap
|
||||
txq.import(b.tx().nonce(5).new()).unwrap();
|
||||
|
||||
let tx5 = txq.import(b.tx().sender(1).nonce(0).new()).unwrap();
|
||||
let tx6 = txq.import(b.tx().sender(1).nonce(1).new()).unwrap();
|
||||
let tx7 = txq.import(b.tx().sender(1).nonce(2).new()).unwrap();
|
||||
let tx8 = txq.import(b.tx().sender(1).nonce(3).gas_price(4).new()).unwrap();
|
||||
// gap
|
||||
txq.import(b.tx().sender(1).nonce(5).new()).unwrap();
|
||||
|
||||
let tx9 = txq.import(b.tx().sender(2).nonce(0).new()).unwrap();
|
||||
assert_eq!(txq.light_status().transaction_count, 11);
|
||||
assert_eq!(txq.status(NonceReady::default()), Status {
|
||||
stalled: 0,
|
||||
pending: 9,
|
||||
future: 2,
|
||||
});
|
||||
assert_eq!(txq.status(NonceReady::new(1)), Status {
|
||||
stalled: 3,
|
||||
pending: 6,
|
||||
future: 2,
|
||||
});
|
||||
|
||||
txq.update_scores(&0.into(), ());
|
||||
|
||||
// when
|
||||
let mut current_gas = U256::zero();
|
||||
let limit = (21_000 * 8).into();
|
||||
let mut pending = txq.pending(NonceReady::default()).take_while(|tx| {
|
||||
let should_take = tx.gas + current_gas <= limit;
|
||||
if should_take {
|
||||
current_gas = current_gas + tx.gas
|
||||
}
|
||||
should_take
|
||||
});
|
||||
|
||||
assert_eq!(pending.next(), Some(tx9));
|
||||
assert_eq!(pending.next(), Some(tx5));
|
||||
assert_eq!(pending.next(), Some(tx6));
|
||||
assert_eq!(pending.next(), Some(tx7));
|
||||
assert_eq!(pending.next(), Some(tx8));
|
||||
// penalized transactions
|
||||
assert_eq!(pending.next(), Some(tx0));
|
||||
assert_eq!(pending.next(), Some(tx1));
|
||||
assert_eq!(pending.next(), Some(tx2));
|
||||
assert_eq!(pending.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_remove_transaction() {
|
||||
// given
|
||||
@@ -375,6 +435,20 @@ fn should_re_insert_after_cull() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_worst_transaction() {
|
||||
// given
|
||||
let b = TransactionBuilder::default();
|
||||
let mut txq = TestPool::default();
|
||||
assert!(txq.worst_transaction().is_none());
|
||||
|
||||
// when
|
||||
txq.import(b.tx().nonce(0).gas_price(5).new()).unwrap();
|
||||
|
||||
// then
|
||||
assert!(txq.worst_transaction().is_some());
|
||||
}
|
||||
|
||||
mod listener {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
@@ -389,11 +463,11 @@ mod listener {
|
||||
self.0.borrow_mut().push(if old.is_some() { "replaced" } else { "added" });
|
||||
}
|
||||
|
||||
fn rejected(&mut self, _tx: Transaction) {
|
||||
fn rejected(&mut self, _tx: &SharedTransaction, _reason: &error::ErrorKind) {
|
||||
self.0.borrow_mut().push("rejected".into());
|
||||
}
|
||||
|
||||
fn dropped(&mut self, _tx: &SharedTransaction) {
|
||||
fn dropped(&mut self, _tx: &SharedTransaction, _new: Option<&Transaction>) {
|
||||
self.0.borrow_mut().push("dropped".into());
|
||||
}
|
||||
|
||||
@@ -401,8 +475,8 @@ mod listener {
|
||||
self.0.borrow_mut().push("invalid".into());
|
||||
}
|
||||
|
||||
fn cancelled(&mut self, _tx: &SharedTransaction) {
|
||||
self.0.borrow_mut().push("cancelled".into());
|
||||
fn canceled(&mut self, _tx: &SharedTransaction) {
|
||||
self.0.borrow_mut().push("canceled".into());
|
||||
}
|
||||
|
||||
fn mined(&mut self, _tx: &SharedTransaction) {
|
||||
@@ -461,9 +535,9 @@ mod listener {
|
||||
|
||||
// then
|
||||
txq.remove(&tx1.hash(), false);
|
||||
assert_eq!(*results.borrow(), &["added", "added", "cancelled"]);
|
||||
assert_eq!(*results.borrow(), &["added", "added", "canceled"]);
|
||||
txq.remove(&tx2.hash(), true);
|
||||
assert_eq!(*results.borrow(), &["added", "added", "cancelled", "invalid"]);
|
||||
assert_eq!(*results.borrow(), &["added", "added", "canceled", "invalid"]);
|
||||
assert_eq!(txq.light_status().transaction_count, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user