mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
docs(txpool): update BestTransaction docs (#57)
This commit is contained in:
@ -10,10 +10,23 @@ use std::{
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
/// An iterator that returns transactions that can be executed on the current state.
|
||||
/// An iterator that returns transactions that can be executed on the current state (*best*
|
||||
/// transactions).
|
||||
///
|
||||
/// The [`PendingPool`] contains transactions that *could* all be executed on the current state, but
|
||||
/// only yields transactions that are ready to be executed now.
|
||||
/// While it contains all gapless transactions of a sender, it _always_ only returns the transaction
|
||||
/// with the current on chain nonce.
|
||||
pub struct BestTransactions<T: TransactionOrdering> {
|
||||
/// Contains a copy of _all_ transactions of the pending pool at the point in time this
|
||||
/// iterator was created.
|
||||
pub(crate) all: BTreeMap<TransactionId, Arc<PendingTransaction<T>>>,
|
||||
/// Transactions that can be executed right away: these have the expected nonce.
|
||||
///
|
||||
/// Once an `independent` transaction with the nonce `N` is returned, it unlocks `N+1`, which
|
||||
/// then can be moved from the `all` set to the `independent` set.
|
||||
pub(crate) independent: BTreeSet<PendingTransactionRef<T>>,
|
||||
/// There might be the case where a yielded transactions is invalid, this will track it.
|
||||
pub(crate) invalid: HashSet<TxHash>,
|
||||
}
|
||||
|
||||
@ -35,6 +48,7 @@ impl<T: TransactionOrdering> Iterator for BestTransactions<T> {
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
// Remove the next independent tx with the highest priority
|
||||
let best = self.independent.iter().next_back()?.clone();
|
||||
let best = self.independent.take(&best)?;
|
||||
let hash = best.transaction.hash();
|
||||
@ -58,3 +72,62 @@ impl<T: TransactionOrdering> Iterator for BestTransactions<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
pool::pending::PendingPool,
|
||||
test_util::{MockOrdering, MockTransaction, MockTransactionFactory},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_best_iter() {
|
||||
let mut pool = PendingPool::new(Arc::new(MockOrdering::default()));
|
||||
let mut f = MockTransactionFactory::default();
|
||||
|
||||
let num_tx = 10;
|
||||
// insert 10 gapless tx
|
||||
let tx = MockTransaction::eip1559();
|
||||
for nonce in 0..num_tx {
|
||||
let tx = tx.clone().rng_hash().with_nonce(nonce);
|
||||
let valid_tx = f.validated(tx);
|
||||
pool.add_transaction(Arc::new(valid_tx));
|
||||
}
|
||||
|
||||
let mut best = pool.best();
|
||||
assert_eq!(best.all.len(), num_tx as usize);
|
||||
assert_eq!(best.independent.len(), 1);
|
||||
|
||||
// check tx are returned in order
|
||||
for nonce in 0..num_tx {
|
||||
assert_eq!(best.independent.len(), 1);
|
||||
let tx = best.next().unwrap();
|
||||
assert_eq!(tx.nonce(), nonce);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_best_iter_invalid() {
|
||||
let mut pool = PendingPool::new(Arc::new(MockOrdering::default()));
|
||||
let mut f = MockTransactionFactory::default();
|
||||
|
||||
let num_tx = 10;
|
||||
// insert 10 gapless tx
|
||||
let tx = MockTransaction::eip1559();
|
||||
for nonce in 0..num_tx {
|
||||
let tx = tx.clone().rng_hash().with_nonce(nonce);
|
||||
let valid_tx = f.validated(tx);
|
||||
pool.add_transaction(Arc::new(valid_tx));
|
||||
}
|
||||
|
||||
let mut best = pool.best();
|
||||
|
||||
// mark the first tx as invalid
|
||||
let invalid = best.independent.iter().next().unwrap();
|
||||
best.mark_invalid(&invalid.transaction.clone());
|
||||
|
||||
// iterator is empty
|
||||
assert!(best.next().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,16 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// A pool of validated and gapless transactions that are ready on the current state and are waiting
|
||||
/// to be included in a block.
|
||||
/// A pool of validated and gapless transactions that are ready to be executed on the current state
|
||||
/// and are waiting to be included in a block.
|
||||
///
|
||||
/// This pool distinguishes between `independent` transactions and pending transactions. A
|
||||
/// transaction is `independent`, if it is in the pending pool, and it has the current on chain
|
||||
/// nonce of the sender. Meaning `independent` transactions can be executed right away, other
|
||||
/// pending transactions depend on at least one `independent` transaction.
|
||||
///
|
||||
/// Once an `independent` transaction was executed it *unlocks* the next nonce, if this transaction
|
||||
/// is also pending, then this will be moved to the `independent` queue.
|
||||
pub(crate) struct PendingPool<T: TransactionOrdering> {
|
||||
/// How to order transactions.
|
||||
ordering: Arc<T>,
|
||||
|
||||
Reference in New Issue
Block a user