mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(txpool): function to return the next free nonce (#11744)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -59,6 +59,11 @@ impl SenderId {
|
||||
pub const fn start_bound(self) -> std::ops::Bound<TransactionId> {
|
||||
std::ops::Bound::Included(TransactionId::new(self, 0))
|
||||
}
|
||||
|
||||
/// Converts the sender to a [`TransactionId`] with the given nonce.
|
||||
pub const fn into_id(self, nonce: u64) -> TransactionId {
|
||||
TransactionId::new(self, nonce)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for SenderId {
|
||||
|
||||
@ -510,6 +510,14 @@ where
|
||||
self.pool.get_highest_transaction_by_sender(sender)
|
||||
}
|
||||
|
||||
fn get_highest_consecutive_transaction_by_sender(
|
||||
&self,
|
||||
sender: Address,
|
||||
on_chain_nonce: u64,
|
||||
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||
self.pool.get_highest_consecutive_transaction_by_sender(sender, on_chain_nonce)
|
||||
}
|
||||
|
||||
fn get_transaction_by_sender_and_nonce(
|
||||
&self,
|
||||
sender: Address,
|
||||
|
||||
@ -227,6 +227,14 @@ impl TransactionPool for NoopTransactionPool {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_highest_consecutive_transaction_by_sender(
|
||||
&self,
|
||||
_sender: Address,
|
||||
_on_chain_nonce: u64,
|
||||
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_transaction_by_sender_and_nonce(
|
||||
&self,
|
||||
_sender: Address,
|
||||
|
||||
@ -785,6 +785,17 @@ where
|
||||
self.get_pool_data().get_highest_transaction_by_sender(sender_id)
|
||||
}
|
||||
|
||||
/// Returns the transaction with the highest nonce that is executable given the on chain nonce.
|
||||
pub(crate) fn get_highest_consecutive_transaction_by_sender(
|
||||
&self,
|
||||
sender: Address,
|
||||
on_chain_nonce: u64,
|
||||
) -> Option<Arc<ValidPoolTransaction<T::Transaction>>> {
|
||||
let sender_id = self.get_sender_id(sender);
|
||||
self.get_pool_data()
|
||||
.get_highest_consecutive_transaction_by_sender(sender_id.into_id(on_chain_nonce))
|
||||
}
|
||||
|
||||
/// Returns all transactions that where submitted with the given [`TransactionOrigin`]
|
||||
pub(crate) fn get_transactions_by_origin(
|
||||
&self,
|
||||
|
||||
@ -108,6 +108,27 @@ impl<T: TransactionOrdering> TxPool<T> {
|
||||
self.all().txs_iter(sender).last().map(|(_, tx)| Arc::clone(&tx.transaction))
|
||||
}
|
||||
|
||||
/// Returns the transaction with the highest nonce that is executable given the on chain nonce.
|
||||
///
|
||||
/// Note: The next pending pooled transaction must have the on chain nonce.
|
||||
pub(crate) fn get_highest_consecutive_transaction_by_sender(
|
||||
&self,
|
||||
on_chain: TransactionId,
|
||||
) -> Option<Arc<ValidPoolTransaction<T::Transaction>>> {
|
||||
let mut last_consecutive_tx = None;
|
||||
|
||||
let mut next_expected_nonce = on_chain.nonce;
|
||||
for (id, tx) in self.all().descendant_txs_inclusive(&on_chain) {
|
||||
if next_expected_nonce != id.nonce {
|
||||
break
|
||||
}
|
||||
next_expected_nonce = id.next_nonce();
|
||||
last_consecutive_tx = Some(tx);
|
||||
}
|
||||
|
||||
last_consecutive_tx.map(|tx| Arc::clone(&tx.transaction))
|
||||
}
|
||||
|
||||
/// Returns access to the [`AllTransactions`] container.
|
||||
pub(crate) const fn all(&self) -> &AllTransactions<T::Transaction> {
|
||||
&self.all_transactions
|
||||
@ -2755,6 +2776,36 @@ mod tests {
|
||||
assert_eq!(highest_tx.as_ref().transaction, tx1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_highest_consecutive_transaction_by_sender() {
|
||||
// Set up a mock transaction factory and a new transaction pool.
|
||||
let mut pool = TxPool::new(MockOrdering::default(), PoolConfig::default());
|
||||
let mut f = MockTransactionFactory::default();
|
||||
|
||||
// Create transactions with nonces 0, 1, 2, 4, 5.
|
||||
let sender = Address::random();
|
||||
let txs: Vec<_> = vec![0, 1, 2, 4, 5];
|
||||
for nonce in txs {
|
||||
let mut mock_tx = MockTransaction::eip1559();
|
||||
mock_tx.set_sender(sender);
|
||||
mock_tx.set_nonce(nonce);
|
||||
|
||||
let validated_tx = f.validated(mock_tx);
|
||||
pool.add_transaction(validated_tx, U256::from(1000), 0).unwrap();
|
||||
}
|
||||
|
||||
// Get last consecutive transaction
|
||||
let sender_id = f.ids.sender_id(&sender).unwrap();
|
||||
let next_tx = pool.get_highest_consecutive_transaction_by_sender(sender_id.into_id(0));
|
||||
assert_eq!(next_tx.map(|tx| tx.nonce()), Some(2), "Expected nonce 2 for on-chain nonce 0");
|
||||
|
||||
let next_tx = pool.get_highest_consecutive_transaction_by_sender(sender_id.into_id(4));
|
||||
assert_eq!(next_tx.map(|tx| tx.nonce()), Some(5), "Expected nonce 5 for on-chain nonce 4");
|
||||
|
||||
let next_tx = pool.get_highest_consecutive_transaction_by_sender(sender_id.into_id(5));
|
||||
assert_eq!(next_tx.map(|tx| tx.nonce()), Some(5), "Expected nonce 5 for on-chain nonce 5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discard_nonce_too_low() {
|
||||
let mut f = MockTransactionFactory::default();
|
||||
|
||||
@ -357,6 +357,21 @@ pub trait TransactionPool: Send + Sync + Clone {
|
||||
sender: Address,
|
||||
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>>;
|
||||
|
||||
/// Returns the transaction with the highest nonce that is executable given the on chain nonce.
|
||||
/// In other words the highest non nonce gapped transaction.
|
||||
///
|
||||
/// Note: The next pending pooled transaction must have the on chain nonce.
|
||||
///
|
||||
/// For example, for a given on chain nonce of `5`, the next transaction must have that nonce.
|
||||
/// If the pool contains txs `[5,6,7]` this returns tx `7`.
|
||||
/// If the pool contains txs `[6,7]` this returns `None` because the next valid nonce (5) is
|
||||
/// missing, which means txs `[6,7]` are nonce gapped.
|
||||
fn get_highest_consecutive_transaction_by_sender(
|
||||
&self,
|
||||
sender: Address,
|
||||
on_chain_nonce: u64,
|
||||
) -> Option<Arc<ValidPoolTransaction<Self::Transaction>>>;
|
||||
|
||||
/// Returns a transaction sent by a given user and a nonce
|
||||
fn get_transaction_by_sender_and_nonce(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user