diff --git a/src/eth/executor/evm_input.rs b/src/eth/executor/evm_input.rs index 193d2783a..54a3e80d2 100644 --- a/src/eth/executor/evm_input.rs +++ b/src/eth/executor/evm_input.rs @@ -82,12 +82,12 @@ pub struct EvmInput { impl EvmInput { /// Creates from a transaction that was sent directly to Stratus with `eth_sendRawTransaction`. - pub fn from_eth_transaction(input: TransactionInput, pending_header: PendingBlockHeader) -> Self { + pub fn from_eth_transaction(input: &TransactionInput, pending_header: &PendingBlockHeader) -> Self { Self { from: input.signer, to: input.to, value: input.value, - data: input.input, + data: input.input.clone(), gas_limit: Gas::MAX, gas_price: Wei::ZERO, nonce: Some(input.nonce), diff --git a/src/eth/executor/executor.rs b/src/eth/executor/executor.rs index d140fa562..d9eeb6031 100644 --- a/src/eth/executor/executor.rs +++ b/src/eth/executor/executor.rs @@ -371,7 +371,11 @@ impl Executor { /// Executes a transaction persisting state changes. #[tracing::instrument(name = "executor::local_transaction", skip_all, fields(tx_hash, tx_from, tx_to, tx_nonce))] - pub fn execute_local_transaction(&self, tx: TransactionInput) -> Result { + pub fn execute_local_transaction(&self, tx: TransactionInput) -> Result<(), StratusError> { + #[cfg(feature = "metrics")] + let function = codegen::function_sig_for_o11y(&tx.input); + #[cfg(feature = "metrics")] + let contract = codegen::contract_name_for_o11y(&tx.to); #[cfg(feature = "metrics")] let start = metrics::now(); @@ -398,7 +402,7 @@ impl Executor { let _serial_lock = self.locks.serial.lock_or_clear("executor serial lock was poisoned"); // execute transaction - self.execute_local_transaction_attempts(tx.clone(), EvmRoute::Serial, INFINITE_ATTEMPTS) + self.execute_local_transaction_attempts(tx, EvmRoute::Serial, INFINITE_ATTEMPTS) } // Executes transactions in parallel mode: @@ -417,35 +421,14 @@ impl Executor { } }; - // track metrics #[cfg(feature = "metrics")] - { - let function = codegen::function_sig_for_o11y(&tx.input); - let contract = codegen::contract_name_for_o11y(&tx.to); - - match &tx_execution { - Ok(tx_execution) => { - metrics::inc_executor_local_transaction(start.elapsed(), true, contract, function); - metrics::inc_executor_local_transaction_account_reads(tx_execution.metrics().account_reads, contract, function); - metrics::inc_executor_local_transaction_slot_reads(tx_execution.metrics().slot_reads, contract, function); - metrics::inc_executor_local_transaction_gas(tx_execution.execution().gas.as_u64() as usize, true, contract, function); - } - Err(_) => { - metrics::inc_executor_local_transaction(start.elapsed(), false, contract, function); - } - } - } + metrics::inc_executor_local_transaction(start.elapsed(), tx_execution.is_ok(), contract, function); tx_execution } /// Executes a transaction until it reaches the max number of attempts. - fn execute_local_transaction_attempts( - &self, - tx_input: TransactionInput, - evm_route: EvmRoute, - max_attempts: usize, - ) -> Result { + fn execute_local_transaction_attempts(&self, tx_input: TransactionInput, evm_route: EvmRoute, max_attempts: usize) -> Result<(), StratusError> { // validate if tx_input.signer.is_zero() { return Err(StratusError::TransactionFromZeroAddress); @@ -472,7 +455,7 @@ impl Executor { // prepare evm input let pending_header = self.storage.read_pending_block_header(); - let evm_input = EvmInput::from_eth_transaction(tx_input.clone(), pending_header); + let evm_input = EvmInput::from_eth_transaction(&tx_input, &pending_header); // execute transaction in evm (retry only in case of conflict, but do not retry on other failures) tracing::info!( @@ -495,10 +478,25 @@ 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_input, evm_result.clone()); - match self.miner.save_execution(tx_execution.clone(), matches!(evm_route, EvmRoute::Parallel)) { + let tx_execution = TransactionExecution::new_local(tx_input.clone(), evm_input, evm_result); + #[cfg(feature = "metrics")] + let tx_metrics = tx_execution.metrics(); + #[cfg(feature = "metrics")] + let gas_used = tx_execution.execution().gas; + + match self.miner.save_execution(tx_execution, matches!(evm_route, EvmRoute::Parallel)) { Ok(_) => { - return Ok(tx_execution); + // track metrics + #[cfg(feature = "metrics")] + { + let function = codegen::function_sig_for_o11y(&tx_input.input); + let contract = codegen::contract_name_for_o11y(&tx_input.to); + + metrics::inc_executor_local_transaction_account_reads(tx_metrics.account_reads, contract, function); + metrics::inc_executor_local_transaction_slot_reads(tx_metrics.slot_reads, contract, function); + metrics::inc_executor_local_transaction_gas(gas_used.as_u64() as usize, true, contract, function); + } + return Ok(()); } Err(e) => match e { StratusError::TransactionConflict(ref conflicts) => { diff --git a/src/eth/storage/temporary/inmemory.rs b/src/eth/storage/temporary/inmemory.rs index f8cb32a8c..e668396ad 100644 --- a/src/eth/storage/temporary/inmemory.rs +++ b/src/eth/storage/temporary/inmemory.rs @@ -104,7 +104,7 @@ impl TemporaryStorage for InMemoryTemporaryStorage { // check conflicts let mut states = self.lock_write(); if let TransactionExecution::Local(tx) = &tx { - let expected_input = EvmInput::from_eth_transaction(tx.input.clone(), states.head.block.header.clone()); + let expected_input = EvmInput::from_eth_transaction(&tx.input, &states.head.block.header); if expected_input != tx.evm_input { return Err(StratusError::TransactionEvmInputMismatch {