Skip to content

Commit

Permalink
add fork schedule for blob fee calculation post pectra and add testne…
Browse files Browse the repository at this point in the history
…t fork times
  • Loading branch information
ncitron committed Feb 10, 2025
1 parent acb06c7 commit 1e89aa9
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 59 deletions.
4 changes: 3 additions & 1 deletion core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::client::node::Node;
#[cfg(not(target_arch = "wasm32"))]
use crate::client::rpc::Rpc;
use crate::consensus::Consensus;
use crate::fork_schedule::ForkSchedule;
use crate::network_spec::NetworkSpec;
use crate::time::interval;
use crate::types::BlockTag;
Expand All @@ -29,9 +30,10 @@ impl<N: NetworkSpec, C: Consensus<N::BlockResponse>> Client<N, C> {
pub fn new(
execution_rpc: &str,
consensus: C,
fork_schedule: ForkSchedule,
#[cfg(not(target_arch = "wasm32"))] rpc_address: Option<SocketAddr>,
) -> Result<Self> {
let node = Node::new(execution_rpc, consensus)?;
let node = Node::new(execution_rpc, consensus, fork_schedule)?;
let node = Arc::new(node);

#[cfg(not(target_arch = "wasm32"))]
Expand Down
26 changes: 22 additions & 4 deletions core/src/client/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::execution::evm::Evm;
use crate::execution::rpc::http_rpc::HttpRpc;
use crate::execution::state::State;
use crate::execution::ExecutionClient;
use crate::fork_schedule::ForkSchedule;
use crate::network_spec::NetworkSpec;
use crate::time::{SystemTime, UNIX_EPOCH};
use crate::types::BlockTag;
Expand All @@ -20,22 +21,29 @@ pub struct Node<N: NetworkSpec, C: Consensus<N::BlockResponse>> {
pub consensus: C,
pub execution: Arc<ExecutionClient<N, HttpRpc<N>>>,
pub history_size: usize,
fork_schedule: ForkSchedule,
}

impl<N: NetworkSpec, C: Consensus<N::BlockResponse>> Node<N, C> {
pub fn new(execution_rpc: &str, mut consensus: C) -> Result<Self, ClientError> {
pub fn new(
execution_rpc: &str,
mut consensus: C,
fork_schedule: ForkSchedule,
) -> Result<Self, ClientError> {
let block_recv = consensus.block_recv().take().unwrap();
let finalized_block_recv = consensus.finalized_block_recv().take().unwrap();

let state = State::new(block_recv, finalized_block_recv, 256, execution_rpc);
let execution = Arc::new(
ExecutionClient::new(execution_rpc, state).map_err(ClientError::InternalError)?,
ExecutionClient::new(execution_rpc, state, fork_schedule.clone())

Check failure on line 38 in core/src/client/node.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `ForkSchedule` which implements the `Copy` trait
.map_err(ClientError::InternalError)?,
);

Ok(Node {
consensus,
execution,
history_size: 64,
fork_schedule,
})
}

Expand All @@ -46,14 +54,24 @@ impl<N: NetworkSpec, C: Consensus<N::BlockResponse>> Node<N, C> {
) -> Result<Bytes, ClientError> {
self.check_blocktag_age(&block).await?;

let mut evm = Evm::new(self.execution.clone(), self.chain_id(), block);
let mut evm = Evm::new(
self.execution.clone(),
self.chain_id(),
self.fork_schedule.clone(),

Check failure on line 60 in core/src/client/node.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `ForkSchedule` which implements the `Copy` trait
block,
);
evm.call(tx).await.map_err(ClientError::EvmError)
}

pub async fn estimate_gas(&self, tx: &N::TransactionRequest) -> Result<u64, ClientError> {
self.check_head_age().await?;

let mut evm = Evm::new(self.execution.clone(), self.chain_id(), BlockTag::Latest);
let mut evm = Evm::new(
self.execution.clone(),
self.chain_id(),
self.fork_schedule.clone(),

Check failure on line 72 in core/src/client/node.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `ForkSchedule` which implements the `Copy` trait
BlockTag::Latest,
);

evm.estimate_gas(tx).await.map_err(ClientError::EvmError)
}
Expand Down
2 changes: 0 additions & 2 deletions core/src/execution/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@ pub const PARALLEL_QUERY_BATCH_SIZE: usize = 20;
// We currently limit the max number of logs to fetch,
// to avoid blocking the client for too long.
pub const MAX_SUPPORTED_LOGS_NUMBER: usize = 5;
pub const BLOB_BASE_FEE_UPDATE_FRACTION: u64 = 3338477;
pub const MIN_BASE_FEE_PER_BLOB_GAS: u64 = 1;
27 changes: 19 additions & 8 deletions core/src/execution/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,37 @@ use revm::{
};
use tracing::trace;

use crate::execution::{
constants::PARALLEL_QUERY_BATCH_SIZE,
errors::{EvmError, ExecutionError},
rpc::ExecutionRpc,
ExecutionClient,
};
use crate::network_spec::NetworkSpec;
use crate::types::BlockTag;
use crate::{
execution::{
constants::PARALLEL_QUERY_BATCH_SIZE,
errors::{EvmError, ExecutionError},
rpc::ExecutionRpc,
ExecutionClient,
},
fork_schedule::ForkSchedule,
};

pub struct Evm<N: NetworkSpec, R: ExecutionRpc<N>> {
execution: Arc<ExecutionClient<N, R>>,
chain_id: u64,
tag: BlockTag,
fork_schedule: ForkSchedule,
}

impl<N: NetworkSpec, R: ExecutionRpc<N>> Evm<N, R> {
pub fn new(execution: Arc<ExecutionClient<N, R>>, chain_id: u64, tag: BlockTag) -> Self {
pub fn new(
execution: Arc<ExecutionClient<N, R>>,
chain_id: u64,
fork_schedule: ForkSchedule,
tag: BlockTag,
) -> Self {
Evm {
execution,
chain_id,
tag,
fork_schedule,
}
}

Expand Down Expand Up @@ -100,7 +110,8 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> Evm<N, R> {
.await
.ok_or(ExecutionError::BlockNotFound(tag))
.unwrap();
env.block = N::block_env(&block);

env.block = N::block_env(&block, &self.fork_schedule);

env.cfg.chain_id = self.chain_id;
env.cfg.disable_block_gas_limit = true;
Expand Down
50 changes: 17 additions & 33 deletions core/src/execution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ use alloy::primitives::{keccak256, Address, B256, U256};
use alloy::rlp;
use alloy::rpc::types::{BlockTransactions, Filter, FilterChanges, Log};
use alloy_trie::root::ordered_trie_root_with_encoder;
use constants::{BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS};
use eyre::Result;
use futures::future::try_join_all;
use proof::{verify_account_proof, verify_storage_proof};
use revm::primitives::KECCAK_EMPTY;
use revm::primitives::{BlobExcessGasAndPrice, KECCAK_EMPTY};
use tracing::warn;

use crate::fork_schedule::ForkSchedule;
use crate::network_spec::NetworkSpec;
use crate::types::BlockTag;

use self::constants::MAX_SUPPORTED_LOGS_NUMBER;
use self::errors::ExecutionError;
use self::proof::{verify_account_proof, verify_storage_proof};
use self::rpc::ExecutionRpc;
use self::state::{FilterType, State};
use self::types::Account;
Expand All @@ -35,12 +35,17 @@ pub mod types;
pub struct ExecutionClient<N: NetworkSpec, R: ExecutionRpc<N>> {
pub rpc: R,
state: State<N, R>,
fork_schedule: ForkSchedule,
}

impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionClient<N, R> {
pub fn new(rpc: &str, state: State<N, R>) -> Result<Self> {
pub fn new(rpc: &str, state: State<N, R>, fork_schedule: ForkSchedule) -> Result<Self> {
let rpc: R = ExecutionRpc::new(rpc)?;
Ok(ExecutionClient::<N, R> { rpc, state })
Ok(ExecutionClient::<N, R> {
rpc,
state,
fork_schedule,
})
}

pub async fn check_rpc(&self, chain_id: u64) -> Result<()> {
Expand Down Expand Up @@ -121,42 +126,21 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionClient<N, R> {

pub async fn blob_base_fee(&self, block: BlockTag) -> U256 {
let block = self.state.get_block(block).await;
if block.is_none() {
let Some(block) = block else {
warn!(target: "helios::execution", "requested block not found");
return U256::from(0);
}
let parent_hash = block.unwrap().header().parent_hash();
};

let parent_hash = block.header().parent_hash();
let parent_block = self.get_block_by_hash(parent_hash, false).await;
if parent_block.is_none() {
warn!(target: "helios::execution", "requested parent block not foundß");
return U256::from(0);
};

let blob_base_fee = Self::calculate_base_fee_per_blob_gas(
parent_block.unwrap().header().excess_blob_gas().unwrap(),
);

U256::from(blob_base_fee)
}

fn calculate_base_fee_per_blob_gas(parent_excess_blob_gas: u64) -> u64 {
Self::fake_exponential(
MIN_BASE_FEE_PER_BLOB_GAS,
parent_excess_blob_gas,
BLOB_BASE_FEE_UPDATE_FRACTION,
)
}
//https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4844.md#helpers
fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u64 {
let mut i = 1;
let mut output = 0;
let mut numerator_accum = factor * denominator;
while numerator_accum > 0 {
output += numerator_accum;
numerator_accum = numerator_accum * numerator / (denominator * i);
i += 1;
}
output / denominator
let excess_blob_gas = parent_block.unwrap().header().excess_blob_gas().unwrap();
let is_prague = block.header().timestamp() >= self.fork_schedule.prague_timestamp;
U256::from(BlobExcessGasAndPrice::new(excess_blob_gas, is_prague).blob_gasprice)
}

pub async fn get_block_by_hash(&self, hash: B256, full_tx: bool) -> Option<N::BlockResponse> {
Expand Down
6 changes: 6 additions & 0 deletions core/src/fork_schedule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Serialize, Deserialize, Default, Debug)]
pub struct ForkSchedule {
pub prague_timestamp: u64,
}
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod client;
pub mod consensus;
pub mod errors;
pub mod execution;
pub mod fork_schedule;
pub mod network_spec;
pub mod time;
pub mod types;
4 changes: 3 additions & 1 deletion core/src/network_spec.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use alloy::{network::Network, rpc::types::Log};
use revm::primitives::{BlockEnv, TxEnv};

use crate::fork_schedule::ForkSchedule;

pub trait NetworkSpec: Network {
fn encode_receipt(receipt: &Self::ReceiptResponse) -> Vec<u8>;
fn is_hash_valid(block: &Self::BlockResponse) -> bool;
fn receipt_contains(list: &[Self::ReceiptResponse], elem: &Self::ReceiptResponse) -> bool;
fn receipt_logs(receipt: &Self::ReceiptResponse) -> Vec<Log>;
fn tx_env(request: &Self::TransactionRequest) -> TxEnv;
fn block_env(block: &Self::BlockResponse) -> BlockEnv;
fn block_env(block: &Self::BlockResponse, fork_schedule: &ForkSchedule) -> BlockEnv;
}
2 changes: 2 additions & 0 deletions ethereum/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ impl EthereumClientBuilder {
data_dir: None,
chain: base_config.chain,
forks: base_config.forks,
execution_forks: base_config.execution_forks,
max_checkpoint_age: base_config.max_checkpoint_age,
fallback,
load_external_fallback,
Expand All @@ -226,6 +227,7 @@ impl EthereumClientBuilder {
Client::<Ethereum, ConsensusClient<MainnetConsensusSpec, HttpRpc, DB>>::new(
&config.execution_rpc.clone(),
consensus,
config.execution_forks.clone(),
#[cfg(not(target_arch = "wasm32"))]
socket,
)
Expand Down
3 changes: 3 additions & 0 deletions ethereum/src/config/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf;

use alloy::primitives::B256;
use helios_core::fork_schedule::ForkSchedule;
use serde::Serialize;

use helios_consensus_core::types::Forks;
Expand All @@ -18,6 +19,7 @@ pub struct BaseConfig {
pub default_checkpoint: B256,
pub chain: ChainConfig,
pub forks: Forks,
pub execution_forks: ForkSchedule,
pub max_checkpoint_age: u64,
pub data_dir: Option<PathBuf>,
pub load_external_fallback: bool,
Expand All @@ -35,6 +37,7 @@ impl Default for BaseConfig {
forks: Default::default(),
max_checkpoint_age: 0,
data_dir: None,
execution_forks: ForkSchedule::default(),
load_external_fallback: false,
strict_checkpoint_age: false,
}
Expand Down
4 changes: 4 additions & 0 deletions ethereum/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use figment::{
providers::{Format, Serialized, Toml},
Figment,
};
use helios_core::fork_schedule::ForkSchedule;
use serde::Deserialize;

use helios_consensus_core::types::Forks;
Expand Down Expand Up @@ -34,6 +35,7 @@ pub struct Config {
pub data_dir: Option<PathBuf>,
pub chain: ChainConfig,
pub forks: Forks,
pub execution_forks: ForkSchedule,
pub max_checkpoint_age: u64,
pub fallback: Option<String>,
pub load_external_fallback: bool,
Expand Down Expand Up @@ -84,6 +86,7 @@ impl Config {
default_checkpoint: self.default_checkpoint,
chain: self.chain.clone(),
forks: self.forks.clone(),
execution_forks: self.execution_forks,
max_checkpoint_age: self.max_checkpoint_age,
data_dir: self.data_dir.clone(),
load_external_fallback: self.load_external_fallback,
Expand All @@ -103,6 +106,7 @@ impl From<BaseConfig> for Config {
default_checkpoint: base.default_checkpoint,
chain: base.chain,
forks: base.forks,
execution_forks: base.execution_forks,
max_checkpoint_age: base.max_checkpoint_age,
data_dir: base.data_dir,
fallback: None,
Expand Down
17 changes: 15 additions & 2 deletions ethereum/src/config/networks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use alloy::primitives::{b256, fixed_bytes};
#[cfg(not(target_arch = "wasm32"))]
use dirs::home_dir;
use eyre::Result;
use helios_core::fork_schedule::ForkSchedule;
use serde::{Deserialize, Serialize};
use strum::EnumIter;

Expand Down Expand Up @@ -110,6 +111,9 @@ pub fn mainnet() -> BaseConfig {
fork_version: fixed_bytes!("05000000"),
},
},
execution_forks: ForkSchedule {
prague_timestamp: u64::MAX,
},
max_checkpoint_age: 1_209_600, // 14 days
#[cfg(not(target_arch = "wasm32"))]
data_dir: Some(data_dir(Network::Mainnet)),
Expand Down Expand Up @@ -151,10 +155,13 @@ pub fn sepolia() -> BaseConfig {
fork_version: fixed_bytes!("90000073"),
},
electra: Fork {
epoch: u64::MAX,
epoch: 222464,
fork_version: fixed_bytes!("90000074"),
},
},
execution_forks: ForkSchedule {
prague_timestamp: 1741159776,
},
max_checkpoint_age: 1_209_600, // 14 days
#[cfg(not(target_arch = "wasm32"))]
data_dir: Some(data_dir(Network::Sepolia)),
Expand Down Expand Up @@ -196,10 +203,13 @@ pub fn holesky() -> BaseConfig {
fork_version: fixed_bytes!("05017000"),
},
electra: Fork {
epoch: u64::MAX,
epoch: 115968,
fork_version: fixed_bytes!("06017000"),
},
},
execution_forks: ForkSchedule {
prague_timestamp: 1740434112,
},
max_checkpoint_age: 1_209_600, // 14 days
#[cfg(not(target_arch = "wasm32"))]
data_dir: Some(data_dir(Network::Holesky)),
Expand Down Expand Up @@ -245,6 +255,9 @@ pub fn pectra_devnet() -> BaseConfig {
fork_version: fixed_bytes!("60585557"),
},
},
execution_forks: ForkSchedule {
prague_timestamp: 1738607700,
},
max_checkpoint_age: 1_209_600, // 14 days
#[cfg(not(target_arch = "wasm32"))]
data_dir: Some(data_dir(Network::PectraDevnet)),
Expand Down
Loading

0 comments on commit 1e89aa9

Please sign in to comment.