diff --git a/crates/mempool/src/mempool.rs b/crates/mempool/src/mempool.rs index 976b38a7..bc061b96 100644 --- a/crates/mempool/src/mempool.rs +++ b/crates/mempool/src/mempool.rs @@ -21,6 +21,8 @@ pub struct Mempool { tx_pool: TransactionPool, // Transactions eligible for sequencing. tx_queue: TransactionQueue, + // Represents the current state of the mempool during block creation. + mempool_state: HashMap, } impl Mempool { @@ -55,6 +57,11 @@ impl Mempool { eligible_txs.push(tx); } + // Update the mempool state with the new nonces. + for tx in &eligible_txs { + self.mempool_state.entry(tx.sender_address).or_default().nonce = tx.nonce; + } + Ok(eligible_txs) } @@ -62,6 +69,7 @@ impl Mempool { /// TODO: support fee escalation and transactions with future nonces. /// TODO: check Account nonce and balance. pub fn add_tx(&mut self, input: MempoolInput) -> MempoolResult<()> { + self.is_duplicated_tx(&input.tx)?; self.insert_tx(input) } @@ -108,6 +116,15 @@ impl Mempool { Ok(()) } + fn is_duplicated_tx(&self, tx: &ThinTransaction) -> MempoolResult<()> { + if let Some(AccountState { nonce }) = self.mempool_state.get(&tx.sender_address) { + if nonce >= &tx.nonce { + return Err(MempoolError::DuplicateTransaction { tx_hash: tx.tx_hash }); + } + } + Ok(()) + } + #[cfg(test)] pub(crate) fn _tx_pool(&self) -> &TransactionPool { &self.tx_pool diff --git a/crates/mempool/src/mempool_test.rs b/crates/mempool/src/mempool_test.rs index 8ee7256f..e1d5ed8a 100644 --- a/crates/mempool/src/mempool_test.rs +++ b/crates/mempool/src/mempool_test.rs @@ -44,7 +44,7 @@ impl MempoolState { impl From for Mempool { fn from(mempool_state: MempoolState) -> Mempool { let MempoolState { tx_pool, tx_queue } = mempool_state; - Mempool { tx_pool, tx_queue } + Mempool { tx_pool, tx_queue, ..Default::default() } } }