Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bin/reth/src/args/rpc_server_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,10 @@ impl RpcServerArgs {
) -> Result<AuthServerHandle, RpcError>
where
Provider: BlockReaderIdExt
+ ChainSpecProvider
+ EvmEnvProvider
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ Clone
+ Unpin
+ 'static,
Expand Down
1 change: 1 addition & 0 deletions bin/reth/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
15 changes: 11 additions & 4 deletions crates/consensus/auto-seal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 };

Expand Down
5 changes: 3 additions & 2 deletions crates/consensus/auto-seal/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
6 changes: 4 additions & 2 deletions crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 })
Expand Down
4 changes: 3 additions & 1 deletion crates/payload/builder/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
23 changes: 15 additions & 8 deletions crates/primitives/src/basefee.rs
Original file line number Diff line number Diff line change
@@ -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
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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(),
)
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down
48 changes: 47 additions & 1 deletion crates/primitives/src/chain/spec.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -60,6 +63,7 @@ pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
11052984,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
Expand Down Expand Up @@ -100,6 +104,7 @@ pub static GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
4367322,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
Expand Down Expand Up @@ -144,6 +149,7 @@ pub static SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
1273020,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -457,6 +501,7 @@ impl From<Genesis> for ChainSpec {
hardforks,
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
}
}
}
Expand Down Expand Up @@ -680,6 +725,7 @@ impl ChainSpecBuilder {
hardforks: self.hardforks,
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
}
}
}
Expand Down
16 changes: 10 additions & 6 deletions crates/primitives/src/constants/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions crates/primitives/src/hardfork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
12 changes: 9 additions & 3 deletions crates/primitives/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down
11 changes: 7 additions & 4 deletions crates/rpc/rpc-builder/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -40,10 +41,11 @@ pub async fn launch<Provider, Pool, Network, Tasks, EngineApi>(
) -> Result<AuthServerHandle, RpcError>
where
Provider: BlockReaderIdExt
+ ReceiptProviderIdExt
+ ChainSpecProvider
+ EvmEnvProvider
+ HeaderProvider
+ ReceiptProviderIdExt
+ StateProviderFactory
+ EvmEnvProvider
+ Clone
+ Unpin
+ 'static,
Expand Down Expand Up @@ -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,
Expand Down
Loading
Loading