feat: make base fee computation parameters configurable via chain spec (#3992)

This commit is contained in:
Roberto Bayardo
2023-08-07 08:52:27 -07:00
committed by GitHub
parent aaf2d2cf19
commit 9569debbb5
24 changed files with 211 additions and 78 deletions

View File

@ -339,9 +339,10 @@ impl RpcServerArgs {
) -> Result<AuthServerHandle, RpcError>
where
Provider: BlockReaderIdExt
+ ChainSpecProvider
+ EvmEnvProvider
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ Clone
+ Unpin
+ 'static,

View File

@ -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();

View File

@ -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<TransactionSigned>) -> Header {
pub(crate) fn build_header_template(
&self,
transactions: &Vec<TransactionSigned>,
chain_spec: Arc<ChainSpec>,
) -> 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<TransactionSigned>,
executor: &mut Executor<DB>,
chain_spec: Arc<ChainSpec>,
) -> 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 };

View File

@ -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()));

View File

@ -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 })

View File

@ -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)

View File

@ -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(),
)
);
}
}

View File

@ -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,
};

View File

@ -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<Arc<ChainSpec>> = Lazy::new(|| {
11052984,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@ -100,6 +104,7 @@ pub static GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
4367322,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@ -144,6 +149,7 @@ pub static SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
1273020,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@ -182,10 +188,30 @@ pub static DEV: Lazy<Arc<ChainSpec>> = 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<DepositContract>,
/// 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<Genesis> 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()
}
}
}

View File

@ -37,11 +37,15 @@ pub const BEACON_NONCE: u64 = 0u64;
/// See <https://github.com/paradigmxyz/reth/issues/3233>.
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` <https://eips.ethereum.org/EIPS/eip-1559> 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` <https://eips.ethereum.org/EIPS/eip-1559>
/// 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;

View File

@ -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);

View File

@ -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<u64> {
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<u64> {
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.

View File

@ -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::{

View File

@ -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<Provider, Pool, Network, Tasks, EngineApi>(
) -> Result<AuthServerHandle, RpcError>
where
Provider: BlockReaderIdExt
+ ReceiptProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ ChainSpecProvider
+ EvmEnvProvider
+ HeaderProvider
+ ReceiptProviderIdExt
+ StateProviderFactory
+ Clone
+ Unpin
+ 'static,
@ -86,9 +88,10 @@ pub async fn launch_with_eth_api<Provider, Pool, Network, EngineApi>(
) -> Result<AuthServerHandle, RpcError>
where
Provider: BlockReaderIdExt
+ ChainSpecProvider
+ EvmEnvProvider
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ Clone
+ Unpin
+ 'static,

View File

@ -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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
where
Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Provider:
BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Send + Sync + 'static,
{

View File

@ -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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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].

View File

@ -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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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 {

View File

@ -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<Provider, Pool, Network> {
impl<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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<StateProviderBox<'_>> {
@ -228,7 +231,8 @@ where
impl<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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<Provider, Pool, Events> Clone for EthApi<Provider, Pool, Events> {
impl<Provider, Pool, Network> EthApiSpec for EthApi<Provider, Pool, Network>
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.

View File

@ -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);

View File

@ -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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
where
Provider: BlockReaderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Provider:
BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static,
Pool: TransactionPool + Clone + 'static,
Network: Send + Sync + 'static,
{

View File

@ -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<Provider, Pool, Network> EthTransactions for EthApi<Provider, Pool, Network>
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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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<Provider, Pool, Network> EthApi<Provider, Pool, Network>
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(

View File

@ -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<Mutex<HashMap<H256, Block>>>,
@ -30,6 +30,19 @@ pub struct MockEthProvider {
pub headers: Arc<Mutex<HashMap<H256, Header>>>,
/// Local account store
pub accounts: Arc<Mutex<HashMap<Address, ExtendedAccount>>>,
/// Local chain spec
pub chain_spec: Arc<ChainSpec>,
}
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<ChainSpec> {
self.chain_spec.clone()
}
}
impl TransactionsProvider for MockEthProvider {
fn transaction_id(&self, _tx_hash: TxHash) -> Result<Option<TxNumber>> {
todo!()

View File

@ -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<C>(client: C) where C: StateProviderFactory + Clone + 'static{
//! async fn t<C>(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<C, St>(client: C, stream: St)
//! where C: StateProviderFactory + BlockReaderIdExt + Clone + 'static,
//! where C: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + 'static,
//! St: Stream<Item = CanonStateNotification> + Send + Unpin + 'static,
//! {
//! let pool = Pool::eth_pool(

View File

@ -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<Client, P, St, Tasks>(
config: MaintainPoolConfig,
) -> BoxFuture<'static, ()>
where
Client: StateProviderFactory + BlockReaderIdExt + Clone + Send + 'static,
Client: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + Send + 'static,
P: TransactionPoolExt + 'static,
St: Stream<Item = CanonStateNotification> + Send + Unpin + 'static,
Tasks: TaskSpawner + 'static,
@ -70,7 +72,7 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
task_spawner: Tasks,
config: MaintainPoolConfig,
) where
Client: StateProviderFactory + BlockReaderIdExt + Clone + Send + 'static,
Client: StateProviderFactory + BlockReaderIdExt + ChainSpecProvider + Clone + Send + 'static,
P: TransactionPoolExt + 'static,
St: Stream<Item = CanonStateNotification> + Send + Unpin + 'static,
Tasks: TaskSpawner + 'static,
@ -80,10 +82,13 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
// 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<Client, P, St, Tasks>(
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<Client, P, St, Tasks>(
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!(