mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor: unify all chains confs (#747)
Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4368,6 +4368,7 @@ dependencies = [
|
||||
"hex-literal",
|
||||
"impl-serde",
|
||||
"modular-bitfield",
|
||||
"once_cell",
|
||||
"parity-scale-codec",
|
||||
"plain_hasher",
|
||||
"proptest",
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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,
|
||||
});
|
||||
|
||||
|
||||
@ -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?;
|
||||
|
||||
|
||||
@ -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?;
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)?
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
8
crates/consensus/src/constants.rs
Normal file
8
crates/consensus/src/constants.rs
Normal 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;
|
||||
@ -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),
|
||||
|
||||
@ -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(),
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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())
|
||||
);
|
||||
|
||||
@ -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 {
|
||||
pub fn revm_spec(chain_spec: &ChainSpec, 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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>(
|
||||
// block’s 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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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),
|
||||
);
|
||||
|
||||
|
||||
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
795
crates/primitives/res/genesis/goerli.json
Normal file
795
crates/primitives/res/genesis/goerli.json
Normal 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"
|
||||
}
|
||||
26694
crates/primitives/res/genesis/mainnet.json
Normal file
26694
crates/primitives/res/genesis/mainnet.json
Normal file
File diff suppressed because it is too large
Load Diff
60
crates/primitives/res/genesis/sepolia.json
Normal file
60
crates/primitives/res/genesis/sepolia.json
Normal 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"
|
||||
}
|
||||
353
crates/primitives/src/chain_spec.rs
Normal file
353
crates/primitives/src/chain_spec.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
60
crates/primitives/src/genesis.rs
Normal file
60
crates/primitives/src/genesis.rs
Normal 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,
|
||||
}
|
||||
@ -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)
|
||||
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:?}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user