Skip to content

Commit

Permalink
perf: do not depend on entire block
Browse files Browse the repository at this point in the history
  • Loading branch information
dinhani-cw committed Aug 12, 2024
1 parent d4fca19 commit 1c40569
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 18 deletions.
7 changes: 3 additions & 4 deletions src/eth/executor/evm_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::eth::primitives::BlockNumber;
use crate::eth::primitives::Bytes;
use crate::eth::primitives::CallInput;
use crate::eth::primitives::ChainId;
use crate::eth::primitives::ExternalBlock;
use crate::eth::primitives::ExternalReceipt;
use crate::eth::primitives::ExternalTransaction;
use crate::eth::primitives::Gas;
Expand Down Expand Up @@ -132,7 +131,7 @@ impl EvmInput {
/// Creates a transaction that was executed in an external blockchain and imported to Stratus.
///
/// Successful external transactions executes with max gas and zero gas price to ensure we will have the same execution result.
pub fn from_external(tx: &ExternalTransaction, receipt: &ExternalReceipt, block: &ExternalBlock) -> anyhow::Result<Self> {
pub fn from_external(tx: &ExternalTransaction, receipt: &ExternalReceipt, block_number: BlockNumber, block_timestamp: UnixTime) -> anyhow::Result<Self> {
Ok(Self {
from: tx.0.from.into(),
to: tx.0.to.map_into(),
Expand All @@ -142,8 +141,8 @@ impl EvmInput {
gas_limit: if_else!(receipt.is_success(), Gas::MAX, tx.0.gas.try_into()?),
gas_price: if_else!(receipt.is_success(), Wei::ZERO, tx.0.gas_price.map_into().unwrap_or(Wei::ZERO)),
point_in_time: StoragePointInTime::Pending,
block_number: block.number(),
block_timestamp: block.timestamp(),
block_number,
block_timestamp,
chain_id: match tx.0.chain_id {
Some(chain_id) => Some(chain_id.try_into()?),
None => None,
Expand Down
27 changes: 16 additions & 11 deletions src/eth/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::eth::executor::EvmInput;
use crate::eth::executor::ExecutorConfig;
use crate::eth::miner::Miner;
use crate::eth::primitives::BlockFilter;
use crate::eth::primitives::BlockNumber;
use crate::eth::primitives::CallInput;
use crate::eth::primitives::EvmExecution;
use crate::eth::primitives::EvmExecutionMetrics;
Expand All @@ -27,6 +28,7 @@ use crate::eth::primitives::ExternalTransactionExecution;
use crate::eth::primitives::StratusError;
use crate::eth::primitives::TransactionExecution;
use crate::eth::primitives::TransactionInput;
use crate::eth::primitives::UnixTime;
use crate::eth::storage::StoragePointInTime;
use crate::eth::storage::StratusStorage;
use crate::ext::spawn_thread;
Expand Down Expand Up @@ -231,18 +233,20 @@ impl Executor {
let _span = info_span!("executor::external_block", block_number = %block.number()).entered();
tracing::info!(block_number = %block.number(), "reexecuting external block");

// track pending block number
let storage = &self.storage;
storage.set_pending_external_block(block.clone())?;
storage.set_pending_block_number(block.number())?;
// track pending block
let block_number = block.number();
let block_timpestamp = block.timestamp();
self.storage.set_pending_external_block(block.clone())?;
self.storage.set_pending_block_number(block_number)?;

// determine how to execute each transaction
for tx in &block.transactions {
let receipt = receipts.try_get(&tx.hash())?;
self.execute_external_transaction(
tx,
receipt,
block,
block_number,
block_timpestamp,
#[cfg(feature = "metrics")]
&mut block_metrics,
)?;
Expand All @@ -267,23 +271,24 @@ impl Executor {
&self,
tx: &ExternalTransaction,
receipt: &ExternalReceipt,
block: &ExternalBlock,
block_number: BlockNumber,
block_timestamp: UnixTime,
#[cfg(feature = "metrics")] block_metrics: &mut EvmExecutionMetrics,
) -> anyhow::Result<()> {
// track
#[cfg(feature = "metrics")]
let start = metrics::now();
#[cfg(feature = "tracing")]
let _span = info_span!("executor::external_transaction", tx_hash = %tx.hash).entered();
tracing::info!(block_number = %block.number(), tx_hash = %tx.hash(), "reexecuting external transaction");
tracing::info!(%block_number, tx_hash = %tx.hash(), "reexecuting external transaction");

// when transaction externally failed, create fake transaction instead of reexecuting
let tx_execution = match receipt.is_success() {
//
// successful external transaction, re-execute locally
true => {
// re-execute transaction
let evm_input = EvmInput::from_external(tx, receipt, block)?;
let evm_input = EvmInput::from_external(tx, receipt, block_number, block_timestamp)?;
let evm_execution = self.evms.execute(evm_input.clone(), EvmRoute::External);

// handle re-execution result
Expand All @@ -292,7 +297,7 @@ impl Executor {
Err(e) => {
let json_tx = to_json_string(&tx);
let json_receipt = to_json_string(&receipt);
tracing::error!(reason = ?e, block_number = %block.number(), tx_hash = %tx.hash(), %json_tx, %json_receipt, "failed to reexecute external transaction");
tracing::error!(reason = ?e, %block_number, tx_hash = %tx.hash(), %json_tx, %json_receipt, "failed to reexecute external transaction");
return Err(e.into());
}
};
Expand All @@ -305,7 +310,7 @@ impl Executor {
let json_tx = to_json_string(&tx);
let json_receipt = to_json_string(&receipt);
let json_execution_logs = to_json_string(&evm_execution.execution.logs);
tracing::error!(reason = %"mismatch reexecuting transaction", block_number = %block.number(), tx_hash = %tx.hash(), %json_tx, %json_receipt, %json_execution_logs, "failed to reexecute external transaction");
tracing::error!(reason = %"mismatch reexecuting transaction", %block_number, tx_hash = %tx.hash(), %json_tx, %json_receipt, %json_execution_logs, "failed to reexecute external transaction");
return Err(e);
};

Expand All @@ -315,7 +320,7 @@ impl Executor {
// failed external transaction, re-cretea from receipt without re-executing
false => {
let sender = self.storage.read_account(&receipt.from.into(), &StoragePointInTime::Pending)?;
let execution = EvmExecution::from_failed_external_transaction(sender, receipt, block)?;
let execution = EvmExecution::from_failed_external_transaction(sender, receipt, block_timestamp)?;
let evm_result = EvmExecutionResult {
execution,
metrics: EvmExecutionMetrics::default(),
Expand Down
5 changes: 2 additions & 3 deletions src/eth/primitives/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::eth::primitives::Address;
use crate::eth::primitives::Bytes;
use crate::eth::primitives::ExecutionAccountChanges;
use crate::eth::primitives::ExecutionResult;
use crate::eth::primitives::ExternalBlock;
use crate::eth::primitives::ExternalReceipt;
use crate::eth::primitives::Gas;
use crate::eth::primitives::Log;
Expand Down Expand Up @@ -51,7 +50,7 @@ pub struct EvmExecution {

impl EvmExecution {
/// Creates an execution from an external transaction that failed.
pub fn from_failed_external_transaction(sender: Account, receipt: &ExternalReceipt, block: &ExternalBlock) -> anyhow::Result<Self> {
pub fn from_failed_external_transaction(sender: Account, receipt: &ExternalReceipt, block_timestamp: UnixTime) -> anyhow::Result<Self> {
if receipt.is_success() {
return log_and_err!("cannot create failed execution for successful transaction");
}
Expand All @@ -66,7 +65,7 @@ impl EvmExecution {

// crete execution and apply costs
let mut execution = Self {
block_timestamp: block.timestamp(),
block_timestamp,
receipt_applied: false,
result: ExecutionResult::new_reverted(), // assume it reverted
output: Bytes::default(), // we cannot really know without performing an eth_call to the external system
Expand Down

0 comments on commit 1c40569

Please sign in to comment.