From 9fb66ffeff8bf9ba8f74b52465e0fa87b12354e8 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 26 Apr 2023 12:31:35 +0200 Subject: [PATCH] chore: move next base fee to header impl (#2400) --- Cargo.lock | 1 - crates/consensus/common/src/validation.rs | 59 +--------------------- crates/payload/builder/Cargo.toml | 1 - crates/payload/builder/src/payload.rs | 7 +-- crates/primitives/src/basefee.rs | 61 +++++++++++++++++++++++ crates/primitives/src/header.rs | 8 +++ crates/primitives/src/lib.rs | 1 + crates/transaction-pool/src/maintain.rs | 21 ++------ 8 files changed, 77 insertions(+), 82 deletions(-) create mode 100644 crates/primitives/src/basefee.rs diff --git a/Cargo.lock b/Cargo.lock index 3cd31ff30..f2dc6ad75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5086,7 +5086,6 @@ dependencies = [ "futures-core", "futures-util", "metrics", - "reth-consensus-common", "reth-interfaces", "reth-metrics-derive", "reth-primitives", diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index d79845e5b..f8a35dc01 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -234,32 +234,6 @@ pub fn validate_block_standalone( Ok(()) } -/// Calculate base fee for next block. EIP-1559 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; - - if gas_used == gas_target { - return base_fee - } - if gas_used > gas_target { - let gas_used_delta = gas_used - gas_target; - let base_fee_delta = std::cmp::max( - 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 + (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.saturating_sub(base_fee_per_gas_delta as u64) - } -} - /// Validate block in regards to parent pub fn validate_header_regarding_parent( parent: &SealedHeader, @@ -320,11 +294,7 @@ 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. - calculate_next_block_base_fee( - parent.gas_used, - parent.gas_limit, - parent.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)?, - ) + parent.next_block_base_fee().ok_or(ConsensusError::BaseFeeMissing)? }; if expected_base_fee != base_fee { return Err(ConsensusError::BaseFeeDiff { expected: expected_base_fee, got: base_fee }) @@ -428,33 +398,6 @@ mod tests { }; use std::ops::RangeBounds; - #[test] - fn calculate_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, - 2, 3, - ]; - - 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]) - ); - } - } - mock! { WithdrawalsProvider {} diff --git a/crates/payload/builder/Cargo.toml b/crates/payload/builder/Cargo.toml index 5d06a4a3c..87e2ce953 100644 --- a/crates/payload/builder/Cargo.toml +++ b/crates/payload/builder/Cargo.toml @@ -13,7 +13,6 @@ reth-primitives = { path = "../../primitives" } reth-rpc-types = { path = "../../rpc/rpc-types" } reth-rlp = { path = "../../rlp" } reth-interfaces = { path = "../../interfaces" } -reth-consensus-common = { path = "../../consensus/common" } reth-revm-primitives = { path = "../../revm/revm-primitives" } ## ethereum diff --git a/crates/payload/builder/src/payload.rs b/crates/payload/builder/src/payload.rs index 9d564d9cc..8adc3c124 100644 --- a/crates/payload/builder/src/payload.rs +++ b/crates/payload/builder/src/payload.rs @@ -1,6 +1,5 @@ //! Contains types required for building a payload. -use reth_consensus_common::validation::calculate_next_block_base_fee; use reth_primitives::{Address, ChainSpec, Header, SealedBlock, Withdrawal, H256, U256}; use reth_revm_primitives::config::revm_spec_by_timestamp_after_merge; use reth_rlp::Encodable; @@ -135,11 +134,7 @@ 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(calculate_next_block_base_fee( - parent.gas_used, - parent.gas_limit, - parent.base_fee_per_gas.unwrap_or_default(), - )), + basefee: U256::from(parent.next_block_base_fee().unwrap_or_default()), }; (cfg, block_env) diff --git a/crates/primitives/src/basefee.rs b/crates/primitives/src/basefee.rs new file mode 100644 index 000000000..be60c3dcc --- /dev/null +++ b/crates/primitives/src/basefee.rs @@ -0,0 +1,61 @@ +//! 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; + + if gas_used == gas_target { + return base_fee + } + if gas_used > gas_target { + let gas_used_delta = gas_used - gas_target; + let base_fee_delta = std::cmp::max( + 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 + (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.saturating_sub(base_fee_per_gas_delta as u64) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn calculate_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, + 2, 3, + ]; + + 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]) + ); + } + } +} diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs index 012a5ca4a..575652e93 100644 --- a/crates/primitives/src/header.rs +++ b/crates/primitives/src/header.rs @@ -1,4 +1,5 @@ use crate::{ + basefee::calculate_next_block_base_fee, keccak256, proofs::{EMPTY_LIST_HASH, EMPTY_ROOT}, BlockHash, BlockNumber, Bloom, Bytes, H160, H256, U256, @@ -145,6 +146,13 @@ impl Header { self.transactions_root == EMPTY_ROOT } + /// 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?)) + } + /// Seal the header with a known hash. /// /// WARNING: This method does not perform validation whether the hash is correct. diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e8a38fd23..62810e2b0 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -10,6 +10,7 @@ //! This crate contains Ethereum primitive types and helper functions. mod account; +pub mod basefee; mod bits; mod block; pub mod bloom; diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 5bf78a1c6..625159569 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -5,7 +5,6 @@ use crate::{ Pool, TransactionOrdering, TransactionPool, TransactionValidator, }; use futures_util::{Stream, StreamExt}; -use reth_consensus_common::validation::calculate_next_block_base_fee; use reth_primitives::{Address, BlockHash, FromRecoveredTransaction}; use reth_provider::{BlockProvider, CanonStateNotification, PostState, StateProviderFactory}; use std::{ @@ -46,11 +45,8 @@ pub async fn maintain_transaction_pool( let new_tip = new_blocks.tip(); // base fee for the next block: `new_tip+1` - let pending_block_base_fee = calculate_next_block_base_fee( - new_tip.gas_used, - new_tip.gas_limit, - new_tip.base_fee_per_gas.unwrap_or_default(), - ) as u128; + let pending_block_base_fee = + new_tip.next_block_base_fee().unwrap_or_default() as u128; // we know all changed account in the new chain let new_changed_accounts: HashSet<_> = @@ -133,11 +129,8 @@ pub async fn maintain_transaction_pool( } // base fee for the next block: `first_block+1` - let pending_block_base_fee = calculate_next_block_base_fee( - first_block.gas_used, - first_block.gas_limit, - first_block.base_fee_per_gas.unwrap_or_default(), - ) as u128; + let pending_block_base_fee = + first_block.next_block_base_fee().unwrap_or_default() as u128; let changed_accounts = changed_accounts_iter(state).collect(); let update = CanonicalStateUpdate { hash: first_block.hash, @@ -169,11 +162,7 @@ pub async fn maintain_transaction_pool( let (blocks, state) = new.inner(); let tip = blocks.tip(); // base fee for the next block: `tip+1` - let pending_block_base_fee = calculate_next_block_base_fee( - tip.gas_used, - tip.gas_limit, - tip.base_fee_per_gas.unwrap_or_default(), - ) as u128; + let pending_block_base_fee = tip.next_block_base_fee().unwrap_or_default() as u128; let first_block = blocks.first(); // check if the range of the commit is canonical