refactor: unify all chains confs (#747)

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>
This commit is contained in:
Aurélien
2023-01-17 16:47:34 +01:00
committed by GitHub
parent 55d1db0c1d
commit f9de425ad8
33 changed files with 28324 additions and 737 deletions

1
Cargo.lock generated
View File

@ -4368,6 +4368,7 @@ dependencies = [
"hex-literal",
"impl-serde",
"modular-bitfield",
"once_cell",
"parity-scale-codec",
"plain_hasher",
"proptest",

View File

@ -6,7 +6,7 @@ use reth_network::{
config::{mainnet_nodes, rng_secret_key},
NetworkConfig, PeersConfig,
};
use reth_primitives::{NodeRecord, H256};
use reth_primitives::{ChainSpec, NodeRecord};
use reth_provider::ProviderImpl;
use serde::{Deserialize, Serialize};
@ -26,8 +26,7 @@ impl Config {
pub fn network_config<DB: Database>(
&self,
db: Arc<DB>,
chain_id: u64,
genesis_hash: H256,
chain_spec: ChainSpec,
disable_discovery: bool,
bootnodes: Option<Vec<NodeRecord>>,
) -> NetworkConfig<ProviderImpl<DB>> {
@ -37,8 +36,7 @@ impl Config {
NetworkConfig::builder(Arc::new(ProviderImpl::new(db)), rng_secret_key())
.boot_nodes(bootnodes.unwrap_or_else(mainnet_nodes))
.peer_config(peer_config)
.genesis_hash(genesis_hash)
.chain_id(chain_id)
.chain_spec(chain_spec)
.set_discovery(disable_discovery)
.build()
}

View File

@ -5,11 +5,7 @@ use crate::{
config::Config,
dirs::{ConfigPath, DbPath, PlatformPath},
prometheus_exporter,
utils::{
chainspec::{chain_spec_value_parser, ChainSpecification},
init::{init_db, init_genesis},
parse_socket_address,
},
utils::{chainspec::chain_spec_value_parser, init::init_db, parse_socket_address},
NetworkOpts,
};
use clap::{crate_version, Parser};
@ -18,11 +14,10 @@ use fdlimit::raise_fd_limit;
use futures::{stream::select as stream_select, Stream, StreamExt};
use reth_consensus::BeaconConsensus;
use reth_downloaders::{bodies, headers};
use reth_executor::Config as ExecutorConfig;
use reth_interfaces::consensus::ForkchoiceState;
use reth_network::NetworkEvent;
use reth_network_api::NetworkInfo;
use reth_primitives::{BlockNumber, NodeRecord, H256};
use reth_primitives::{BlockNumber, ChainSpec, NodeRecord, H256};
use reth_stages::{
metrics::HeaderMetrics,
stages::{
@ -68,7 +63,7 @@ pub struct Command {
default_value = "mainnet",
value_parser = chain_spec_value_parser
)]
chain: ChainSpecification,
chain: ChainSpec,
/// Enable Prometheus metrics.
///
@ -119,15 +114,12 @@ impl Command {
HeaderMetrics::describe();
}
let chain_id = self.chain.consensus.chain_id;
let consensus = Arc::new(BeaconConsensus::new(self.chain.consensus.clone()));
let genesis_hash = init_genesis(db.clone(), self.chain.genesis.clone())?;
let consensus: Arc<BeaconConsensus> = Arc::new(BeaconConsensus::new(self.chain.clone()));
let network = config
.network_config(
db.clone(),
chain_id,
genesis_hash,
self.chain.clone(),
self.network.disable_discovery,
self.bootnodes.clone(),
)
@ -178,7 +170,7 @@ impl Command {
commit_threshold: config.stages.sender_recovery.commit_threshold,
})
.push(ExecutionStage {
config: ExecutorConfig::new_ethereum(),
chain_spec: self.chain.clone(),
commit_threshold: config.stages.execution.commit_threshold,
});

View File

@ -2,10 +2,7 @@
use crate::{
config::Config,
dirs::{ConfigPath, PlatformPath},
utils::{
chainspec::{chain_spec_value_parser, ChainSpecification},
hash_or_num_value_parser,
},
utils::{chainspec::chain_spec_value_parser, hash_or_num_value_parser},
};
use backon::{ConstantBackoff, Retryable};
use clap::{Parser, Subcommand};
@ -15,7 +12,7 @@ use reth_interfaces::p2p::{
headers::client::{HeadersClient, HeadersRequest},
};
use reth_network::FetchClient;
use reth_primitives::{BlockHashOrNumber, Header, NodeRecord, SealedHeader};
use reth_primitives::{BlockHashOrNumber, ChainSpec, NodeRecord, SealedHeader};
use std::sync::Arc;
/// `reth p2p` command
@ -40,7 +37,7 @@ pub struct Command {
default_value = "mainnet",
value_parser = chain_spec_value_parser
)]
chain: ChainSpecification,
chain: ChainSpec,
/// Disable the discovery service.
#[arg(short, long)]
@ -86,10 +83,6 @@ impl Command {
let mut config: Config = confy::load_path(&self.config).unwrap_or_default();
let chain_id = self.chain.consensus.chain_id;
let genesis: Header = self.chain.genesis.clone().into();
let genesis_hash = genesis.hash_slow();
if let Some(peer) = self.trusted_peer {
config.peers.trusted_nodes.insert(peer);
}
@ -101,7 +94,7 @@ impl Command {
config.peers.connect_trusted_nodes_only = self.trusted_only;
let network = config
.network_config(noop_db, chain_id, genesis_hash, self.disable_discovery, None)
.network_config(noop_db, self.chain.clone(), self.disable_discovery, None)
.start_network()
.await?;

View File

@ -5,15 +5,13 @@ use crate::{
config::Config,
dirs::{ConfigPath, DbPath, PlatformPath},
prometheus_exporter,
utils::{
chainspec::{chain_spec_value_parser, ChainSpecification},
init::{init_db, init_genesis},
},
utils::{chainspec::chain_spec_value_parser, init::init_db},
NetworkOpts,
};
use reth_consensus::BeaconConsensus;
use reth_downloaders::bodies::concurrent::ConcurrentDownloader;
use reth_executor::Config as ExecutorConfig;
use reth_primitives::ChainSpec;
use reth_stages::{
metrics::HeaderMetrics,
stages::{bodies::BodyStage, execution::ExecutionStage, sender_recovery::SenderRecoveryStage},
@ -56,7 +54,7 @@ pub struct Command {
default_value = "mainnet",
value_parser = chain_spec_value_parser
)]
chain: ChainSpecification,
chain: ChainSpec,
/// Enable Prometheus metrics.
///
@ -126,9 +124,8 @@ impl Command {
match self.stage {
StageEnum::Bodies => {
let chain_id = self.chain.consensus.chain_id;
let consensus = Arc::new(BeaconConsensus::new(self.chain.consensus.clone()));
let genesis_hash = init_genesis(db.clone(), self.chain.genesis.clone())?;
let consensus: Arc<BeaconConsensus> =
Arc::new(BeaconConsensus::new(self.chain.clone()));
let mut config = config;
config.peers.connect_trusted_nodes_only = self.network.trusted_only;
@ -141,8 +138,7 @@ impl Command {
let network = config
.network_config(
db.clone(),
chain_id,
genesis_hash,
self.chain.clone(),
self.network.disable_discovery,
None,
)
@ -179,10 +175,8 @@ impl Command {
stage.execute(&mut tx, input).await?;
}
StageEnum::Execution => {
let mut stage = ExecutionStage {
config: ExecutorConfig::new_ethereum(),
commit_threshold: num_blocks,
};
let mut stage =
ExecutionStage { chain_spec: self.chain.clone(), commit_threshold: num_blocks };
if !self.skip_unwind {
stage.unwind(&mut tx, unwind).await?;
}

View File

@ -1,6 +1,6 @@
use reth_primitives::{
Address, BigEndianHash, Bloom, Bytes, Header as RethHeader, JsonU256, SealedHeader, H160, H256,
H64,
Address, BigEndianHash, Bloom, Bytes, ChainSpec, ChainSpecBuilder, Header as RethHeader,
JsonU256, SealedHeader, H160, H256, H64,
};
use serde::{self, Deserialize};
use std::collections::BTreeMap;
@ -209,28 +209,30 @@ pub enum ForkSpec {
Unknown,
}
impl From<ForkSpec> for reth_executor::SpecUpgrades {
impl From<ForkSpec> for ChainSpec {
fn from(fork_spec: ForkSpec) -> Self {
let spec_builder = ChainSpecBuilder::mainnet();
match fork_spec {
ForkSpec::Frontier => Self::new_frontier_activated(),
ForkSpec::Frontier => spec_builder.frontier_activated(),
ForkSpec::Homestead | ForkSpec::FrontierToHomesteadAt5 => {
Self::new_homestead_activated()
spec_builder.homestead_activated()
}
ForkSpec::EIP150 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => {
Self::new_tangerine_whistle_activated()
spec_builder.tangerine_whistle_activated()
}
ForkSpec::EIP158 => Self::new_spurious_dragon_activated(),
ForkSpec::EIP158 => spec_builder.spurious_dragon_activated(),
ForkSpec::Byzantium |
ForkSpec::EIP158ToByzantiumAt5 |
ForkSpec::ConstantinopleFix |
ForkSpec::ByzantiumToConstantinopleFixAt5 => Self::new_byzantium_activated(),
ForkSpec::Istanbul => Self::new_istanbul_activated(),
ForkSpec::Berlin => Self::new_berlin_activated(),
ForkSpec::London | ForkSpec::BerlinToLondonAt5 => Self::new_london_activated(),
ForkSpec::Merge => Self::new_paris_activated(),
ForkSpec::MergeEOF => Self::new_paris_activated(),
ForkSpec::MergeMeterInitCode => Self::new_paris_activated(),
ForkSpec::MergePush0 => Self::new_paris_activated(),
ForkSpec::ByzantiumToConstantinopleFixAt5 => spec_builder.byzantium_activated(),
ForkSpec::Istanbul => spec_builder.istanbul_activated(),
ForkSpec::Berlin => spec_builder.berlin_activated(),
ForkSpec::London | ForkSpec::BerlinToLondonAt5 => spec_builder.london_activated(),
ForkSpec::Merge => spec_builder.paris_activated(),
ForkSpec::MergeEOF => spec_builder.paris_activated(),
ForkSpec::MergeMeterInitCode => spec_builder.paris_activated(),
ForkSpec::MergePush0 => spec_builder.paris_activated(),
ForkSpec::Shanghai => {
panic!("Not supported")
}
@ -241,6 +243,7 @@ impl From<ForkSpec> for reth_executor::SpecUpgrades {
panic!("Unknown fork");
}
}
.build()
}
}

View File

@ -9,10 +9,9 @@ use reth_db::{
transaction::{DbTx, DbTxMut},
Error as DbError,
};
use reth_executor::SpecUpgrades;
use reth_primitives::{
keccak256, Account as RethAccount, Address, JsonU256, SealedBlock, SealedHeader, StorageEntry,
H256, U256,
keccak256, Account as RethAccount, Address, ChainSpec, JsonU256, SealedBlock, SealedHeader,
StorageEntry, H256, U256,
};
use reth_rlp::Decodable;
use reth_stages::{stages::execution::ExecutionStage, ExecInput, Stage, StageId, Transaction};
@ -124,9 +123,9 @@ pub async fn run_test(path: PathBuf) -> eyre::Result<TestOutcome> {
debug!(target: "reth::cli", name, network = ?suite.network, "Running test");
let spec_upgrades: SpecUpgrades = suite.network.into();
let chain_spec: ChainSpec = suite.network.into();
// if paris aka merge is not activated we dont have block rewards;
let has_block_reward = spec_upgrades.paris != 0;
let has_block_reward = chain_spec.paris_status().block_number().is_some();
// Create db and acquire transaction
let db = create_test_rw_db::<WriteMap>();
@ -189,10 +188,7 @@ pub async fn run_test(path: PathBuf) -> eyre::Result<TestOutcome> {
// Initialize the execution stage
// Hardcode the chain_id to Ethereum 1.
let mut stage = ExecutionStage::new(
reth_executor::Config { chain_id: U256::from(1), spec_upgrades },
1000,
);
let mut stage = ExecutionStage::new(chain_spec, 1000);
// Call execution stage
let input = ExecInput {

View File

@ -1,86 +1,13 @@
use reth_primitives::{
utils::serde_helpers::deserialize_stringified_u64, Address, Bytes, Header, H256, U256,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, path::PathBuf};
use reth_primitives::{ChainSpec, GOERLI, MAINNET, SEPOLIA};
use std::path::PathBuf;
/// Defines a chain, including it's genesis block, chain ID and fork block numbers.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ChainSpecification {
/// Consensus configuration.
#[serde(rename = "config")]
pub consensus: reth_consensus::Config,
/// The genesis block of the chain.
#[serde(flatten)]
pub genesis: Genesis,
}
/// The genesis block specification.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Genesis {
/// The genesis header nonce.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub nonce: u64,
/// The genesis header timestamp.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub timestamp: u64,
/// The genesis header extra data.
pub extra_data: Bytes,
/// The genesis header gas limit.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub gas_limit: u64,
/// The genesis header difficulty.
pub difficulty: U256,
/// The genesis header mix hash.
pub mix_hash: H256,
/// The genesis header coinbase address.
pub coinbase: Address,
/// The genesis state root.
pub state_root: H256,
/// The initial state of accounts in the genesis block.
pub alloc: HashMap<Address, GenesisAccount>,
}
impl From<Genesis> for Header {
fn from(genesis: Genesis) -> Header {
Header {
gas_limit: genesis.gas_limit,
difficulty: genesis.difficulty,
nonce: genesis.nonce,
extra_data: genesis.extra_data,
state_root: genesis.state_root,
timestamp: genesis.timestamp,
mix_hash: genesis.mix_hash,
beneficiary: genesis.coinbase,
..Default::default()
}
}
}
/// An account in the state of the genesis block.
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct GenesisAccount {
/// The nonce of the account at genesis.
#[serde(skip_serializing_if = "Option::is_none")]
pub nonce: Option<u64>,
/// The balance of the account at genesis.
pub balance: U256,
}
/// Clap value parser for [ChainSpecification]s that takes either a built-in chainspec or the path
/// Clap value parser for [ChainSpec]s that takes either a built-in chainspec or the path
/// to a custom one.
pub fn chain_spec_value_parser(s: &str) -> Result<ChainSpecification, eyre::Error> {
pub fn chain_spec_value_parser(s: &str) -> Result<ChainSpec, eyre::Error> {
Ok(match s {
"mainnet" => {
serde_json::from_str(include_str!("../../../../bin/reth/res/chainspec/mainnet.json"))?
}
"goerli" => {
serde_json::from_str(include_str!("../../../../bin/reth/res/chainspec/goerli.json"))?
}
"sepolia" => {
serde_json::from_str(include_str!("../../../../bin/reth/res/chainspec/sepolia.json"))?
}
"mainnet" => MAINNET.clone(),
"goerli" => GOERLI.clone(),
"sepolia" => SEPOLIA.clone(),
_ => {
let raw = std::fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned()))?;
serde_json::from_str(&raw)?

View File

@ -1,4 +1,3 @@
use crate::chainspec::Genesis;
use reth_db::{
cursor::DbCursorRO,
database::Database,
@ -6,7 +5,7 @@ use reth_db::{
tables,
transaction::{DbTx, DbTxMut},
};
use reth_primitives::{Account, Header, H256};
use reth_primitives::{Account, Genesis, Header, H256};
use std::{path::Path, sync::Arc};
use tracing::debug;

View File

@ -1,100 +0,0 @@
//! Reth block execution/validation configuration and constants
use reth_executor::{Config as ExecutorConfig, SpecUpgrades};
use reth_primitives::{BlockNumber, U256};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// Initial base fee as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_INITIAL_BASE_FEE: u64 = 1_000_000_000;
/// Base fee max change denominator as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8;
/// Elasticity multiplier as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_ELASTICITY_MULTIPLIER: u64 = 2;
/// Common configuration for consensus algorithms.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Config {
/// Blockchain identifier introduced in EIP-155: Simple replay attack protection.
pub chain_id: u64,
/// Homestead switch block.
pub homestead_block: BlockNumber,
/// TheDAO hard-fork switch block.
pub dao_fork_block: BlockNumber,
/// Whether the node supports or opposes the DAO hard-fork
pub dao_fork_support: bool,
/// EIP150 implements gas price changes.
pub eip_150_block: BlockNumber,
/// EIP155 hard-fork block (Spurious Dragon)
pub eip_155_block: BlockNumber,
/// EIP158 hard-fork block.
pub eip_158_block: BlockNumber,
/// Byzantium switch block.
pub byzantium_block: BlockNumber,
/// Constantinople switch block.
pub constantinople_block: BlockNumber,
/// Petersburg switch block.
pub petersburg_block: BlockNumber,
/// Istanbul switch block.
pub istanbul_block: BlockNumber,
/// EIP-2728 switch block.
pub berlin_block: BlockNumber,
/// EIP-1559 switch block.
pub london_block: BlockNumber,
/// The Merge/Paris hard-fork block number.
pub paris_block: BlockNumber,
/// Terminal total difficulty after the paris hard-fork to reach before The Merge is considered
/// activated.
#[cfg_attr(feature = "serde", serde(rename = "terminalTotalDifficulty"))]
pub merge_terminal_total_difficulty: u128,
}
impl Default for Config {
fn default() -> Self {
Self {
chain_id: 1,
homestead_block: 1150000,
dao_fork_block: 1920000,
dao_fork_support: true,
eip_150_block: 2463000,
eip_155_block: 2675000,
eip_158_block: 2675000,
byzantium_block: 4370000,
constantinople_block: 7280000,
petersburg_block: 7280000,
istanbul_block: 9069000,
berlin_block: 12244000,
london_block: 12965000,
paris_block: 15537394,
merge_terminal_total_difficulty: 58750000000000000000000,
}
}
}
impl From<&Config> for ExecutorConfig {
fn from(value: &Config) -> Self {
Self {
chain_id: U256::from(value.chain_id),
spec_upgrades: SpecUpgrades {
frontier: 0,
homestead: value.homestead_block,
dao_fork: value.dao_fork_block,
tangerine_whistle: value.eip_150_block,
spurious_dragon: value.eip_158_block,
byzantium: value.byzantium_block,
petersburg: value.petersburg_block,
istanbul: value.istanbul_block,
berlin: value.berlin_block,
london: value.london_block,
paris: value.paris_block,
shanghai: u64::MAX, // TODO: change once known
},
}
}
}

View File

@ -1,7 +1,7 @@
//! Consensus for ethereum network
use crate::{verification, Config};
use crate::verification;
use reth_interfaces::consensus::{Consensus, Error, ForkchoiceState};
use reth_primitives::{BlockNumber, SealedBlock, SealedHeader, H256};
use reth_primitives::{BlockNumber, ChainSpec, SealedBlock, SealedHeader, H256};
use tokio::sync::{watch, watch::error::SendError};
/// Ethereum beacon consensus
@ -12,19 +12,19 @@ pub struct BeaconConsensus {
/// Watcher over the forkchoice state
channel: (watch::Sender<ForkchoiceState>, watch::Receiver<ForkchoiceState>),
/// Configuration
config: Config,
chain_spec: ChainSpec,
}
impl BeaconConsensus {
/// Create a new instance of [BeaconConsensus]
pub fn new(config: Config) -> Self {
pub fn new(chain_spec: ChainSpec) -> Self {
Self {
channel: watch::channel(ForkchoiceState {
head_block_hash: H256::zero(),
finalized_block_hash: H256::zero(),
safe_block_hash: H256::zero(),
}),
config,
chain_spec,
}
}
@ -43,10 +43,10 @@ impl Consensus for BeaconConsensus {
}
fn validate_header(&self, header: &SealedHeader, parent: &SealedHeader) -> Result<(), Error> {
verification::validate_header_standalone(header, &self.config)?;
verification::validate_header_regarding_parent(parent, header, &self.config)?;
verification::validate_header_standalone(header, &self.chain_spec)?;
verification::validate_header_regarding_parent(parent, header, &self.chain_spec)?;
if header.number < self.config.paris_block {
if Some(header.number) < self.chain_spec.paris_status().block_number() {
// TODO Consensus checks for old blocks:
// * difficulty, mix_hash & nonce aka PoW stuff
// low priority as syncing is done in reverse order
@ -59,6 +59,6 @@ impl Consensus for BeaconConsensus {
}
fn has_block_reward(&self, block_num: BlockNumber) -> bool {
block_num < self.config.paris_block
Some(block_num) < self.chain_spec.paris_status().block_number()
}
}

View File

@ -0,0 +1,8 @@
//! Reth block execution/validation configuration and constants
/// Initial base fee as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_INITIAL_BASE_FEE: u64 = 1_000_000_000;
/// Base fee max change denominator as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8;
/// Elasticity multiplier as defined in: https://eips.ethereum.org/EIPS/eip-1559
pub const EIP1559_ELASTICITY_MULTIPLIER: u64 = 2;

View File

@ -64,6 +64,9 @@ pub enum EngineApiError {
/// Forkchoice zero hash head received.
#[error("Received zero hash as forkchoice head")]
ForkchoiceEmptyHead,
/// Chain spec merge terminal total difficulty is not set
#[error("The merge terminal total difficulty is not known")]
UnknownMergeTerminalTotalDifficulty,
/// Encountered decoding error.
#[error(transparent)]
Decode(#[from] reth_rlp::DecodeError),

View File

@ -7,7 +7,7 @@ use reth_interfaces::consensus::ForkchoiceState;
use reth_primitives::{
proofs::{self, EMPTY_LIST_HASH},
rpc::{BlockId, H256 as EthersH256},
Header, SealedBlock, TransactionSigned, H64, U256,
ChainSpec, Header, SealedBlock, TransactionSigned, H64, U256,
};
use reth_provider::{BlockProvider, HeaderProvider, StateProvider};
use reth_rlp::Decodable;
@ -25,8 +25,6 @@ use std::{
use tokio::sync::oneshot;
use tokio_stream::wrappers::UnboundedReceiverStream;
use crate::Config;
mod error;
pub use error::{EngineApiError, EngineApiResult};
@ -80,7 +78,7 @@ pub enum EngineMessage {
pub struct EthConsensusEngine<Client> {
client: Arc<Client>,
/// Consensus configuration
config: Config,
chain_spec: ChainSpec,
rx: UnboundedReceiverStream<EngineMessage>,
// TODO: Placeholder for storing future blocks. Make cache bounded.
// Use [lru](https://crates.io/crates/lru) crate
@ -190,7 +188,7 @@ impl<Client: HeaderProvider + BlockProvider + StateProvider> ConsensusEngine
};
if let Some(parent_td) = self.client.header_td(&block.parent_hash)? {
if parent_td <= U256::from(self.config.merge_terminal_total_difficulty) {
if Some(parent_td) <= self.chain_spec.paris_status().terminal_total_difficulty() {
return Ok(PayloadStatus::from_status(PayloadStatusEnum::Invalid {
validation_error: EngineApiError::PayloadPreMerge.to_string(),
}))
@ -216,12 +214,11 @@ impl<Client: HeaderProvider + BlockProvider + StateProvider> ConsensusEngine
})
.collect::<Result<Vec<_>, EngineApiError>>()?;
let mut state_provider = SubState::new(State::new(&*self.client));
let config = (&self.config).into();
match executor::execute_and_verify_receipt(
&header,
&transactions,
&[],
&config,
&self.chain_spec,
&mut state_provider,
) {
Ok(_) => Ok(PayloadStatus::new(PayloadStatusEnum::Valid, header.hash())),
@ -272,8 +269,13 @@ impl<Client: HeaderProvider + BlockProvider + StateProvider> ConsensusEngine
terminal_block_number,
} = config;
let merge_terminal_td = self
.chain_spec
.paris_status()
.terminal_total_difficulty()
.ok_or(EngineApiError::UnknownMergeTerminalTotalDifficulty)?;
// Compare total difficulty values
let merge_terminal_td = U256::from(self.config.merge_terminal_total_difficulty);
if merge_terminal_td != terminal_total_difficulty {
return Err(EngineApiError::TerminalTD {
execution: merge_terminal_td,
@ -340,7 +342,7 @@ mod tests {
use super::*;
use bytes::{Bytes, BytesMut};
use reth_interfaces::test_utils::generators::random_header;
use reth_primitives::Block;
use reth_primitives::{Block, MAINNET};
use reth_rlp::DecodeError;
fn transform_block<F: FnOnce(Block) -> Block>(src: SealedBlock, f: F) -> SealedBlock {
@ -363,7 +365,7 @@ mod tests {
let (_tx, rx) = unbounded_channel();
let engine = EthConsensusEngine {
client: Arc::new(MockEthProvider::default()),
config: Config::default(),
chain_spec: MAINNET.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -452,7 +454,7 @@ mod tests {
let client = Arc::new(MockEthProvider::default());
let engine = EthConsensusEngine {
client: client.clone(),
config: Config::default(),
chain_spec: MAINNET.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -480,7 +482,7 @@ mod tests {
let (tx, rx) = unbounded_channel();
let engine = EthConsensusEngine {
client: Arc::new(MockEthProvider::default()),
config: Config::default(),
chain_spec: MAINNET.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -501,11 +503,11 @@ mod tests {
#[tokio::test]
async fn payload_pre_merge() {
let (tx, rx) = unbounded_channel();
let config = Config::default();
let chain_spec = MAINNET.clone();
let client = Arc::new(MockEthProvider::default());
let engine = EthConsensusEngine {
client: client.clone(),
config: config.clone(),
chain_spec: chain_spec.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -514,7 +516,8 @@ mod tests {
let (result_tx, result_rx) = oneshot::channel();
let parent = transform_block(random_block(100, None, None, Some(0)), |mut b| {
b.header.difficulty = U256::from(config.merge_terminal_total_difficulty);
b.header.difficulty =
chain_spec.paris_status().terminal_total_difficulty().unwrap();
b
});
let block = random_block(101, Some(parent.hash()), None, Some(0));
@ -535,11 +538,11 @@ mod tests {
#[tokio::test]
async fn invalid_payload_timestamp() {
let (tx, rx) = unbounded_channel();
let config = Config::default();
let chain_spec = MAINNET.clone();
let client = Arc::new(MockEthProvider::default());
let engine = EthConsensusEngine {
client: client.clone(),
config: config.clone(),
chain_spec: chain_spec.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -551,7 +554,8 @@ mod tests {
let parent_timestamp = block_timestamp + 10;
let parent = transform_block(random_block(100, None, None, Some(0)), |mut b| {
b.header.timestamp = parent_timestamp;
b.header.difficulty = U256::from(config.merge_terminal_total_difficulty + 1);
b.header.difficulty =
chain_spec.paris_status().terminal_total_difficulty().unwrap() + U256::from(1);
b
});
let block =
@ -583,6 +587,8 @@ mod tests {
// non exhaustive tests for engine_getPayload
// TODO: amend when block building is implemented
mod get_payload {
use reth_primitives::MAINNET;
use super::*;
#[tokio::test]
@ -590,7 +596,7 @@ mod tests {
let (tx, rx) = unbounded_channel();
let engine = EthConsensusEngine {
client: Arc::new(MockEthProvider::default()),
config: Config::default(),
chain_spec: MAINNET.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -609,15 +615,17 @@ mod tests {
// https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#specification-3
mod exchange_transition_configuration {
use reth_primitives::MAINNET;
use super::*;
#[tokio::test]
async fn terminal_td_mismatch() {
let (tx, rx) = unbounded_channel();
let config = Config::default();
let chain_spec = MAINNET.clone();
let engine = EthConsensusEngine {
client: Arc::new(MockEthProvider::default()),
config: config.clone(),
chain_spec: chain_spec.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -625,7 +633,11 @@ mod tests {
tokio::spawn(engine);
let transition_config = TransitionConfiguration {
terminal_total_difficulty: U256::from(config.merge_terminal_total_difficulty + 1),
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap() +
U256::from(1),
..Default::default()
};
@ -639,7 +651,7 @@ mod tests {
assert_matches!(
result_rx.await,
Ok(Err(EngineApiError::TerminalTD { execution, consensus }))
if execution == U256::from(config.merge_terminal_total_difficulty)
if execution == chain_spec.paris_status().terminal_total_difficulty().unwrap()
&& consensus == U256::from(transition_config.terminal_total_difficulty)
);
}
@ -648,10 +660,10 @@ mod tests {
async fn terminal_block_hash_mismatch() {
let (tx, rx) = unbounded_channel();
let client = Arc::new(MockEthProvider::default());
let config = Config::default();
let chain_spec = MAINNET.clone();
let engine = EthConsensusEngine {
client: client.clone(),
config: config.clone(),
chain_spec: chain_spec.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -663,7 +675,10 @@ mod tests {
let execution_terminal_block = random_block(terminal_block_number, None, None, None);
let transition_config = TransitionConfiguration {
terminal_total_difficulty: U256::from(config.merge_terminal_total_difficulty),
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap(),
terminal_block_hash: consensus_terminal_block.hash(),
terminal_block_number: terminal_block_number.into(),
};
@ -708,10 +723,10 @@ mod tests {
async fn configurations_match() {
let (tx, rx) = unbounded_channel();
let client = Arc::new(MockEthProvider::default());
let config = Config::default();
let chain_spec = MAINNET.clone();
let engine = EthConsensusEngine {
client: client.clone(),
config: config.clone(),
chain_spec: chain_spec.clone(),
local_store: Default::default(),
rx: UnboundedReceiverStream::new(rx),
};
@ -722,7 +737,10 @@ mod tests {
let terminal_block = random_block(terminal_block_number, None, None, None);
let transition_config = TransitionConfiguration {
terminal_total_difficulty: U256::from(config.merge_terminal_total_difficulty),
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap(),
terminal_block_hash: terminal_block.hash(),
terminal_block_number: terminal_block_number.into(),
};

View File

@ -9,13 +9,12 @@
//! # Features
//!
//! - `serde`: Enable serde support for configuration types.
pub mod config;
pub mod consensus;
pub mod constants;
pub mod verification;
/// Engine API module.
pub mod engine;
pub use config::Config;
pub use consensus::BeaconConsensus;
pub use reth_interfaces::consensus::Error;

View File

@ -1,9 +1,8 @@
//! ALl functions for verification of block
use crate::{config, Config};
use reth_interfaces::{consensus::Error, Result as RethResult};
use reth_primitives::{
BlockNumber, Header, SealedBlock, SealedHeader, Transaction, TransactionSignedEcRecovered,
TxEip1559, TxEip2930, TxLegacy, EMPTY_OMMER_ROOT, U256,
BlockNumber, ChainSpec, Hardfork, Header, SealedBlock, SealedHeader, Transaction,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxLegacy, EMPTY_OMMER_ROOT, U256,
};
use reth_provider::{AccountProvider, HeaderProvider};
use std::{
@ -11,10 +10,12 @@ use std::{
time::SystemTime,
};
use crate::constants;
/// Validate header standalone
pub fn validate_header_standalone(
header: &SealedHeader,
config: &config::Config,
chain_spec: &ChainSpec,
) -> Result<(), Error> {
// Gas used needs to be less then gas limit. Gas used is going to be check after execution.
if header.gas_used > header.gas_limit {
@ -38,13 +39,14 @@ pub fn validate_header_standalone(
}
// Check if base fee is set.
if header.number >= config.london_block && header.base_fee_per_gas.is_none() {
if chain_spec.fork_active(Hardfork::London, header.number) && header.base_fee_per_gas.is_none()
{
return Err(Error::BaseFeeMissing)
}
// EIP-3675: Upgrade consensus to Proof-of-Stake:
// https://eips.ethereum.org/EIPS/eip-3675#replacing-difficulty-with-0
if header.number >= config.paris_block {
if Some(header.number) >= chain_spec.paris_status().block_number() {
if header.difficulty != U256::ZERO {
return Err(Error::TheMergeDifficultyIsNotZero)
}
@ -69,21 +71,23 @@ pub fn validate_header_standalone(
/// The only parameter from the header that affects the transaction is `base_fee`.
pub fn validate_transaction_regarding_header(
transaction: &Transaction,
config: &Config,
chain_spec: &ChainSpec,
at_block_number: BlockNumber,
base_fee: Option<u64>,
) -> Result<(), Error> {
let chain_id = match transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
// EIP-155: Simple replay attack protection: https://eips.ethereum.org/EIPS/eip-155
if config.eip_155_block <= at_block_number && chain_id.is_some() {
if chain_spec.fork_active(Hardfork::SpuriousDragon, at_block_number) &&
chain_id.is_some()
{
return Err(Error::TransactionOldLegacyChainId)
}
*chain_id
}
Transaction::Eip2930(TxEip2930 { chain_id, .. }) => {
// EIP-2930: Optional access lists: https://eips.ethereum.org/EIPS/eip-2930 (New transaction type)
if config.berlin_block > at_block_number {
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number) {
return Err(Error::TransactionEip2930Disabled)
}
Some(*chain_id)
@ -95,7 +99,7 @@ pub fn validate_transaction_regarding_header(
..
}) => {
// EIP-1559: Fee market change for ETH 1.0 chain https://eips.ethereum.org/EIPS/eip-1559
if config.berlin_block > at_block_number {
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number) {
return Err(Error::TransactionEip1559Disabled)
}
@ -109,7 +113,7 @@ pub fn validate_transaction_regarding_header(
}
};
if let Some(chain_id) = chain_id {
if chain_id != config.chain_id {
if chain_id != chain_spec.chain().id() {
return Err(Error::TransactionChainId)
}
}
@ -133,14 +137,14 @@ pub fn validate_all_transaction_regarding_block_and_nonces<
transactions: impl Iterator<Item = &'a TransactionSignedEcRecovered>,
header: &Header,
provider: Provider,
config: &Config,
chain_spec: &ChainSpec,
) -> RethResult<()> {
let mut account_nonces = HashMap::new();
for transaction in transactions {
validate_transaction_regarding_header(
transaction,
config,
chain_spec,
header.number,
header.base_fee_per_gas,
)?;
@ -208,7 +212,7 @@ pub fn validate_block_standalone(block: &SealedBlock) -> Result<(), Error> {
/// 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 / config::EIP1559_ELASTICITY_MULTIPLIER;
let gas_target = gas_limit / constants::EIP1559_ELASTICITY_MULTIPLIER;
if gas_used == gas_target {
return base_fee
@ -219,14 +223,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 /
config::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR 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 /
config::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128;
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128;
base_fee.saturating_sub(base_fee_per_gas_delta as u64)
}
@ -236,7 +240,7 @@ pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u6
pub fn validate_header_regarding_parent(
parent: &SealedHeader,
child: &SealedHeader,
config: &config::Config,
chain_spec: &ChainSpec,
) -> Result<(), Error> {
// Parent number is consistent.
if parent.number + 1 != child.number {
@ -255,7 +259,7 @@ pub fn validate_header_regarding_parent(
}
// difficulty check is done by consensus.
if config.paris_block > child.number {
if chain_spec.paris_status().block_number() > Some(child.number) {
// TODO how this needs to be checked? As ice age did increment it by some formula
}
@ -263,8 +267,8 @@ pub fn validate_header_regarding_parent(
// By consensus, gas_limit is multiplied by elasticity (*2) on
// on exact block that hardfork happens.
if config.london_block == child.number {
parent_gas_limit = parent.gas_limit * config::EIP1559_ELASTICITY_MULTIPLIER;
if chain_spec.fork_block(Hardfork::London) == Some(child.number) {
parent_gas_limit = parent.gas_limit * constants::EIP1559_ELASTICITY_MULTIPLIER;
}
// Check gas limit, max diff between child/parent gas_limit should be max_diff=parent_gas/1024
@ -283,11 +287,11 @@ pub fn validate_header_regarding_parent(
}
// EIP-1559 check base fee
if child.number >= config.london_block {
if chain_spec.fork_active(Hardfork::London, child.number) {
let base_fee = child.base_fee_per_gas.ok_or(Error::BaseFeeMissing)?;
let expected_base_fee = if config.london_block == child.number {
config::EIP1559_INITIAL_BASE_FEE
let expected_base_fee = if chain_spec.fork_block(Hardfork::London) == Some(child.number) {
constants::EIP1559_INITIAL_BASE_FEE
} else {
// This BaseFeeMissing will not happen as previous blocks are checked to have them.
calculate_next_block_base_fee(
@ -335,12 +339,12 @@ pub fn validate_block_regarding_chain<PROV: HeaderProvider>(
pub fn full_validation<Provider: HeaderProvider + AccountProvider>(
block: &SealedBlock,
provider: Provider,
config: &Config,
chain_spec: &ChainSpec,
) -> RethResult<()> {
validate_header_standalone(&block.header, config)?;
validate_header_standalone(&block.header, chain_spec)?;
validate_block_standalone(block)?;
let parent = validate_block_regarding_chain(block, &provider)?;
validate_header_regarding_parent(&parent, &block.header, config)?;
validate_header_regarding_parent(&parent, &block.header, chain_spec)?;
// NOTE: depending on the need of the stages, recovery could be done in different place.
let transactions = block
@ -353,7 +357,7 @@ pub fn full_validation<Provider: HeaderProvider + AccountProvider>(
transactions.iter(),
&block.header,
provider,
config,
chain_spec,
)?;
Ok(())
}
@ -363,7 +367,7 @@ mod tests {
use reth_interfaces::Result;
use reth_primitives::{
hex_literal::hex, Account, Address, BlockHash, Bytes, Header, Signature, TransactionKind,
TransactionSigned,
TransactionSigned, MAINNET,
};
use super::*;
@ -495,19 +499,17 @@ mod tests {
fn sanity_check() {
let (block, parent) = mock_block();
let provider = Provider::new(Some(parent));
let config = Config::default();
assert_eq!(full_validation(&block, provider, &config), Ok(()), "Validation should pass");
assert_eq!(full_validation(&block, provider, &MAINNET), Ok(()), "Validation should pass");
}
#[test]
fn validate_known_block() {
let (block, _) = mock_block();
let provider = Provider::new_known();
let config = Config::default();
assert_eq!(
full_validation(&block, provider, &config),
full_validation(&block, provider, &MAINNET),
Err(Error::BlockKnown { hash: block.hash(), number: block.number }.into()),
"Should fail with error"
);
@ -519,14 +521,13 @@ mod tests {
let tx1 = mock_tx(0);
let tx2 = mock_tx(1);
let provider = Provider::new_known();
let config = Config::default();
let txs = vec![tx1, tx2];
validate_all_transaction_regarding_block_and_nonces(
txs.iter(),
&block.header,
provider,
&config,
&MAINNET,
)
.expect("To Pass");
}
@ -536,7 +537,6 @@ mod tests {
let (block, _) = mock_block();
let tx1 = mock_tx(1);
let provider = Provider::new_known();
let config = Config::default();
let txs = vec![tx1];
assert_eq!(
@ -544,7 +544,7 @@ mod tests {
txs.iter(),
&block.header,
provider,
&config,
&MAINNET,
),
Err(Error::TransactionNonceNotConsistent.into())
)
@ -556,7 +556,6 @@ mod tests {
let tx1 = mock_tx(0);
let tx2 = mock_tx(3);
let provider = Provider::new_known();
let config = Config::default();
let txs = vec![tx1, tx2];
assert_eq!(
@ -564,7 +563,7 @@ mod tests {
txs.iter(),
&block.header,
provider,
&config,
&MAINNET,
),
Err(Error::TransactionNonceNotConsistent.into())
);

View File

@ -1,6 +1,6 @@
//! Reth block execution/validation configuration and constants
use reth_primitives::{BlockNumber, U256};
use reth_primitives::{BlockNumber, ChainSpec, Hardfork};
/// Two ethereum worth of wei
pub const WEI_2ETH: u128 = 2000000000000000000u128;
@ -9,188 +9,83 @@ pub const WEI_3ETH: u128 = 3000000000000000000u128;
/// Five ethereum worth of wei
pub const WEI_5ETH: u128 = 5000000000000000000u128;
/// Configuration for executor
#[derive(Debug, Clone)]
pub struct Config {
/// Chain id.
pub chain_id: U256,
/// Spec upgrades.
pub spec_upgrades: SpecUpgrades,
}
impl Config {
/// Create new config for ethereum.
pub fn new_ethereum() -> Self {
Self { chain_id: U256::from(1), spec_upgrades: SpecUpgrades::new_ethereum() }
}
}
/// Spec with there ethereum codenames.
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct SpecUpgrades {
pub frontier: BlockNumber,
//pub frontier_thawing: BlockNumber,
pub homestead: BlockNumber,
pub dao_fork: BlockNumber,
pub tangerine_whistle: BlockNumber,
pub spurious_dragon: BlockNumber,
pub byzantium: BlockNumber,
//pub constantinople: BlockNumber,
pub petersburg: BlockNumber, //Overrider Constantinople
pub istanbul: BlockNumber,
//pub muir_glacier: BlockNumber,
pub berlin: BlockNumber,
pub london: BlockNumber,
//pub arrow_glacier: BlockNumber,
//pub gray_glacier: BlockNumber,
pub paris: BlockNumber, // Aka the merge
pub shanghai: BlockNumber,
}
impl SpecUpgrades {
/// After merge/peric block reward was removed from execution layer.
pub fn has_block_reward(&self, block_num: BlockNumber) -> bool {
block_num < self.paris
}
/// Ethereum mainnet spec
pub fn new_ethereum() -> Self {
Self {
frontier: 0,
//frontier_thawing: 200000,
homestead: 1150000,
dao_fork: 1920000,
tangerine_whistle: 2463000,
spurious_dragon: 2675000,
byzantium: 4370000,
//constantinople: 7280000,
petersburg: 7280000, //Overrider Constantinople
istanbul: 9069000,
//muir_glacier: 9200000,
berlin: 12244000,
london: 12965000,
//arrow_glacier: 13773000,
//gray_glacier: 15050000,
paris: 15537394, // TheMerge,
shanghai: u64::MAX,
}
}
/// New frontier enabled spec
pub fn new_frontier_activated() -> Self {
Self {
frontier: 0,
homestead: u64::MAX,
dao_fork: u64::MAX,
tangerine_whistle: u64::MAX,
spurious_dragon: u64::MAX,
byzantium: u64::MAX,
petersburg: u64::MAX,
istanbul: u64::MAX,
berlin: u64::MAX,
london: u64::MAX,
paris: u64::MAX,
shanghai: u64::MAX,
}
}
/// New homestead enabled spec
pub fn new_homestead_activated() -> Self {
Self { homestead: 0, ..Self::new_frontier_activated() }
}
/// New tangerine enabled spec
pub fn new_tangerine_whistle_activated() -> Self {
Self { tangerine_whistle: 0, ..Self::new_homestead_activated() }
}
/// New spurious_dragon enabled spec
pub fn new_spurious_dragon_activated() -> Self {
Self { spurious_dragon: 0, ..Self::new_tangerine_whistle_activated() }
}
/// New byzantium enabled spec
pub fn new_byzantium_activated() -> Self {
Self { byzantium: 0, ..Self::new_spurious_dragon_activated() }
}
/// New petersburg enabled spec
pub fn new_petersburg_activated() -> Self {
Self { petersburg: 0, ..Self::new_byzantium_activated() }
}
/// New istanbul enabled spec
pub fn new_istanbul_activated() -> Self {
Self { istanbul: 0, ..Self::new_petersburg_activated() }
}
/// New berlin enabled spec
pub fn new_berlin_activated() -> Self {
Self { berlin: 0, ..Self::new_istanbul_activated() }
}
/// New london enabled spec
pub fn new_london_activated() -> Self {
Self { london: 0, ..Self::new_berlin_activated() }
}
/// New paris enabled spec
pub fn new_paris_activated() -> Self {
Self { paris: 0, ..Self::new_london_activated() }
}
/// return revm_spec from spec configuration.
pub fn revm_spec(&self, for_block: BlockNumber) -> revm::SpecId {
match for_block {
b if b >= self.shanghai => revm::MERGE_EOF,
b if b >= self.paris => revm::MERGE,
b if b >= self.london => revm::LONDON,
b if b >= self.berlin => revm::BERLIN,
b if b >= self.istanbul => revm::ISTANBUL,
b if b >= self.petersburg => revm::PETERSBURG,
b if b >= self.byzantium => revm::BYZANTIUM,
b if b >= self.spurious_dragon => revm::SPURIOUS_DRAGON,
b if b >= self.tangerine_whistle => revm::TANGERINE,
b if b >= self.homestead => revm::HOMESTEAD,
b if b >= self.frontier => revm::FRONTIER,
_ => panic!("wrong configuration"),
}
/// return revm_spec from spec configuration.
pub fn revm_spec(chain_spec: &ChainSpec, for_block: BlockNumber) -> revm::SpecId {
match for_block {
b if chain_spec.fork_active(Hardfork::Shanghai, b) => revm::MERGE_EOF,
b if Some(b) >= chain_spec.paris_status().block_number() => revm::MERGE,
b if chain_spec.fork_active(Hardfork::London, b) => revm::LONDON,
b if chain_spec.fork_active(Hardfork::Berlin, b) => revm::BERLIN,
b if chain_spec.fork_active(Hardfork::Istanbul, b) => revm::ISTANBUL,
b if chain_spec.fork_active(Hardfork::Petersburg, b) => revm::PETERSBURG,
b if chain_spec.fork_active(Hardfork::Byzantium, b) => revm::BYZANTIUM,
b if chain_spec.fork_active(Hardfork::SpuriousDragon, b) => revm::SPURIOUS_DRAGON,
b if chain_spec.fork_active(Hardfork::Tangerine, b) => revm::TANGERINE,
b if chain_spec.fork_active(Hardfork::Homestead, b) => revm::HOMESTEAD,
b if chain_spec.fork_active(Hardfork::Frontier, b) => revm::FRONTIER,
_ => panic!("wrong configuration"),
}
}
#[cfg(test)]
mod tests {
use super::SpecUpgrades;
use crate::config::revm_spec;
use reth_primitives::{ChainSpecBuilder, MAINNET};
#[test]
fn test_to_revm_spec() {
assert_eq!(SpecUpgrades::new_paris_activated().revm_spec(1), revm::MERGE);
assert_eq!(SpecUpgrades::new_london_activated().revm_spec(1), revm::LONDON);
assert_eq!(SpecUpgrades::new_berlin_activated().revm_spec(1), revm::BERLIN);
assert_eq!(SpecUpgrades::new_istanbul_activated().revm_spec(1), revm::ISTANBUL);
assert_eq!(SpecUpgrades::new_petersburg_activated().revm_spec(1), revm::PETERSBURG);
assert_eq!(SpecUpgrades::new_byzantium_activated().revm_spec(1), revm::BYZANTIUM);
assert_eq!(
SpecUpgrades::new_spurious_dragon_activated().revm_spec(1),
revm_spec(&ChainSpecBuilder::mainnet().paris_activated().build(), 1),
revm::MERGE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().london_activated().build(), 1),
revm::LONDON
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().berlin_activated().build(), 1),
revm::BERLIN
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().istanbul_activated().build(), 1),
revm::ISTANBUL
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().petersburg_activated().build(), 1),
revm::PETERSBURG
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().byzantium_activated().build(), 1),
revm::BYZANTIUM
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().spurious_dragon_activated().build(), 1),
revm::SPURIOUS_DRAGON
);
assert_eq!(SpecUpgrades::new_tangerine_whistle_activated().revm_spec(1), revm::TANGERINE);
assert_eq!(SpecUpgrades::new_homestead_activated().revm_spec(1), revm::HOMESTEAD);
assert_eq!(SpecUpgrades::new_frontier_activated().revm_spec(1), revm::FRONTIER);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().tangerine_whistle_activated().build(), 1),
revm::TANGERINE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().homestead_activated().build(), 1),
revm::HOMESTEAD
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().frontier_activated().build(), 1),
revm::FRONTIER
);
}
#[test]
fn test_eth_spec() {
let spec = SpecUpgrades::new_ethereum();
assert_eq!(spec.revm_spec(15537394 + 10), revm::MERGE);
assert_eq!(spec.revm_spec(15537394 - 10), revm::LONDON);
assert_eq!(spec.revm_spec(12244000 + 10), revm::BERLIN);
assert_eq!(spec.revm_spec(12244000 - 10), revm::ISTANBUL);
assert_eq!(spec.revm_spec(7280000 + 10), revm::PETERSBURG);
assert_eq!(spec.revm_spec(7280000 - 10), revm::BYZANTIUM);
assert_eq!(spec.revm_spec(2675000 + 10), revm::SPURIOUS_DRAGON);
assert_eq!(spec.revm_spec(2675000 - 10), revm::TANGERINE);
assert_eq!(spec.revm_spec(1150000 + 10), revm::HOMESTEAD);
assert_eq!(spec.revm_spec(1150000 - 10), revm::FRONTIER);
assert_eq!(revm_spec(&MAINNET, 15537394 + 10), revm::MERGE);
assert_eq!(revm_spec(&MAINNET, 15537394 - 10), revm::LONDON);
assert_eq!(revm_spec(&MAINNET, 12244000 + 10), revm::BERLIN);
assert_eq!(revm_spec(&MAINNET, 12244000 - 10), revm::ISTANBUL);
assert_eq!(revm_spec(&MAINNET, 7280000 + 10), revm::PETERSBURG);
assert_eq!(revm_spec(&MAINNET, 7280000 - 10), revm::BYZANTIUM);
assert_eq!(revm_spec(&MAINNET, 2675000 + 10), revm::SPURIOUS_DRAGON);
assert_eq!(revm_spec(&MAINNET, 2675000 - 10), revm::TANGERINE);
assert_eq!(revm_spec(&MAINNET, 1150000 + 10), revm::HOMESTEAD);
assert_eq!(revm_spec(&MAINNET, 1150000 - 10), revm::FRONTIER);
}
}

View File

@ -1,14 +1,13 @@
use crate::{
config::{WEI_2ETH, WEI_3ETH, WEI_5ETH},
config::{revm_spec, WEI_2ETH, WEI_3ETH, WEI_5ETH},
revm_wrap::{self, to_reth_acc, SubState},
Config,
};
use hashbrown::hash_map::Entry;
use reth_db::{models::AccountBeforeTx, tables, transaction::DbTxMut, Error as DbError};
use reth_interfaces::executor::Error;
use reth_primitives::{
bloom::logs_bloom, Account, Address, Bloom, Header, Log, Receipt, TransactionSignedEcRecovered,
H160, H256, U256,
bloom::logs_bloom, Account, Address, Bloom, ChainSpec, Hardfork, Header, Log, Receipt,
TransactionSignedEcRecovered, H160, H256, U256,
};
use reth_provider::StateProvider;
use revm::{
@ -18,10 +17,7 @@ use revm::{
use std::collections::BTreeMap;
/// Main block executor
pub struct Executor {
/// Configuration, Spec and optional flags.
pub config: Config,
}
pub struct Executor {}
/// Contains old/new account changes
#[derive(Debug, Clone, Eq, PartialEq)]
@ -250,15 +246,15 @@ pub fn execute_and_verify_receipt<DB: StateProvider>(
header: &Header,
transactions: &[TransactionSignedEcRecovered],
ommers: &[Header],
config: &Config,
chain_spec: &ChainSpec,
db: &mut SubState<DB>,
) -> Result<ExecutionResult, Error> {
let transaction_change_set = execute(header, transactions, ommers, config, db)?;
let transaction_change_set = execute(header, transactions, ommers, chain_spec, db)?;
let receipts_iter =
transaction_change_set.changesets.iter().map(|changeset| &changeset.receipt);
if header.number >= config.spec_upgrades.byzantium {
if Some(header.number) >= chain_spec.fork_block(Hardfork::Byzantium) {
verify_receipt(header.receipts_root, header.logs_bloom, receipts_iter)?;
}
// TODO Before Byzantium, receipts contained state root that would mean that expensive operation
@ -300,15 +296,15 @@ pub fn execute<DB: StateProvider>(
header: &Header,
transactions: &[TransactionSignedEcRecovered],
ommers: &[Header],
config: &Config,
chain_spec: &ChainSpec,
db: &mut SubState<DB>,
) -> Result<ExecutionResult, Error> {
let mut evm = EVM::new();
evm.database(db);
let spec_id = config.spec_upgrades.revm_spec(header.number);
evm.env.cfg.chain_id = config.chain_id;
evm.env.cfg.spec_id = config.spec_upgrades.revm_spec(header.number);
let spec_id = revm_spec(chain_spec, header.number);
evm.env.cfg.chain_id = U256::from(chain_spec.chain().id());
evm.env.cfg.spec_id = spec_id;
evm.env.cfg.perf_all_precompiles_have_balance = false;
evm.env.cfg.perf_analyse_created_bytecodes = AnalysisKind::Raw;
@ -393,9 +389,9 @@ pub fn execute<DB: StateProvider>(
}
let db = evm.db.expect("Db is set at the start of the function");
let mut block_reward = block_reward_changeset(header, ommers, db, config)?;
let mut block_reward = block_reward_changeset(header, ommers, db, chain_spec)?;
if config.spec_upgrades.dao_fork == header.number {
if chain_spec.fork_block(Hardfork::Dao) == Some(header.number) {
let mut irregular_state_changeset = dao_fork_changeset(db)?;
irregular_state_changeset.extend(block_reward.take().unwrap_or_default().into_iter());
block_reward = Some(irregular_state_changeset);
@ -444,7 +440,7 @@ pub fn block_reward_changeset<DB: StateProvider>(
header: &Header,
ommers: &[Header],
db: &mut SubState<DB>,
config: &Config,
chain_spec: &ChainSpec,
) -> Result<Option<BTreeMap<H160, AccountInfoChangeSet>>, Error> {
// NOTE: Related to Ethereum reward change, for other network this is probably going to be moved
// to config.
@ -456,9 +452,9 @@ pub fn block_reward_changeset<DB: StateProvider>(
// blocks beneficiary by an additional 1/32 of the block reward and the beneficiary of the
// ommer gets rewarded depending on the blocknumber. Formally we define the function Ω:
match header.number {
n if n >= config.spec_upgrades.paris => None,
n if n >= config.spec_upgrades.petersburg => Some(WEI_2ETH),
n if n >= config.spec_upgrades.byzantium => Some(WEI_3ETH),
n if Some(n) >= chain_spec.paris_status().block_number() => None,
n if Some(n) >= chain_spec.fork_block(Hardfork::Petersburg) => Some(WEI_2ETH),
n if Some(n) >= chain_spec.fork_block(Hardfork::Byzantium) => Some(WEI_3ETH),
_ => Some(WEI_5ETH),
}
.map(|reward| -> Result<_, _> {
@ -535,15 +531,15 @@ mod tests {
use std::{collections::HashMap, sync::Arc};
use crate::{config::SpecUpgrades, revm_wrap::State};
use crate::revm_wrap::State;
use reth_db::{
database::Database,
mdbx::{test_utils, Env, EnvKind, WriteMap},
transaction::DbTx,
};
use reth_primitives::{
hex_literal::hex, keccak256, Account, Address, Bytes, SealedBlock, StorageKey, H160, H256,
U256,
hex_literal::hex, keccak256, Account, Address, Bytes, ChainSpecBuilder, SealedBlock,
StorageKey, H160, H256, MAINNET, U256,
};
use reth_provider::{AccountProvider, BlockHashProvider, StateProvider};
use reth_rlp::Decodable;
@ -648,9 +644,8 @@ mod tests {
HashMap::new(),
);
let mut config = Config::new_ethereum();
// make it berlin fork
config.spec_upgrades = SpecUpgrades::new_berlin_activated();
// spec at berlin fork
let chain_spec = ChainSpecBuilder::mainnet().berlin_activated().build();
let mut db = SubState::new(State::new(db));
let transactions: Vec<TransactionSignedEcRecovered> =
@ -658,7 +653,7 @@ mod tests {
// execute chain and verify receipts
let out =
execute_and_verify_receipt(&block.header, &transactions, &ommers, &config, &mut db)
execute_and_verify_receipt(&block.header, &transactions, &ommers, &chain_spec, &mut db)
.unwrap();
assert_eq!(out.changesets.len(), 1, "Should executed one transaction");
@ -779,14 +774,14 @@ mod tests {
beneficiary_balance += i;
}
let mut config = Config::new_ethereum();
config.spec_upgrades = SpecUpgrades::new_homestead_activated();
// hardcode it to first block to match our mock data.
config.spec_upgrades.dao_fork = 1;
let chain_spec = ChainSpecBuilder::from(&*MAINNET)
.homestead_activated()
.with_fork(Hardfork::Dao, 1)
.build();
let mut db = SubState::new(State::new(db));
// execute chain and verify receipts
let out = execute_and_verify_receipt(&header, &[], &[], &config, &mut db).unwrap();
let out = execute_and_verify_receipt(&header, &[], &[], &chain_spec, &mut db).unwrap();
assert_eq!(out.changesets.len(), 0, "No tx");
// Check if cache is set

View File

@ -8,9 +8,8 @@
//! Reth executor executes transaction in block of data.
pub mod config;
pub mod eth_dao_fork;
/// Executor
pub mod executor;
/// Wrapper around revm database and types
pub mod revm_wrap;
pub use config::{Config, SpecUpgrades};
pub mod eth_dao_fork;

View File

@ -402,7 +402,7 @@ mod tests {
use super::*;
use crate::tree::TreeRootEntry;
use enr::{EnrBuilder, EnrKey};
use reth_primitives::{Chain, Hardfork};
use reth_primitives::{Chain, Hardfork, MAINNET};
use reth_rlp::Encodable;
use secp256k1::rand::thread_rng;
use std::{future::poll_fn, net::Ipv4Addr};
@ -452,7 +452,7 @@ mod tests {
let mut builder = EnrBuilder::new("v4");
let mut buf = Vec::new();
let fork_id = Hardfork::Frontier.fork_id();
let fork_id = Hardfork::Frontier.fork_id(&MAINNET).unwrap();
fork_id.encode(&mut buf);
builder.ip4(Ipv4Addr::LOCALHOST).udp4(30303).tcp4(30303).add_value(b"eth", &buf);
let enr = builder.build(&secret_key).unwrap();

View File

@ -1,7 +1,7 @@
use crate::{EthVersion, StatusBuilder};
use reth_codecs::derive_arbitrary;
use reth_primitives::{Chain, ForkId, Hardfork, H256, MAINNET_GENESIS, U256};
use reth_primitives::{Chain, ForkId, Hardfork, H256, MAINNET, U256};
use reth_rlp::{RlpDecodable, RlpEncodable};
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display};
@ -100,9 +100,11 @@ impl Default for Status {
version: EthVersion::Eth67 as u8,
chain: Chain::Named(ethers_core::types::Chain::Mainnet),
total_difficulty: U256::from(17_179_869_184u64),
blockhash: MAINNET_GENESIS,
genesis: MAINNET_GENESIS,
forkid: Hardfork::Frontier.fork_id(),
blockhash: MAINNET.genesis_hash(),
genesis: MAINNET.genesis_hash(),
forkid: Hardfork::Frontier
.fork_id(&MAINNET)
.expect("The Frontier hardfork should always exist"),
}
}
}

View File

@ -8,7 +8,7 @@ use crate::{
NetworkHandle, NetworkManager,
};
use reth_discv4::{Discv4Config, Discv4ConfigBuilder, DEFAULT_DISCOVERY_PORT};
use reth_primitives::{Chain, ForkFilter, Hardfork, NodeRecord, PeerId, H256, MAINNET_GENESIS};
use reth_primitives::{ChainSpec, ForkFilter, NodeRecord, PeerId, MAINNET};
use reth_provider::{BlockProvider, HeaderProvider};
use reth_tasks::TaskExecutor;
use secp256k1::{SecretKey, SECP256K1};
@ -54,10 +54,8 @@ pub struct NetworkConfig<C> {
pub peers_config: PeersConfig,
/// How to configure the [SessionManager](crate::session::SessionManager).
pub sessions_config: SessionsConfig,
/// The id of the network
pub chain: Chain,
/// Genesis hash of the network
pub genesis_hash: H256,
/// The chain spec
pub chain_spec: ChainSpec,
/// The [`ForkFilter`] to use at launch for authenticating sessions.
///
/// See also <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2124.md#stale-software-examples>
@ -141,10 +139,8 @@ pub struct NetworkConfigBuilder<C> {
peers_config: Option<PeersConfig>,
/// How to configure the sessions manager
sessions_config: Option<SessionsConfig>,
/// The network's chain id
chain: Chain,
/// Network genesis hash
genesis_hash: H256,
/// The network's chain spec
chain_spec: ChainSpec,
/// The block importer type.
block_import: Box<dyn BlockImport>,
/// The default mode of the network.
@ -176,8 +172,7 @@ impl<C> NetworkConfigBuilder<C> {
listener_addr: None,
peers_config: None,
sessions_config: None,
chain: Chain::Named(reth_primitives::rpc::Chain::Mainnet),
genesis_hash: MAINNET_GENESIS,
chain_spec: MAINNET.clone(),
block_import: Box::<ProofOfStakeBlockImport>::default(),
network_mode: Default::default(),
executor: None,
@ -209,9 +204,9 @@ impl<C> NetworkConfigBuilder<C> {
self
}
/// Sets the chain ID.
pub fn chain_id<Id: Into<Chain>>(mut self, chain_id: Id) -> Self {
self.chain = chain_id.into();
/// Sets the chain spec.
pub fn chain_spec(mut self, chain_spec: ChainSpec) -> Self {
self.chain_spec = chain_spec;
self
}
@ -250,12 +245,6 @@ impl<C> NetworkConfigBuilder<C> {
self
}
/// Sets the genesis hash for the network.
pub fn genesis_hash(mut self, genesis_hash: H256) -> Self {
self.genesis_hash = genesis_hash;
self
}
/// Sets the [`BlockImport`] type to configure.
pub fn block_import<T: BlockImport + 'static>(mut self, block_import: T) -> Self {
self.block_import = Box::new(block_import);
@ -318,8 +307,7 @@ impl<C> NetworkConfigBuilder<C> {
listener_addr,
peers_config,
sessions_config,
chain,
genesis_hash,
chain_spec,
block_import,
network_mode,
executor,
@ -340,8 +328,7 @@ impl<C> NetworkConfigBuilder<C> {
// get the fork filter
let fork_filter = fork_filter.unwrap_or_else(|| {
let head = head.unwrap_or_default();
// TODO(mattsse): this should be chain agnostic: <https://github.com/paradigmxyz/reth/issues/485>
ForkFilter::new(head, genesis_hash, Hardfork::all_forks())
chain_spec.fork_filter(head)
});
// If default DNS config is used then we add the known dns network to bootstrap from
@ -349,7 +336,7 @@ impl<C> NetworkConfigBuilder<C> {
dns_discovery_config.as_mut().and_then(|c| c.bootstrap_dns_networks.as_mut())
{
if dns_networks.is_empty() {
if let Some(link) = chain.public_dns_network_protocol() {
if let Some(link) = chain_spec.chain().public_dns_network_protocol() {
dns_networks.insert(link.parse().expect("is valid DNS link entry"));
}
}
@ -367,8 +354,7 @@ impl<C> NetworkConfigBuilder<C> {
listener_addr,
peers_config: peers_config.unwrap_or_default(),
sessions_config: sessions_config.unwrap_or_default(),
chain,
genesis_hash,
chain_spec,
block_import,
network_mode,
executor,
@ -407,6 +393,7 @@ mod tests {
use super::*;
use rand::thread_rng;
use reth_dns_discovery::tree::LinkEntry;
use reth_primitives::Chain;
use reth_provider::test_utils::NoopProvider;
fn builder() -> NetworkConfigBuilder<NoopProvider> {

View File

@ -153,7 +153,7 @@ where
listener_addr,
peers_config,
sessions_config,
genesis_hash,
chain_spec,
block_import,
network_mode,
boot_nodes,
@ -196,11 +196,12 @@ where
fork_filter,
bandwidth_meter.clone(),
);
let state = NetworkState::new(
client,
discovery,
peers_manager,
genesis_hash,
chain_spec.genesis_hash(),
Arc::clone(&num_active_peers),
);

View File

@ -568,7 +568,7 @@ mod tests {
StatusBuilder, UnauthedEthStream, UnauthedP2PStream,
};
use reth_net_common::bandwidth_meter::BandwidthMeter;
use reth_primitives::{ForkFilter, Hardfork};
use reth_primitives::{ForkFilter, Hardfork, MAINNET};
use secp256k1::{SecretKey, SECP256K1};
use std::time::Duration;
use tokio::net::TcpListener;
@ -714,7 +714,9 @@ mod tests {
secret_key,
local_peer_id,
status: StatusBuilder::default().build(),
fork_filter: Hardfork::Frontier.fork_filter(),
fork_filter: Hardfork::Frontier
.fork_filter(&MAINNET)
.expect("The Frontier fork filter should exist on mainnet"),
bandwidth_meter: BandwidthMeter::default(),
}
}

View File

@ -17,7 +17,9 @@ reth-rlp = { path = "../common/rlp", features = [
reth-rlp-derive = { path = "../common/rlp-derive" }
reth-codecs = { version = "0.1.0", path = "../storage/codecs" }
revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a05fb262d87c78ee52d400e6c0f4708d4c527f32", features = ["serde"] }
revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a05fb262d87c78ee52d400e6c0f4708d4c527f32", features = [
"serde",
] }
# ethereum
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
@ -42,6 +44,7 @@ crc = "1"
# misc
bytes = "1.2"
serde = "1.0"
serde_json = "1.0"
serde_with = "2.1.0"
thiserror = "1"
sucds = "0.5.0"
@ -51,6 +54,7 @@ modular-bitfield = "0.11.2"
derive_more = "0.99"
url = "2.3"
impl-serde = "0.4.0"
once_cell = "1.17.0"
# proof related
triehash = "0.8"
@ -69,7 +73,10 @@ serde_json = "1.0"
hex-literal = "0.3"
test-fuzz = "3.0.4"
rand = "0.8"
revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a05fb262d87c78ee52d400e6c0f4708d4c527f32", features = ["serde", "arbitrary"] }
revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a05fb262d87c78ee52d400e6c0f4708d4c527f32", features = [
"serde",
"arbitrary",
] }
arbitrary = { version = "1.1.7", features = ["derive"] }
proptest = { version = "1.0" }
@ -82,7 +89,12 @@ criterion = "0.4.0"
[features]
default = []
arbitrary = ["revm-interpreter/arbitrary", "dep:arbitrary", "dep:proptest", "dep:proptest-derive"]
arbitrary = [
"revm-interpreter/arbitrary",
"dep:arbitrary",
"dep:proptest",
"dep:proptest-derive",
]
[[bench]]
name = "recover_ecdsa_crit"

View File

@ -0,0 +1,795 @@
{
"nonce": "0x0",
"timestamp": "0x5c51a607",
"extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xa00000",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"stateRoot": "0x5d6cded585e73c4e322c30c2f782a336316f17dd85a4863b9d838d2d4b8b3008",
"alloc": {
"0000000000000000000000000000000000000000": {
"balance": "0x1"
},
"0000000000000000000000000000000000000001": {
"balance": "0x1"
},
"0000000000000000000000000000000000000002": {
"balance": "0x1"
},
"0000000000000000000000000000000000000003": {
"balance": "0x1"
},
"0000000000000000000000000000000000000004": {
"balance": "0x1"
},
"0000000000000000000000000000000000000005": {
"balance": "0x1"
},
"0000000000000000000000000000000000000006": {
"balance": "0x1"
},
"0000000000000000000000000000000000000007": {
"balance": "0x1"
},
"0000000000000000000000000000000000000008": {
"balance": "0x1"
},
"0000000000000000000000000000000000000009": {
"balance": "0x1"
},
"000000000000000000000000000000000000000a": {
"balance": "0x1"
},
"000000000000000000000000000000000000000b": {
"balance": "0x1"
},
"000000000000000000000000000000000000000c": {
"balance": "0x1"
},
"000000000000000000000000000000000000000d": {
"balance": "0x1"
},
"000000000000000000000000000000000000000e": {
"balance": "0x1"
},
"000000000000000000000000000000000000000f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000010": {
"balance": "0x1"
},
"0000000000000000000000000000000000000011": {
"balance": "0x1"
},
"0000000000000000000000000000000000000012": {
"balance": "0x1"
},
"0000000000000000000000000000000000000013": {
"balance": "0x1"
},
"0000000000000000000000000000000000000014": {
"balance": "0x1"
},
"0000000000000000000000000000000000000015": {
"balance": "0x1"
},
"0000000000000000000000000000000000000016": {
"balance": "0x1"
},
"0000000000000000000000000000000000000017": {
"balance": "0x1"
},
"0000000000000000000000000000000000000018": {
"balance": "0x1"
},
"0000000000000000000000000000000000000019": {
"balance": "0x1"
},
"000000000000000000000000000000000000001a": {
"balance": "0x1"
},
"000000000000000000000000000000000000001b": {
"balance": "0x1"
},
"000000000000000000000000000000000000001c": {
"balance": "0x1"
},
"000000000000000000000000000000000000001d": {
"balance": "0x1"
},
"000000000000000000000000000000000000001e": {
"balance": "0x1"
},
"000000000000000000000000000000000000001f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000020": {
"balance": "0x1"
},
"0000000000000000000000000000000000000021": {
"balance": "0x1"
},
"0000000000000000000000000000000000000022": {
"balance": "0x1"
},
"0000000000000000000000000000000000000023": {
"balance": "0x1"
},
"0000000000000000000000000000000000000024": {
"balance": "0x1"
},
"0000000000000000000000000000000000000025": {
"balance": "0x1"
},
"0000000000000000000000000000000000000026": {
"balance": "0x1"
},
"0000000000000000000000000000000000000027": {
"balance": "0x1"
},
"0000000000000000000000000000000000000028": {
"balance": "0x1"
},
"0000000000000000000000000000000000000029": {
"balance": "0x1"
},
"000000000000000000000000000000000000002a": {
"balance": "0x1"
},
"000000000000000000000000000000000000002b": {
"balance": "0x1"
},
"000000000000000000000000000000000000002c": {
"balance": "0x1"
},
"000000000000000000000000000000000000002d": {
"balance": "0x1"
},
"000000000000000000000000000000000000002e": {
"balance": "0x1"
},
"000000000000000000000000000000000000002f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000030": {
"balance": "0x1"
},
"0000000000000000000000000000000000000031": {
"balance": "0x1"
},
"0000000000000000000000000000000000000032": {
"balance": "0x1"
},
"0000000000000000000000000000000000000033": {
"balance": "0x1"
},
"0000000000000000000000000000000000000034": {
"balance": "0x1"
},
"0000000000000000000000000000000000000035": {
"balance": "0x1"
},
"0000000000000000000000000000000000000036": {
"balance": "0x1"
},
"0000000000000000000000000000000000000037": {
"balance": "0x1"
},
"0000000000000000000000000000000000000038": {
"balance": "0x1"
},
"0000000000000000000000000000000000000039": {
"balance": "0x1"
},
"000000000000000000000000000000000000003a": {
"balance": "0x1"
},
"000000000000000000000000000000000000003b": {
"balance": "0x1"
},
"000000000000000000000000000000000000003c": {
"balance": "0x1"
},
"000000000000000000000000000000000000003d": {
"balance": "0x1"
},
"000000000000000000000000000000000000003e": {
"balance": "0x1"
},
"000000000000000000000000000000000000003f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000040": {
"balance": "0x1"
},
"0000000000000000000000000000000000000041": {
"balance": "0x1"
},
"0000000000000000000000000000000000000042": {
"balance": "0x1"
},
"0000000000000000000000000000000000000043": {
"balance": "0x1"
},
"0000000000000000000000000000000000000044": {
"balance": "0x1"
},
"0000000000000000000000000000000000000045": {
"balance": "0x1"
},
"0000000000000000000000000000000000000046": {
"balance": "0x1"
},
"0000000000000000000000000000000000000047": {
"balance": "0x1"
},
"0000000000000000000000000000000000000048": {
"balance": "0x1"
},
"0000000000000000000000000000000000000049": {
"balance": "0x1"
},
"000000000000000000000000000000000000004a": {
"balance": "0x1"
},
"000000000000000000000000000000000000004b": {
"balance": "0x1"
},
"000000000000000000000000000000000000004c": {
"balance": "0x1"
},
"000000000000000000000000000000000000004d": {
"balance": "0x1"
},
"000000000000000000000000000000000000004e": {
"balance": "0x1"
},
"000000000000000000000000000000000000004f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000050": {
"balance": "0x1"
},
"0000000000000000000000000000000000000051": {
"balance": "0x1"
},
"0000000000000000000000000000000000000052": {
"balance": "0x1"
},
"0000000000000000000000000000000000000053": {
"balance": "0x1"
},
"0000000000000000000000000000000000000054": {
"balance": "0x1"
},
"0000000000000000000000000000000000000055": {
"balance": "0x1"
},
"0000000000000000000000000000000000000056": {
"balance": "0x1"
},
"0000000000000000000000000000000000000057": {
"balance": "0x1"
},
"0000000000000000000000000000000000000058": {
"balance": "0x1"
},
"0000000000000000000000000000000000000059": {
"balance": "0x1"
},
"000000000000000000000000000000000000005a": {
"balance": "0x1"
},
"000000000000000000000000000000000000005b": {
"balance": "0x1"
},
"000000000000000000000000000000000000005c": {
"balance": "0x1"
},
"000000000000000000000000000000000000005d": {
"balance": "0x1"
},
"000000000000000000000000000000000000005e": {
"balance": "0x1"
},
"000000000000000000000000000000000000005f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000060": {
"balance": "0x1"
},
"0000000000000000000000000000000000000061": {
"balance": "0x1"
},
"0000000000000000000000000000000000000062": {
"balance": "0x1"
},
"0000000000000000000000000000000000000063": {
"balance": "0x1"
},
"0000000000000000000000000000000000000064": {
"balance": "0x1"
},
"0000000000000000000000000000000000000065": {
"balance": "0x1"
},
"0000000000000000000000000000000000000066": {
"balance": "0x1"
},
"0000000000000000000000000000000000000067": {
"balance": "0x1"
},
"0000000000000000000000000000000000000068": {
"balance": "0x1"
},
"0000000000000000000000000000000000000069": {
"balance": "0x1"
},
"000000000000000000000000000000000000006a": {
"balance": "0x1"
},
"000000000000000000000000000000000000006b": {
"balance": "0x1"
},
"000000000000000000000000000000000000006c": {
"balance": "0x1"
},
"000000000000000000000000000000000000006d": {
"balance": "0x1"
},
"000000000000000000000000000000000000006e": {
"balance": "0x1"
},
"000000000000000000000000000000000000006f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000070": {
"balance": "0x1"
},
"0000000000000000000000000000000000000071": {
"balance": "0x1"
},
"0000000000000000000000000000000000000072": {
"balance": "0x1"
},
"0000000000000000000000000000000000000073": {
"balance": "0x1"
},
"0000000000000000000000000000000000000074": {
"balance": "0x1"
},
"0000000000000000000000000000000000000075": {
"balance": "0x1"
},
"0000000000000000000000000000000000000076": {
"balance": "0x1"
},
"0000000000000000000000000000000000000077": {
"balance": "0x1"
},
"0000000000000000000000000000000000000078": {
"balance": "0x1"
},
"0000000000000000000000000000000000000079": {
"balance": "0x1"
},
"000000000000000000000000000000000000007a": {
"balance": "0x1"
},
"000000000000000000000000000000000000007b": {
"balance": "0x1"
},
"000000000000000000000000000000000000007c": {
"balance": "0x1"
},
"000000000000000000000000000000000000007d": {
"balance": "0x1"
},
"000000000000000000000000000000000000007e": {
"balance": "0x1"
},
"000000000000000000000000000000000000007f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000080": {
"balance": "0x1"
},
"0000000000000000000000000000000000000081": {
"balance": "0x1"
},
"0000000000000000000000000000000000000082": {
"balance": "0x1"
},
"0000000000000000000000000000000000000083": {
"balance": "0x1"
},
"0000000000000000000000000000000000000084": {
"balance": "0x1"
},
"0000000000000000000000000000000000000085": {
"balance": "0x1"
},
"0000000000000000000000000000000000000086": {
"balance": "0x1"
},
"0000000000000000000000000000000000000087": {
"balance": "0x1"
},
"0000000000000000000000000000000000000088": {
"balance": "0x1"
},
"0000000000000000000000000000000000000089": {
"balance": "0x1"
},
"000000000000000000000000000000000000008a": {
"balance": "0x1"
},
"000000000000000000000000000000000000008b": {
"balance": "0x1"
},
"000000000000000000000000000000000000008c": {
"balance": "0x1"
},
"000000000000000000000000000000000000008d": {
"balance": "0x1"
},
"000000000000000000000000000000000000008e": {
"balance": "0x1"
},
"000000000000000000000000000000000000008f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000090": {
"balance": "0x1"
},
"0000000000000000000000000000000000000091": {
"balance": "0x1"
},
"0000000000000000000000000000000000000092": {
"balance": "0x1"
},
"0000000000000000000000000000000000000093": {
"balance": "0x1"
},
"0000000000000000000000000000000000000094": {
"balance": "0x1"
},
"0000000000000000000000000000000000000095": {
"balance": "0x1"
},
"0000000000000000000000000000000000000096": {
"balance": "0x1"
},
"0000000000000000000000000000000000000097": {
"balance": "0x1"
},
"0000000000000000000000000000000000000098": {
"balance": "0x1"
},
"0000000000000000000000000000000000000099": {
"balance": "0x1"
},
"000000000000000000000000000000000000009a": {
"balance": "0x1"
},
"000000000000000000000000000000000000009b": {
"balance": "0x1"
},
"000000000000000000000000000000000000009c": {
"balance": "0x1"
},
"000000000000000000000000000000000000009d": {
"balance": "0x1"
},
"000000000000000000000000000000000000009e": {
"balance": "0x1"
},
"000000000000000000000000000000000000009f": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000aa": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ab": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ac": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ad": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ae": {
"balance": "0x1"
},
"00000000000000000000000000000000000000af": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ba": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000be": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bf": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ca": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ce": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cf": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000da": {
"balance": "0x1"
},
"00000000000000000000000000000000000000db": {
"balance": "0x1"
},
"00000000000000000000000000000000000000dc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000dd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000de": {
"balance": "0x1"
},
"00000000000000000000000000000000000000df": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ea": {
"balance": "0x1"
},
"00000000000000000000000000000000000000eb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ec": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ed": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ee": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ef": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fa": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fe": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ff": {
"balance": "0x1"
},
"4c2ae482593505f0163cdefc073e81c63cda4107": {
"balance": "0x152d02c7e14af6800000"
},
"a8e8f14732658e4b51e8711931053a8a69baf2b1": {
"balance": "0x152d02c7e14af6800000"
},
"d9a5179f091d85051d3c982785efd1455cec8699": {
"balance": "0x84595161401484a000000"
},
"e0a2bd4258d2768837baa26a28fe71dc079f84c7": {
"balance": "0x4a47e3c12448f4ad000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
{
"nonce": "0x00",
"timestamp": "0x6159af19",
"extraData": "0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521",
"gasLimit": "0x1c9c380",
"difficulty": "0x20000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"stateRoot": "0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494",
"alloc": {
"0xa2A6d93439144FFE4D27c9E088dCD8b783946263": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xBc11295936Aa79d594139de1B2e12629414F3BDB": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x7cF5b79bfe291A67AB02b393E456cCc4c266F753": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xaaec86394441f915bce3e6ab399977e9906f3b69": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xF47CaE1CF79ca6758Bfc787dbD21E6bdBe7112B8": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xd7eDDB78ED295B3C9629240E8924fb8D8874ddD8": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x8b7F0977Bb4f0fBE7076FA22bC24acA043583F5e": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xe2e2659028143784d557bcec6ff3a0721048880a": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xd9a5179f091d85051d3c982785efd1455cec8699": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0xbeef32ca5b9a198d27B4e02F4c70439fE60356Cf": {
"balance": "0xD3C21BCECCEDA1000000"
},
"0x0000006916a87b82333f4245046623b23794c65c": {
"balance": "0x84595161401484A000000"
},
"0xb21c33de1fab3fa15499c62b59fe0cc3250020d1": {
"balance": "0x52B7D2DCC80CD2E4000000"
},
"0x10F5d45854e038071485AC9e402308cF80D2d2fE": {
"balance": "0x52B7D2DCC80CD2E4000000"
},
"0xd7d76c58b3a519e9fA6Cc4D22dC017259BC49F1E": {
"balance": "0x52B7D2DCC80CD2E4000000"
},
"0x799D329e5f583419167cD722962485926E338F4a": {
"balance": "0xDE0B6B3A7640000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

View File

@ -0,0 +1,353 @@
use hex_literal::hex;
use once_cell::sync::Lazy;
use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{BlockNumber, Chain, ForkFilter, ForkHash, ForkId, Genesis, Hardfork, H256, U256};
/// The Etereum mainnet spec
pub static MAINNET: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
chain: Chain::mainnet(),
genesis: serde_json::from_str(include_str!("../res/genesis/mainnet.json"))
.expect("Can't deserialize Mainnet genesis json"),
genesis_hash: H256(hex!("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")),
hardforks: BTreeMap::from([
(Hardfork::Frontier, 0),
(Hardfork::Homestead, 1150000),
(Hardfork::Dao, 1920000),
(Hardfork::Tangerine, 2463000),
(Hardfork::SpuriousDragon, 2675000),
(Hardfork::Byzantium, 4370000),
(Hardfork::Constantinople, 7280000),
(Hardfork::Petersburg, 7280000),
(Hardfork::Istanbul, 9069000),
(Hardfork::Muirglacier, 9200000),
(Hardfork::Berlin, 12244000),
(Hardfork::London, 12965000),
(Hardfork::ArrowGlacier, 13773000),
(Hardfork::GrayGlacier, 15050000),
(Hardfork::Latest, 15050000),
]),
dao_fork_support: true,
paris_block: Some(15537394),
paris_ttd: Some(U256::from(58750000000000000000000_u128)),
});
/// The Goerli spec
pub static GOERLI: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
chain: Chain::goerli(),
genesis: serde_json::from_str(include_str!("../res/genesis/goerli.json"))
.expect("Can't deserialize Goerli genesis json"),
genesis_hash: H256(hex!("bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")),
hardforks: BTreeMap::from([
(Hardfork::Frontier, 0),
(Hardfork::Istanbul, 1561651),
(Hardfork::Berlin, 4460644),
(Hardfork::London, 5062605),
]),
dao_fork_support: true,
paris_block: Some(7382818),
paris_ttd: Some(U256::from(10790000)),
});
/// The Sepolia spec
pub static SEPOLIA: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
chain: Chain::sepolia(),
genesis: serde_json::from_str(include_str!("../res/genesis/sepolia.json"))
.expect("Can't deserialize Sepolia genesis json"),
genesis_hash: H256(hex!("25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")),
hardforks: BTreeMap::new(),
dao_fork_support: true,
paris_block: Some(1450408),
paris_ttd: Some(U256::from(17000000000000000_u64)),
});
/// The Ethereum chain spec
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ChainSpec {
chain: Chain,
genesis: Genesis,
genesis_hash: H256,
hardforks: BTreeMap<Hardfork, BlockNumber>,
dao_fork_support: bool,
paris_block: Option<u64>,
paris_ttd: Option<U256>,
}
impl ChainSpec {
/// Returns the chain id
pub fn chain(&self) -> Chain {
self.chain
}
/// Returns the chain genesis hash
pub fn genesis_hash(&self) -> H256 {
self.genesis_hash
}
/// Get the first block number of the hardfork.
pub fn fork_block(&self, fork: Hardfork) -> Option<BlockNumber> {
self.hardforks.get(&fork).copied()
}
/// Returns `true` if the given fork is active on the given block
pub fn fork_active(&self, fork: Hardfork, current_block: BlockNumber) -> bool {
self.fork_block(fork).map(|target| target <= current_block).unwrap_or_default()
}
/// Returns `true` if the DAO fork is supported
pub fn dao_fork_support(&self) -> bool {
self.dao_fork_support
}
/// Get the Paris status
pub fn paris_status(&self) -> ParisStatus {
match self.paris_ttd {
Some(terminal_total_difficulty) => {
ParisStatus::Supported { terminal_total_difficulty, block: self.paris_block }
}
None => ParisStatus::NotSupported,
}
}
/// Get an iterator of all harforks with theirs respectives block number
pub fn forks_iter(&self) -> impl Iterator<Item = (Hardfork, BlockNumber)> + '_ {
self.hardforks.iter().map(|(f, b)| (*f, *b))
}
/// Creates a [`ForkFilter`](crate::ForkFilter) for the given [BlockNumber].
pub fn fork_filter(&self, block: BlockNumber) -> ForkFilter {
let future_forks =
self.forks_iter().map(|(_, b)| b).filter(|b| *b > block).collect::<Vec<_>>();
ForkFilter::new(block, self.genesis_hash(), future_forks)
}
/// Compute the forkid for the given [BlockNumber]
pub fn fork_id(&self, block: BlockNumber) -> ForkId {
let mut curr_forkhash = ForkHash::from(self.genesis_hash());
let mut curr_block_number = 0;
for (_, b) in self.forks_iter() {
if block >= b {
if b != curr_block_number {
curr_forkhash += b;
curr_block_number = b;
}
} else {
return ForkId { hash: curr_forkhash, next: b }
}
}
ForkId { hash: curr_forkhash, next: 0 }
}
/// Returns a [ChainSpecBuilder] to help build custom specs
pub fn builder() -> ChainSpecBuilder {
ChainSpecBuilder::default()
}
}
/// A helper to build custom chain specs
#[derive(Debug, Default)]
pub struct ChainSpecBuilder {
chain: Option<Chain>,
genesis: Option<Genesis>,
genesis_hash: Option<H256>,
hardforks: BTreeMap<Hardfork, BlockNumber>,
dao_fork_support: bool,
paris_block: Option<u64>,
paris_ttd: Option<U256>,
}
impl ChainSpecBuilder {
/// Returns a [ChainSpec] builder initialized with Ethereum mainnet config
pub fn mainnet() -> Self {
Self {
chain: Some(MAINNET.chain),
genesis: Some(MAINNET.genesis.clone()),
genesis_hash: Some(MAINNET.genesis_hash),
hardforks: MAINNET.hardforks.clone(),
dao_fork_support: MAINNET.dao_fork_support,
paris_block: MAINNET.paris_block,
paris_ttd: MAINNET.paris_ttd,
}
}
/// Sets the chain id
pub fn chain(mut self, chain: Chain) -> Self {
self.chain = Some(chain);
self
}
/// Sets the genesis
pub fn genesis(mut self, genesis: Genesis) -> Self {
self.genesis = Some(genesis);
self
}
/// Insert the given fork at the given block number
pub fn with_fork(mut self, fork: Hardfork, block: BlockNumber) -> Self {
self.hardforks.insert(fork, block);
self
}
/// Enables Frontier
pub fn frontier_activated(mut self) -> Self {
self.hardforks.insert(Hardfork::Frontier, 0);
self
}
/// Enables Homestead
pub fn homestead_activated(mut self) -> Self {
self = self.frontier_activated();
self.hardforks.insert(Hardfork::Homestead, 0);
self
}
/// Enables Tangerine
pub fn tangerine_whistle_activated(mut self) -> Self {
self = self.homestead_activated();
self.hardforks.insert(Hardfork::Tangerine, 0);
self
}
/// Enables SpuriousDragon
pub fn spurious_dragon_activated(mut self) -> Self {
self = self.tangerine_whistle_activated();
self.hardforks.insert(Hardfork::SpuriousDragon, 0);
self
}
/// Enables Byzantium
pub fn byzantium_activated(mut self) -> Self {
self = self.spurious_dragon_activated();
self.hardforks.insert(Hardfork::Byzantium, 0);
self
}
/// Enables Petersburg
pub fn petersburg_activated(mut self) -> Self {
self = self.byzantium_activated();
self.hardforks.insert(Hardfork::Petersburg, 0);
self
}
/// Enables Istanbul
pub fn istanbul_activated(mut self) -> Self {
self = self.petersburg_activated();
self.hardforks.insert(Hardfork::Istanbul, 0);
self
}
/// Enables Berlin
pub fn berlin_activated(mut self) -> Self {
self = self.istanbul_activated();
self.hardforks.insert(Hardfork::Berlin, 0);
self
}
/// Enables London
pub fn london_activated(mut self) -> Self {
self = self.berlin_activated();
self.hardforks.insert(Hardfork::London, 0);
self
}
/// Sets the DAO fork as supported
pub fn dao_fork_supported(mut self) -> Self {
self.dao_fork_support = true;
self
}
/// Enables Paris
pub fn paris_activated(mut self) -> Self {
self = self.berlin_activated();
self.paris_block = Some(0);
self
}
/// Build a [ChainSpec]
pub fn build(self) -> ChainSpec {
ChainSpec {
chain: self.chain.expect("The chain is required"),
genesis: self.genesis.expect("The genesis is required"),
genesis_hash: self.genesis_hash.expect("The genesis hash is required"),
hardforks: self.hardforks,
dao_fork_support: self.dao_fork_support,
paris_block: self.paris_block,
paris_ttd: self.paris_ttd,
}
}
}
impl From<&ChainSpec> for ChainSpecBuilder {
fn from(value: &ChainSpec) -> Self {
Self {
chain: Some(value.chain),
genesis: Some(value.genesis.clone()),
genesis_hash: Some(value.genesis_hash),
hardforks: value.hardforks.clone(),
dao_fork_support: value.dao_fork_support,
paris_block: value.paris_block,
paris_ttd: value.paris_ttd,
}
}
}
/// Merge Status
#[derive(Debug)]
pub enum ParisStatus {
/// Paris is not supported
NotSupported,
/// Paris settings has been set in the chain spec
Supported {
/// The merge terminal total difficulty
terminal_total_difficulty: U256,
/// The Paris block number
block: Option<BlockNumber>,
},
}
impl ParisStatus {
/// Returns the Paris block number if it is known ahead of time.
///
/// This is only the case for chains that have already activated the merge.
pub fn block_number(&self) -> Option<BlockNumber> {
match &self {
ParisStatus::NotSupported => None,
ParisStatus::Supported { block, .. } => *block,
}
}
/// Returns the merge terminal total difficulty
pub fn terminal_total_difficulty(&self) -> Option<U256> {
match &self {
ParisStatus::NotSupported => None,
ParisStatus::Supported { terminal_total_difficulty, .. } => {
Some(*terminal_total_difficulty)
}
}
}
}
#[cfg(test)]
mod tests {
use crate::MAINNET;
#[test]
// this test checks that the forkid computation is accurate
fn test_forkid_from_hardfork() {
let frontier_forkid = MAINNET.fork_id(0);
assert_eq!([0xfc, 0x64, 0xec, 0x04], frontier_forkid.hash.0);
assert_eq!(1150000, frontier_forkid.next);
let berlin_forkid = MAINNET.fork_id(12244000);
assert_eq!([0x0e, 0xb4, 0x40, 0xf6], berlin_forkid.hash.0);
assert_eq!(12965000, berlin_forkid.next);
let latest_forkid = MAINNET.fork_id(15050000);
assert_eq!(0, latest_forkid.next);
}
}

View File

@ -0,0 +1,60 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::{
utils::serde_helpers::deserialize_stringified_u64, Address, Bytes, Header, H256, U256,
};
/// The genesis block specification.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Genesis {
/// The genesis header nonce.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub nonce: u64,
/// The genesis header timestamp.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub timestamp: u64,
/// The genesis header extra data.
pub extra_data: Bytes,
/// The genesis header gas limit.
#[serde(deserialize_with = "deserialize_stringified_u64")]
pub gas_limit: u64,
/// The genesis header difficulty.
pub difficulty: U256,
/// The genesis header mix hash.
pub mix_hash: H256,
/// The genesis header coinbase address.
pub coinbase: Address,
/// The genesis state root.
pub state_root: H256,
/// The initial state of accounts in the genesis block.
pub alloc: HashMap<Address, GenesisAccount>,
}
impl From<Genesis> for Header {
fn from(genesis: Genesis) -> Header {
Header {
gas_limit: genesis.gas_limit,
difficulty: genesis.difficulty,
nonce: genesis.nonce,
extra_data: genesis.extra_data,
state_root: genesis.state_root,
timestamp: genesis.timestamp,
mix_hash: genesis.mix_hash,
beneficiary: genesis.coinbase,
..Default::default()
}
}
}
/// An account in the state of the genesis block.
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct GenesisAccount {
/// The nonce of the account at genesis.
#[serde(skip_serializing_if = "Option::is_none")]
pub nonce: Option<u64>,
/// The balance of the account at genesis.
pub balance: U256,
}

View File

@ -1,9 +1,13 @@
use crate::{BlockNumber, ForkFilter, ForkHash, ForkId, MAINNET_GENESIS};
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use std::{fmt::Display, str::FromStr};
use crate::{BlockNumber, ChainSpec, ForkFilter, ForkHash, ForkId};
/// Ethereum mainnet hardforks
#[allow(missing_docs)]
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
#[derive(
Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub enum Hardfork {
Frontier,
Homestead,
@ -19,74 +23,12 @@ pub enum Hardfork {
London,
ArrowGlacier,
GrayGlacier,
Shanghai,
#[default]
Latest,
}
impl Hardfork {
/// Get the first block number of the hardfork.
pub fn fork_block(&self) -> u64 {
match *self {
Hardfork::Frontier => 0,
Hardfork::Homestead => 1150000,
Hardfork::Dao => 1920000,
Hardfork::Tangerine => 2463000,
Hardfork::SpuriousDragon => 2675000,
Hardfork::Byzantium => 4370000,
Hardfork::Constantinople | Hardfork::Petersburg => 7280000,
Hardfork::Istanbul => 9069000,
Hardfork::Muirglacier => 9200000,
Hardfork::Berlin => 12244000,
Hardfork::London => 12965000,
Hardfork::ArrowGlacier => 13773000,
Hardfork::GrayGlacier | Hardfork::Latest => 15050000,
}
}
/// Get the EIP-2124 fork id for a given hardfork
///
/// The [`ForkId`](ethereum_forkid::ForkId) includes a CRC32 checksum of the all fork block
/// numbers from genesis, and the next upcoming fork block number.
/// If the next fork block number is not yet known, it is set to 0.
pub fn fork_id(&self) -> ForkId {
match *self {
Hardfork::Frontier => {
ForkId { hash: ForkHash([0xfc, 0x64, 0xec, 0x04]), next: 1150000 }
}
Hardfork::Homestead => {
ForkId { hash: ForkHash([0x97, 0xc2, 0xc3, 0x4c]), next: 1920000 }
}
Hardfork::Dao => ForkId { hash: ForkHash([0x91, 0xd1, 0xf9, 0x48]), next: 2463000 },
Hardfork::Tangerine => {
ForkId { hash: ForkHash([0x7a, 0x64, 0xda, 0x13]), next: 2675000 }
}
Hardfork::SpuriousDragon => {
ForkId { hash: ForkHash([0x3e, 0xdd, 0x5b, 0x10]), next: 4370000 }
}
Hardfork::Byzantium => {
ForkId { hash: ForkHash([0xa0, 0x0b, 0xc3, 0x24]), next: 7280000 }
}
Hardfork::Constantinople | Hardfork::Petersburg => {
ForkId { hash: ForkHash([0x66, 0x8d, 0xb0, 0xaf]), next: 9069000 }
}
Hardfork::Istanbul => {
ForkId { hash: ForkHash([0x87, 0x9d, 0x6e, 0x30]), next: 9200000 }
}
Hardfork::Muirglacier => {
ForkId { hash: ForkHash([0xe0, 0x29, 0xe9, 0x91]), next: 12244000 }
}
Hardfork::Berlin => ForkId { hash: ForkHash([0x0e, 0xb4, 0x40, 0xf6]), next: 12965000 },
Hardfork::London => ForkId { hash: ForkHash([0xb7, 0x15, 0x07, 0x7d]), next: 13773000 },
Hardfork::ArrowGlacier => {
ForkId { hash: ForkHash([0x20, 0xc3, 0x27, 0xfc]), next: 15050000 }
}
Hardfork::Latest | Hardfork::GrayGlacier => {
// update `next` when another fork block num is known
ForkId { hash: ForkHash([0xf0, 0xaf, 0xd0, 0xe3]), next: 0 }
}
}
}
/// This returns all known hardforks in order.
pub fn all_forks() -> Vec<Self> {
vec![
@ -106,26 +48,43 @@ impl Hardfork {
]
}
/// This returns all known hardfork block numbers as a vector.
pub fn all_fork_blocks() -> Vec<BlockNumber> {
Hardfork::all_forks().iter().map(|f| f.fork_block()).collect()
/// Compute the forkid for the given [ChainSpec]
pub fn fork_id(&self, chain_spec: &ChainSpec) -> Option<ForkId> {
if let Some(fork_block) = chain_spec.fork_block(*self) {
let mut curr_forkhash = ForkHash::from(chain_spec.genesis_hash());
let mut curr_block_number = 0;
for (_, b) in chain_spec.forks_iter() {
if fork_block >= b {
if b != curr_block_number {
curr_forkhash += b;
curr_block_number = b;
}
} else {
return Some(ForkId { hash: curr_forkhash, next: b })
}
}
Some(ForkId { hash: curr_forkhash, next: 0 })
} else {
None
}
}
/// Creates a [`ForkFilter`](crate::ForkFilter) for the given hardfork.
///
/// **CAUTION**: This assumes the current hardfork's block number is the current head and uses
/// all known future hardforks to initialize the filter.
pub fn fork_filter(&self) -> ForkFilter {
let all_forks = Hardfork::all_forks();
let future_forks: Vec<BlockNumber> = all_forks
.iter()
.filter(|f| f.fork_block() > self.fork_block())
.map(|f| f.fork_block())
.collect();
pub fn fork_filter(&self, chain_spec: &ChainSpec) -> Option<ForkFilter> {
if let Some(fork_block) = chain_spec.fork_block(*self) {
let future_forks: Vec<BlockNumber> =
chain_spec.forks_iter().filter(|(_, b)| b > &fork_block).map(|(_, b)| b).collect();
// this data structure is not chain-agnostic, so we can pass in the constant mainnet
// genesis
ForkFilter::new(self.fork_block(), MAINNET_GENESIS, future_forks)
// this data structure is not chain-agnostic, so we can pass in the constant mainnet
// genesis
Some(ForkFilter::new(fork_block, chain_spec.genesis_hash(), future_forks))
} else {
None
}
}
}
@ -156,72 +115,8 @@ impl FromStr for Hardfork {
}
}
impl From<BlockNumber> for Hardfork {
fn from(num: BlockNumber) -> Hardfork {
match num {
_i if num < 1_150_000 => Hardfork::Frontier,
_i if num < 1_920_000 => Hardfork::Dao,
_i if num < 2_463_000 => Hardfork::Homestead,
_i if num < 2_675_000 => Hardfork::Tangerine,
_i if num < 4_370_000 => Hardfork::SpuriousDragon,
_i if num < 7_280_000 => Hardfork::Byzantium,
_i if num < 9_069_000 => Hardfork::Constantinople,
_i if num < 9_200_000 => Hardfork::Istanbul,
_i if num < 12_244_000 => Hardfork::Muirglacier,
_i if num < 12_965_000 => Hardfork::Berlin,
_i if num < 13_773_000 => Hardfork::London,
_i if num < 15_050_000 => Hardfork::ArrowGlacier,
_ => Hardfork::Latest,
}
}
}
impl From<Hardfork> for BlockNumber {
fn from(value: Hardfork) -> Self {
value.fork_block()
}
}
#[cfg(test)]
mod tests {
use crate::{forkid::ForkHash, hardfork::Hardfork};
use crc::crc32;
#[test]
fn test_hardfork_blocks() {
let hf: Hardfork = 12_965_000u64.into();
assert_eq!(hf, Hardfork::London);
let hf: Hardfork = 4370000u64.into();
assert_eq!(hf, Hardfork::Byzantium);
let hf: Hardfork = 12244000u64.into();
assert_eq!(hf, Hardfork::Berlin);
}
#[test]
// this test checks that the fork hash assigned to forks accurately map to the fork_id method
fn test_forkhash_from_fork_blocks() {
// set the genesis hash
let genesis =
hex::decode("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
// set the frontier forkhash
let mut curr_forkhash = ForkHash(crc32::checksum_ieee(&genesis[..]).to_be_bytes());
// now we go through enum members
let frontier_forkid = Hardfork::Frontier.fork_id();
assert_eq!(curr_forkhash, frontier_forkid.hash);
// list of the above hardforks
let hardforks = Hardfork::all_forks();
// check that the curr_forkhash we compute matches the output of each fork_id returned
for hardfork in hardforks {
curr_forkhash += hardfork.fork_block();
assert_eq!(curr_forkhash, hardfork.fork_id().hash);
}
impl Display for Hardfork {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}

View File

@ -14,9 +14,11 @@ mod bits;
mod block;
pub mod bloom;
mod chain;
mod chain_spec;
mod constants;
mod error;
mod forkid;
mod genesis;
mod hardfork;
mod header;
mod hex_bytes;
@ -37,8 +39,10 @@ pub use bits::H512;
pub use block::{Block, BlockHashOrNumber, SealedBlock};
pub use bloom::Bloom;
pub use chain::Chain;
pub use chain_spec::{ChainSpec, ChainSpecBuilder, ParisStatus, GOERLI, MAINNET, SEPOLIA};
pub use constants::{EMPTY_OMMER_ROOT, KECCAK_EMPTY, MAINNET_GENESIS};
pub use forkid::{ForkFilter, ForkHash, ForkId, ForkTransition, ValidationError};
pub use genesis::{Genesis, GenesisAccount};
pub use hardfork::Hardfork;
pub use header::{Header, HeadersDirection, SealedHeader};
pub use hex_bytes::Bytes;

View File

@ -10,12 +10,12 @@ use reth_db::{
transaction::{DbTx, DbTxMut},
};
use reth_executor::{
config::SpecUpgrades,
executor::AccountChangeSet,
revm_wrap::{State, SubState},
Config,
};
use reth_primitives::{Address, Header, StorageEntry, TransactionSignedEcRecovered, H256, U256};
use reth_primitives::{
Address, ChainSpec, Header, StorageEntry, TransactionSignedEcRecovered, H256, MAINNET, U256,
};
use reth_provider::LatestStateProviderRef;
use std::fmt::Debug;
use tracing::*;
@ -52,24 +52,21 @@ const EXECUTION: StageId = StageId("Execution");
#[derive(Debug)]
pub struct ExecutionStage {
/// Executor configuration.
pub config: Config,
pub chain_spec: ChainSpec,
/// Commit threshold
pub commit_threshold: u64,
}
impl Default for ExecutionStage {
fn default() -> Self {
Self {
config: Config { chain_id: U256::from(1), spec_upgrades: SpecUpgrades::new_ethereum() },
commit_threshold: 1000,
}
Self { chain_spec: MAINNET.clone(), commit_threshold: 1000 }
}
}
impl ExecutionStage {
/// Create new execution stage with specified config.
pub fn new(config: Config, commit_threshold: u64) -> Self {
Self { config, commit_threshold }
pub fn new(chain_spec: ChainSpec, commit_threshold: u64) -> Self {
Self { chain_spec, commit_threshold }
}
}
@ -193,7 +190,7 @@ impl<DB: Database> Stage<DB> for ExecutionStage {
header,
&recovered_transactions,
ommers,
&self.config,
&self.chain_spec,
&mut state_provider,
)
})
@ -381,7 +378,9 @@ mod tests {
use super::*;
use reth_db::mdbx::{test_utils::create_test_db, EnvKind, WriteMap};
use reth_primitives::{hex_literal::hex, keccak256, Account, SealedBlock, H160, U256};
use reth_primitives::{
hex_literal::hex, keccak256, Account, ChainSpecBuilder, SealedBlock, H160, U256,
};
use reth_provider::insert_canonical_block;
use reth_rlp::Decodable;
@ -427,8 +426,10 @@ mod tests {
tx.commit().unwrap();
// execute
let mut execution_stage = ExecutionStage::default();
execution_stage.config.spec_upgrades = SpecUpgrades::new_berlin_activated();
let mut execution_stage = ExecutionStage {
chain_spec: ChainSpecBuilder::mainnet().berlin_activated().build(),
..Default::default()
};
let output = execution_stage.execute(&mut tx, input).await.unwrap();
tx.commit().unwrap();
assert_eq!(output, ExecOutput { stage_progress: 1, done: true });
@ -513,8 +514,10 @@ mod tests {
// execute
let mut execution_stage = ExecutionStage::default();
execution_stage.config.spec_upgrades = SpecUpgrades::new_berlin_activated();
let mut execution_stage = ExecutionStage {
chain_spec: ChainSpecBuilder::mainnet().berlin_activated().build(),
..Default::default()
};
let _ = execution_stage.execute(&mut tx, input).await.unwrap();
tx.commit().unwrap();