Optimize pending transactions filter (#9026)
* rpc: return unordered transactions in pending transactions filter * ethcore: use LruCache for nonce cache Only clear the nonce cache when a block is retracted * Revert "ethcore: use LruCache for nonce cache" This reverts commit b382c19abdb9985be1724c3b8cde83906da07d68. * Use only cached nonces when computing pending hashes. * Give filters their own locks, so that they don't block one another. * Fix pending transaction count if not sealing. * Clear cache only when block is enacted. * Fix RPC tests. * Address review comments.
This commit is contained in:
committed by
André Silva
parent
9438afde32
commit
08332f1945
@@ -19,7 +19,7 @@
|
||||
use std::{cmp, fmt};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{self, AtomicUsize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use parking_lot::RwLock;
|
||||
@@ -285,7 +285,20 @@ impl TransactionQueue {
|
||||
self.pool.read().pending(ready).collect()
|
||||
}
|
||||
|
||||
/// Returns current pneding transactions.
|
||||
/// Computes unordered set of pending hashes.
|
||||
///
|
||||
/// Since strict nonce-checking is not required, you may get some false positive future transactions as well.
|
||||
pub fn pending_hashes<N>(
|
||||
&self,
|
||||
nonce: N,
|
||||
) -> BTreeSet<H256> where
|
||||
N: Fn(&Address) -> Option<U256>,
|
||||
{
|
||||
let ready = ready::OptionalState::new(nonce);
|
||||
self.pool.read().pending(ready).map(|tx| tx.hash).collect()
|
||||
}
|
||||
|
||||
/// Returns current pending transactions ordered by priority.
|
||||
///
|
||||
/// NOTE: This may return a cached version of pending transaction set.
|
||||
/// Re-computing the pending set is possible with `#collect_pending` method,
|
||||
|
||||
@@ -130,6 +130,43 @@ impl txpool::Ready<VerifiedTransaction> for Condition {
|
||||
}
|
||||
}
|
||||
|
||||
/// Readiness checker that only relies on nonce cache (does actually go to state).
|
||||
///
|
||||
/// Checks readiness of transactions by comparing the nonce to state nonce. If nonce
|
||||
/// isn't found in provided state nonce store, defaults to the tx nonce and updates
|
||||
/// the nonce store. Useful for using with a state nonce cache when false positives are allowed.
|
||||
pub struct OptionalState<C> {
|
||||
nonces: HashMap<Address, U256>,
|
||||
state: C,
|
||||
}
|
||||
|
||||
impl<C> OptionalState<C> {
|
||||
pub fn new(state: C) -> Self {
|
||||
OptionalState {
|
||||
nonces: Default::default(),
|
||||
state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Fn(&Address) -> Option<U256>> txpool::Ready<VerifiedTransaction> for OptionalState<C> {
|
||||
fn is_ready(&mut self, tx: &VerifiedTransaction) -> txpool::Readiness {
|
||||
let sender = tx.sender();
|
||||
let state = &self.state;
|
||||
let nonce = self.nonces.entry(*sender).or_insert_with(|| {
|
||||
state(sender).unwrap_or_else(|| tx.transaction.nonce)
|
||||
});
|
||||
match tx.transaction.nonce.cmp(nonce) {
|
||||
cmp::Ordering::Greater => txpool::Readiness::Future,
|
||||
cmp::Ordering::Less => txpool::Readiness::Stale,
|
||||
cmp::Ordering::Equal => {
|
||||
*nonce = *nonce + 1.into();
|
||||
txpool::Readiness::Ready
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user