mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(isthmus): withdrawals root in block building (#14209)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -6,7 +6,10 @@ use crate::{
|
||||
payload::{OpBuiltPayload, OpPayloadBuilderAttributes},
|
||||
OpPayloadPrimitives,
|
||||
};
|
||||
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_rlp::Encodable;
|
||||
@ -26,7 +29,9 @@ use reth_optimism_chainspec::OpChainSpec;
|
||||
use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
|
||||
use reth_optimism_evm::{OpReceiptBuilder, ReceiptBuilderCtx};
|
||||
use reth_optimism_forks::OpHardforks;
|
||||
use reth_optimism_primitives::{transaction::signed::OpTransaction, OpTransactionSigned};
|
||||
use reth_optimism_primitives::{
|
||||
transaction::signed::OpTransaction, OpTransactionSigned, ADDRESS_L2_TO_L1_MESSAGE_PASSER,
|
||||
};
|
||||
use reth_payload_builder_primitives::PayloadBuilderError;
|
||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||
use reth_payload_util::{NoopPayloadTransactions, PayloadTransactions};
|
||||
@ -36,7 +41,7 @@ use reth_primitives::{
|
||||
use reth_primitives_traits::{block::Block as _, proofs, RecoveredBlock};
|
||||
use reth_provider::{
|
||||
HashedPostStateProvider, ProviderError, StateProofProvider, StateProviderFactory,
|
||||
StateRootProvider,
|
||||
StateRootProvider, StorageRootProvider,
|
||||
};
|
||||
use reth_revm::{
|
||||
cancelled::Cancelled, database::StateProviderDatabase, witness::ExecutionWitnessRecord,
|
||||
@ -330,7 +335,7 @@ where
|
||||
Txs: PayloadTransactions,
|
||||
{
|
||||
/// Executes the payload and returns the outcome.
|
||||
pub fn execute<EvmConfig, N, DB>(
|
||||
pub fn execute<EvmConfig, N, DB, P>(
|
||||
self,
|
||||
state: &mut State<DB>,
|
||||
ctx: &OpPayloadBuilderCtx<EvmConfig, N>,
|
||||
@ -339,7 +344,8 @@ where
|
||||
N: OpPayloadPrimitives,
|
||||
Txs: PayloadTransactions<Transaction = N::SignedTx>,
|
||||
EvmConfig: ConfigureEvmFor<N>,
|
||||
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");
|
||||
@ -367,13 +373,28 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let withdrawals_root = ctx.commit_withdrawals(state)?;
|
||||
|
||||
// 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.
|
||||
@ -387,7 +408,7 @@ where
|
||||
N: OpPayloadPrimitives,
|
||||
Txs: PayloadTransactions<Transaction = N::SignedTx>,
|
||||
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,
|
||||
@ -512,7 +533,7 @@ where
|
||||
N: OpPayloadPrimitives,
|
||||
Txs: PayloadTransactions<Transaction = N::SignedTx>,
|
||||
DB: Database<Error = ProviderError> + AsRef<P>,
|
||||
P: StateProofProvider,
|
||||
P: StateProofProvider + StorageRootProvider,
|
||||
{
|
||||
let _ = self.execute(state, ctx)?;
|
||||
let ExecutionWitnessRecord { hashed_state, codes, keys } =
|
||||
@ -735,24 +756,16 @@ impl<EvmConfig: ConfigureEvmEnv, N: NodePrimitives> OpPayloadBuilderCtx<EvmConfi
|
||||
self.chain_spec.is_holocene_active_at_timestamp(self.attributes().timestamp())
|
||||
}
|
||||
|
||||
/// Returns true if isthmus 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)
|
||||
}
|
||||
|
||||
/// Commits the withdrawals from the payload attributes to the state.
|
||||
pub fn commit_withdrawals<DB>(&self, db: &mut State<DB>) -> Result<Option<B256>, ProviderError>
|
||||
where
|
||||
DB: Database<Error = ProviderError>,
|
||||
{
|
||||
commit_withdrawals(
|
||||
db,
|
||||
&self.chain_spec,
|
||||
self.attributes().payload_attributes.timestamp,
|
||||
&self.attributes().payload_attributes.withdrawals,
|
||||
)
|
||||
}
|
||||
|
||||
/// Ensure that the create2deployer is force-deployed at the canyon transition. Optimism
|
||||
/// blocks will always have at least a single transaction in them (the L1 info transaction),
|
||||
/// so we can safely assume that this will always be triggered upon the transition and that
|
||||
|
||||
@ -12,9 +12,11 @@
|
||||
extern crate alloc;
|
||||
|
||||
pub mod bedrock;
|
||||
pub mod transaction;
|
||||
|
||||
use reth_primitives_traits::Block;
|
||||
pub mod predeploys;
|
||||
pub use predeploys::ADDRESS_L2_TO_L1_MESSAGE_PASSER;
|
||||
|
||||
pub mod transaction;
|
||||
pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType};
|
||||
|
||||
mod receipt;
|
||||
@ -24,7 +26,7 @@ pub use receipt::{DepositReceipt, OpReceipt};
|
||||
pub type OpBlock = alloy_consensus::Block<OpTransactionSigned>;
|
||||
|
||||
/// Optimism-specific block body type.
|
||||
pub type OpBlockBody = <OpBlock as Block>::Body;
|
||||
pub type OpBlockBody = <OpBlock as reth_primitives_traits::Block>::Body;
|
||||
|
||||
/// Primitive types for Optimism Node.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
|
||||
8
crates/optimism/primitives/src/predeploys.rs
Normal file
8
crates/optimism/primitives/src/predeploys.rs
Normal file
@ -0,0 +1,8 @@
|
||||
//! Addresses of OP pre-deploys.
|
||||
// todo: move to op-alloy
|
||||
|
||||
use alloy_primitives::{address, Address};
|
||||
|
||||
/// The L2 contract `L2ToL1MessagePasser`, stores commitments to withdrawal transactions.
|
||||
pub const ADDRESS_L2_TO_L1_MESSAGE_PASSER: Address =
|
||||
address!("4200000000000000000000000000000000000016");
|
||||
Reference in New Issue
Block a user