Skip to content
Merged
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
74 changes: 21 additions & 53 deletions crates/op-rbuilder/src/builders/flashblocks/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
traits::{ClientBounds, PoolBounds},
};
use alloy_consensus::{
BlockBody, EMPTY_OMMER_ROOT_HASH, Header, constants::EMPTY_WITHDRAWALS, proofs,
BlockBody, EMPTY_OMMER_ROOT_HASH, Header, TxReceipt, constants::EMPTY_WITHDRAWALS, proofs,
};
use alloy_eips::{Encodable2718, eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE};
use alloy_evm::block::BlockExecutionResult;
Expand All @@ -40,8 +40,7 @@ use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
use reth_payload_util::BestPayloadTransactions;
use reth_primitives_traits::RecoveredBlock;
use reth_provider::{
ExecutionOutcome, HashedPostStateProvider, ProviderError, StateRootProvider,
StorageRootProvider,
HashedPostStateProvider, ProviderError, StateRootProvider, StorageRootProvider,
};
use reth_revm::{
State, database::StateProviderDatabase, db::states::bundle_state::BundleRetention,
Expand Down Expand Up @@ -923,41 +922,12 @@ where
));
}

let execution_outcome = ExecutionOutcome::new(
state.bundle_state.clone(),
vec![info.receipts.clone()],
block_number,
vec![],
let receipts_root = calculate_receipt_root_no_memo_optimism(
&info.receipts,
&ctx.chain_spec,
ctx.attributes().timestamp(),
);

let receipts_root = execution_outcome
.generic_receipts_root_slow(block_number, |receipts| {
calculate_receipt_root_no_memo_optimism(
receipts,
&ctx.chain_spec,
ctx.attributes().timestamp(),
)
})
.ok_or_else(|| {
PayloadBuilderError::Other(
eyre::eyre!(
"receipts and block number not in range, block number {}",
block_number
)
.into(),
)
})?;
let logs_bloom = execution_outcome
.block_logs_bloom(block_number)
.ok_or_else(|| {
PayloadBuilderError::Other(
eyre::eyre!(
"logs bloom and block number not in range, block number {}",
block_number
)
.into(),
)
})?;
let logs_bloom = alloy_primitives::logs_bloom(info.receipts.iter().flat_map(|r| r.logs()));
Comment on lines +925 to +930
Copy link
Member

Choose a reason for hiding this comment

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

I think we could try to compute logs bloom first with &info.receipts.with_bloom_ref() / ReceiptWithBloom and use calculate_receipt_root_optimism with memoized logs blooms to not compute it twice.

Copy link
Contributor Author

@0xl3on 0xl3on Feb 18, 2026

Choose a reason for hiding this comment

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

I think we could try to compute logs bloom first with &info.receipts.with_bloom_ref() / ReceiptWithBloom and use calculate_receipt_root_optimism with memoized logs blooms to not compute it twice.

Yes, good idea

I'll open a PR there suggesting changing the visibility, because atm its pub(crate) (https://github.com/ethereum-optimism/optimism/blame/2eb7e3c074b6b77cf94956529508ec882b0b5f18/rust/op-reth/crates/consensus/src/proof.rs#L12)

So I think for now we can merge this and once its merged there I update here?

edit: saw you opened the PR already!

Copy link
Member

Choose a reason for hiding this comment

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

yeah found out the same. Sorry for the frontrun


// TODO: maybe recreate state with bundle in here
// calculate the state root
Expand All @@ -968,7 +938,7 @@ where

if calculate_state_root {
let state_provider = state.database.as_ref();
hashed_state = state_provider.hashed_post_state(execution_outcome.state());
hashed_state = state_provider.hashed_post_state(&state.bundle_state);
(state_root, trie_output) = {
state
.database
Expand Down Expand Up @@ -1002,7 +972,7 @@ where
// withdrawals root field in block header is used for storage root of L2 predeploy
// `l2tol1-message-passer`
Some(
isthmus::withdrawals_root(execution_outcome.state(), state.database.as_ref())
isthmus::withdrawals_root(&state.bundle_state, state.database.as_ref())
.map_err(PayloadBuilderError::other)?,
)
} else if ctx
Expand All @@ -1020,9 +990,17 @@ where
let (excess_blob_gas, blob_gas_used) = ctx.blob_fields(info);
let extra_data = ctx.extra_data()?;

// Create BlockExecutionOutput for BuiltPayloadExecutedBlock
// need to read balances before take_bundle() below
let new_account_balances = state
.bundle_state
.state
.iter()
.filter_map(|(address, account)| account.info.as_ref().map(|info| (*address, info.balance)))
.collect::<BTreeMap<Address, U256>>();

let bundle_state = state.take_bundle();
let execution_output = BlockExecutionOutput {
state: state.bundle_state.clone(),
state: bundle_state,
result: BlockExecutionResult {
receipts: info.receipts.clone(),
requests: Default::default(),
Expand Down Expand Up @@ -1095,8 +1073,7 @@ where
let new_transactions = info.executed_transactions[info.extra.last_flashblock_index..].to_vec();

let new_transactions_encoded = new_transactions
.clone()
.into_iter()
.iter()
.map(|tx| tx.encoded_2718().into())
.collect::<Vec<_>>();

Expand All @@ -1107,13 +1084,6 @@ where
.zip(new_receipts.iter())
.map(|(tx, receipt)| (tx.tx_hash(), convert_receipt(receipt)))
.collect::<BTreeMap<B256, op_alloy_consensus::OpReceipt>>();
let new_account_balances = state
.bundle_state
.state
.iter()
.filter_map(|(address, account)| account.info.as_ref().map(|info| (*address, info.balance)))
.collect::<BTreeMap<Address, U256>>();

let metadata = OpFlashblockPayloadMetadata {
receipts: receipts_with_hash,
new_account_balances,
Expand Down Expand Up @@ -1158,9 +1128,7 @@ where
},
metadata,
};

// We clean bundle and place initial state transaction back
state.take_bundle();
// Need to ensure `state.bundle = None`, was done previously with `state.take_bundle()`
state.transition_state = untouched_transition_state;

Ok((
Expand Down
51 changes: 20 additions & 31 deletions crates/op-rbuilder/src/builders/standard/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
traits::{ClientBounds, PayloadTxsBounds, PoolBounds},
};
use alloy_consensus::{
BlockBody, EMPTY_OMMER_ROOT_HASH, Header, constants::EMPTY_WITHDRAWALS, proofs,
BlockBody, EMPTY_OMMER_ROOT_HASH, Header, TxReceipt, constants::EMPTY_WITHDRAWALS, proofs,
};
use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE};
use alloy_evm::{Database, block::BlockExecutionResult};
Expand All @@ -26,7 +26,7 @@ use reth_payload_primitives::BuiltPayloadExecutedBlock;
use reth_payload_util::{BestPayloadTransactions, NoopPayloadTransactions, PayloadTransactions};
use reth_primitives::RecoveredBlock;
use reth_primitives_traits::InMemorySize;
use reth_provider::{ExecutionOutcome, StateProvider};
use reth_provider::StateProvider;
use reth_revm::{
State, database::StateProviderDatabase, db::states::bundle_state::BundleRetention,
};
Expand Down Expand Up @@ -478,45 +478,24 @@ impl<Txs: PayloadTxsBounds> OpBuilder<'_, Txs> {
}
};

let block_number = ctx.block_number();
// OP doesn't support blobs/EIP-4844.
// https://specs.optimism.io/protocol/exec-engine.html#ecotone-disable-blob-transactions
// Need [Some] or [None] based on hardfork to match block hash.
let (excess_blob_gas, blob_gas_used) = ctx.blob_fields(&info);

let bundle_state = db.take_bundle();
let execution_outcome = ExecutionOutcome::new(
bundle_state.clone(),
vec![info.receipts.clone()],
block_number,
Vec::new(),

let receipts_root = calculate_receipt_root_no_memo_optimism(
&info.receipts,
&ctx.chain_spec,
ctx.attributes().timestamp(),
);
let execution_output = BlockExecutionOutput {
state: bundle_state,
result: BlockExecutionResult {
receipts: info.receipts,
requests: Default::default(),
gas_used: info.cumulative_gas_used,
blob_gas_used: blob_gas_used.unwrap_or_default(),
},
};
let receipts_root = execution_outcome
.generic_receipts_root_slow(block_number, |receipts| {
calculate_receipt_root_no_memo_optimism(
receipts,
&ctx.chain_spec,
ctx.attributes().timestamp(),
)
})
.expect("Number is in range");
let logs_bloom = execution_outcome
.block_logs_bloom(block_number)
.expect("Number is in range");
let logs_bloom = alloy_primitives::logs_bloom(info.receipts.iter().flat_map(|r| r.logs()));

// calculate the state root
let state_root_start_time = Instant::now();

let hashed_state = state_provider.hashed_post_state(execution_outcome.state());
let hashed_state = state_provider.hashed_post_state(&bundle_state);
let (state_root, trie_output) = {
state_provider
.state_root_with_updates(hashed_state.clone())
Expand All @@ -542,7 +521,7 @@ impl<Txs: PayloadTxsBounds> OpBuilder<'_, Txs> {
// `l2tol1-message-passer`
(
Some(
isthmus::withdrawals_root(execution_outcome.state(), state_provider)
isthmus::withdrawals_root(&bundle_state, state_provider)
.map_err(PayloadBuilderError::other)?,
),
Some(EMPTY_REQUESTS_HASH),
Expand All @@ -553,6 +532,16 @@ impl<Txs: PayloadTxsBounds> OpBuilder<'_, Txs> {
(None, None)
};

let execution_output = BlockExecutionOutput {
state: bundle_state,
result: BlockExecutionResult {
receipts: info.receipts,
requests: Default::default(),
gas_used: info.cumulative_gas_used,
blob_gas_used: blob_gas_used.unwrap_or_default(),
},
};

// create the block header
let transactions_root = proofs::calculate_transaction_root(&info.executed_transactions);

Expand Down
Loading