diff --git a/src/vm.rs b/src/vm.rs index 91864ec3..3c32c6b1 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -352,10 +352,8 @@ impl<'a, S: Storage, C: PevmChain> Database for VmDb<'a, S, C> { // Check sender nonce account.nonce += nonce_addition; if location_hash == self.from_hash && account.nonce != self.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::BlockingIndex(self.tx_idx - 1)); + if let Some(prev_tx_idx) = self.vm.get_prev_sender(*self.tx_idx, self.from) { + return Err(ReadError::BlockingIndex(prev_tx_idx)); } else { return Err(ReadError::InvalidNonce); } @@ -509,6 +507,13 @@ impl<'a, S: Storage, C: PevmChain> Vm<'a, S, C> { self.hasher.hash_one(MemoryLocation::Basic(*address)) } + #[inline(always)] + fn get_prev_sender(&self, tx_idx: TxIdx, sender: &Address) -> Option { + (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. @@ -674,19 +679,25 @@ 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 { .. }) - ) - { - VmExecutionResult::ReadError { - blocking_tx_idx: tx_version.tx_idx - 1, + ) { + return VmExecutionResult::ReadError { + blocking_tx_idx: tx_version.tx_idx - 1, + }; + } else if matches!( + err, + EVMError::Transaction(InvalidTransaction::NonceTooHigh { .. }) + ) { + if let Some(blocking_tx_idx) = self.get_prev_sender(tx_version.tx_idx, from) + { + return VmExecutionResult::ReadError { blocking_tx_idx }; + } } - } else { - VmExecutionResult::ExecutionError(err) } + VmExecutionResult::ExecutionError(err) } } }