Skip to content

Commit

Permalink
feat(l2-withdrawals): withdrawals root in block building (#60)
Browse files Browse the repository at this point in the history
Closes #59

Block building code ported from
#3
  • Loading branch information
emhane authored Jan 31, 2025
1 parent 3e185bd commit 7f54539
Showing 1 changed file with 37 additions and 9 deletions.
46 changes: 37 additions & 9 deletions crates/optimism/payload/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{
error::OpPayloadBuilderError,
payload::{OpBuiltPayload, OpPayloadBuilderAttributes},
};
use alloy_consensus::{Eip658Value, Header, Transaction, Typed2718, EMPTY_OMMER_ROOT_HASH};
use alloy_consensus::{
constants::EMPTY_WITHDRAWALS, Eip658Value, Header, Transaction, Typed2718,
EMPTY_OMMER_ROOT_HASH,
};
use alloy_eips::{eip4895::Withdrawals, merge::BEACON_NONCE};
use alloy_primitives::{Address, Bytes, B256, U256};
use alloy_rpc_types_debug::ExecutionWitness;
Expand All @@ -20,7 +23,9 @@ use reth_execution_types::ExecutionOutcome;
use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
use reth_optimism_forks::OpHardforks;
use reth_optimism_primitives::{OpPrimitives, OpReceipt, OpTransactionSigned};
use reth_optimism_primitives::{
OpPrimitives, OpReceipt, OpTransactionSigned, ADDRESS_L2_TO_L1_MESSAGE_PASSER,
};
use reth_payload_builder_primitives::PayloadBuilderError;
use reth_payload_primitives::PayloadBuilderAttributes;
use reth_payload_util::{NoopPayloadTransactions, PayloadTransactions};
Expand All @@ -30,7 +35,7 @@ use reth_primitives::{
};
use reth_provider::{
HashedPostStateProvider, ProviderError, StateProofProvider, StateProviderFactory,
StateRootProvider,
StateRootProvider, StorageRootProvider,
};
use reth_revm::{database::StateProviderDatabase, witness::ExecutionWitnessRecord};
use reth_transaction_pool::{
Expand Down Expand Up @@ -297,14 +302,15 @@ where
Txs: PayloadTransactions<Transaction = OpTransactionSigned>,
{
/// Executes the payload and returns the outcome.
pub fn execute<EvmConfig, DB>(
pub fn execute<EvmConfig, DB, P>(
self,
state: &mut State<DB>,
ctx: &OpPayloadBuilderCtx<EvmConfig>,
) -> Result<BuildOutcomeKind<ExecutedPayload>, PayloadBuilderError>
where
EvmConfig: ConfigureEvm<Header = Header, Transaction = OpTransactionSigned>,
DB: Database<Error = ProviderError>,
DB: Database<Error = ProviderError> + AsRef<P>,
P: StorageRootProvider,
{
let Self { best } = self;
debug!(target: "payload_builder", id=%ctx.payload_id(), parent_header = ?ctx.parent().hash(), parent_number = ctx.parent().number, "building new payload");
Expand Down Expand Up @@ -332,13 +338,30 @@ where
}
}

let withdrawals_root = ctx.commit_withdrawals(state)?;
debug_assert!(ctx.attributes().payload_attributes.withdrawals.is_empty());

// merge all transitions into bundle state, this would apply the withdrawal balance changes
// and 4788 contract call
state.merge_transitions(BundleRetention::Reverts);

Ok(BuildOutcomeKind::Better { payload: ExecutedPayload { info, withdrawals_root } })
let withdrawals_root = if ctx.is_isthmus_active() {
// withdrawals root field in block header is used for storage root of L2 predeploy
// `l2tol1-message-passer`
Some(
state
.database
.as_ref()
.storage_root(ADDRESS_L2_TO_L1_MESSAGE_PASSER, Default::default())?,
)
} else if ctx.is_canyon_active() {
Some(EMPTY_WITHDRAWALS)
} else {
None
};

let payload = ExecutedPayload { info, withdrawals_root };

Ok(BuildOutcomeKind::Better { payload })
}

/// Builds the payload on top of the state.
Expand All @@ -350,7 +373,7 @@ where
where
EvmConfig: ConfigureEvm<Header = Header, Transaction = OpTransactionSigned>,
DB: Database<Error = ProviderError> + AsRef<P>,
P: StateRootProvider + HashedPostStateProvider,
P: StateRootProvider + HashedPostStateProvider + StorageRootProvider,
{
let ExecutedPayload { info, withdrawals_root } = match self.execute(&mut state, &ctx)? {
BuildOutcomeKind::Better { payload } | BuildOutcomeKind::Freeze(payload) => payload,
Expand Down Expand Up @@ -475,7 +498,7 @@ where
where
EvmConfig: ConfigureEvm<Header = Header, Transaction = OpTransactionSigned>,
DB: Database<Error = ProviderError> + AsRef<P>,
P: StateProofProvider,
P: StateProofProvider + StorageRootProvider,
{
let _ = self.execute(state, ctx)?;
let ExecutionWitnessRecord { hashed_state, codes, keys } =
Expand Down Expand Up @@ -667,6 +690,11 @@ impl<EvmConfig> OpPayloadBuilderCtx<EvmConfig> {
self.chain_spec.is_holocene_active_at_timestamp(self.attributes().timestamp())
}

/// Returns true if holocene is active for the payload.
pub fn is_isthmus_active(&self) -> bool {
self.chain_spec.is_isthmus_active_at_timestamp(self.attributes().timestamp())
}

/// Returns true if the fees are higher than the previous payload.
pub fn is_better_payload(&self, total_fees: U256) -> bool {
is_better_payload(self.best_payload.as_ref(), total_fees)
Expand Down

0 comments on commit 7f54539

Please sign in to comment.