diff --git a/src/eth/executor/executor.rs b/src/eth/executor/executor.rs index 3a9ac909b..78a943fce 100644 --- a/src/eth/executor/executor.rs +++ b/src/eth/executor/executor.rs @@ -334,7 +334,7 @@ impl Executor { // persist state let tx_execution = TransactionExecution::External(tx_execution); - self.miner.save_execution(tx_execution)?; + self.miner.save_execution(tx_execution, false)?; // track metrics #[cfg(feature = "metrics")] @@ -497,7 +497,7 @@ impl Executor { // save execution to temporary storage // in case of failure, retry if conflict or abandon if unexpected error let tx_execution = TransactionExecution::new_local(tx_input.clone(), evm_result.clone()); - match self.miner.save_execution(tx_execution.clone()) { + match self.miner.save_execution(tx_execution.clone(), true) { Ok(_) => { return Ok(tx_execution); } diff --git a/src/eth/miner/miner.rs b/src/eth/miner/miner.rs index 0f4ac5e07..5620f831d 100644 --- a/src/eth/miner/miner.rs +++ b/src/eth/miner/miner.rs @@ -92,7 +92,7 @@ impl Miner { } /// Persists a transaction execution. - pub fn save_execution(&self, tx_execution: TransactionExecution) -> Result<(), StratusError> { + pub fn save_execution(&self, tx_execution: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> { // track #[cfg(feature = "tracing")] let _span = info_span!("miner::save_execution", tx_hash = %tx_execution.hash()).entered(); @@ -106,7 +106,7 @@ impl Miner { // save execution to temporary storage let tx_hash = tx_execution.hash(); - self.storage.save_execution(tx_execution)?; + self.storage.save_execution(tx_execution, check_conflicts)?; // if automine is enabled, automatically mines a block let _ = self.notifier_pending_txs.send(tx_hash); diff --git a/src/eth/storage/inmemory/inmemory_temporary.rs b/src/eth/storage/inmemory/inmemory_temporary.rs index d7b3a5d6b..c78aeff22 100644 --- a/src/eth/storage/inmemory/inmemory_temporary.rs +++ b/src/eth/storage/inmemory/inmemory_temporary.rs @@ -145,11 +145,13 @@ impl TemporaryStorage for InMemoryTemporaryStorage { Ok(()) } - fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError> { + fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> { // check conflicts let mut states = self.lock_write(); - if let Some(conflicts) = check_conflicts(&states, tx.execution()) { - return Err(StratusError::TransactionConflict(conflicts.into())); + if check_conflicts { + if let Some(conflicts) = do_check_conflicts(&states, tx.execution()) { + return Err(StratusError::TransactionConflict(conflicts.into())); + } } // save account changes @@ -226,12 +228,12 @@ impl TemporaryStorage for InMemoryTemporaryStorage { fn read_account(&self, address: &Address) -> anyhow::Result> { let states = self.lock_read(); - Ok(read_account(&states, address)) + Ok(do_read_account(&states, address)) } fn read_slot(&self, address: &Address, index: &SlotIndex) -> anyhow::Result> { let states = self.lock_read(); - Ok(read_slot(&states, address, index)) + Ok(do_read_slot(&states, address, index)) } // ------------------------------------------------------------------------- @@ -248,7 +250,7 @@ impl TemporaryStorage for InMemoryTemporaryStorage { // ----------------------------------------------------------------------------- // Implementations without lock // ----------------------------------------------------------------------------- -fn read_account(states: &NonEmpty, address: &Address) -> Option { +fn do_read_account(states: &NonEmpty, address: &Address) -> Option { // search all for state in states.iter() { let Some(account) = state.accounts.get(address) else { continue }; @@ -271,7 +273,7 @@ fn read_account(states: &NonEmpty, address: &Addr None } -fn read_slot(states: &NonEmpty, address: &Address, index: &SlotIndex) -> Option { +fn do_read_slot(states: &NonEmpty, address: &Address, index: &SlotIndex) -> Option { // search all for state in states.iter() { let Some(account) = state.accounts.get(address) else { continue }; @@ -286,12 +288,12 @@ fn read_slot(states: &NonEmpty, address: &Address None } -fn check_conflicts(states: &NonEmpty, execution: &EvmExecution) -> Option { +fn do_check_conflicts(states: &NonEmpty, execution: &EvmExecution) -> Option { let mut conflicts = ExecutionConflictsBuilder::default(); for (address, change) in &execution.changes { // check account info conflicts - if let Some(account) = read_account(states, address) { + if let Some(account) = do_read_account(states, address) { if let Some(expected) = change.nonce.take_original_ref() { let original = &account.nonce; if expected != original { @@ -309,7 +311,7 @@ fn check_conflicts(states: &NonEmpty, execution: // check slots conflicts for (slot_index, slot_change) in &change.slots { if let Some(expected) = slot_change.take_original_ref() { - let Some(original) = read_slot(states, address, slot_index) else { + let Some(original) = do_read_slot(states, address, slot_index) else { continue; }; if expected.value != original.value { diff --git a/src/eth/storage/stratus_storage.rs b/src/eth/storage/stratus_storage.rs index c31df3986..00b19d0ce 100644 --- a/src/eth/storage/stratus_storage.rs +++ b/src/eth/storage/stratus_storage.rs @@ -324,12 +324,12 @@ impl StratusStorage { // Blocks // ------------------------------------------------------------------------- - pub fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError> { + pub fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> { #[cfg(feature = "tracing")] let _span = tracing::info_span!("storage::save_execution", tx_hash = %tx.hash()).entered(); tracing::debug!(storage = %label::TEMP, tx_hash = %tx.hash(), "saving execution"); - timed(|| self.temp.save_execution(tx)) + timed(|| self.temp.save_execution(tx, check_conflicts)) .with(|m| { metrics::inc_storage_save_execution(m.elapsed, label::TEMP, m.result.is_ok()); if let Err(ref e) = m.result { diff --git a/src/eth/storage/temporary_storage.rs b/src/eth/storage/temporary_storage.rs index b5602f144..770588296 100644 --- a/src/eth/storage/temporary_storage.rs +++ b/src/eth/storage/temporary_storage.rs @@ -36,7 +36,7 @@ pub trait TemporaryStorage: Send + Sync + 'static { fn set_pending_external_block(&self, block: ExternalBlock) -> anyhow::Result<()>; /// Saves a re-executed transaction to the pending mined block. - fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError>; + fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError>; /// Retrieves the pending transactions of the pending block. fn pending_transactions(&self) -> anyhow::Result>;