Skip to content
Open
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions crates/op-rbuilder/src/builders/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ impl<ExtraCtx: Debug + Default> OpPayloadBuilderCtx<ExtraCtx> {
&self,
info: &ExecutionInfo<Extra>,
) -> (Option<u64>, Option<u64>) {
// For payload validation
if let Some(blob_fields) = info.optional_blob_fields {
return blob_fields;
}
// Compute from execution info
if self.is_jovian_active() {
let scalar = info
.da_footprint_scalar
Expand Down
54 changes: 47 additions & 7 deletions crates/op-rbuilder/src/builders/flashblocks/payload_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ use alloy_primitives::B64;
use eyre::{WrapErr as _, bail};
use op_alloy_consensus::OpTxEnvelope;
use op_alloy_rpc_types_engine::OpFlashblockPayload;
use op_revm::L1BlockInfo;
use reth::revm::{State, database::StateProviderDatabase};
use reth_basic_payload_builder::PayloadConfig;
use reth_evm::FromRecoveredTx;
use reth_node_builder::Events;
use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes};
use reth_optimism_forks::OpHardforks;
use reth_optimism_node::{OpEngineTypes, OpPayloadBuilderAttributes};
use reth_optimism_payload_builder::OpBuiltPayload;
use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
Expand Down Expand Up @@ -190,19 +192,44 @@ where
.wrap_err("failed to apply pre execution changes")?;

let mut info = ExecutionInfo::with_capacity(payload.block().body().transactions.len());
info.optional_blob_fields = Some((
payload.block().sealed_header().excess_blob_gas,
payload.block().sealed_header().blob_gas_used,
));

let extra_data = payload.block().sealed_header().extra_data.clone();
if extra_data.len() != 9 {
tracing::error!(len = extra_data.len(), data = ?extra_data, "invalid extra data length in flashblock");
bail!("extra data length should be 9 bytes");
}
let (eip_1559_parameters, min_base_fee): (Option<B64>, Option<u64>) = if chain_spec
.is_jovian_active_at_timestamp(timestamp)
{
if extra_data.len() != 17 {
tracing::debug!(len = extra_data.len(), data = ?extra_data, "invalid extra data length in flashblock for jovian fork");
bail!("extra data length should be 17 bytes");
}
let eip_1559_params = extra_data[1..9].try_into().ok();
let min_base_fee_bytes: [u8; 8] = extra_data[9..17]
.try_into()
.wrap_err("failed to extract min base fee from jovian extra data")?;
let min_base_fee = u64::from_be_bytes(min_base_fee_bytes);
(eip_1559_params, Some(min_base_fee))
} else if chain_spec.is_holocene_active_at_timestamp(timestamp) {
if extra_data.len() != 9 {
tracing::debug!(len = extra_data.len(), data = ?extra_data, "invalid extra data length in flashblock for holocene fork");
bail!("extra data length should be 9 bytes");
}
(extra_data[1..9].try_into().ok(), None)
} else {
if !extra_data.is_empty() {
tracing::debug!(len = extra_data.len(), data = ?extra_data, "invalid extra data length in flashblock for pre holocene fork");
bail!("extra data length should be 0 bytes");
}
(None, None)
};

// see https://specs.optimism.io/protocol/holocene/exec-engine.html#eip-1559-parameters-in-block-header
let eip_1559_parameters: B64 = extra_data[1..9].try_into().unwrap();
let payload_config = PayloadConfig::new(
Arc::new(SealedHeader::new(parent_header.clone(), parent_hash)),
OpPayloadBuilderAttributes {
eip_1559_params: Some(eip_1559_parameters),
eip_1559_params: eip_1559_parameters,
min_base_fee,
payload_attributes: EthPayloadBuilderAttributes {
id: payload.id(), // unused
parent: parent_hash, // unused
Expand All @@ -226,8 +253,10 @@ where
&mut state,
payload.block().body().transactions.clone(),
payload.block().header().gas_used,
timestamp,
ctx.evm_config(),
evm_env.clone(),
chain_spec.clone(),
ctx.max_gas_per_txn(),
is_canyon_active(&chain_spec, timestamp),
is_regolith_active(&chain_spec, timestamp),
Expand Down Expand Up @@ -276,8 +305,10 @@ fn execute_transactions(
state: &mut State<impl alloy_evm::Database>,
txs: Vec<op_alloy_consensus::OpTxEnvelope>,
gas_limit: u64,
timestamp: u64,
evm_config: &reth_optimism_evm::OpEvmConfig,
evm_env: alloy_evm::EvmEnv<op_revm::OpSpecId>,
chain_spec: Arc<OpChainSpec>,
max_gas_per_txn: Option<u64>,
is_canyon_active: bool,
is_regolith_active: bool,
Expand Down Expand Up @@ -396,6 +427,15 @@ fn execute_transactions(
info.executed_transactions.push(tx.clone());
}

// Fetch DA footprint gas scalar for Jovian blocks
let da_footprint_gas_scalar = chain_spec
.is_jovian_active_at_timestamp(timestamp)
.then(|| {
L1BlockInfo::fetch_da_footprint_gas_scalar(evm.db_mut())
.expect("DA footprint should always be available from the database post jovian")
});
info.da_footprint_scalar = da_footprint_gas_scalar;

Ok(())
}

Expand Down
3 changes: 3 additions & 0 deletions crates/op-rbuilder/src/primitives/reth/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct ExecutionInfo<Extra: Debug + Default = ()> {
pub extra: Extra,
/// DA Footprint Scalar for Jovian
pub da_footprint_scalar: Option<u16>,
/// Optional blob fields for payload validation
pub optional_blob_fields: Option<(Option<u64>, Option<u64>)>,
}

impl<T: Debug + Default> ExecutionInfo<T> {
Expand All @@ -56,6 +58,7 @@ impl<T: Debug + Default> ExecutionInfo<T> {
total_fees: U256::ZERO,
extra: Default::default(),
da_footprint_scalar: None,
optional_blob_fields: None,
}
}

Expand Down