Skip to content

Commit

Permalink
perf: better retry strategy for premature nonce
Browse files Browse the repository at this point in the history
  • Loading branch information
hai-rise committed Oct 30, 2024
1 parent 4279c9d commit a98f7a3
Showing 1 changed file with 25 additions and 12 deletions.
37 changes: 25 additions & 12 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,9 @@ impl<'a, S: Storage, C: PevmChain> Database for VmDb<'a, S, C> {
if location_hash == self.from_hash
&& self.tx.nonce.is_some_and(|nonce| nonce != account.nonce)
{
if self.tx_idx > 0 {
// TODO: Better retry strategy -- immediately, to the
// closest sender tx, to the missing sender tx, etc.
return Err(ReadError::Blocking(self.tx_idx - 1));
if let Some(prev_tx_idx) = self.vm.prev_tx_from_sender(self.tx_idx, &self.tx.caller)
{
return Err(ReadError::Blocking(prev_tx_idx));
} else {
return Err(ReadError::InvalidNonce(self.tx_idx));
}
Expand Down Expand Up @@ -525,6 +524,13 @@ impl<'a, S: Storage, C: PevmChain> Vm<'a, S, C> {
}
}

#[inline(always)]
fn prev_tx_from_sender(&self, tx_idx: TxIdx, sender: &Address) -> Option<TxIdx> {
(0..tx_idx)
.rev()
.find(|&i| &unsafe { self.txs.get_unchecked(i) }.caller == sender)
}

// Execute a transaction. This can read from memory but cannot modify any state.
// A successful execution returns:
// - A write-set consisting of memory locations and their updated values.
Expand Down Expand Up @@ -698,17 +704,24 @@ impl<'a, S: Storage, C: PevmChain> Vm<'a, S, C> {
// Since this retry is safe for syncing canonical blocks but can deadlock
// on new or faulty blocks. We can skip the transaction for new blocks and
// error out after a number of tries for the latter.
if tx_version.tx_idx > 0
&& matches!(
if tx_version.tx_idx > 0 {
if matches!(
err,
EVMError::Transaction(InvalidTransaction::LackOfFundForMaxFee { .. })
| EVMError::Transaction(InvalidTransaction::NonceTooHigh { .. })
)
{
Err(VmExecutionError::Blocking(tx_version.tx_idx - 1))
} else {
Err(VmExecutionError::ExecutionError(err))
) {
return Err(VmExecutionError::Blocking(tx_version.tx_idx - 1));
} else if matches!(
err,
EVMError::Transaction(InvalidTransaction::NonceTooHigh { .. })
) {
if let Some(prev_tx_idx) =
self.prev_tx_from_sender(tx_version.tx_idx, &tx.caller)
{
return Err(VmExecutionError::Blocking(prev_tx_idx));
}
}
}
Err(VmExecutionError::ExecutionError(err))
}
}
}
Expand Down

0 comments on commit a98f7a3

Please sign in to comment.