From 6ef3e12fac14a422c6a05d771126e47de8efee1c Mon Sep 17 00:00:00 2001 From: Waylon Jepsen <57912727+0xJepsen@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:58:11 -0600 Subject: [PATCH] Put ChainsSpecs in Arc<> (#3075) Co-authored-by: Georgios Konstantopoulos --- bin/reth/src/args/utils.rs | 13 +- bin/reth/src/stage/dump/execution.rs | 8 +- bin/reth/src/stage/dump/merkle.rs | 4 +- crates/net/network/src/config.rs | 7 +- crates/primitives/src/chain/spec.rs | 219 +++++++++++--------- crates/rpc/rpc-builder/tests/it/utils.rs | 2 +- crates/rpc/rpc-engine-api/src/engine_api.rs | 2 +- crates/staged-sync/src/utils/init.rs | 10 +- crates/storage/provider/src/transaction.rs | 4 +- 9 files changed, 141 insertions(+), 128 deletions(-) diff --git a/bin/reth/src/args/utils.rs b/bin/reth/src/args/utils.rs index 3978ebe923..56e02780d7 100644 --- a/bin/reth/src/args/utils.rs +++ b/bin/reth/src/args/utils.rs @@ -19,7 +19,7 @@ pub fn parse_duration_from_secs(arg: &str) -> eyre::Result eyre::Result, eyre::Error> { - Ok(Arc::new(match s { + Ok(match s { "mainnet" => MAINNET.clone(), "goerli" => GOERLI.clone(), "sepolia" => SEPOLIA.clone(), @@ -27,22 +27,25 @@ pub fn chain_spec_value_parser(s: &str) -> eyre::Result, eyre::Er let raw = std::fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned()))?; serde_json::from_str(&raw)? } - })) + }) } /// Clap value parser for [ChainSpec]s that takes either a built-in genesis format or the path /// to a custom one. pub fn genesis_value_parser(s: &str) -> eyre::Result, eyre::Error> { - Ok(Arc::new(match s { + Ok(match s { "mainnet" => MAINNET.clone(), "goerli" => GOERLI.clone(), "sepolia" => SEPOLIA.clone(), _ => { let raw = std::fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned()))?; let genesis: AllGenesisFormats = serde_json::from_str(&raw)?; - genesis.into() + match genesis { + AllGenesisFormats::Reth(chain_spec) => Arc::new(chain_spec), + _ => return Err(eyre::eyre!("Unexpected genesis format")), + } } - })) + }) } /// Parse [BlockHashOrNumber] diff --git a/bin/reth/src/stage/dump/execution.rs b/bin/reth/src/stage/dump/execution.rs index 832677331b..c4c313541e 100644 --- a/bin/reth/src/stage/dump/execution.rs +++ b/bin/reth/src/stage/dump/execution.rs @@ -7,7 +7,7 @@ use reth_db::{ use reth_primitives::{stage::StageCheckpoint, MAINNET}; use reth_provider::Transaction; use reth_stages::{stages::ExecutionStage, Stage, UnwindInput}; -use std::{ops::DerefMut, path::PathBuf, sync::Arc}; +use std::{ops::DerefMut, path::PathBuf}; use tracing::info; pub(crate) async fn dump_execution_stage( @@ -95,8 +95,7 @@ async fn unwind_and_copy( ) -> eyre::Result<()> { let mut unwind_tx = Transaction::new(db_tool.db)?; - let mut exec_stage = - ExecutionStage::new_with_factory(reth_revm::Factory::new(Arc::new(MAINNET.clone()))); + let mut exec_stage = ExecutionStage::new_with_factory(reth_revm::Factory::new(MAINNET.clone())); exec_stage .unwind( @@ -129,8 +128,7 @@ async fn dry_run( info!(target: "reth::cli", "Executing stage. [dry-run]"); let mut tx = Transaction::new(&output_db)?; - let mut exec_stage = - ExecutionStage::new_with_factory(reth_revm::Factory::new(Arc::new(MAINNET.clone()))); + let mut exec_stage = ExecutionStage::new_with_factory(reth_revm::Factory::new(MAINNET.clone())); exec_stage .execute( diff --git a/bin/reth/src/stage/dump/merkle.rs b/bin/reth/src/stage/dump/merkle.rs index a1f0d599a6..385afd3a2a 100644 --- a/bin/reth/src/stage/dump/merkle.rs +++ b/bin/reth/src/stage/dump/merkle.rs @@ -11,7 +11,7 @@ use reth_stages::{ }, Stage, UnwindInput, }; -use std::{ops::DerefMut, path::PathBuf, sync::Arc}; +use std::{ops::DerefMut, path::PathBuf}; use tracing::info; pub(crate) async fn dump_merkle_stage( @@ -65,7 +65,7 @@ async fn unwind_and_copy( // Bring Plainstate to TO (hashing stage execution requires it) let mut exec_stage = ExecutionStage::new( - reth_revm::Factory::new(Arc::new(MAINNET.clone())), + reth_revm::Factory::new(MAINNET.clone()), ExecutionStageThresholds { max_blocks: Some(u64::MAX), max_changes: None }, ); diff --git a/crates/net/network/src/config.rs b/crates/net/network/src/config.rs index d563a2dc0c..9cd2dd5840 100644 --- a/crates/net/network/src/config.rs +++ b/crates/net/network/src/config.rs @@ -160,7 +160,7 @@ impl NetworkConfigBuilder { listener_addr: None, peers_config: None, sessions_config: None, - chain_spec: Arc::new(MAINNET.clone()), + chain_spec: MAINNET.clone(), network_mode: Default::default(), executor: None, hello_message: None, @@ -456,11 +456,10 @@ mod tests { #[test] fn test_network_fork_filter_default() { - let mut chain_spec = MAINNET.clone(); + let mut chain_spec = Arc::clone(&MAINNET); // remove any `next` fields we would have by removing all hardforks - chain_spec.hardforks = BTreeMap::new(); - let chain_spec = Arc::new(chain_spec); + Arc::make_mut(&mut chain_spec).hardforks = BTreeMap::new(); // check that the forkid is initialized with the genesis and no other forks let genesis_fork_hash = ForkHash::from(chain_spec.genesis_hash()); diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index 1c264990dd..92e16220c5 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -10,112 +10,124 @@ use ethers_core::utils::Genesis as EthersGenesis; use hex_literal::hex; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use std::collections::{BTreeMap, HashMap}; +use std::{ + collections::{BTreeMap, HashMap}, + sync::Arc, +}; /// The Ethereum mainnet spec -pub static MAINNET: Lazy = 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: Some(H256(hex!( - "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" - ))), - // - paris_block_and_final_difficulty: Some(( - 15537394, - U256::from(58_750_003_716_598_352_816_469u128), - )), - fork_timestamps: ForkTimestamps::default().shanghai(1681338455), - hardforks: BTreeMap::from([ - (Hardfork::Frontier, ForkCondition::Block(0)), - (Hardfork::Homestead, ForkCondition::Block(1150000)), - (Hardfork::Dao, ForkCondition::Block(1920000)), - (Hardfork::Tangerine, ForkCondition::Block(2463000)), - (Hardfork::SpuriousDragon, ForkCondition::Block(2675000)), - (Hardfork::Byzantium, ForkCondition::Block(4370000)), - (Hardfork::Constantinople, ForkCondition::Block(7280000)), - (Hardfork::Petersburg, ForkCondition::Block(7280000)), - (Hardfork::Istanbul, ForkCondition::Block(9069000)), - (Hardfork::MuirGlacier, ForkCondition::Block(9200000)), - (Hardfork::Berlin, ForkCondition::Block(12244000)), - (Hardfork::London, ForkCondition::Block(12965000)), - (Hardfork::ArrowGlacier, ForkCondition::Block(13773000)), - (Hardfork::GrayGlacier, ForkCondition::Block(15050000)), - ( - Hardfork::Paris, - ForkCondition::TTD { - fork_block: None, - total_difficulty: U256::from(58_750_000_000_000_000_000_000_u128), - }, - ), - (Hardfork::Shanghai, ForkCondition::Timestamp(1681338455)), - ]), +pub static MAINNET: Lazy> = 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: Some(H256(hex!( + "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" + ))), + // + paris_block_and_final_difficulty: Some(( + 15537394, + U256::from(58_750_003_716_598_352_816_469u128), + )), + fork_timestamps: ForkTimestamps::default().shanghai(1681338455), + hardforks: BTreeMap::from([ + (Hardfork::Frontier, ForkCondition::Block(0)), + (Hardfork::Homestead, ForkCondition::Block(1150000)), + (Hardfork::Dao, ForkCondition::Block(1920000)), + (Hardfork::Tangerine, ForkCondition::Block(2463000)), + (Hardfork::SpuriousDragon, ForkCondition::Block(2675000)), + (Hardfork::Byzantium, ForkCondition::Block(4370000)), + (Hardfork::Constantinople, ForkCondition::Block(7280000)), + (Hardfork::Petersburg, ForkCondition::Block(7280000)), + (Hardfork::Istanbul, ForkCondition::Block(9069000)), + (Hardfork::MuirGlacier, ForkCondition::Block(9200000)), + (Hardfork::Berlin, ForkCondition::Block(12244000)), + (Hardfork::London, ForkCondition::Block(12965000)), + (Hardfork::ArrowGlacier, ForkCondition::Block(13773000)), + (Hardfork::GrayGlacier, ForkCondition::Block(15050000)), + ( + Hardfork::Paris, + ForkCondition::TTD { + fork_block: None, + total_difficulty: U256::from(58_750_000_000_000_000_000_000_u128), + }, + ), + (Hardfork::Shanghai, ForkCondition::Timestamp(1681338455)), + ]), + } + .into() }); /// The Goerli spec -pub static GOERLI: Lazy = 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: Some(H256(hex!( - "bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a" - ))), - // - paris_block_and_final_difficulty: Some((7382818, U256::from(10_790_000))), - fork_timestamps: ForkTimestamps::default().shanghai(1678832736), - hardforks: BTreeMap::from([ - (Hardfork::Frontier, ForkCondition::Block(0)), - (Hardfork::Homestead, ForkCondition::Block(0)), - (Hardfork::Dao, ForkCondition::Block(0)), - (Hardfork::Tangerine, ForkCondition::Block(0)), - (Hardfork::SpuriousDragon, ForkCondition::Block(0)), - (Hardfork::Byzantium, ForkCondition::Block(0)), - (Hardfork::Constantinople, ForkCondition::Block(0)), - (Hardfork::Petersburg, ForkCondition::Block(0)), - (Hardfork::Istanbul, ForkCondition::Block(1561651)), - (Hardfork::Berlin, ForkCondition::Block(4460644)), - (Hardfork::London, ForkCondition::Block(5062605)), - ( - Hardfork::Paris, - ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(10_790_000) }, - ), - (Hardfork::Shanghai, ForkCondition::Timestamp(1678832736)), - ]), +pub static GOERLI: Lazy> = 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: Some(H256(hex!( + "bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a" + ))), + // + paris_block_and_final_difficulty: Some((7382818, U256::from(10_790_000))), + fork_timestamps: ForkTimestamps::default().shanghai(1678832736), + hardforks: BTreeMap::from([ + (Hardfork::Frontier, ForkCondition::Block(0)), + (Hardfork::Homestead, ForkCondition::Block(0)), + (Hardfork::Dao, ForkCondition::Block(0)), + (Hardfork::Tangerine, ForkCondition::Block(0)), + (Hardfork::SpuriousDragon, ForkCondition::Block(0)), + (Hardfork::Byzantium, ForkCondition::Block(0)), + (Hardfork::Constantinople, ForkCondition::Block(0)), + (Hardfork::Petersburg, ForkCondition::Block(0)), + (Hardfork::Istanbul, ForkCondition::Block(1561651)), + (Hardfork::Berlin, ForkCondition::Block(4460644)), + (Hardfork::London, ForkCondition::Block(5062605)), + ( + Hardfork::Paris, + ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(10_790_000) }, + ), + (Hardfork::Shanghai, ForkCondition::Timestamp(1678832736)), + ]), + } + .into() }); /// The Sepolia spec -pub static SEPOLIA: Lazy = 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: Some(H256(hex!( - "25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9" - ))), - // - paris_block_and_final_difficulty: Some((1450409, U256::from(17_000_018_015_853_232u128))), - fork_timestamps: ForkTimestamps::default().shanghai(1677557088), - hardforks: BTreeMap::from([ - (Hardfork::Frontier, ForkCondition::Block(0)), - (Hardfork::Homestead, ForkCondition::Block(0)), - (Hardfork::Dao, ForkCondition::Block(0)), - (Hardfork::Tangerine, ForkCondition::Block(0)), - (Hardfork::SpuriousDragon, ForkCondition::Block(0)), - (Hardfork::Byzantium, ForkCondition::Block(0)), - (Hardfork::Constantinople, ForkCondition::Block(0)), - (Hardfork::Petersburg, ForkCondition::Block(0)), - (Hardfork::Istanbul, ForkCondition::Block(0)), - (Hardfork::MuirGlacier, ForkCondition::Block(0)), - (Hardfork::Berlin, ForkCondition::Block(0)), - (Hardfork::London, ForkCondition::Block(0)), - ( - Hardfork::Paris, - ForkCondition::TTD { - fork_block: Some(1735371), - total_difficulty: U256::from(17_000_000_000_000_000u64), - }, - ), - (Hardfork::Shanghai, ForkCondition::Timestamp(1677557088)), - ]), +pub static SEPOLIA: Lazy> = 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: Some(H256(hex!( + "25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9" + ))), + // + paris_block_and_final_difficulty: Some((1450409, U256::from(17_000_018_015_853_232u128))), + fork_timestamps: ForkTimestamps::default().shanghai(1677557088), + hardforks: BTreeMap::from([ + (Hardfork::Frontier, ForkCondition::Block(0)), + (Hardfork::Homestead, ForkCondition::Block(0)), + (Hardfork::Dao, ForkCondition::Block(0)), + (Hardfork::Tangerine, ForkCondition::Block(0)), + (Hardfork::SpuriousDragon, ForkCondition::Block(0)), + (Hardfork::Byzantium, ForkCondition::Block(0)), + (Hardfork::Constantinople, ForkCondition::Block(0)), + (Hardfork::Petersburg, ForkCondition::Block(0)), + (Hardfork::Istanbul, ForkCondition::Block(0)), + (Hardfork::MuirGlacier, ForkCondition::Block(0)), + (Hardfork::Berlin, ForkCondition::Block(0)), + (Hardfork::London, ForkCondition::Block(0)), + ( + Hardfork::Paris, + ForkCondition::TTD { + fork_block: Some(1735371), + total_difficulty: U256::from(17_000_000_000_000_000u64), + }, + ), + (Hardfork::Shanghai, ForkCondition::Timestamp(1677557088)), + ]), + } + .into() }); /// An Ethereum chain specification. @@ -416,9 +428,10 @@ impl From for AllGenesisFormats { } } -impl From for AllGenesisFormats { - fn from(genesis: ChainSpec) -> Self { - Self::Reth(genesis) +impl From> for AllGenesisFormats { + fn from(mut genesis: Arc) -> Self { + let cloned_genesis = Arc::make_mut(&mut genesis).clone(); + Self::Reth(cloned_genesis) } } @@ -574,8 +587,8 @@ impl ChainSpecBuilder { } } -impl From<&ChainSpec> for ChainSpecBuilder { - fn from(value: &ChainSpec) -> Self { +impl From<&Arc> for ChainSpecBuilder { + fn from(value: &Arc) -> Self { Self { chain: Some(value.chain), genesis: Some(value.genesis.clone()), diff --git a/crates/rpc/rpc-builder/tests/it/utils.rs b/crates/rpc/rpc-builder/tests/it/utils.rs index 885f989409..5494a97234 100644 --- a/crates/rpc/rpc-builder/tests/it/utils.rs +++ b/crates/rpc/rpc-builder/tests/it/utils.rs @@ -30,7 +30,7 @@ pub async fn launch_auth(secret: JwtSecret) -> AuthServerHandle { let beacon_engine_handle = BeaconConsensusEngineHandle::new(tx); let engine_api = EngineApi::new( NoopProvider::default(), - Arc::new(MAINNET.clone()), + MAINNET.clone(), beacon_engine_handle, spawn_test_payload_service().into(), ); diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 667332d6f8..424658972a 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -443,7 +443,7 @@ mod tests { use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver}; fn setup_engine_api() -> (EngineApiTestHandle, EngineApi>) { - let chain_spec = Arc::new(MAINNET.clone()); + let chain_spec: Arc = MAINNET.clone(); let client = Arc::new(MockEthProvider::default()); let payload_store = spawn_test_payload_service(); let (to_engine, engine_rx) = unbounded_channel(); diff --git a/crates/staged-sync/src/utils/init.rs b/crates/staged-sync/src/utils/init.rs index 9240641eb2..ec72df4651 100644 --- a/crates/staged-sync/src/utils/init.rs +++ b/crates/staged-sync/src/utils/init.rs @@ -168,7 +168,7 @@ mod tests { #[test] fn success_init_genesis_mainnet() { let db = create_test_rw_db(); - let genesis_hash = init_genesis(db, Arc::new(MAINNET.clone())).unwrap(); + let genesis_hash = init_genesis(db, MAINNET.clone()).unwrap(); // actual, expected assert_eq!(genesis_hash, MAINNET_GENESIS); @@ -177,7 +177,7 @@ mod tests { #[test] fn success_init_genesis_goerli() { let db = create_test_rw_db(); - let genesis_hash = init_genesis(db, Arc::new(GOERLI.clone())).unwrap(); + let genesis_hash = init_genesis(db, GOERLI.clone()).unwrap(); // actual, expected assert_eq!(genesis_hash, GOERLI_GENESIS); @@ -186,7 +186,7 @@ mod tests { #[test] fn success_init_genesis_sepolia() { let db = create_test_rw_db(); - let genesis_hash = init_genesis(db, Arc::new(SEPOLIA.clone())).unwrap(); + let genesis_hash = init_genesis(db, SEPOLIA.clone()).unwrap(); // actual, expected assert_eq!(genesis_hash, SEPOLIA_GENESIS); @@ -195,10 +195,10 @@ mod tests { #[test] fn fail_init_inconsistent_db() { let db = create_test_rw_db(); - init_genesis(db.clone(), Arc::new(SEPOLIA.clone())).unwrap(); + init_genesis(db.clone(), SEPOLIA.clone()).unwrap(); // Try to init db with a different genesis block - let genesis_hash = init_genesis(db, Arc::new(MAINNET.clone())); + let genesis_hash = init_genesis(db, MAINNET.clone()); assert_eq!( genesis_hash.unwrap_err(), diff --git a/crates/storage/provider/src/transaction.rs b/crates/storage/provider/src/transaction.rs index 5832828fc9..954e615a50 100644 --- a/crates/storage/provider/src/transaction.rs +++ b/crates/storage/provider/src/transaction.rs @@ -1458,7 +1458,7 @@ mod test { tables, }; use reth_primitives::{ChainSpecBuilder, IntegerList, H160, MAINNET, U256}; - use std::{ops::DerefMut, sync::Arc}; + use std::ops::DerefMut; #[test] fn insert_block_and_hashes_get_take() { @@ -1535,7 +1535,7 @@ mod test { // Check that transactions map onto blocks correctly. { - let provider = ShareableDatabase::new(tx.db, Arc::new(MAINNET.clone())); + let provider = ShareableDatabase::new(tx.db, MAINNET.clone()); assert_eq!( provider.transaction_block(0).unwrap(), Some(1),