Skip to content

Commit

Permalink
enha: reduce number of clones in transaction execution flow (#1901)
Browse files Browse the repository at this point in the history
  • Loading branch information
carneiro-cw authored Dec 5, 2024
1 parent 89f47dc commit 2f05cb1
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 32 deletions.
4 changes: 2 additions & 2 deletions src/eth/executor/evm_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
56 changes: 27 additions & 29 deletions src/eth/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionExecution, StratusError> {
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();

Expand All @@ -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:
Expand All @@ -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<TransactionExecution, StratusError> {
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);
Expand All @@ -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!(
Expand All @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion src/eth/storage/temporary/inmemory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 2f05cb1

Please sign in to comment.