EIP-168, 169: Dust protection (#4757)

* Dust protection

* Track touched accounts in the substate

* Minor alterations
This commit is contained in:
Arkadiy Paronyan
2017-06-28 09:10:57 +02:00
committed by GitHub
parent 6b16fe3f14
commit 57626b60e7
25 changed files with 270 additions and 85 deletions

View File

@@ -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;

View File

@@ -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);
}
}