diff --git a/node-data/src/ledger/transaction.rs b/node-data/src/ledger/transaction.rs index e4d13aa49..ce129bb72 100644 --- a/node-data/src/ledger/transaction.rs +++ b/node-data/src/ledger/transaction.rs @@ -141,6 +141,15 @@ impl SpendingId { } } } + + pub fn next(&self) -> Option { + match self { + SpendingId::Nullifier(_) => None, + SpendingId::AccountNonce(account, nonce) => { + Some(SpendingId::AccountNonce(*account, nonce + 1)) + } + } + } } #[cfg(any(feature = "faker", test))] diff --git a/node/src/database/rocksdb.rs b/node/src/database/rocksdb.rs index 10d3ffdc8..beefd4b2c 100644 --- a/node/src/database/rocksdb.rs +++ b/node/src/database/rocksdb.rs @@ -894,16 +894,25 @@ impl<'db, DB: DBAccess> Mempool for DBTransaction<'db, DB> { deleted.push(h); if cascade { + let mut dependants = vec![]; // Get the next spending id (aka next nonce tx) // retrieve tx_id and delete it - if let Some(spending_id) = tx.next_spending_id() { - for tx_id in - self.mempool_txs_by_spendable_ids(&[spending_id]) - { - let cascade_deleted = - self.delete_mempool_tx(tx_id, cascade)?; - deleted.extend(cascade_deleted); + let mut next_spending_id = tx.next_spending_id(); + while let Some(spending_id) = next_spending_id { + next_spending_id = spending_id.next(); + let next_txs = + self.mempool_txs_by_spendable_ids(&[spending_id]); + if next_txs.is_empty() { + break; } + dependants.extend(next_txs); + } + + // delete all dependants + for tx_id in dependants { + let cascade_deleted = + self.delete_mempool_tx(tx_id, false)?; + deleted.extend(cascade_deleted); } } } diff --git a/node/src/mempool.rs b/node/src/mempool.rs index b8abd6b34..43e9282c5 100644 --- a/node/src/mempool.rs +++ b/node/src/mempool.rs @@ -120,11 +120,19 @@ impl // Remove expired transactions from the mempool db.read().await.update(|db| { - let expired_txs = db.mempool_expired_txs(expiration_time)?; + let expired_txs = db.mempool_expired_txs(expiration_time).unwrap_or_else(|e| { + error!("cannot get expired txs: {e}"); + vec![] + }); for tx_id in expired_txs { info!(event = "expired_tx", hash = hex::encode(tx_id)); - for deleted_tx_id in db.delete_mempool_tx(tx_id, true)? { + let deleted_txs = db.delete_mempool_tx(tx_id, true).unwrap_or_else(|e| { + error!("cannot delete expired tx: {e}"); + vec![] + }); + for deleted_tx_id in deleted_txs{ let event = TransactionEvent::Removed(deleted_tx_id); + info!(event = "mempool_deleted", hash = hex::encode(deleted_tx_id)); if let Err(e) = self.event_sender.try_send(event.into()) { warn!("cannot notify mempool removed transaction {e}") };