diff --git a/Cargo.lock b/Cargo.lock index ecf9e9407..dfec793b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7130,12 +7130,10 @@ dependencies = [ "reth-chain-state", "reth-chainspec", "reth-engine-primitives", - "reth-evm-ethereum", "reth-payload-primitives", "reth-primitives", "reth-rpc-types", "reth-rpc-types-compat", - "revm-primitives", "serde", "serde_json", "sha2 0.10.8", @@ -7166,11 +7164,13 @@ version = "1.0.6" dependencies = [ "reth-basic-payload-builder", "reth-chain-state", + "reth-chainspec", "reth-errors", "reth-evm", "reth-evm-ethereum", "reth-execution-types", "reth-payload-builder", + "reth-payload-primitives", "reth-primitives", "reth-provider", "reth-revm", diff --git a/crates/ethereum/engine-primitives/Cargo.toml b/crates/ethereum/engine-primitives/Cargo.toml index 07ece0083..8785b96f6 100644 --- a/crates/ethereum/engine-primitives/Cargo.toml +++ b/crates/ethereum/engine-primitives/Cargo.toml @@ -13,13 +13,11 @@ workspace = true [dependencies] # reth reth-chainspec.workspace = true -reth-evm-ethereum.workspace = true reth-primitives.workspace = true reth-engine-primitives.workspace = true reth-payload-primitives.workspace = true reth-rpc-types.workspace = true reth-rpc-types-compat.workspace = true -revm-primitives.workspace = true alloy-rlp.workspace = true reth-chain-state.workspace = true diff --git a/crates/ethereum/engine-primitives/src/lib.rs b/crates/ethereum/engine-primitives/src/lib.rs index fe4a050fa..5554beea3 100644 --- a/crates/ethereum/engine-primitives/src/lib.rs +++ b/crates/ethereum/engine-primitives/src/lib.rs @@ -1,4 +1,4 @@ -//! Ethereum specific +//! Ethereum specific engine API types and impls. #![doc( html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", diff --git a/crates/ethereum/engine-primitives/src/payload.rs b/crates/ethereum/engine-primitives/src/payload.rs index be8cf9314..c3edab111 100644 --- a/crates/ethereum/engine-primitives/src/payload.rs +++ b/crates/ethereum/engine-primitives/src/payload.rs @@ -2,13 +2,8 @@ use alloy_rlp::Encodable; use reth_chain_state::ExecutedBlock; -use reth_chainspec::ChainSpec; -use reth_evm_ethereum::revm_spec_by_timestamp_after_merge; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; -use reth_primitives::{ - constants::EIP1559_INITIAL_BASE_FEE, Address, BlobTransactionSidecar, EthereumHardfork, Header, - SealedBlock, Withdrawals, B256, U256, -}; +use reth_primitives::{Address, BlobTransactionSidecar, SealedBlock, Withdrawals, B256, U256}; use reth_rpc_types::engine::{ ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadV1, PayloadAttributes, PayloadId, @@ -17,7 +12,6 @@ use reth_rpc_types_compat::engine::payload::{ block_to_payload_v1, block_to_payload_v3, block_to_payload_v4, convert_block_to_payload_field_v2, }; -use revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId}; use std::convert::Infallible; /// Contains the built payload. @@ -250,65 +244,6 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes { fn withdrawals(&self) -> &Withdrawals { &self.withdrawals } - - fn cfg_and_block_env( - &self, - chain_spec: &ChainSpec, - parent: &Header, - ) -> (CfgEnvWithHandlerCfg, BlockEnv) { - // configure evm env based on parent block - let cfg = CfgEnv::default().with_chain_id(chain_spec.chain().id()); - - // ensure we're not missing any timestamp based hardforks - let spec_id = revm_spec_by_timestamp_after_merge(chain_spec, self.timestamp()); - - // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is - // cancun now, we need to set the excess blob gas to the default value - let blob_excess_gas_and_price = parent - .next_block_excess_blob_gas() - .or_else(|| { - if spec_id == SpecId::CANCUN { - // default excess blob gas is zero - Some(0) - } else { - None - } - }) - .map(BlobExcessGasAndPrice::new); - - let mut basefee = - parent.next_block_base_fee(chain_spec.base_fee_params_at_timestamp(self.timestamp())); - - let mut gas_limit = U256::from(parent.gas_limit); - - // If we are on the London fork boundary, we need to multiply the parent's gas limit by the - // elasticity multiplier to get the new gas limit. - if chain_spec.fork(EthereumHardfork::London).transitions_at_block(parent.number + 1) { - let elasticity_multiplier = - chain_spec.base_fee_params_at_timestamp(self.timestamp()).elasticity_multiplier; - - // multiply the gas limit by the elasticity multiplier - gas_limit *= U256::from(elasticity_multiplier); - - // set the base fee to the initial base fee from the EIP-1559 spec - basefee = Some(EIP1559_INITIAL_BASE_FEE) - } - - let block_env = BlockEnv { - number: U256::from(parent.number + 1), - coinbase: self.suggested_fee_recipient(), - timestamp: U256::from(self.timestamp()), - difficulty: U256::ZERO, - prevrandao: Some(self.prev_randao()), - gas_limit, - // calculate basefee based on parent block's gas usage - basefee: basefee.map(U256::from).unwrap_or_default(), - // calculate excess gas based on parent block's blob gas usage - blob_excess_gas_and_price, - }; - - (CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env) - } } /// Generates the payload id for the configured payload from the [`PayloadAttributes`]. @@ -338,94 +273,10 @@ pub(crate) fn payload_id(parent: &B256, attributes: &PayloadAttributes) -> Paylo #[cfg(test)] mod tests { use super::*; - use reth_primitives::Genesis; #[test] - fn ensure_first_london_block_base_fee_is_set() { - let hive_london = r#" -{ - "config": { - "ethash": {}, - "chainId": 7, - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 1, - "mergeNetsplitBlock": 1, - "terminalTotalDifficulty": 196608, - "shanghaiTime": 4662, - "cancunTime": 4662 - }, - "nonce": "0x0", - "timestamp": "0x1234", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x2fefd8", - "difficulty": "0x30000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0000000000000000000000000000000000000314": { - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000001234", - "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "balance": "0x0" - }, - "0000000000000000000000000000000000000315": { - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029", - "balance": "0x9999999999999999999999999999999" - }, - "0000000000000000000000000000000000000316": { - "code": "0x444355", - "balance": "0x0" - }, - "0000000000000000000000000000000000000317": { - "code": "0x600160003555", - "balance": "0x0" - }, - "000f3df6d732807ef1319fb7b8bb8522d0beac02": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", - "balance": "0x0", - "nonce": "0x1" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": null, - "excessBlobGas": null, - "blobGasUsed": null -} - "#; - + fn attributes_serde() { let attributes = r#"{"timestamp":"0x1235","prevRandao":"0xf343b00e02dc34ec0124241f74f32191be28fb370bb48060f5fa4df99bda774c","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","withdrawals":null,"parentBeaconBlockRoot":null}"#; - let attributes: PayloadAttributes = serde_json::from_str(attributes).unwrap(); - - // check that it deserializes properly - let genesis: Genesis = serde_json::from_str(hive_london).unwrap(); - let chainspec = ChainSpec::from(genesis); - let payload_builder_attributes = - EthPayloadBuilderAttributes::new(chainspec.genesis_hash(), attributes); - - // use cfg_and_block_env - let cfg_and_block_env = - payload_builder_attributes.cfg_and_block_env(&chainspec, chainspec.genesis_header()); - - // ensure the base fee is non zero - assert_eq!(cfg_and_block_env.1.basefee, U256::from(EIP1559_INITIAL_BASE_FEE)); - - // ensure the gas limit is double the previous block's gas limit - assert_eq!( - cfg_and_block_env.1.gas_limit, - U256::from(chainspec.genesis_header().gas_limit * 2) - ); + let _attributes: PayloadAttributes = serde_json::from_str(attributes).unwrap(); } } diff --git a/crates/ethereum/payload/Cargo.toml b/crates/ethereum/payload/Cargo.toml index 9689f6162..82919e73f 100644 --- a/crates/ethereum/payload/Cargo.toml +++ b/crates/ethereum/payload/Cargo.toml @@ -18,11 +18,13 @@ reth-revm.workspace = true reth-transaction-pool.workspace = true reth-provider.workspace = true reth-payload-builder.workspace = true +reth-payload-primitives.workspace = true reth-execution-types.workspace = true reth-basic-payload-builder.workspace = true reth-evm.workspace = true reth-evm-ethereum.workspace = true reth-errors.workspace = true +reth-chainspec.workspace = true reth-trie.workspace = true reth-chain-state.workspace = true diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 92e98d3a4..bc32c4453 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -14,6 +14,7 @@ use reth_basic_payload_builder::{ PayloadConfig, WithdrawalsOutcome, }; use reth_chain_state::ExecutedBlock; +use reth_chainspec::EthereumHardfork; use reth_errors::RethError; use reth_evm::{ system_calls::{ @@ -23,15 +24,19 @@ use reth_evm::{ }, ConfigureEvm, }; -use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig}; +use reth_evm_ethereum::{ + eip6110::parse_deposits_from_receipts, revm_spec_by_timestamp_after_merge, EthEvmConfig, +}; use reth_execution_types::ExecutionOutcome; use reth_payload_builder::{ error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, }; +use reth_payload_primitives::PayloadBuilderAttributes; use reth_primitives::{ - constants::{eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE}, + constants::{eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE, EIP1559_INITIAL_BASE_FEE}, eip4844::calculate_excess_blob_gas, proofs::{self, calculate_requests_root}, + revm_primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId}, Block, EthereumHardforks, Header, IntoRecoveredTransaction, Receipt, EMPTY_OMMER_ROOT_HASH, U256, }; @@ -43,7 +48,9 @@ use reth_transaction_pool::{ use reth_trie::HashedPostState; use revm::{ db::states::bundle_state::BundleRetention, - primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, + primitives::{ + BlobExcessGasAndPrice, EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState, + }, DatabaseCommit, State, }; use std::sync::Arc; @@ -63,6 +70,84 @@ impl EthereumPayloadBuilder { } } +impl EthereumPayloadBuilder +where + EvmConfig: ConfigureEvm, +{ + /// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload + /// (that has the `parent` as its parent). + /// + /// The `chain_spec` is used to determine the correct chain id and hardfork for the payload + /// based on its timestamp. + /// + /// Block related settings are derived from the `parent` block and the configured attributes. + /// + /// NOTE: This is only intended for beacon consensus (after merge). + fn cfg_and_block_env( + &self, + config: &PayloadConfig, + parent: &Header, + ) -> (CfgEnvWithHandlerCfg, BlockEnv) { + // configure evm env based on parent block + let cfg = CfgEnv::default().with_chain_id(config.chain_spec.chain().id()); + + // ensure we're not missing any timestamp based hardforks + let spec_id = + revm_spec_by_timestamp_after_merge(&config.chain_spec, config.attributes.timestamp()); + + // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is + // cancun now, we need to set the excess blob gas to the default value + let blob_excess_gas_and_price = parent + .next_block_excess_blob_gas() + .or_else(|| { + if spec_id == SpecId::CANCUN { + // default excess blob gas is zero + Some(0) + } else { + None + } + }) + .map(BlobExcessGasAndPrice::new); + + let mut basefee = parent.next_block_base_fee( + config.chain_spec.base_fee_params_at_timestamp(config.attributes.timestamp()), + ); + + let mut gas_limit = U256::from(parent.gas_limit); + + // If we are on the London fork boundary, we need to multiply the parent's gas limit by the + // elasticity multiplier to get the new gas limit. + if config.chain_spec.fork(EthereumHardfork::London).transitions_at_block(parent.number + 1) + { + let elasticity_multiplier = config + .chain_spec + .base_fee_params_at_timestamp(config.attributes.timestamp()) + .elasticity_multiplier; + + // multiply the gas limit by the elasticity multiplier + gas_limit *= U256::from(elasticity_multiplier); + + // set the base fee to the initial base fee from the EIP-1559 spec + basefee = Some(EIP1559_INITIAL_BASE_FEE) + } + + let block_env = BlockEnv { + number: U256::from(parent.number + 1), + coinbase: config.attributes.suggested_fee_recipient(), + timestamp: U256::from(config.attributes.timestamp()), + difficulty: U256::ZERO, + prevrandao: Some(config.attributes.prev_randao()), + gas_limit, + // calculate basefee based on parent block's gas usage + basefee: basefee.map(U256::from).unwrap_or_default(), + // calculate excess gas based on parent block's blob gas usage + blob_excess_gas_and_price, + }; + + (CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env) + } +} + // Default implementation of [PayloadBuilder] for unit type impl PayloadBuilder for EthereumPayloadBuilder where @@ -77,7 +162,8 @@ where &self, args: BuildArguments, ) -> Result, PayloadBuilderError> { - default_ethereum_payload(self.evm_config.clone(), args) + let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block); + default_ethereum_payload(self.evm_config.clone(), args, cfg_env, block_env) } fn build_empty_payload( @@ -94,7 +180,8 @@ where cancel: Default::default(), best_payload: None, }; - default_ethereum_payload(self.evm_config.clone(), args)? + let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block); + default_ethereum_payload(self.evm_config.clone(), args, cfg_env, block_env)? .into_payload() .ok_or_else(|| PayloadBuilderError::MissingPayload) } @@ -109,6 +196,8 @@ where pub fn default_ethereum_payload( evm_config: EvmConfig, args: BuildArguments, + initialized_cfg: CfgEnvWithHandlerCfg, + initialized_block_env: BlockEnv, ) -> Result, PayloadBuilderError> where EvmConfig: ConfigureEvm, @@ -121,15 +210,7 @@ where let state = StateProviderDatabase::new(state_provider); let mut db = State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build(); - let extra_data = config.extra_data(); - let PayloadConfig { - initialized_block_env, - initialized_cfg, - parent_block, - attributes, - chain_spec, - .. - } = config; + let PayloadConfig { parent_block, extra_data, attributes, chain_spec } = config; debug!(target: "payload_builder", id=%attributes.id, parent_hash = ?parent_block.hash(), parent_number = parent_block.number, "building new payload"); let mut cumulative_gas_used = 0; diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 2c8e26cd7..04f476143 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -127,7 +127,10 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { data: Bytes, ); - /// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header + /// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header. + /// + /// This must set the corresponding spec id in the handler cfg, based on timestamp or total + /// difficulty fn fill_cfg_env( &self, cfg_env: &mut CfgEnvWithHandlerCfg, @@ -158,6 +161,8 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { /// Convenience function to call both [`fill_cfg_env`](ConfigureEvmEnv::fill_cfg_env) and /// [`ConfigureEvmEnv::fill_block_env`]. + /// + /// Note: Implementers should ensure that all fields are required fields are filled. fn fill_cfg_and_block_env( &self, cfg: &mut CfgEnvWithHandlerCfg, diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 702b8a98c..a949e9991 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -9,11 +9,16 @@ use reth_basic_payload_builder::*; use reth_chain_state::ExecutedBlock; use reth_chainspec::{EthereumHardforks, OptimismHardfork}; use reth_evm::{system_calls::pre_block_beacon_root_contract_call, ConfigureEvm}; +use reth_evm_optimism::revm_spec_by_timestamp_after_bedrock; use reth_execution_types::ExecutionOutcome; use reth_payload_builder::error::PayloadBuilderError; +use reth_payload_primitives::PayloadBuilderAttributes; use reth_primitives::{ - constants::BEACON_NONCE, eip4844::calculate_excess_blob_gas, proofs, Block, Header, - IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH, + constants::BEACON_NONCE, + eip4844::calculate_excess_blob_gas, + proofs, + revm_primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId}, + Block, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH, }; use reth_provider::StateProviderFactory; use reth_revm::database::StateProviderDatabase; @@ -23,7 +28,10 @@ use reth_transaction_pool::{ use reth_trie::HashedPostState; use revm::{ db::states::bundle_state::BundleRetention, - primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, + primitives::{ + BlobExcessGasAndPrice, EVMError, EnvWithHandlerCfg, HandlerCfg, InvalidTransaction, + ResultAndState, + }, DatabaseCommit, State, }; use std::sync::Arc; @@ -60,6 +68,64 @@ impl OptimismPayloadBuilder { pub const fn is_compute_pending_block(&self) -> bool { self.compute_pending_block } + + fn cfg_and_block_env( + &self, + config: &PayloadConfig, + parent: &Header, + ) -> (CfgEnvWithHandlerCfg, BlockEnv) { + // configure evm env based on parent block + let cfg = CfgEnv::default().with_chain_id(config.chain_spec.chain().id()); + + // ensure we're not missing any timestamp based hardforks + let spec_id = + revm_spec_by_timestamp_after_bedrock(&config.chain_spec, config.attributes.timestamp()); + + // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is + // cancun now, we need to set the excess blob gas to the default value + let blob_excess_gas_and_price = parent + .next_block_excess_blob_gas() + .or_else(|| { + if spec_id.is_enabled_in(SpecId::CANCUN) { + // default excess blob gas is zero + Some(0) + } else { + None + } + }) + .map(BlobExcessGasAndPrice::new); + + let block_env = BlockEnv { + number: U256::from(parent.number + 1), + coinbase: config.attributes.suggested_fee_recipient(), + timestamp: U256::from(config.attributes.timestamp()), + difficulty: U256::ZERO, + prevrandao: Some(config.attributes.prev_randao()), + gas_limit: U256::from(parent.gas_limit), + // calculate basefee based on parent block's gas usage + basefee: U256::from( + parent + .next_block_base_fee( + config + .chain_spec + .base_fee_params_at_timestamp(config.attributes.timestamp()), + ) + .unwrap_or_default(), + ), + // calculate excess gas based on parent block's blob gas usage + blob_excess_gas_and_price, + }; + + let cfg_with_handler_cfg; + { + cfg_with_handler_cfg = CfgEnvWithHandlerCfg { + cfg_env: cfg, + handler_cfg: HandlerCfg { spec_id, is_optimism: true }, + }; + } + + (cfg_with_handler_cfg, block_env) + } } /// Implementation of the [`PayloadBuilder`] trait for [`OptimismPayloadBuilder`]. @@ -76,7 +142,14 @@ where &self, args: BuildArguments, ) -> Result, PayloadBuilderError> { - optimism_payload(self.evm_config.clone(), args, self.compute_pending_block) + let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block); + optimism_payload( + self.evm_config.clone(), + args, + cfg_env, + block_env, + self.compute_pending_block, + ) } fn on_missing_payload( @@ -104,7 +177,8 @@ where cancel: Default::default(), best_payload: None, }; - optimism_payload(self.evm_config.clone(), args, false)? + let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block); + optimism_payload(self.evm_config.clone(), args, cfg_env, block_env, false)? .into_payload() .ok_or_else(|| PayloadBuilderError::MissingPayload) } @@ -122,6 +196,8 @@ where pub(crate) fn optimism_payload( evm_config: EvmConfig, args: BuildArguments, + initialized_cfg: CfgEnvWithHandlerCfg, + initialized_block_env: BlockEnv, _compute_pending_block: bool, ) -> Result, PayloadBuilderError> where @@ -135,15 +211,7 @@ where let state = StateProviderDatabase::new(state_provider); let mut db = State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build(); - let extra_data = config.extra_data(); - let PayloadConfig { - initialized_block_env, - initialized_cfg, - parent_block, - attributes, - chain_spec, - .. - } = config; + let PayloadConfig { parent_block, attributes, chain_spec, extra_data } = config; debug!(target: "payload_builder", id=%attributes.payload_attributes.payload_id(), parent_hash = ?parent_block.hash(), parent_number = parent_block.number, "building new payload"); diff --git a/crates/optimism/payload/src/payload.rs b/crates/optimism/payload/src/payload.rs index 62c559b32..2acf875a5 100644 --- a/crates/optimism/payload/src/payload.rs +++ b/crates/optimism/payload/src/payload.rs @@ -6,13 +6,10 @@ use alloy_primitives::{Address, B256, U256}; use alloy_rlp::Encodable; use reth_chain_state::ExecutedBlock; use reth_chainspec::{ChainSpec, EthereumHardforks}; -use reth_evm_optimism::revm_spec_by_timestamp_after_bedrock; use reth_payload_builder::EthPayloadBuilderAttributes; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; use reth_primitives::{ - revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId}, - transaction::WithEncoded, - BlobTransactionSidecar, Header, SealedBlock, TransactionSigned, Withdrawals, + transaction::WithEncoded, BlobTransactionSidecar, SealedBlock, TransactionSigned, Withdrawals, }; /// Re-export for use in downstream arguments. pub use reth_rpc_types::optimism::OptimismPayloadAttributes; @@ -24,7 +21,6 @@ use reth_rpc_types_compat::engine::payload::{ block_to_payload_v1, block_to_payload_v3, block_to_payload_v4, convert_block_to_payload_field_v2, }; -use revm::primitives::HandlerCfg; use std::sync::Arc; /// Optimism Payload Builder Attributes @@ -106,59 +102,6 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes { fn withdrawals(&self) -> &Withdrawals { &self.payload_attributes.withdrawals } - - fn cfg_and_block_env( - &self, - chain_spec: &ChainSpec, - parent: &Header, - ) -> (CfgEnvWithHandlerCfg, BlockEnv) { - // configure evm env based on parent block - let cfg = CfgEnv::default().with_chain_id(chain_spec.chain().id()); - - // ensure we're not missing any timestamp based hardforks - let spec_id = revm_spec_by_timestamp_after_bedrock(chain_spec, self.timestamp()); - - // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is - // cancun now, we need to set the excess blob gas to the default value - let blob_excess_gas_and_price = parent - .next_block_excess_blob_gas() - .or_else(|| { - if spec_id.is_enabled_in(SpecId::CANCUN) { - // default excess blob gas is zero - Some(0) - } else { - None - } - }) - .map(BlobExcessGasAndPrice::new); - - let block_env = BlockEnv { - number: U256::from(parent.number + 1), - coinbase: self.suggested_fee_recipient(), - timestamp: U256::from(self.timestamp()), - difficulty: U256::ZERO, - prevrandao: Some(self.prev_randao()), - gas_limit: U256::from(parent.gas_limit), - // calculate basefee based on parent block's gas usage - basefee: U256::from( - parent - .next_block_base_fee(chain_spec.base_fee_params_at_timestamp(self.timestamp())) - .unwrap_or_default(), - ), - // calculate excess gas based on parent block's blob gas usage - blob_excess_gas_and_price, - }; - - let cfg_with_handler_cfg; - { - cfg_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: cfg, - handler_cfg: HandlerCfg { spec_id, is_optimism: true }, - }; - } - - (cfg_with_handler_cfg, block_env) - } } /// Contains the built payload. diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index 3847d46a5..b565e37fe 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -27,10 +27,7 @@ use reth_provider::{ use reth_revm::state_change::post_block_withdrawals_balance_increments; use reth_tasks::TaskSpawner; use reth_transaction_pool::TransactionPool; -use revm::{ - primitives::{BlockEnv, CfgEnvWithHandlerCfg}, - Database, State, -}; +use revm::{Database, State}; use std::{ fmt, future::Future, @@ -673,10 +670,6 @@ impl Drop for Cancelled { /// Static config for how to build a payload. #[derive(Clone, Debug)] pub struct PayloadConfig { - /// Pre-configured block environment. - pub initialized_block_env: BlockEnv, - /// Configuration for the environment. - pub initialized_cfg: CfgEnvWithHandlerCfg, /// The parent block. pub parent_block: Arc, /// Block extra data. @@ -699,24 +692,13 @@ where Attributes: PayloadBuilderAttributes, { /// Create new payload config. - pub fn new( + pub const fn new( parent_block: Arc, extra_data: Bytes, attributes: Attributes, chain_spec: Arc, ) -> Self { - // configure evm env based on parent block - let (initialized_cfg, initialized_block_env) = - attributes.cfg_and_block_env(&chain_spec, &parent_block); - - Self { - initialized_block_env, - initialized_cfg, - parent_block, - extra_data, - attributes, - chain_spec, - } + Self { parent_block, extra_data, attributes, chain_spec } } /// Returns the payload id. diff --git a/crates/payload/primitives/src/traits.rs b/crates/payload/primitives/src/traits.rs index 80ae38127..5c231d1a6 100644 --- a/crates/payload/primitives/src/traits.rs +++ b/crates/payload/primitives/src/traits.rs @@ -1,19 +1,15 @@ +use crate::{ + validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError, +}; use reth_chain_state::ExecutedBlock; use reth_chainspec::ChainSpec; -use reth_primitives::{ - revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, - Address, Header, SealedBlock, Withdrawals, B256, U256, -}; +use reth_primitives::{Address, SealedBlock, Withdrawals, B256, U256}; use reth_rpc_types::{ engine::{PayloadAttributes as EthPayloadAttributes, PayloadId}, optimism::OptimismPayloadAttributes, Withdrawal, }; -use crate::{ - validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError, -}; - /// Represents a built payload type that contains a built [`SealedBlock`] and can be converted into /// engine API execution payloads. pub trait BuiltPayload: Send + Sync + std::fmt::Debug { @@ -70,21 +66,6 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug { /// Returns the withdrawals for the running payload job. fn withdrawals(&self) -> &Withdrawals; - - /// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload - /// (that has the `parent` as its parent). - /// - /// The `chain_spec` is used to determine the correct chain id and hardfork for the payload - /// based on its timestamp. - /// - /// Block related settings are derived from the `parent` block and the configured attributes. - /// - /// NOTE: This is only intended for beacon consensus (after merge). - fn cfg_and_block_env( - &self, - chain_spec: &ChainSpec, - parent: &Header, - ) -> (CfgEnvWithHandlerCfg, BlockEnv); } /// The execution payload attribute type the CL node emits via the engine API. diff --git a/examples/custom-engine-types/src/main.rs b/examples/custom-engine-types/src/main.rs index 274fb4aae..b6bccd2be 100644 --- a/examples/custom-engine-types/src/main.rs +++ b/examples/custom-engine-types/src/main.rs @@ -30,7 +30,6 @@ use reth::{ node::{NodeTypes, NodeTypesWithEngine}, BuilderContext, FullNodeTypes, Node, NodeBuilder, PayloadBuilderConfig, }, - primitives::revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, providers::{CanonStateSubscriptions, StateProviderFactory}, tasks::TaskManager, transaction_pool::TransactionPool, @@ -56,7 +55,7 @@ use reth_payload_builder::{ error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, PayloadBuilderHandle, PayloadBuilderService, }; -use reth_primitives::{Address, Header, Withdrawals, B256}; +use reth_primitives::{Address, Withdrawals, B256}; use reth_rpc_types::{ engine::{ ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, @@ -153,14 +152,6 @@ impl PayloadBuilderAttributes for CustomPayloadBuilderAttributes { fn withdrawals(&self) -> &Withdrawals { &self.0.withdrawals } - - fn cfg_and_block_env( - &self, - chain_spec: &ChainSpec, - parent: &Header, - ) -> (CfgEnvWithHandlerCfg, BlockEnv) { - self.0.cfg_and_block_env(chain_spec, parent) - } } /// Custom engine types - uses a custom payload attributes RPC type, but uses the default @@ -294,14 +285,7 @@ where args: BuildArguments, ) -> Result, PayloadBuilderError> { let BuildArguments { client, pool, cached_reads, config, cancel, best_payload } = args; - let PayloadConfig { - initialized_block_env, - initialized_cfg, - parent_block, - extra_data, - attributes, - chain_spec, - } = config; + let PayloadConfig { parent_block, extra_data, attributes, chain_spec } = config; // This reuses the default EthereumPayloadBuilder to build the payload // but any custom logic can be implemented here @@ -313,8 +297,6 @@ where pool, cached_reads, config: PayloadConfig { - initialized_block_env, - initialized_cfg, parent_block, extra_data, attributes: attributes.0, @@ -330,16 +312,9 @@ where client: &Client, config: PayloadConfig, ) -> Result { - let PayloadConfig { - initialized_block_env, - initialized_cfg, - parent_block, - extra_data, - attributes, - chain_spec, - } = config; + let PayloadConfig { parent_block, extra_data, attributes, chain_spec } = config; >::build_empty_payload(&reth_ethereum_payload_builder::EthereumPayloadBuilder::new(EthEvmConfig::new(chain_spec.clone())),client, - PayloadConfig { initialized_block_env, initialized_cfg, parent_block, extra_data, attributes: attributes.0, chain_spec }) + PayloadConfig { parent_block, extra_data, attributes: attributes.0, chain_spec }) } }