diff --git a/bin/reth/src/args/rpc_server_args.rs b/bin/reth/src/args/rpc_server_args.rs index 67bd39cac552..0d2cd9bd6620 100644 --- a/bin/reth/src/args/rpc_server_args.rs +++ b/bin/reth/src/args/rpc_server_args.rs @@ -339,9 +339,10 @@ impl RpcServerArgs { ) -> Result where Provider: BlockReaderIdExt + + ChainSpecProvider + + EvmEnvProvider + HeaderProvider + StateProviderFactory - + EvmEnvProvider + Clone + Unpin + 'static, diff --git a/bin/reth/src/init.rs b/bin/reth/src/init.rs index 693940a93a03..5296c249762c 100644 --- a/bin/reth/src/init.rs +++ b/bin/reth/src/init.rs @@ -273,6 +273,7 @@ mod tests { genesis_hash: None, paris_block_and_final_difficulty: None, deposit_contract: None, + ..Default::default() }); let db = create_test_rw_db(); diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index abd0fada2c55..7b14f544a483 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -246,10 +246,16 @@ impl StorageInner { /// Fills in pre-execution header fields based on the current best block and given /// transactions. - pub(crate) fn build_header_template(&self, transactions: &Vec) -> Header { + pub(crate) fn build_header_template( + &self, + transactions: &Vec, + chain_spec: Arc, + ) -> Header { // check previous block for base fee - let base_fee_per_gas = - self.headers.get(&self.best_block).and_then(|parent| parent.next_block_base_fee()); + let base_fee_per_gas = self + .headers + .get(&self.best_block) + .and_then(|parent| parent.next_block_base_fee(chain_spec.base_fee_params)); let mut header = Header { parent_hash: self.best_hash, @@ -337,8 +343,9 @@ impl StorageInner { &mut self, transactions: Vec, executor: &mut Executor, + chain_spec: Arc, ) -> Result<(SealedHeader, PostState), BlockExecutionError> { - let header = self.build_header_template(&transactions); + let header = self.build_header_template(&transactions, chain_spec); let block = Block { header, body: transactions, ommers: vec![], withdrawals: None }; diff --git a/crates/consensus/auto-seal/src/task.rs b/crates/consensus/auto-seal/src/task.rs index 6d77784b1add..ddb450acea62 100644 --- a/crates/consensus/auto-seal/src/task.rs +++ b/crates/consensus/auto-seal/src/task.rs @@ -129,9 +129,10 @@ where // execute the new block let substate = SubState::new(State::new(client.latest().unwrap())); - let mut executor = Executor::new(chain_spec, substate); + let mut executor = Executor::new(Arc::clone(&chain_spec), substate); - match storage.build_and_execute(transactions.clone(), &mut executor) { + match storage.build_and_execute(transactions.clone(), &mut executor, chain_spec) + { Ok((new_header, post_state)) => { // clear all transactions from pool pool.remove_transactions(transactions.iter().map(|tx| tx.hash())); diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index fd7c6140d16c..baf7d5edc104 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -271,7 +271,7 @@ pub fn validate_header_regarding_parent( // By consensus, gas_limit is multiplied by elasticity (*2) on // on exact block that hardfork happens. if chain_spec.fork(Hardfork::London).transitions_at_block(child.number) { - parent_gas_limit = parent.gas_limit * constants::EIP1559_ELASTICITY_MULTIPLIER; + parent_gas_limit = parent.gas_limit * chain_spec.base_fee_params.elasticity_multiplier; } // Check gas limit, max diff between child/parent gas_limit should be max_diff=parent_gas/1024 @@ -298,7 +298,9 @@ pub fn validate_header_regarding_parent( constants::EIP1559_INITIAL_BASE_FEE } else { // This BaseFeeMissing will not happen as previous blocks are checked to have them. - parent.next_block_base_fee().ok_or(ConsensusError::BaseFeeMissing)? + parent + .next_block_base_fee(chain_spec.base_fee_params) + .ok_or(ConsensusError::BaseFeeMissing)? }; if expected_base_fee != base_fee { return Err(ConsensusError::BaseFeeDiff { expected: expected_base_fee, got: base_fee }) diff --git a/crates/payload/builder/src/payload.rs b/crates/payload/builder/src/payload.rs index 83cfe75ec1ed..c930585a457d 100644 --- a/crates/payload/builder/src/payload.rs +++ b/crates/payload/builder/src/payload.rs @@ -134,7 +134,9 @@ impl PayloadBuilderAttributes { 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().unwrap_or_default()), + basefee: U256::from( + parent.next_block_base_fee(chain_spec.base_fee_params).unwrap_or_default(), + ), }; (cfg, block_env) diff --git a/crates/primitives/src/basefee.rs b/crates/primitives/src/basefee.rs index be60c3dcc4a2..3614c850aa17 100644 --- a/crates/primitives/src/basefee.rs +++ b/crates/primitives/src/basefee.rs @@ -1,11 +1,13 @@ //! Helpers for working with EIP-1559 base fee -use crate::constants; - /// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec -pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 { - let gas_target = gas_limit / constants::EIP1559_ELASTICITY_MULTIPLIER; - +pub fn calculate_next_block_base_fee( + gas_used: u64, + gas_limit: u64, + base_fee: u64, + base_fee_params: crate::BaseFeeParams, +) -> u64 { + let gas_target = gas_limit / base_fee_params.elasticity_multiplier; if gas_used == gas_target { return base_fee } @@ -15,14 +17,14 @@ pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u6 1, base_fee as u128 * gas_used_delta as u128 / gas_target as u128 / - constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128, + base_fee_params.max_change_denominator as u128, ); base_fee + (base_fee_delta as u64) } else { let gas_used_delta = gas_target - gas_used; let base_fee_per_gas_delta = base_fee as u128 * gas_used_delta as u128 / gas_target as u128 / - constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128; + base_fee_params.max_change_denominator as u128; base_fee.saturating_sub(base_fee_per_gas_delta as u64) } @@ -54,7 +56,12 @@ mod tests { for i in 0..base_fee.len() { assert_eq!( next_base_fee[i], - calculate_next_block_base_fee(gas_used[i], gas_limit[i], base_fee[i]) + calculate_next_block_base_fee( + gas_used[i], + gas_limit[i], + base_fee[i], + crate::BaseFeeParams::ethereum(), + ) ); } } diff --git a/crates/primitives/src/chain/mod.rs b/crates/primitives/src/chain/mod.rs index b46519f32566..69afd1fe03fc 100644 --- a/crates/primitives/src/chain/mod.rs +++ b/crates/primitives/src/chain/mod.rs @@ -10,7 +10,7 @@ use std::{fmt, str::FromStr}; // The chain spec module. mod spec; pub use spec::{ - AllGenesisFormats, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition, + AllGenesisFormats, BaseFeeParams, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition, ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA, }; diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index ca514a628808..f82d93052c22 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -1,5 +1,8 @@ use crate::{ - constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_WITHDRAWALS}, + constants::{ + EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + EIP1559_INITIAL_BASE_FEE, EMPTY_WITHDRAWALS, + }, forkid::ForkFilterKey, header::Head, proofs::genesis_state_root, @@ -60,6 +63,7 @@ pub static MAINNET: Lazy> = Lazy::new(|| { 11052984, H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")), )), + ..Default::default() } .into() }); @@ -100,6 +104,7 @@ pub static GOERLI: Lazy> = Lazy::new(|| { 4367322, H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")), )), + ..Default::default() } .into() }); @@ -144,6 +149,7 @@ pub static SEPOLIA: Lazy> = Lazy::new(|| { 1273020, H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")), )), + ..Default::default() } .into() }); @@ -182,10 +188,30 @@ pub static DEV: Lazy> = Lazy::new(|| { (Hardfork::Shanghai, ForkCondition::Timestamp(0)), ]), deposit_contract: None, // TODO: do we even have? + ..Default::default() } .into() }); +/// BaseFeeParams contains the config parameters that control block base fee computation +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] +pub struct BaseFeeParams { + /// The base_fee_max_change_denominator from EIP-1559 + pub max_change_denominator: u64, + /// The elasticity multiplier from EIP-1559 + pub elasticity_multiplier: u64, +} + +impl BaseFeeParams { + /// Get the base fee parameters for ethereum mainnet + pub const fn ethereum() -> BaseFeeParams { + BaseFeeParams { + max_change_denominator: EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + } + } +} + /// An Ethereum chain specification. /// /// A chain specification describes: @@ -224,6 +250,24 @@ pub struct ChainSpec { /// The deposit contract deployed for PoS. #[serde(skip, default)] pub deposit_contract: Option, + + /// The parameters that configure how a block's base fee is computed + pub base_fee_params: BaseFeeParams, +} + +impl Default for ChainSpec { + fn default() -> ChainSpec { + ChainSpec { + chain: Default::default(), + genesis_hash: Default::default(), + genesis: Default::default(), + paris_block_and_final_difficulty: Default::default(), + fork_timestamps: Default::default(), + hardforks: Default::default(), + deposit_contract: Default::default(), + base_fee_params: BaseFeeParams::ethereum(), + } + } } impl ChainSpec { @@ -457,6 +501,7 @@ impl From for ChainSpec { hardforks, paris_block_and_final_difficulty: None, deposit_contract: None, + ..Default::default() } } } @@ -680,6 +725,7 @@ impl ChainSpecBuilder { hardforks: self.hardforks, paris_block_and_final_difficulty: None, deposit_contract: None, + ..Default::default() } } } diff --git a/crates/primitives/src/constants/mod.rs b/crates/primitives/src/constants/mod.rs index 96c55cbbe11b..f3f09c4f3107 100644 --- a/crates/primitives/src/constants/mod.rs +++ b/crates/primitives/src/constants/mod.rs @@ -37,11 +37,15 @@ pub const BEACON_NONCE: u64 = 0u64; /// See . pub const ETHEREUM_BLOCK_GAS_LIMIT: u64 = 30_000_000; -/// The minimal value the basefee can decrease to. +/// The minimum tx fee below which the txpool will reject the transaction. /// -/// The `BASE_FEE_MAX_CHANGE_DENOMINATOR` is `8`, or 12.5%. -/// Once the base fee has dropped to `7` WEI it cannot decrease further because 12.5% of 7 is less -/// than 1. +/// Configured to `7` WEI which is the lowest possible value of base fee under mainnet EIP-1559 +/// parameters. `BASE_FEE_MAX_CHANGE_DENOMINATOR` +/// is `8`, or 12.5%. Once the base fee has dropped to `7` WEI it cannot decrease further because +/// 12.5% of 7 is less than 1. +/// +/// Note that min base fee under different 1559 parameterizations may differ, but there's no +/// signifant harm in leaving this setting as is. pub const MIN_PROTOCOL_BASE_FEE: u64 = 7; /// Same as [MIN_PROTOCOL_BASE_FEE] but as a U256. @@ -51,10 +55,10 @@ pub const MIN_PROTOCOL_BASE_FEE_U256: U256 = U256::from_limbs([7u64, 0, 0, 0]); pub const EIP1559_INITIAL_BASE_FEE: u64 = 1_000_000_000; /// Base fee max change denominator as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) -pub const EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8; +pub const EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8; /// Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) -pub const EIP1559_ELASTICITY_MULTIPLIER: u64 = 2; +pub const EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u64 = 2; /// Multiplier for converting gwei to wei. pub const GWEI_TO_WEI: u64 = 1_000_000_000; diff --git a/crates/primitives/src/hardfork.rs b/crates/primitives/src/hardfork.rs index f82310d68de9..c30d6a865e6a 100644 --- a/crates/primitives/src/hardfork.rs +++ b/crates/primitives/src/hardfork.rs @@ -162,9 +162,9 @@ mod tests { genesis: Genesis::default(), genesis_hash: None, hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]), - fork_timestamps: Default::default(), paris_block_and_final_difficulty: None, deposit_contract: None, + ..Default::default() }; assert_eq!(Hardfork::Frontier.fork_id(&spec), None); @@ -177,9 +177,9 @@ mod tests { genesis: Genesis::default(), genesis_hash: None, hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]), - fork_timestamps: Default::default(), paris_block_and_final_difficulty: None, deposit_contract: None, + ..Default::default() }; assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None); diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs index e39c6a8287ad..8aeab18b84f8 100644 --- a/crates/primitives/src/header.rs +++ b/crates/primitives/src/header.rs @@ -3,7 +3,8 @@ use crate::{ blobfee::calculate_excess_blob_gas, keccak256, proofs::{EMPTY_LIST_HASH, EMPTY_ROOT}, - BlockBodyRoots, BlockHash, BlockNumHash, BlockNumber, Bloom, Bytes, H160, H256, H64, U256, + BaseFeeParams, BlockBodyRoots, BlockHash, BlockNumHash, BlockNumber, Bloom, Bytes, H160, H256, + H64, U256, }; use bytes::{Buf, BufMut, BytesMut}; @@ -176,8 +177,13 @@ impl Header { /// Calculate base fee for next block according to the EIP-1559 spec. /// /// Returns a `None` if no base fee is set, no EIP-1559 support - pub fn next_block_base_fee(&self) -> Option { - Some(calculate_next_block_base_fee(self.gas_used, self.gas_limit, self.base_fee_per_gas?)) + pub fn next_block_base_fee(&self, base_fee_params: BaseFeeParams) -> Option { + Some(calculate_next_block_base_fee( + self.gas_used, + self.gas_limit, + self.base_fee_per_gas?, + base_fee_params, + )) } /// Calculate excess blob gas for the next block according to the EIP-4844 spec. diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 249073804f1f..82c0929e150b 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -60,8 +60,8 @@ pub use block::{ }; pub use bloom::Bloom; pub use chain::{ - AllGenesisFormats, Chain, ChainInfo, ChainSpec, ChainSpecBuilder, DisplayHardforks, - ForkCondition, ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA, + AllGenesisFormats, BaseFeeParams, Chain, ChainInfo, ChainSpec, ChainSpecBuilder, + DisplayHardforks, ForkCondition, ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA, }; pub use compression::*; pub use constants::{ diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index f30b29ee35a2..d0450ab4b42f 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -12,7 +12,8 @@ use jsonrpsee::{ }; use reth_network_api::{NetworkInfo, Peers}; use reth_provider::{ - BlockReaderIdExt, EvmEnvProvider, HeaderProvider, ReceiptProviderIdExt, StateProviderFactory, + BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, HeaderProvider, ReceiptProviderIdExt, + StateProviderFactory, }; use reth_rpc::{ eth::{cache::EthStateCache, gas_oracle::GasPriceOracle}, @@ -40,10 +41,11 @@ pub async fn launch( ) -> Result where Provider: BlockReaderIdExt - + ReceiptProviderIdExt + + ChainSpecProvider + + EvmEnvProvider + HeaderProvider + + ReceiptProviderIdExt + StateProviderFactory - + EvmEnvProvider + Clone + Unpin + 'static, @@ -86,9 +88,10 @@ pub async fn launch_with_eth_api( ) -> Result where Provider: BlockReaderIdExt + + ChainSpecProvider + + EvmEnvProvider + HeaderProvider + StateProviderFactory - + EvmEnvProvider + Clone + Unpin + 'static, diff --git a/crates/rpc/rpc/src/eth/api/block.rs b/crates/rpc/rpc/src/eth/api/block.rs index 1cb547e31535..ab297add7114 100644 --- a/crates/rpc/rpc/src/eth/api/block.rs +++ b/crates/rpc/rpc/src/eth/api/block.rs @@ -9,13 +9,14 @@ use crate::{ }; use reth_network_api::NetworkInfo; use reth_primitives::{BlockId, BlockNumberOrTag, TransactionMeta}; -use reth_provider::{BlockReaderIdExt, EvmEnvProvider, StateProviderFactory}; +use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; use reth_rpc_types::{Block, Index, RichBlock, TransactionReceipt}; use reth_transaction_pool::TransactionPool; impl EthApi where - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Pool: TransactionPool + Clone + 'static, Network: NetworkInfo + Send + Sync + 'static, { diff --git a/crates/rpc/rpc/src/eth/api/call.rs b/crates/rpc/rpc/src/eth/api/call.rs index d7c0a065325c..e47555429ca8 100644 --- a/crates/rpc/rpc/src/eth/api/call.rs +++ b/crates/rpc/rpc/src/eth/api/call.rs @@ -14,7 +14,9 @@ use crate::{ use ethers_core::utils::get_contract_address; use reth_network_api::NetworkInfo; use reth_primitives::{AccessList, BlockId, BlockNumberOrTag, Bytes, U256}; -use reth_provider::{BlockReaderIdExt, EvmEnvProvider, StateProvider, StateProviderFactory}; +use reth_provider::{ + BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProvider, StateProviderFactory, +}; use reth_revm::{ access_list::AccessListInspector, database::{State, SubState}, @@ -38,7 +40,8 @@ const MIN_CREATE_GAS: u64 = 53_000u64; impl EthApi where Pool: TransactionPool + Clone + 'static, - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + Send + Sync + 'static, { /// Estimate gas needed for execution of the `request` at the [BlockId]. diff --git a/crates/rpc/rpc/src/eth/api/fees.rs b/crates/rpc/rpc/src/eth/api/fees.rs index 49b0291a1195..5d8cbc4d1ff8 100644 --- a/crates/rpc/rpc/src/eth/api/fees.rs +++ b/crates/rpc/rpc/src/eth/api/fees.rs @@ -8,7 +8,7 @@ use reth_network_api::NetworkInfo; use reth_primitives::{ basefee::calculate_next_block_base_fee, BlockNumberOrTag, SealedHeader, U256, }; -use reth_provider::{BlockReaderIdExt, EvmEnvProvider, StateProviderFactory}; +use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; use reth_rpc_types::{FeeHistory, TxGasAndReward}; use reth_transaction_pool::TransactionPool; use tracing::debug; @@ -16,7 +16,8 @@ use tracing::debug; impl EthApi where Pool: TransactionPool + Clone + 'static, - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + Send + Sync + 'static, { /// Returns a suggestion for a gas price for legacy transactions. @@ -115,10 +116,12 @@ where // // The unwrap is safe since we checked earlier that we got at least 1 header. let last_header = headers.last().unwrap(); + let chain_spec = self.provider().chain_spec(); base_fee_per_gas.push(U256::from(calculate_next_block_base_fee( last_header.gas_used, last_header.gas_limit, last_header.base_fee_per_gas.unwrap_or_default(), + chain_spec.base_fee_params, ))); Ok(FeeHistory { diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index 20ecf114e2a9..d4f30a5ad665 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -16,7 +16,9 @@ use reth_network_api::NetworkInfo; use reth_primitives::{ Address, BlockId, BlockNumberOrTag, ChainInfo, SealedBlock, H256, U256, U64, }; -use reth_provider::{BlockReaderIdExt, EvmEnvProvider, StateProviderBox, StateProviderFactory}; +use reth_provider::{ + BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory, +}; use reth_rpc_types::{SyncInfo, SyncStatus}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; use reth_transaction_pool::TransactionPool; @@ -79,7 +81,7 @@ pub struct EthApi { impl EthApi where - Provider: BlockReaderIdExt, + Provider: BlockReaderIdExt + ChainSpecProvider, { /// Creates a new, shareable instance using the default tokio task spawner. pub fn new( @@ -194,7 +196,8 @@ where impl EthApi where - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, { /// Returns the state at the given [BlockId] enum. pub fn state_at_block_id(&self, at: BlockId) -> EthResult> { @@ -228,7 +231,8 @@ where impl EthApi where - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Pool: TransactionPool + Clone + 'static, Network: NetworkInfo + Send + Sync + 'static, { @@ -249,7 +253,8 @@ where // assumed child block is in the next slot latest.timestamp += 12; // base fee of the child block - latest.base_fee_per_gas = latest.next_block_base_fee(); + let chain_spec = self.provider().chain_spec(); + latest.base_fee_per_gas = latest.next_block_base_fee(chain_spec.base_fee_params); PendingBlockEnvOrigin::DerivedFromLatest(latest) }; @@ -327,7 +332,8 @@ impl Clone for EthApi { impl EthApiSpec for EthApi where Pool: TransactionPool + Clone + 'static, - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + 'static, { /// Returns the current ethereum protocol version. diff --git a/crates/rpc/rpc/src/eth/api/server.rs b/crates/rpc/rpc/src/eth/api/server.rs index 32c985cf9831..1df566086d71 100644 --- a/crates/rpc/rpc/src/eth/api/server.rs +++ b/crates/rpc/rpc/src/eth/api/server.rs @@ -16,8 +16,8 @@ use reth_primitives::{ AccessListWithGasUsed, Address, BlockId, BlockNumberOrTag, Bytes, H256, H64, U256, U64, }; use reth_provider::{ - BlockIdReader, BlockReader, BlockReaderIdExt, EvmEnvProvider, HeaderProvider, - StateProviderFactory, + BlockIdReader, BlockReader, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, + HeaderProvider, StateProviderFactory, }; use reth_rpc_api::EthApiServer; use reth_rpc_types::{ @@ -37,6 +37,7 @@ where Provider: BlockReader + BlockIdReader + BlockReaderIdExt + + ChainSpecProvider + HeaderProvider + StateProviderFactory + EvmEnvProvider @@ -410,12 +411,13 @@ mod tests { use reth_interfaces::test_utils::{generators, generators::Rng}; use reth_network_api::noop::NoopNetwork; use reth_primitives::{ - basefee::calculate_next_block_base_fee, constants::ETHEREUM_BLOCK_GAS_LIMIT, Block, - BlockNumberOrTag, Header, TransactionSigned, H256, U256, + basefee::calculate_next_block_base_fee, + constants::{self, ETHEREUM_BLOCK_GAS_LIMIT}, + BaseFeeParams, Block, BlockNumberOrTag, Header, TransactionSigned, H256, U256, }; use reth_provider::{ test_utils::{MockEthProvider, NoopProvider}, - BlockReader, BlockReaderIdExt, EvmEnvProvider, StateProviderFactory, + BlockReader, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory, }; use reth_rpc_api::EthApiServer; use reth_rpc_types::FeeHistory; @@ -424,6 +426,7 @@ mod tests { fn build_test_eth_api< P: BlockReaderIdExt + BlockReader + + ChainSpecProvider + EvmEnvProvider + StateProviderFactory + Unpin @@ -538,6 +541,7 @@ mod tests { last_header.gas_used, last_header.gas_limit, last_header.base_fee_per_gas.unwrap_or_default(), + BaseFeeParams::ethereum(), ))); let eth_api = build_test_eth_api(mock_provider); diff --git a/crates/rpc/rpc/src/eth/api/state.rs b/crates/rpc/rpc/src/eth/api/state.rs index 2887ac58fb8f..4d4b29060e2a 100644 --- a/crates/rpc/rpc/src/eth/api/state.rs +++ b/crates/rpc/rpc/src/eth/api/state.rs @@ -9,14 +9,16 @@ use reth_primitives::{ U256, }; use reth_provider::{ - AccountReader, BlockReaderIdExt, EvmEnvProvider, StateProvider, StateProviderFactory, + AccountReader, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProvider, + StateProviderFactory, }; use reth_rpc_types::{EIP1186AccountProofResponse, StorageProof}; use reth_transaction_pool::{PoolTransaction, TransactionPool}; impl EthApi where - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Pool: TransactionPool + Clone + 'static, Network: Send + Sync + 'static, { diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 6d869daa6048..6784b62ec0c8 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -19,7 +19,9 @@ use reth_primitives::{ TransactionKind::{Call, Create}, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, H256, U128, U256, U64, }; -use reth_provider::{BlockReaderIdExt, EvmEnvProvider, StateProviderBox, StateProviderFactory}; +use reth_provider::{ + BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory, +}; use reth_revm::{ database::{State, SubState}, env::{fill_block_env_with_coinbase, tx_env_with_recovered}, @@ -236,7 +238,8 @@ pub trait EthTransactions: Send + Sync { impl EthTransactions for EthApi where Pool: TransactionPool + Clone + 'static, - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + Send + Sync + 'static, { fn call_gas_limit(&self) -> u64 { @@ -668,7 +671,8 @@ where impl EthApi where - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: 'static, { /// Helper function for `eth_getTransactionReceipt` @@ -692,7 +696,8 @@ where impl EthApi where Pool: TransactionPool + 'static, - Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static, + Provider: + BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + Send + Sync + 'static, { pub(crate) fn sign_request( diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index d679a7ed5446..ccb39f6c97b9 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -1,18 +1,18 @@ use crate::{ traits::{BlockSource, ReceiptProvider}, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - EvmEnvProvider, HeaderProvider, PostState, PostStateDataProvider, ReceiptProviderIdExt, - StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider, - WithdrawalsProvider, + ChainSpecProvider, EvmEnvProvider, HeaderProvider, PostState, PostStateDataProvider, + ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, + TransactionsProvider, WithdrawalsProvider, }; use parking_lot::Mutex; use reth_db::models::StoredBlockBodyIndices; use reth_interfaces::{provider::ProviderError, Result}; use reth_primitives::{ keccak256, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, - BlockWithSenders, Bytecode, Bytes, ChainInfo, Header, Receipt, SealedBlock, SealedHeader, - StorageKey, StorageValue, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, - TxNumber, H256, U256, + BlockWithSenders, Bytecode, Bytes, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, + SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned, + TransactionSignedNoHash, TxHash, TxNumber, H256, U256, }; use reth_revm_primitives::primitives::{BlockEnv, CfgEnv}; use std::{ @@ -22,7 +22,7 @@ use std::{ }; /// A mock implementation for Provider interfaces. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub struct MockEthProvider { /// Local block store pub blocks: Arc>>, @@ -30,6 +30,19 @@ pub struct MockEthProvider { pub headers: Arc>>, /// Local account store pub accounts: Arc>>, + /// Local chain spec + pub chain_spec: Arc, +} + +impl Default for MockEthProvider { + fn default() -> MockEthProvider { + MockEthProvider { + blocks: Default::default(), + headers: Default::default(), + accounts: Default::default(), + chain_spec: Arc::new(reth_primitives::ChainSpecBuilder::mainnet().build()), + } + } } /// An extended account for local store @@ -160,6 +173,12 @@ impl HeaderProvider for MockEthProvider { } } +impl ChainSpecProvider for MockEthProvider { + fn chain_spec(&self) -> Arc { + self.chain_spec.clone() + } +} + impl TransactionsProvider for MockEthProvider { fn transaction_id(&self, _tx_hash: TxHash) -> Result> { todo!() diff --git a/crates/transaction-pool/src/lib.rs b/crates/transaction-pool/src/lib.rs index 63e1936a76f7..ccdf752e0dc9 100644 --- a/crates/transaction-pool/src/lib.rs +++ b/crates/transaction-pool/src/lib.rs @@ -92,10 +92,10 @@ //! //! ``` //! use reth_primitives::MAINNET; -//! use reth_provider::StateProviderFactory; +//! use reth_provider::{ChainSpecProvider, StateProviderFactory}; //! use reth_tasks::TokioTaskExecutor; //! use reth_transaction_pool::{EthTransactionValidator, Pool, TransactionPool}; -//! async fn t(client: C) where C: StateProviderFactory + Clone + 'static{ +//! async fn t(client: C) where C: StateProviderFactory + ChainSpecProvider + Clone + 'static{ //! let pool = Pool::eth_pool( //! EthTransactionValidator::new(client, MAINNET.clone(), TokioTaskExecutor::default()), //! Default::default(), @@ -117,12 +117,12 @@ //! ``` //! use futures_util::Stream; //! use reth_primitives::MAINNET; -//! use reth_provider::{BlockReaderIdExt, CanonStateNotification, StateProviderFactory}; +//! use reth_provider::{BlockReaderIdExt, CanonStateNotification, ChainSpecProvider, StateProviderFactory}; //! use reth_tasks::TokioTaskExecutor; //! use reth_transaction_pool::{EthTransactionValidator, Pool}; //! use reth_transaction_pool::maintain::maintain_transaction_pool_future; //! async fn t(client: C, stream: St) -//! where C: StateProviderFactory + BlockReaderIdExt + Clone + 'static, +//! where C: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + 'static, //! St: Stream + Send + Unpin + 'static, //! { //! let pool = Pool::eth_pool( diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 22cc62ddaab3..1aa446345efd 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -10,7 +10,9 @@ use futures_util::{ FutureExt, Stream, StreamExt, }; use reth_primitives::{Address, BlockHash, BlockNumberOrTag, FromRecoveredTransaction}; -use reth_provider::{BlockReaderIdExt, CanonStateNotification, PostState, StateProviderFactory}; +use reth_provider::{ + BlockReaderIdExt, CanonStateNotification, ChainSpecProvider, PostState, StateProviderFactory, +}; use reth_tasks::TaskSpawner; use std::{ borrow::Borrow, @@ -49,7 +51,7 @@ pub fn maintain_transaction_pool_future( config: MaintainPoolConfig, ) -> BoxFuture<'static, ()> where - Client: StateProviderFactory + BlockReaderIdExt + Clone + Send + 'static, + Client: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + Send + 'static, P: TransactionPoolExt + 'static, St: Stream + Send + Unpin + 'static, Tasks: TaskSpawner + 'static, @@ -70,7 +72,7 @@ pub async fn maintain_transaction_pool( task_spawner: Tasks, config: MaintainPoolConfig, ) where - Client: StateProviderFactory + BlockReaderIdExt + Clone + Send + 'static, + Client: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + Send + 'static, P: TransactionPoolExt + 'static, St: Stream + Send + Unpin + 'static, Tasks: TaskSpawner + 'static, @@ -80,10 +82,13 @@ pub async fn maintain_transaction_pool( // ensure the pool points to latest state if let Ok(Some(latest)) = client.block_by_number_or_tag(BlockNumberOrTag::Latest) { let latest = latest.seal_slow(); + let chain_spec = client.chain_spec(); let info = BlockInfo { last_seen_block_hash: latest.hash, last_seen_block_number: latest.number, - pending_basefee: latest.next_block_base_fee().unwrap_or_default(), + pending_basefee: latest + .next_block_base_fee(chain_spec.base_fee_params) + .unwrap_or_default(), }; pool.set_block_info(info); } @@ -204,8 +209,11 @@ pub async fn maintain_transaction_pool( maintained_state = MaintainedPoolState::Drifted; } + let chain_spec = client.chain_spec(); + // base fee for the next block: `new_tip+1` - let pending_block_base_fee = new_tip.next_block_base_fee().unwrap_or_default(); + let pending_block_base_fee = + new_tip.next_block_base_fee(chain_spec.base_fee_params).unwrap_or_default(); // we know all changed account in the new chain let new_changed_accounts: HashSet<_> = @@ -279,9 +287,11 @@ pub async fn maintain_transaction_pool( CanonStateNotification::Commit { new } => { let (blocks, state) = new.inner(); let tip = blocks.tip(); + let chain_spec = client.chain_spec(); // base fee for the next block: `tip+1` - let pending_block_base_fee = tip.next_block_base_fee().unwrap_or_default(); + let pending_block_base_fee = + tip.next_block_base_fee(chain_spec.base_fee_params).unwrap_or_default(); let first_block = blocks.first(); trace!(