EIP-168, 169: Dust protection (#4757)
* Dust protection * Track touched accounts in the substate * Minor alterations
This commit is contained in:
@@ -328,7 +328,10 @@ impl Miner {
|
||||
let _timer = PerfTimer::new("prepare_block");
|
||||
let chain_info = chain.chain_info();
|
||||
let (transactions, mut open_block, original_work_hash) = {
|
||||
let transactions = {self.transaction_queue.read().top_transactions_at(chain_info.best_block_number, chain_info.best_block_timestamp)};
|
||||
let nonce_cap = if chain_info.best_block_number + 1 >= self.engine.params().dust_protection_transition {
|
||||
Some((self.engine.params().nonce_cap_increment * (chain_info.best_block_number + 1)).into())
|
||||
} else { None };
|
||||
let transactions = {self.transaction_queue.read().top_transactions_at(chain_info.best_block_number, chain_info.best_block_timestamp, nonce_cap)};
|
||||
let mut sealing_work = self.sealing_work.lock();
|
||||
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash());
|
||||
let best_hash = chain_info.best_block_hash;
|
||||
|
||||
@@ -1084,11 +1084,11 @@ impl TransactionQueue {
|
||||
|
||||
/// Returns top transactions from the queue ordered by priority.
|
||||
pub fn top_transactions(&self) -> Vec<SignedTransaction> {
|
||||
self.top_transactions_at(BlockNumber::max_value(), u64::max_value())
|
||||
self.top_transactions_at(BlockNumber::max_value(), u64::max_value(), None)
|
||||
|
||||
}
|
||||
|
||||
fn filter_pending_transaction<F>(&self, best_block: BlockNumber, best_timestamp: u64, mut f: F)
|
||||
fn filter_pending_transaction<F>(&self, best_block: BlockNumber, best_timestamp: u64, nonce_cap: Option<U256>, mut f: F)
|
||||
where F: FnMut(&VerifiedTransaction) {
|
||||
|
||||
let mut delayed = HashSet::new();
|
||||
@@ -1098,6 +1098,11 @@ impl TransactionQueue {
|
||||
if delayed.contains(&sender) {
|
||||
continue;
|
||||
}
|
||||
if let Some(max_nonce) = nonce_cap {
|
||||
if tx.nonce() >= max_nonce {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let delay = match tx.condition {
|
||||
Some(Condition::Number(n)) => n > best_block,
|
||||
Some(Condition::Timestamp(t)) => t > best_timestamp,
|
||||
@@ -1112,16 +1117,16 @@ impl TransactionQueue {
|
||||
}
|
||||
|
||||
/// Returns top transactions from the queue ordered by priority.
|
||||
pub fn top_transactions_at(&self, best_block: BlockNumber, best_timestamp: u64) -> Vec<SignedTransaction> {
|
||||
pub fn top_transactions_at(&self, best_block: BlockNumber, best_timestamp: u64, nonce_cap: Option<U256>) -> Vec<SignedTransaction> {
|
||||
let mut r = Vec::new();
|
||||
self.filter_pending_transaction(best_block, best_timestamp, |tx| r.push(tx.transaction.clone()));
|
||||
self.filter_pending_transaction(best_block, best_timestamp, nonce_cap, |tx| r.push(tx.transaction.clone()));
|
||||
r
|
||||
}
|
||||
|
||||
/// Return all ready transactions.
|
||||
pub fn pending_transactions(&self, best_block: BlockNumber, best_timestamp: u64) -> Vec<PendingTransaction> {
|
||||
let mut r = Vec::new();
|
||||
self.filter_pending_transaction(best_block, best_timestamp, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.condition.clone())));
|
||||
self.filter_pending_transaction(best_block, best_timestamp, None, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.condition.clone())));
|
||||
r
|
||||
}
|
||||
|
||||
@@ -2205,9 +2210,9 @@ pub mod test {
|
||||
// then
|
||||
assert_eq!(res1, TransactionImportResult::Current);
|
||||
assert_eq!(res2, TransactionImportResult::Current);
|
||||
let top = txq.top_transactions_at(0, 0);
|
||||
let top = txq.top_transactions_at(0, 0, None);
|
||||
assert_eq!(top.len(), 0);
|
||||
let top = txq.top_transactions_at(1, 0);
|
||||
let top = txq.top_transactions_at(1, 0, None);
|
||||
assert_eq!(top.len(), 2);
|
||||
}
|
||||
|
||||
@@ -2809,4 +2814,19 @@ pub mod test {
|
||||
// then
|
||||
assert_eq!(txq.top_transactions().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_return_transactions_over_nonce_cap() {
|
||||
// given
|
||||
let keypair = Random.generate().unwrap();
|
||||
let mut txq = TransactionQueue::default();
|
||||
// when
|
||||
for nonce in 123..130 {
|
||||
let tx = new_unsigned_tx(nonce.into(), default_gas_val(), default_gas_price()).sign(keypair.secret(), None);
|
||||
txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap();
|
||||
}
|
||||
|
||||
// then
|
||||
assert_eq!(txq.top_transactions_at(BlockNumber::max_value(), u64::max_value(), Some(127.into())).len(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user