Skip to content

Commit

Permalink
feat(mempool): reject tx of lower nonce in add_tx (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
ayeletstarkware authored Aug 1, 2024
1 parent 495b403 commit ac83ee0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 14 deletions.
42 changes: 28 additions & 14 deletions crates/mempool/src/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,38 @@ impl Mempool {
}

fn validate_input(&self, input: &MempoolInput) -> MempoolResult<()> {
let MempoolInput {
tx: ThinTransaction { sender_address, nonce: tx_nonce, .. },
account: Account { state: AccountState { nonce: account_nonce }, .. },
} = input;
let duplicate_nonce_error =
MempoolError::DuplicateNonce { address: *sender_address, nonce: *tx_nonce };

// Stateless checks.

// Check the input: transaction nonce against given account state.
if account_nonce > tx_nonce {
return Err(duplicate_nonce_error);
}

// Stateful checks.

// Check nonce against mempool state.
let MempoolInput { tx, account } = input;
if let Some(AccountState { nonce }) = self.mempool_state.get(&tx.sender_address) {
if nonce >= &tx.nonce {
return Err(MempoolError::DuplicateNonce {
address: tx.sender_address,
nonce: tx.nonce,
});
if let Some(AccountState { nonce: mempool_state_nonce }) =
self.mempool_state.get(sender_address)
{
if mempool_state_nonce >= tx_nonce {
return Err(duplicate_nonce_error);
}
}

// Check nonce against given account state.
let Account { state: AccountState { nonce }, .. } = account;
if nonce > &tx.nonce {
return Err(MempoolError::DuplicateNonce {
address: tx.sender_address,
nonce: tx.nonce,
});
// Check nonce against the queue.
if self
.tx_queue
.get_nonce(*sender_address)
.is_some_and(|queued_nonce| queued_nonce > *tx_nonce)
{
return Err(duplicate_nonce_error);
}

Ok(())
Expand Down
18 changes: 18 additions & 0 deletions crates/mempool/src/mempool_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,24 @@ fn test_add_tx_with_duplicate_tx(mut mempool: Mempool) {
expected_mempool_state.assert_eq_pool_state(&mempool);
}

#[rstest]
fn test_add_tx_lower_than_queued_nonce() {
// Setup.
let valid_input =
add_tx_input!(tx_hash: 1, sender_address: "0x0", tx_nonce: 1_u8, account_nonce: 1_u8);
let lower_nonce_input =
add_tx_input!(tx_hash: 2, sender_address: "0x0", tx_nonce: 0_u8, account_nonce: 0_u8);

let queue_txs = [TransactionReference::new(&valid_input.tx)];
let expected_mempool_state = MempoolState::with_queue(queue_txs);
let pool_txs = [valid_input.tx];
let mut mempool: Mempool = MempoolState::new(pool_txs, queue_txs).into();

// Test and assert the original transaction remains.
assert_matches!(mempool.add_tx(lower_nonce_input), Err(MempoolError::DuplicateNonce { .. }));
expected_mempool_state.assert_eq_queue_state(&mempool);
}

#[rstest]
fn test_add_tx_with_identical_tip_succeeds(mut mempool: Mempool) {
// Setup.
Expand Down

0 comments on commit ac83ee0

Please sign in to comment.