Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions crates/op-rbuilder/src/builders/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use alloy_primitives::{Address, Bytes, TxKind, U256};
use alloy_rpc_types_eth::Withdrawals;
use core::fmt::Debug;
use op_alloy_consensus::{OpDepositReceipt, OpTypedTransaction};
use op_revm::OpSpecId;
use op_revm::{OpSpecId, OpTransactionError};
use reth::payload::PayloadBuilderAttributes;
use reth_basic_payload_builder::PayloadConfig;
use reth_chainspec::{EthChainSpec, EthereumHardforks};
Expand Down Expand Up @@ -187,6 +187,33 @@ impl OpPayloadBuilderCtx {
}
}

#[derive(Debug)]
enum TxnExecutionResult {
InvalidDASize,
SequencerTransaction,
NonceTooLow,
InternalError(OpTransactionError),
EvmError,
Success,
Reverted,
RevertedAndExcluded,
}

impl std::fmt::Display for TxnExecutionResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: there's this that can simplify it in future PRs: https://docs.rs/derive_more/latest/derive_more/derive.Display.html

fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TxnExecutionResult::InvalidDASize => write!(f, "InvalidDASize"),
TxnExecutionResult::SequencerTransaction => write!(f, "SequencerTransaction"),
TxnExecutionResult::NonceTooLow => write!(f, "NonceTooLow"),
TxnExecutionResult::InternalError(err) => write!(f, "InternalError({err})"),
TxnExecutionResult::EvmError => write!(f, "EvmError"),
TxnExecutionResult::Success => write!(f, "Success"),
TxnExecutionResult::Reverted => write!(f, "Reverted"),
TxnExecutionResult::RevertedAndExcluded => write!(f, "RevertedAndExcluded"),
}
}
}

impl OpPayloadBuilderCtx {
/// Constructs a receipt for the given transaction.
fn build_receipt<E: Evm>(
Expand Down Expand Up @@ -331,8 +358,13 @@ impl OpPayloadBuilderCtx {
while let Some(tx) = best_txs.next(()) {
let exclude_reverting_txs = tx.exclude_reverting_txs();
let tx_da_size = tx.estimated_da_size();

let tx = tx.into_consensus();
let tx_hash = tx.tx_hash();

let log_txn = |result: TxnExecutionResult| {
info!(target: "payload_builder", tx_hash = ?tx_hash, tx_da_size = ?tx_da_size, exclude_reverting_txs = ?exclude_reverting_txs, result = %result, "Considering transaction");
};

num_txs_considered += 1;
// ensure we still have capacity for this transaction
if info.is_tx_over_limits(
Expand All @@ -345,12 +377,14 @@ impl OpPayloadBuilderCtx {
// we can't fit this transaction into the block, so we need to mark it as
// invalid which also removes all dependent transaction from
// the iterator before we can continue
log_txn(TxnExecutionResult::InvalidDASize);
best_txs.mark_invalid(tx.signer(), tx.nonce());
continue;
}

// A sequencer's block should never contain blob or deposit transactions from the pool.
if tx.is_eip4844() || tx.is_deposit() {
log_txn(TxnExecutionResult::SequencerTransaction);
best_txs.mark_invalid(tx.signer(), tx.nonce());
continue;
}
Expand All @@ -367,17 +401,20 @@ impl OpPayloadBuilderCtx {
if let Some(err) = err.as_invalid_tx_err() {
if err.is_nonce_too_low() {
// if the nonce is too low, we can skip this transaction
log_txn(TxnExecutionResult::NonceTooLow);
trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction");
} else {
// if the transaction is invalid, we can skip it and all of its
// descendants
log_txn(TxnExecutionResult::InternalError(err.clone()));
trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants");
best_txs.mark_invalid(tx.signer(), tx.nonce());
}

continue;
}
// this is an error that we should treat as fatal for this attempt
log_txn(TxnExecutionResult::EvmError);
return Err(PayloadBuilderError::EvmExecutionError(Box::new(err)));
}
};
Expand All @@ -388,13 +425,17 @@ impl OpPayloadBuilderCtx {
self.metrics.tx_byte_size.record(tx.inner().size() as f64);
num_txs_simulated += 1;
if result.is_success() {
log_txn(TxnExecutionResult::Success);
num_txs_simulated_success += 1;
} else {
num_txs_simulated_fail += 1;
if exclude_reverting_txs {
log_txn(TxnExecutionResult::RevertedAndExcluded);
info!(target: "payload_builder", tx_hash = ?tx.tx_hash(), "skipping reverted transaction");
best_txs.mark_invalid(tx.signer(), tx.nonce());
continue;
} else {
log_txn(TxnExecutionResult::Reverted);
}
}

Expand Down
Loading