mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(op-reth): Canyon - Dynamic eip1559 params (#5542)
This commit is contained in:
@ -254,11 +254,13 @@ impl StorageInner {
|
||||
transactions: &Vec<TransactionSigned>,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
) -> Header {
|
||||
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
|
||||
|
||||
// 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(chain_spec.base_fee_params));
|
||||
.and_then(|parent| parent.next_block_base_fee(chain_spec.base_fee_params(timestamp)));
|
||||
|
||||
let mut header = Header {
|
||||
parent_hash: self.best_hash,
|
||||
@ -273,7 +275,7 @@ impl StorageInner {
|
||||
number: self.best_block + 1,
|
||||
gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
|
||||
gas_used: 0,
|
||||
timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs(),
|
||||
timestamp,
|
||||
mix_hash: Default::default(),
|
||||
nonce: 0,
|
||||
base_fee_per_gas,
|
||||
|
||||
@ -263,7 +263,8 @@ fn check_gas_limit(
|
||||
// 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 * chain_spec.base_fee_params.elasticity_multiplier;
|
||||
parent_gas_limit =
|
||||
parent.gas_limit * chain_spec.base_fee_params(child.timestamp).elasticity_multiplier;
|
||||
}
|
||||
|
||||
if child.gas_limit > parent_gas_limit {
|
||||
@ -336,7 +337,7 @@ pub fn validate_header_regarding_parent(
|
||||
} else {
|
||||
// This BaseFeeMissing will not happen as previous blocks are checked to have them.
|
||||
parent
|
||||
.next_block_base_fee(chain_spec.base_fee_params)
|
||||
.next_block_base_fee(chain_spec.base_fee_params(child.timestamp))
|
||||
.ok_or(ConsensusError::BaseFeeMissing)?
|
||||
};
|
||||
if expected_base_fee != base_fee {
|
||||
|
||||
@ -251,7 +251,9 @@ impl PayloadBuilderAttributes {
|
||||
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).unwrap_or_default(),
|
||||
parent
|
||||
.next_block_base_fee(chain_spec.base_fee_params(self.timestamp))
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
// calculate excess gas based on parent block's blob gas usage
|
||||
blob_excess_gas_and_price,
|
||||
|
||||
@ -13,8 +13,9 @@ use strum::{AsRefStr, EnumCount, EnumIter, EnumString, EnumVariantNames};
|
||||
// The chain spec module.
|
||||
mod spec;
|
||||
pub use spec::{
|
||||
AllGenesisFormats, BaseFeeParams, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition,
|
||||
ForkTimestamps, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA,
|
||||
AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder,
|
||||
DisplayHardforks, ForkBaseFeeParams, ForkCondition, ForkTimestamps, DEV, GOERLI, HOLESKY,
|
||||
MAINNET, SEPOLIA,
|
||||
};
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
|
||||
@ -63,7 +63,7 @@ pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
11052984,
|
||||
b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"),
|
||||
)),
|
||||
base_fee_params: BaseFeeParams::ethereum(),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: 3500,
|
||||
snapshot_block_interval: 500_000,
|
||||
}
|
||||
@ -106,7 +106,7 @@ pub static GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
4367322,
|
||||
b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"),
|
||||
)),
|
||||
base_fee_params: BaseFeeParams::ethereum(),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
}
|
||||
@ -153,8 +153,7 @@ pub static SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
1273020,
|
||||
b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"),
|
||||
)),
|
||||
|
||||
base_fee_params: BaseFeeParams::ethereum(),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
}
|
||||
@ -196,7 +195,7 @@ pub static HOLESKY: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
0,
|
||||
b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"),
|
||||
)),
|
||||
base_fee_params: BaseFeeParams::ethereum(),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
}
|
||||
@ -236,6 +235,7 @@ pub static DEV: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(0)),
|
||||
]),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
deposit_contract: None, // TODO: do we even have?
|
||||
..Default::default()
|
||||
}
|
||||
@ -277,7 +277,13 @@ pub static OP_GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1699981200)),
|
||||
]),
|
||||
base_fee_params: BaseFeeParams::optimism(),
|
||||
base_fee_params: BaseFeeParamsKind::Variable(
|
||||
vec![
|
||||
(Hardfork::London, BaseFeeParams::optimism_goerli()),
|
||||
(Hardfork::Canyon, BaseFeeParams::optimism_goerli_canyon()),
|
||||
]
|
||||
.into(),
|
||||
),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
..Default::default()
|
||||
@ -320,7 +326,13 @@ pub static BASE_GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1699981200)),
|
||||
]),
|
||||
base_fee_params: BaseFeeParams::optimism_goerli(),
|
||||
base_fee_params: BaseFeeParamsKind::Variable(
|
||||
vec![
|
||||
(Hardfork::London, BaseFeeParams::optimism_goerli()),
|
||||
(Hardfork::Canyon, BaseFeeParams::optimism_goerli_canyon()),
|
||||
]
|
||||
.into(),
|
||||
),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
..Default::default()
|
||||
@ -361,7 +373,13 @@ pub static BASE_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
(Hardfork::Bedrock, ForkCondition::Block(0)),
|
||||
(Hardfork::Regolith, ForkCondition::Timestamp(0)),
|
||||
]),
|
||||
base_fee_params: BaseFeeParams::optimism(),
|
||||
base_fee_params: BaseFeeParamsKind::Variable(
|
||||
vec![
|
||||
(Hardfork::London, BaseFeeParams::optimism()),
|
||||
(Hardfork::Canyon, BaseFeeParams::optimism_canyon()),
|
||||
]
|
||||
.into(),
|
||||
),
|
||||
prune_delete_limit: 1700,
|
||||
snapshot_block_interval: 1_000_000,
|
||||
..Default::default()
|
||||
@ -369,6 +387,41 @@ pub static BASE_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
||||
.into()
|
||||
});
|
||||
|
||||
/// A wrapper around [BaseFeeParams] that allows for specifying constant or dynamic EIP-1559
|
||||
/// parameters based on the active [Hardfork].
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BaseFeeParamsKind {
|
||||
/// Constant [BaseFeeParams]; used for chains that don't have dynamic EIP-1559 parameters
|
||||
Constant(BaseFeeParams),
|
||||
/// Variable [BaseFeeParams]; used for chains that have dynamic EIP-1559 parameters like
|
||||
/// Optimism
|
||||
Variable(ForkBaseFeeParams),
|
||||
}
|
||||
|
||||
impl From<BaseFeeParams> for BaseFeeParamsKind {
|
||||
fn from(params: BaseFeeParams) -> Self {
|
||||
BaseFeeParamsKind::Constant(params)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ForkBaseFeeParams> for BaseFeeParamsKind {
|
||||
fn from(params: ForkBaseFeeParams) -> Self {
|
||||
BaseFeeParamsKind::Variable(params)
|
||||
}
|
||||
}
|
||||
|
||||
/// A type alias to a vector of tuples of [Hardfork] and [BaseFeeParams], sorted by [Hardfork]
|
||||
/// activation order. This is used to specify dynamic EIP-1559 parameters for chains like Optimism.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ForkBaseFeeParams(Vec<(Hardfork, BaseFeeParams)>);
|
||||
|
||||
impl From<Vec<(Hardfork, BaseFeeParams)>> for ForkBaseFeeParams {
|
||||
fn from(params: Vec<(Hardfork, BaseFeeParams)>) -> Self {
|
||||
ForkBaseFeeParams(params)
|
||||
}
|
||||
}
|
||||
|
||||
/// BaseFeeParams contains the config parameters that control block base fee computation
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct BaseFeeParams {
|
||||
@ -398,6 +451,17 @@ impl BaseFeeParams {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the base fee parameters for optimism goerli (post Canyon)
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn optimism_goerli_canyon() -> BaseFeeParams {
|
||||
BaseFeeParams {
|
||||
max_change_denominator:
|
||||
crate::constants::OP_GOERLI_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON,
|
||||
elasticity_multiplier:
|
||||
crate::constants::OP_GOERLI_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the base fee parameters for optimism mainnet
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn optimism() -> BaseFeeParams {
|
||||
@ -408,6 +472,17 @@ impl BaseFeeParams {
|
||||
crate::constants::OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the base fee parameters for optimism mainnet (post Canyon)
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn optimism_canyon() -> BaseFeeParams {
|
||||
BaseFeeParams {
|
||||
max_change_denominator:
|
||||
crate::constants::OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON,
|
||||
elasticity_multiplier:
|
||||
crate::constants::OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An Ethereum chain specification.
|
||||
@ -450,7 +525,7 @@ pub struct ChainSpec {
|
||||
pub deposit_contract: Option<DepositContract>,
|
||||
|
||||
/// The parameters that configure how a block's base fee is computed
|
||||
pub base_fee_params: BaseFeeParams,
|
||||
pub base_fee_params: BaseFeeParamsKind,
|
||||
|
||||
/// The delete limit for pruner, per block. In the actual pruner run it will be multiplied by
|
||||
/// the amount of blocks between pruner runs to account for the difference in amount of new
|
||||
@ -472,7 +547,7 @@ impl Default for ChainSpec {
|
||||
fork_timestamps: Default::default(),
|
||||
hardforks: Default::default(),
|
||||
deposit_contract: Default::default(),
|
||||
base_fee_params: BaseFeeParams::ethereum(),
|
||||
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: MAINNET.prune_delete_limit,
|
||||
snapshot_block_interval: Default::default(),
|
||||
}
|
||||
@ -559,6 +634,25 @@ impl ChainSpec {
|
||||
(self.fork(Hardfork::London).active_at_block(0)).then_some(genesis_base_fee)
|
||||
}
|
||||
|
||||
/// Get the [BaseFeeParams] for the chain at the given timestamp.
|
||||
pub fn base_fee_params(&self, timestamp: u64) -> BaseFeeParams {
|
||||
match self.base_fee_params {
|
||||
BaseFeeParamsKind::Constant(bf_params) => bf_params,
|
||||
BaseFeeParamsKind::Variable(ForkBaseFeeParams { 0: ref bf_params }) => {
|
||||
// Walk through the base fee params configuration in reverse order, and return the
|
||||
// first one that corresponds to a hardfork that is active at the
|
||||
// given timestamp.
|
||||
for (fork, params) in bf_params.iter().rev() {
|
||||
if self.is_fork_active_at_timestamp(*fork, timestamp) {
|
||||
return *params
|
||||
}
|
||||
}
|
||||
|
||||
bf_params.first().map(|(_, params)| *params).unwrap_or(BaseFeeParams::ethereum())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the hash of the genesis block.
|
||||
pub fn genesis_hash(&self) -> B256 {
|
||||
if let Some(hash) = self.genesis_hash {
|
||||
|
||||
@ -67,6 +67,11 @@ pub const EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u64 = 2;
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 50;
|
||||
|
||||
/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism Canyon
|
||||
/// hardfork.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u64 = 250;
|
||||
|
||||
/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism
|
||||
/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc.
|
||||
#[cfg(feature = "optimism")]
|
||||
@ -77,6 +82,11 @@ pub const OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u64 = 6;
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const OP_GOERLI_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 50;
|
||||
|
||||
/// Base fee max change denominator for Optimism Goerli as defined in the Optimism Canyon
|
||||
/// hardfork.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const OP_GOERLI_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u64 = 250;
|
||||
|
||||
/// Base fee max change denominator for Optimism Goerli as defined in the Optimism
|
||||
/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc.
|
||||
#[cfg(feature = "optimism")]
|
||||
|
||||
@ -55,9 +55,9 @@ pub use block::{
|
||||
};
|
||||
pub use bytes::{self, Buf, BufMut, BytesMut};
|
||||
pub use chain::{
|
||||
AllGenesisFormats, BaseFeeParams, Chain, ChainInfo, ChainSpec, ChainSpecBuilder,
|
||||
DisplayHardforks, ForkCondition, ForkTimestamps, NamedChain, DEV, GOERLI, HOLESKY, MAINNET,
|
||||
SEPOLIA,
|
||||
AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, Chain, ChainInfo, ChainSpec,
|
||||
ChainSpecBuilder, DisplayHardforks, ForkBaseFeeParams, ForkCondition, ForkTimestamps,
|
||||
NamedChain, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA,
|
||||
};
|
||||
#[cfg(feature = "optimism")]
|
||||
pub use chain::{BASE_GOERLI, BASE_MAINNET, OP_GOERLI};
|
||||
|
||||
@ -130,11 +130,18 @@ where
|
||||
}
|
||||
}
|
||||
let last_entry = fee_entries.last().expect("is not empty");
|
||||
|
||||
let last_entry_timestamp = self
|
||||
.provider()
|
||||
.header_by_hash_or_number(last_entry.header_hash.into())?
|
||||
.map(|h| h.timestamp)
|
||||
.unwrap_or_default();
|
||||
|
||||
base_fee_per_gas.push(U256::from(calculate_next_block_base_fee(
|
||||
last_entry.gas_used,
|
||||
last_entry.gas_limit,
|
||||
last_entry.base_fee_per_gas,
|
||||
self.provider().chain_spec().base_fee_params,
|
||||
self.provider().chain_spec().base_fee_params(last_entry_timestamp),
|
||||
)));
|
||||
} else {
|
||||
// read the requested header range
|
||||
@ -183,7 +190,7 @@ where
|
||||
last_header.gas_used,
|
||||
last_header.gas_limit,
|
||||
last_header.base_fee_per_gas.unwrap_or_default(),
|
||||
self.provider().chain_spec().base_fee_params,
|
||||
self.provider().chain_spec().base_fee_params(last_header.timestamp),
|
||||
)));
|
||||
};
|
||||
|
||||
|
||||
@ -277,7 +277,8 @@ where
|
||||
latest.timestamp += 12;
|
||||
// base fee of the child block
|
||||
let chain_spec = self.provider().chain_spec();
|
||||
latest.base_fee_per_gas = latest.next_block_base_fee(chain_spec.base_fee_params);
|
||||
latest.base_fee_per_gas =
|
||||
latest.next_block_base_fee(chain_spec.base_fee_params(latest.timestamp));
|
||||
|
||||
PendingBlockEnvOrigin::DerivedFromLatest(latest)
|
||||
};
|
||||
|
||||
@ -92,7 +92,7 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
|
||||
last_seen_block_hash: latest.hash,
|
||||
last_seen_block_number: latest.number,
|
||||
pending_basefee: latest
|
||||
.next_block_base_fee(chain_spec.base_fee_params)
|
||||
.next_block_base_fee(chain_spec.base_fee_params(latest.timestamp + 12))
|
||||
.unwrap_or_default(),
|
||||
pending_blob_fee: latest.next_block_blob_fee(),
|
||||
};
|
||||
@ -238,8 +238,9 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
|
||||
let chain_spec = client.chain_spec();
|
||||
|
||||
// fees for the next block: `new_tip+1`
|
||||
let pending_block_base_fee =
|
||||
new_tip.next_block_base_fee(chain_spec.base_fee_params).unwrap_or_default();
|
||||
let pending_block_base_fee = new_tip
|
||||
.next_block_base_fee(chain_spec.base_fee_params(new_tip.timestamp + 12))
|
||||
.unwrap_or_default();
|
||||
let pending_block_blob_fee = new_tip.next_block_blob_fee();
|
||||
|
||||
// we know all changed account in the new chain
|
||||
@ -342,8 +343,9 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
|
||||
let chain_spec = client.chain_spec();
|
||||
|
||||
// fees for the next block: `tip+1`
|
||||
let pending_block_base_fee =
|
||||
tip.next_block_base_fee(chain_spec.base_fee_params).unwrap_or_default();
|
||||
let pending_block_base_fee = tip
|
||||
.next_block_base_fee(chain_spec.base_fee_params(tip.timestamp + 12))
|
||||
.unwrap_or_default();
|
||||
let pending_block_blob_fee = tip.next_block_blob_fee();
|
||||
|
||||
let first_block = blocks.first();
|
||||
|
||||
Reference in New Issue
Block a user