diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 2a95ae3f4..883944a36 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -61,7 +61,7 @@ jobs: name: Run tests run: | cargo nextest run \ - --locked -p reth-node-bsc --features "bsc ${{ matrix.extra-features }}" \ + --locked -p reth-bsc-node --features "bsc ${{ matrix.extra-features }}" \ -E "kind(test)" integration-success: diff --git a/Cargo.lock b/Cargo.lock index f930df596..2862724d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7027,6 +7027,8 @@ dependencies = [ "reth-basic-payload-builder", "reth-beacon-consensus", "reth-blockchain-tree", + "reth-bsc-evm", + "reth-bsc-node", "reth-chainspec", "reth-cli", "reth-cli-commands", @@ -7044,7 +7046,6 @@ dependencies = [ "reth-ethereum-cli", "reth-ethereum-payload-builder", "reth-evm", - "reth-evm-bsc", "reth-execution-types", "reth-exex", "reth-fs-util", @@ -7052,7 +7053,6 @@ dependencies = [ "reth-network-api", "reth-network-p2p", "reth-node-api", - "reth-node-bsc", "reth-node-builder", "reth-node-core", "reth-node-ethereum", @@ -7290,6 +7290,7 @@ dependencies = [ "reth-bsc-forks", "reth-chainspec", "reth-ethereum-forks", + "reth-network-peers", "reth-primitives-traits", "serde_json", ] @@ -7323,6 +7324,7 @@ dependencies = [ "mockall 0.12.1", "parking_lot 0.12.3", "rand 0.8.5", + "reth-bsc-chainspec", "reth-bsc-forks", "reth-chainspec", "reth-codecs", @@ -7366,6 +7368,7 @@ dependencies = [ "rand 0.8.5", "reth-beacon-consensus", "reth-bsc-consensus", + "reth-bsc-evm", "reth-chainspec", "reth-codecs", "reth-consensus", @@ -7373,7 +7376,6 @@ dependencies = [ "reth-db-api", "reth-engine-primitives", "reth-evm", - "reth-evm-bsc", "reth-network", "reth-network-api", "reth-network-p2p", @@ -7392,6 +7394,34 @@ dependencies = [ "tracing", ] +[[package]] +name = "reth-bsc-evm" +version = "1.0.5" +dependencies = [ + "alloy-genesis 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives", + "bitset", + "blst", + "lazy_static", + "lru", + "parking_lot 0.12.3", + "reth-bsc-chainspec", + "reth-bsc-consensus", + "reth-bsc-forks", + "reth-chainspec", + "reth-errors", + "reth-ethereum-forks", + "reth-evm", + "reth-primitives", + "reth-provider", + "reth-prune-types", + "reth-revm", + "revm-primitives", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "reth-bsc-forks" version = "1.0.5" @@ -7403,6 +7433,77 @@ dependencies = [ "serde", ] +[[package]] +name = "reth-bsc-node" +version = "1.0.5" +dependencies = [ + "eyre", + "futures", + "futures-util", + "reth", + "reth-basic-payload-builder", + "reth-bsc-chainspec", + "reth-bsc-consensus", + "reth-bsc-evm", + "reth-chainspec", + "reth-config", + "reth-db", + "reth-e2e-test-utils", + "reth-ethereum-engine-primitives", + "reth-ethereum-payload-builder", + "reth-exex", + "reth-network", + "reth-node-api", + "reth-node-builder", + "reth-node-core", + "reth-payload-builder", + "reth-primitives", + "reth-provider", + "reth-rpc", + "reth-tracing", + "reth-transaction-pool", + "serde_json", + "tokio", +] + +[[package]] +name = "reth-bsc-rpc" +version = "1.0.5" +dependencies = [ + "alloy-eips", + "alloy-network", + "alloy-primitives", + "alloy-rpc-types", + "alloy-rpc-types-eth", + "derive_more 1.0.0", + "jsonrpsee-types", + "parking_lot 0.12.3", + "reqwest 0.12.8", + "reth-bsc-chainspec", + "reth-bsc-consensus", + "reth-bsc-evm", + "reth-bsc-forks", + "reth-chainspec", + "reth-evm", + "reth-network-api", + "reth-node-api", + "reth-node-builder", + "reth-primitives", + "reth-provider", + "reth-revm", + "reth-rpc", + "reth-rpc-eth-api", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-tasks", + "reth-transaction-pool", + "revm", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "reth-chain-state" version = "1.0.5" @@ -8282,33 +8383,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "reth-evm-bsc" -version = "1.0.5" -dependencies = [ - "alloy-genesis 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "bitset", - "blst", - "lazy_static", - "lru", - "parking_lot 0.12.3", - "reth-bsc-consensus", - "reth-bsc-forks", - "reth-chainspec", - "reth-errors", - "reth-ethereum-forks", - "reth-evm", - "reth-primitives", - "reth-provider", - "reth-prune-types", - "reth-revm", - "revm-primitives", - "thiserror", - "tokio", - "tracing", -] - [[package]] name = "reth-evm-ethereum" version = "1.0.5" @@ -8741,38 +8815,6 @@ dependencies = [ "reth-transaction-pool", ] -[[package]] -name = "reth-node-bsc" -version = "1.0.5" -dependencies = [ - "eyre", - "futures", - "futures-util", - "reth", - "reth-basic-payload-builder", - "reth-bsc-consensus", - "reth-chainspec", - "reth-config", - "reth-db", - "reth-e2e-test-utils", - "reth-ethereum-engine-primitives", - "reth-ethereum-payload-builder", - "reth-evm-bsc", - "reth-exex", - "reth-network", - "reth-node-api", - "reth-node-builder", - "reth-node-core", - "reth-payload-builder", - "reth-primitives", - "reth-provider", - "reth-rpc", - "reth-tracing", - "reth-transaction-pool", - "serde_json", - "tokio", -] - [[package]] name = "reth-node-builder" version = "1.0.5" @@ -8854,7 +8896,6 @@ dependencies = [ "humantime", "proptest", "rand 0.8.5", - "reth-bsc-chainspec", "reth-chainspec", "reth-cli-util", "reth-config", @@ -9513,7 +9554,6 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "async-trait", - "cfg-if", "derive_more 1.0.0", "futures", "http 1.1.0", @@ -9525,7 +9565,6 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "rand 0.8.5", - "reth-bsc-forks", "reth-chainspec", "reth-consensus-common", "reth-errors", @@ -9708,13 +9747,11 @@ dependencies = [ "alloy-rpc-types-mev", "async-trait", "auto_impl", - "cfg-if", "dyn-clone", "futures", "jsonrpsee", "jsonrpsee-types", "parking_lot 0.12.3", - "reth-bsc-forks", "reth-chainspec", "reth-errors", "reth-evm", @@ -9841,6 +9878,7 @@ dependencies = [ "pprof", "rand 0.8.5", "rayon", + "reth-bsc-evm", "reth-chainspec", "reth-codecs", "reth-config", @@ -9850,7 +9888,6 @@ dependencies = [ "reth-downloaders", "reth-etl", "reth-evm", - "reth-evm-bsc", "reth-evm-ethereum", "reth-execution-errors", "reth-execution-types", diff --git a/Cargo.toml b/Cargo.toml index 09b4059df..b7ceb55aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,9 @@ members = [ "crates/bsc/chainspec", "crates/bsc/cli", "crates/bsc/consensus", - "crates/bsc/node/", "crates/bsc/evm/", + "crates/bsc/node/", + "crates/bsc/rpc/", "crates/chainspec/", "crates/cli/cli/", "crates/cli/commands/", @@ -305,6 +306,9 @@ reth-bsc-chainspec = { path = "crates/bsc/chainspec" } reth-bsc-forks = { path = "crates/bsc/hardforks" } reth-bsc-cli = { path = "crates/bsc/cli" } reth-bsc-consensus = { path = "crates/bsc/consensus" } +reth-bsc-evm = { path = "crates/bsc/evm" } +reth-bsc-node = { path = "crates/bsc/node" } +reth-bsc-rpc = { path = "crates/bsc/rpc" } reth-blockchain-tree = { path = "crates/blockchain-tree" } reth-blockchain-tree-api = { path = "crates/blockchain-tree-api" } reth-chain-state = { path = "crates/chain-state" } @@ -344,9 +348,7 @@ reth-ethereum-forks = { path = "crates/ethereum-forks" } reth-ethereum-payload-builder = { path = "crates/ethereum/payload" } reth-etl = { path = "crates/etl" } reth-evm = { path = "crates/evm" } -reth-evm-bsc = { path = "crates/bsc/evm" } reth-evm-ethereum = { path = "crates/ethereum/evm" } -reth-optimism-evm = { path = "crates/optimism/evm" } reth-execution-errors = { path = "crates/evm/execution-errors" } reth-execution-types = { path = "crates/evm/execution-types" } reth-exex = { path = "crates/exex/exex" } @@ -368,17 +370,17 @@ reth-network-types = { path = "crates/net/network-types" } reth-nippy-jar = { path = "crates/storage/nippy-jar" } reth-node-api = { path = "crates/node/api" } reth-node-builder = { path = "crates/node/builder" } -reth-node-bsc = { path = "crates/bsc/node" } reth-node-core = { path = "crates/node/core" } reth-node-ethereum = { path = "crates/ethereum/node" } reth-node-events = { path = "crates/node/events" } reth-node-metrics = { path = "crates/node/metrics" } -reth-optimism-node = { path = "crates/optimism/node" } reth-node-types = { path = "crates/node/types" } reth-optimism-chainspec = { path = "crates/optimism/chainspec" } reth-optimism-cli = { path = "crates/optimism/cli" } reth-optimism-consensus = { path = "crates/optimism/consensus" } +reth-optimism-evm = { path = "crates/optimism/evm" } reth-optimism-forks = { path = "crates/optimism/hardforks" } +reth-optimism-node = { path = "crates/optimism/node" } reth-optimism-payload-builder = { path = "crates/optimism/payload" } reth-optimism-primitives = { path = "crates/optimism/primitives" } reth-optimism-rpc = { path = "crates/optimism/rpc" } diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index d0212679e..4085a2696 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -69,10 +69,10 @@ reth-node-metrics.workspace = true reth-consensus.workspace = true reth-engine-util.workspace = true reth-prune.workspace = true -reth-node-bsc = { workspace = true, optional = true, features = [ +reth-bsc-node = { workspace = true, optional = true, features = [ "bsc", ] } -reth-evm-bsc = { workspace = true, optional = true, features = [ +reth-bsc-evm = { workspace = true, optional = true, features = [ "bsc", ] } @@ -137,8 +137,8 @@ bsc = [ "reth-stages/bsc", "reth-node-builder/bsc", "reth-beacon-consensus/bsc", - "reth-node-bsc/bsc", - "reth-evm-bsc/bsc", + "reth-bsc-node/bsc", + "reth-bsc-evm/bsc", ] # no-op feature flag for switching between the `optimism` and default functionality in CI matrices diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index a08a961cf..82ce28a2b 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -21,7 +21,7 @@ use reth_consensus::Consensus; use reth_errors::RethResult; use reth_evm::execute::{BlockExecutorProvider, Executor}; #[cfg(feature = "bsc")] -use reth_evm_bsc::{BscEvmConfig, BscExecutorProvider}; +use reth_bsc_evm::{BscEvmConfig, BscExecutorProvider}; use reth_execution_types::ExecutionOutcome; use reth_fs_util as fs; use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine, PayloadBuilderAttributes}; diff --git a/bin/reth/src/commands/debug_cmd/execution.rs b/bin/reth/src/commands/debug_cmd/execution.rs index cf0710a54..3a9d3f64e 100644 --- a/bin/reth/src/commands/debug_cmd/execution.rs +++ b/bin/reth/src/commands/debug_cmd/execution.rs @@ -24,7 +24,7 @@ use reth_network_p2p::{headers::client::HeadersClient, BlockClient}; use reth_node_api::{NodeTypesWithDB, NodeTypesWithDBAdapter, NodeTypesWithEngine}; #[cfg(feature = "bsc")] -use reth_evm_bsc::BscExecutorProvider; +use reth_bsc_evm::BscExecutorProvider; #[cfg(not(feature = "bsc"))] use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; diff --git a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs index f02c31ac8..09493f08d 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -15,7 +15,7 @@ use reth_config::Config; use reth_errors::BlockValidationError; use reth_evm::execute::{BlockExecutorProvider, Executor}; #[cfg(feature = "bsc")] -use reth_evm_bsc::BscExecutorProvider; +use reth_bsc_evm::BscExecutorProvider; use reth_execution_types::ExecutionOutcome; use reth_network::NetworkHandle; use reth_network_api::NetworkInfo; diff --git a/bin/reth/src/commands/debug_cmd/merkle.rs b/bin/reth/src/commands/debug_cmd/merkle.rs index df840789c..6bee273f9 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -14,7 +14,7 @@ use reth_db::tables; use reth_db_api::{cursor::DbCursorRO, transaction::DbTx}; use reth_evm::execute::{BatchExecutor, BlockExecutorProvider}; #[cfg(feature = "bsc")] -use reth_evm_bsc::BscExecutorProvider; +use reth_bsc_evm::BscExecutorProvider; use reth_network::NetworkHandle; use reth_network_api::NetworkInfo; use reth_network_p2p::full_block::FullBlockClient; diff --git a/bin/reth/src/commands/debug_cmd/replay_engine.rs b/bin/reth/src/commands/debug_cmd/replay_engine.rs index 9b618deb1..f3f236de4 100644 --- a/bin/reth/src/commands/debug_cmd/replay_engine.rs +++ b/bin/reth/src/commands/debug_cmd/replay_engine.rs @@ -16,7 +16,7 @@ use reth_consensus::Consensus; use reth_db::DatabaseEnv; use reth_engine_util::engine_store::{EngineMessageStore, StoredEngineApiMessage}; #[cfg(feature = "bsc")] -use reth_evm_bsc::{BscEvmConfig, BscExecutorProvider}; +use reth_bsc_evm::{BscEvmConfig, BscExecutorProvider}; use reth_fs_util as fs; use reth_network::NetworkHandle; use reth_network_api::NetworkInfo; diff --git a/bin/reth/src/lib.rs b/bin/reth/src/lib.rs index 9cc0319bd..2ff0c476e 100644 --- a/bin/reth/src/lib.rs +++ b/bin/reth/src/lib.rs @@ -193,6 +193,6 @@ pub use reth_cli_runner::{tokio_runtime, CliContext, CliRunner}; // for rendering diagrams use aquamarine as _; #[cfg(feature = "bsc")] -use reth_evm_bsc as _; +use reth_bsc_evm as _; #[cfg(feature = "bsc")] use reth_node_bsc as _; diff --git a/crates/blockchain-tree/src/chain.rs b/crates/blockchain-tree/src/chain.rs index a9e2f2604..5c6449e69 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -15,7 +15,9 @@ use reth_consensus::{Consensus, ConsensusError, PostExecutionInput}; use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_execution_errors::BlockExecutionError; use reth_execution_types::{Chain, ExecutionOutcome}; -use reth_primitives::{revm_primitives::EvmState, GotExpected, Header, SealedBlockWithSenders, SealedHeader}; +use reth_primitives::{ + revm_primitives::EvmState, GotExpected, Header, SealedBlockWithSenders, SealedHeader, +}; use reth_provider::{ providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes}, FullExecutionDataProvider, ProviderError, StateRootProvider, TryIntoHistoricalStateProvider, diff --git a/crates/bsc/chainspec/Cargo.toml b/crates/bsc/chainspec/Cargo.toml index 610f8f517..a1834e099 100644 --- a/crates/bsc/chainspec/Cargo.toml +++ b/crates/bsc/chainspec/Cargo.toml @@ -16,12 +16,14 @@ workspace = true reth-chainspec = { workspace = true, features = ["bsc"] } reth-ethereum-forks = { workspace = true, features = ["bsc"] } reth-primitives-traits.workspace = true +reth-network-peers.workspace = true # bsc reth-bsc-forks.workspace = true # ethereum alloy-chains.workspace = true +alloy-genesis.workspace = true alloy-primitives.workspace = true # io diff --git a/crates/bsc/chainspec/src/bsc.rs b/crates/bsc/chainspec/src/bsc.rs index 89ffd5ff3..4b8e4938f 100644 --- a/crates/bsc/chainspec/src/bsc.rs +++ b/crates/bsc/chainspec/src/bsc.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use alloy_chains::{Chain, NamedChain}; use alloy_primitives::{b256, U256}; use once_cell::sync::Lazy; -use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_bsc_forks::BscHardfork; +use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use crate::BscChainSpec; diff --git a/crates/bsc/chainspec/src/bsc_chapel.rs b/crates/bsc/chainspec/src/bsc_chapel.rs index 8544b455a..b56a22094 100644 --- a/crates/bsc/chainspec/src/bsc_chapel.rs +++ b/crates/bsc/chainspec/src/bsc_chapel.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use alloy_chains::{Chain, NamedChain}; use alloy_primitives::{b256, U256}; use once_cell::sync::Lazy; -use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_bsc_forks::BscHardfork; +use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use crate::BscChainSpec; diff --git a/crates/bsc/chainspec/src/bsc_rialto.rs b/crates/bsc/chainspec/src/bsc_rialto.rs index df19b7981..37e0a5fd8 100644 --- a/crates/bsc/chainspec/src/bsc_rialto.rs +++ b/crates/bsc/chainspec/src/bsc_rialto.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use alloy_chains::Chain; use alloy_primitives::{b256, U256}; use once_cell::sync::Lazy; -use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_bsc_forks::BscHardfork; +use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use crate::BscChainSpec; diff --git a/crates/bsc/chainspec/src/dev.rs b/crates/bsc/chainspec/src/dev.rs index 5ab321ae6..e8f2d5a2f 100644 --- a/crates/bsc/chainspec/src/dev.rs +++ b/crates/bsc/chainspec/src/dev.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use alloy_chains::Chain; use alloy_primitives::U256; use once_cell::sync::Lazy; -use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_bsc_forks::DEV_HARDFORKS; +use reth_chainspec::{once_cell_set, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_primitives_traits::constants::DEV_GENESIS_HASH; use crate::BscChainSpec; diff --git a/crates/bsc/chainspec/src/lib.rs b/crates/bsc/chainspec/src/lib.rs index 786848280..594d2b9f9 100644 --- a/crates/bsc/chainspec/src/lib.rs +++ b/crates/bsc/chainspec/src/lib.rs @@ -15,21 +15,115 @@ mod bsc_chapel; mod bsc_rialto; mod dev; +use core::fmt::Display; + +use alloy_genesis::Genesis; +use alloy_primitives::{B256, U256}; pub use bsc::BSC_MAINNET; pub use bsc_chapel::BSC_CHAPEL; pub use bsc_rialto::BSC_RIALTO; -pub use dev::BSC_DEV; - use derive_more::{Constructor, Deref, Into}; -use reth_chainspec::ChainSpec; +pub use dev::BSC_DEV; +use reth_chainspec::{BaseFeeParams, ChainSpec, DepositContract, EthChainSpec}; +use reth_ethereum_forks::{EthereumHardforks, ForkFilter, ForkId, Hardforks, Head}; +use reth_network_peers::NodeRecord; +use reth_primitives_traits::Header; /// Bsc chain spec type. -#[derive(Debug, Deref, Into, Constructor)] +#[derive(Debug, Clone, Deref, Into, Constructor, PartialEq, Eq)] pub struct BscChainSpec { /// [`ChainSpec`]. pub inner: ChainSpec, } +impl EthChainSpec for BscChainSpec { + fn chain(&self) -> alloy_chains::Chain { + self.inner.chain() + } + + fn base_fee_params_at_block(&self, block_number: u64) -> BaseFeeParams { + self.inner.base_fee_params_at_block(block_number) + } + + fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams { + self.inner.base_fee_params_at_timestamp(timestamp) + } + + fn deposit_contract(&self) -> Option<&DepositContract> { + None + } + + fn genesis_hash(&self) -> B256 { + self.inner.genesis_hash() + } + + fn prune_delete_limit(&self) -> usize { + self.inner.prune_delete_limit() + } + + fn display_hardforks(&self) -> impl Display { + self.inner.display_hardforks() + } + + fn genesis_header(&self) -> &Header { + self.inner.genesis_header() + } + + fn genesis(&self) -> &Genesis { + self.inner.genesis() + } + + fn max_gas_limit(&self) -> u64 { + self.inner.max_gas_limit() + } + + fn bootnodes(&self) -> Option> { + self.inner.bootnodes() + } + + fn is_optimism(&self) -> bool { + false + } + + fn is_bsc(&self) -> bool { + true + } +} + +impl Hardforks for BscChainSpec { + fn fork(&self, fork: H) -> reth_chainspec::ForkCondition { + self.inner.fork(fork) + } + + fn forks_iter( + &self, + ) -> impl Iterator { + self.inner.forks_iter() + } + + fn fork_id(&self, head: &Head) -> ForkId { + self.inner.fork_id(head) + } + + fn latest_fork_id(&self) -> ForkId { + self.inner.latest_fork_id() + } + + fn fork_filter(&self, head: Head) -> ForkFilter { + self.inner.fork_filter(head) + } +} + +impl EthereumHardforks for BscChainSpec { + fn get_final_paris_total_difficulty(&self) -> Option { + self.inner.get_final_paris_total_difficulty() + } + + fn final_paris_total_difficulty(&self, block_number: u64) -> Option { + self.inner.final_paris_total_difficulty(block_number) + } +} + // #[cfg(test)] // mod tests { // use alloy_genesis::Genesis; diff --git a/crates/bsc/consensus/Cargo.toml b/crates/bsc/consensus/Cargo.toml index f20f4bf5f..62ca5187e 100644 --- a/crates/bsc/consensus/Cargo.toml +++ b/crates/bsc/consensus/Cargo.toml @@ -26,6 +26,7 @@ reth-network-peers.workspace = true # bsc reth-bsc-forks.workspace = true +reth-bsc-chainspec.workspace = true # eth alloy-rlp.workspace = true diff --git a/crates/bsc/consensus/src/abi.rs b/crates/bsc/consensus/src/abi.rs index a91025e26..743ed957e 100644 --- a/crates/bsc/consensus/src/abi.rs +++ b/crates/bsc/consensus/src/abi.rs @@ -1,11 +1,10 @@ -use crate::{Parlia, VoteAddress}; use alloy_dyn_abi::{DynSolValue, FunctionExt, JsonAbiExt}; use alloy_primitives::{Address, BlockNumber, Bytes, U256}; use lazy_static::lazy_static; use reth_bsc_forks::BscHardforks; -use reth_primitives::{ - system_contracts::{STAKE_HUB_CONTRACT, VALIDATOR_CONTRACT}, -}; +use reth_primitives::system_contracts::{STAKE_HUB_CONTRACT, VALIDATOR_CONTRACT}; + +use crate::{Parlia, VoteAddress}; lazy_static! { pub static ref VALIDATOR_SET_ABI: &'static str = r#" @@ -6005,10 +6004,11 @@ impl Parlia { #[cfg(test)] mod tests { - use super::*; use alloy_json_abi::JsonAbi; use alloy_primitives::{address, hex}; + use super::*; + #[test] fn abi_encode() { let expected = "63a036b500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; diff --git a/crates/bsc/consensus/src/feynman_fork.rs b/crates/bsc/consensus/src/feynman_fork.rs index 377f6b222..bd228eadf 100644 --- a/crates/bsc/consensus/src/feynman_fork.rs +++ b/crates/bsc/consensus/src/feynman_fork.rs @@ -1,6 +1,7 @@ -use alloy_primitives::{Address, U256}; use std::{cmp::Ordering, collections::BinaryHeap}; +use alloy_primitives::{Address, U256}; + #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct ValidatorElectionInfo { pub address: Address, @@ -69,9 +70,10 @@ pub fn get_top_validators_by_voting_power( #[cfg(test)] mod tests { - use super::*; use alloy_primitives::hex; + use super::*; + #[test] fn validator_heap() { let test_cases = vec![ diff --git a/crates/bsc/consensus/src/lib.rs b/crates/bsc/consensus/src/lib.rs index 1a2b73834..5336579ac 100644 --- a/crates/bsc/consensus/src/lib.rs +++ b/crates/bsc/consensus/src/lib.rs @@ -6,14 +6,22 @@ // The `bsc` feature must be enabled to use this crate. #![cfg(feature = "bsc")] +use std::{ + clone::Clone, + fmt::{Debug, Formatter}, + num::NonZeroUsize, + sync::Arc, + time::SystemTime, +}; + use alloy_json_abi::JsonAbi; use alloy_primitives::{Address, B256, U256}; use alloy_rlp::Decodable; use lazy_static::lazy_static; use lru::LruCache; use parking_lot::RwLock; -use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_bsc_forks::BscHardforks; +use reth_chainspec::{ChainSpec, EthChainSpec, EthereumHardforks}; use reth_consensus::{Consensus, ConsensusError, PostExecutionInput}; use reth_primitives::{ constants::EMPTY_MIX_HASH, @@ -25,13 +33,6 @@ use secp256k1::{ Message, SECP256K1, }; use sha3::{Digest, Keccak256}; -use std::{ - clone::Clone, - fmt::{Debug, Formatter}, - num::NonZeroUsize, - sync::Arc, - time::SystemTime, -}; use tracing::{log::debug, trace}; mod util; @@ -82,12 +83,6 @@ pub struct ValidatorsInfo { pub vote_addrs: Option>, } -impl Default for Parlia { - fn default() -> Self { - Self::new(Arc::new(ChainSpec::default()), ParliaConfig::default()) - } -} - impl Parlia { pub fn new(chain_spec: Arc, cfg: ParliaConfig) -> Self { let validator_abi = serde_json::from_str(*VALIDATOR_SET_ABI).unwrap(); @@ -144,7 +139,7 @@ impl Parlia { .map_err(|_| ParliaConsensusError::RecoverECDSAInnerError)?; let message = Message::from_digest_slice( - hash_with_chain_id(header, self.chain_spec.chain.id()).as_slice(), + hash_with_chain_id(header, self.chain_spec.chain().id()).as_slice(), ) .map_err(|_| ParliaConsensusError::RecoverECDSAInnerError)?; let public = &SECP256K1 @@ -618,16 +613,3 @@ impl Debug for Parlia { .finish() } } - -#[cfg(test)] -mod tests { - use super::*; - - // To make sure the abi is correct - #[test] - fn test_new_parlia() { - let parlia = Parlia::new(Arc::new(ChainSpec::default()), ParliaConfig::default()); - assert_eq!(parlia.epoch(), 200); - assert_eq!(parlia.period(), 3); - } -} diff --git a/crates/bsc/consensus/src/system_tx.rs b/crates/bsc/consensus/src/system_tx.rs index 20fa4862a..1945c45a3 100644 --- a/crates/bsc/consensus/src/system_tx.rs +++ b/crates/bsc/consensus/src/system_tx.rs @@ -1,7 +1,7 @@ -use crate::Parlia; use alloy_consensus::TxLegacy; -use alloy_primitives::{Address, Bytes, TxKind, U256}; use alloy_dyn_abi::{DynSolValue, JsonAbiExt}; +use alloy_primitives::{Address, Bytes, TxKind, U256}; +use reth_chainspec::EthChainSpec; use reth_primitives::{ system_contracts::{ CROSS_CHAIN_CONTRACT, GOVERNOR_CONTRACT, GOV_TOKEN_CONTRACT, LIGHT_CLIENT_CONTRACT, @@ -12,6 +12,8 @@ use reth_primitives::{ Transaction, }; +use crate::Parlia; + /// Assemble system tx impl Parlia { pub fn init_genesis_contracts(&self) -> Vec { @@ -32,7 +34,7 @@ impl Parlia { .into_iter() .map(|contract| { Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -60,7 +62,7 @@ impl Parlia { .into_iter() .map(|contract| { Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -77,7 +79,7 @@ impl Parlia { let input = function.abi_encode_input(&[DynSolValue::from(address)]).unwrap(); Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -89,7 +91,7 @@ impl Parlia { pub fn distribute_to_system(&self, system_reward: u128) -> Transaction { Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -104,7 +106,7 @@ impl Parlia { let input = function.abi_encode_input(&[DynSolValue::from(address)]).unwrap(); Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -129,7 +131,7 @@ impl Parlia { .unwrap(); Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, @@ -160,7 +162,7 @@ impl Parlia { .unwrap(); Transaction::Legacy(TxLegacy { - chain_id: Some(self.chain_spec.chain.id()), + chain_id: Some(self.chain_spec.chain().id()), nonce: 0, gas_limit: u64::MAX / 2, gas_price: 0, diff --git a/crates/bsc/consensus/src/util.rs b/crates/bsc/consensus/src/util.rs index ba0352b78..8c11c905b 100644 --- a/crates/bsc/consensus/src/util.rs +++ b/crates/bsc/consensus/src/util.rs @@ -1,8 +1,13 @@ -use crate::EXTRA_SEAL_LEN; -use alloy_primitives::{keccak256, bytes::{BufMut, BytesMut}, B256, B64, U256}; +use std::env; + +use alloy_primitives::{ + bytes::{BufMut, BytesMut}, + keccak256, B256, U256, +}; use alloy_rlp::Encodable; use reth_primitives::Header; -use std::env; + +use crate::EXTRA_SEAL_LEN; const SECONDS_PER_DAY: u64 = 86400; // 24 * 60 * 60 @@ -91,10 +96,11 @@ fn rlp_header(header: &Header, chain_id: u64) -> alloy_rlp::Header { #[cfg(test)] mod tests { - use crate::{encode_header_with_chain_id, hash_with_chain_id}; use alloy_primitives::{address, b256, hex, Bloom, Bytes, B64, U256}; use reth_primitives::Header; + use crate::{encode_header_with_chain_id, hash_with_chain_id}; + #[test] fn test_encode_header_with_chain_id() { // test data from bsc testnet diff --git a/crates/bsc/consensus/src/validation.rs b/crates/bsc/consensus/src/validation.rs index 91f6c0f92..cf5d2e409 100644 --- a/crates/bsc/consensus/src/validation.rs +++ b/crates/bsc/consensus/src/validation.rs @@ -1,5 +1,5 @@ use alloy_primitives::{Bloom, B256}; -use reth_chainspec::{ChainSpec, EthereumHardforks}; +use reth_chainspec::EthereumHardforks; use reth_consensus::ConsensusError; use reth_primitives::{ constants::eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK}, @@ -42,7 +42,7 @@ pub fn validate_4844_header_of_bsc(header: &SealedHeader) -> Result<(), Consensu /// /// - Compares the receipts root in the block header to the block body /// - Compares the gas used in the block header to the actual gas usage after execution -pub fn validate_block_post_execution( +pub fn validate_block_post_execution( block: &BlockWithSenders, chain_spec: &ChainSpec, receipts: &[Receipt], diff --git a/crates/bsc/engine/Cargo.toml b/crates/bsc/engine/Cargo.toml index 7d166d5b6..f7110fc5e 100644 --- a/crates/bsc/engine/Cargo.toml +++ b/crates/bsc/engine/Cargo.toml @@ -26,7 +26,7 @@ reth-network-p2p.workspace = true reth-network-peers.workspace = true reth-beacon-consensus.workspace = true reth-bsc-consensus.workspace = true -reth-evm-bsc.workspace = true +reth-bsc-evm.workspace = true reth-evm.workspace = true reth-primitives-traits.workspace = true @@ -69,6 +69,6 @@ bsc = [ "reth-primitives/bsc", "reth-consensus-common/bsc", "reth-bsc-consensus/bsc", - "reth-evm-bsc/bsc", + "reth-bsc-evm/bsc", "reth-beacon-consensus/bsc", ] diff --git a/crates/bsc/engine/src/lib.rs b/crates/bsc/engine/src/lib.rs index 2d419c6f2..d9fa5c1ce 100644 --- a/crates/bsc/engine/src/lib.rs +++ b/crates/bsc/engine/src/lib.rs @@ -10,7 +10,7 @@ use reth_beacon_consensus::BeaconEngineMessage; use reth_bsc_consensus::Parlia; use reth_chainspec::ChainSpec; use reth_engine_primitives::EngineTypes; -use reth_evm_bsc::SnapshotReader; +use reth_bsc_evm::SnapshotReader; use reth_network_api::events::EngineMessage; use reth_network_p2p::BlockClient; use reth_primitives::{ diff --git a/crates/bsc/engine/src/task.rs b/crates/bsc/engine/src/task.rs index 190ad57f5..569445f89 100644 --- a/crates/bsc/engine/src/task.rs +++ b/crates/bsc/engine/src/task.rs @@ -4,9 +4,9 @@ use alloy_primitives::{Sealable, B256}; use alloy_rpc_types::{engine::ForkchoiceState, BlockId, RpcBlockHash}; use reth_beacon_consensus::{BeaconEngineMessage, ForkchoiceStatus, MIN_BLOCKS_FOR_PIPELINE_RUN}; use reth_bsc_consensus::Parlia; +use reth_bsc_evm::SnapshotReader; use reth_chainspec::ChainSpec; use reth_engine_primitives::EngineTypes; -use reth_evm_bsc::SnapshotReader; use reth_network_api::events::EngineMessage; use reth_network_p2p::{ headers::client::{HeadersClient, HeadersDirection, HeadersRequest}, @@ -262,7 +262,9 @@ impl< // than the predicted timestamp and less than the current timestamp. let predicted_timestamp = trusted_header.timestamp + block_interval * (latest_header.number - 1 - trusted_header.number); - let sealed_header = latest_header.clone().seal_slow(); + let sealed = latest_header.clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + let sealed_header = SealedHeader::new(header, seal); let is_valid_header = match consensus .validate_header_with_predicted_timestamp(&sealed_header, predicted_timestamp) { @@ -323,7 +325,9 @@ impl< } let mut parent_hash = sealed_header.parent_hash; for (i, _) in headers.iter().enumerate() { - let sealed_header = headers[i].clone().seal_slow(); + let sealed = headers[i].clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + let sealed_header = SealedHeader::new(header, seal); if sealed_header.hash_slow() != parent_hash { break; } diff --git a/crates/bsc/evm/Cargo.toml b/crates/bsc/evm/Cargo.toml index 5c6aa895b..bce83cb9d 100644 --- a/crates/bsc/evm/Cargo.toml +++ b/crates/bsc/evm/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "reth-evm-bsc" +name = "reth-bsc-evm" version.workspace = true edition.workspace = true rust-version.workspace = true @@ -20,9 +20,10 @@ reth-primitives.workspace = true reth-prune-types.workspace = true reth-revm.workspace = true reth-provider.workspace = true -reth-bsc-consensus.workspace = true # bsc +reth-bsc-consensus.workspace = true +reth-bsc-chainspec.workspace = true reth-bsc-forks.workspace = true # Revm diff --git a/crates/bsc/evm/src/config.rs b/crates/bsc/evm/src/config.rs index 09695d039..dd998a7d1 100644 --- a/crates/bsc/evm/src/config.rs +++ b/crates/bsc/evm/src/config.rs @@ -1,5 +1,5 @@ -use reth_chainspec::ChainSpec; use reth_bsc_forks::BscHardfork; +use reth_chainspec::ChainSpec; use reth_ethereum_forks::{EthereumHardfork, Head}; /// Returns the spec id at the given timestamp. diff --git a/crates/bsc/evm/src/execute.rs b/crates/bsc/evm/src/execute.rs index f02b5e0e1..90663d571 100644 --- a/crates/bsc/evm/src/execute.rs +++ b/crates/bsc/evm/src/execute.rs @@ -1,7 +1,7 @@ //! Bsc block executor. use crate::{post_execution::PostExecutionInput, BscBlockExecutionError, BscEvmConfig}; -use alloy_primitives::{Address, BlockNumber, B256, Bytes, U256}; +use alloy_primitives::{Address, BlockNumber, Bytes, B256, U256}; use core::fmt::Display; use lazy_static::lazy_static; use lru::LruCache; @@ -9,13 +9,14 @@ use parking_lot::RwLock; use reth_bsc_consensus::{ is_breathe_block, validate_block_post_execution, Parlia, ValidatorElectionInfo, ValidatorsInfo, }; -use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_bsc_forks::BscHardforks; +use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_errors::{BlockExecutionError, BlockValidationError, ProviderError}; use reth_evm::{ execute::{ BatchExecutor, BlockExecutionInput, BlockExecutionOutput, BlockExecutorProvider, Executor, }, + system_calls::{NoopHook, OnStateHook}, ConfigureEvm, }; use reth_primitives::{ @@ -81,7 +82,7 @@ where prefetch_tx: Option>, ) -> BscBlockExecutor where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { if let Some(tx) = prefetch_tx { BscBlockExecutor::new_with_prefetch_tx( @@ -117,10 +118,10 @@ where P: ParliaProvider + Clone + Unpin + 'static, EvmConfig: ConfigureEvm
, { - type Executor + std::fmt::Display>> = + type Executor + Display>> = BscBlockExecutor; - type BatchExecutor + std::fmt::Display>> = + type BatchExecutor + Display>> = BscBatchExecutor; fn executor( @@ -129,14 +130,14 @@ where prefetch_tx: Option>, ) -> Self::Executor where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { self.bsc_executor(db, prefetch_tx) } fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let executor = self.bsc_executor(db, None); BscBatchExecutor { @@ -172,22 +173,26 @@ where /// /// This applies the pre-execution changes, and executes the transactions. /// + /// The optional `state_hook` is unused for now. + /// /// # Note /// /// It does __not__ apply post-execution changes. - fn execute_pre_and_transactions( + fn execute_pre_and_transactions( &self, block: &BlockWithSenders, mut evm: Evm<'_, Ext, &mut State>, + _state_hook: Option, tx: Option>, ) -> Result<(Vec, Vec, u64), BlockExecutionError> where - DB: Database + std::fmt::Display>, + DB: Database + Display>, + F: OnStateHook, { // execute transactions let mut cumulative_gas_used = 0; let mut system_txs = Vec::with_capacity(2); // Normally there are 2 system transactions. - let mut receipts = Vec::with_capacity(block.body.len()); + let mut receipts = Vec::with_capacity(block.body.transactions.len()); for (sender, transaction) in block.transactions_with_sender() { if is_system_transaction(transaction, *sender, block.beneficiary) { system_txs.push(transaction.clone()); @@ -363,19 +368,37 @@ where EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, Default::default()) } + /// Convenience method to invoke `execute_without_verification_with_state_hook` setting the + /// state hook as `None`. + fn execute_without_verification( + &mut self, + block: &BlockWithSenders, + total_difficulty: U256, + ancestor: Option<&alloy_primitives::map::HashMap>, + ) -> Result { + self.execute_without_verification_with_state_hook( + block, + total_difficulty, + ancestor, + None::, + ) + } + /// Execute a single block and apply the state changes to the internal state. /// /// Returns the receipts of the transactions in the block and the total gas used. /// - /// Returns an error if execution fails or parlia verification fails. - /// - /// This function does not perform receipt root and gas used check. - fn execute_and_verify( + /// Returns an error if execution fails. + fn execute_without_verification_with_state_hook( &mut self, block: &BlockWithSenders, total_difficulty: U256, - ancestor: Option<&HashMap>, - ) -> Result { + ancestor: Option<&alloy_primitives::map::HashMap>, + state_hook: Option, + ) -> Result + where + F: OnStateHook, + { // 1. get parent header and snapshot let parent = &(self.get_header_by_hash(block.parent_hash, ancestor)?); let snapshot_reader = SnapshotReader::new(self.provider.clone(), self.parlia.clone()); @@ -398,7 +421,12 @@ where let (mut system_txs, mut receipts, mut gas_used) = { let evm = self.executor.evm_config.evm_with_env(&mut self.state, env.clone()); - self.executor.execute_pre_and_transactions(block, evm, self.prefetch_tx.clone()) + self.executor.execute_pre_and_transactions( + block, + evm, + state_hook, + self.prefetch_tx.clone(), + ) }?; // 5. apply post execution changes @@ -423,7 +451,7 @@ where pub(crate) fn get_justified_header( &self, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, snap: &Snapshot, ) -> Result { if snap.vote_data.source_hash == B256::ZERO && snap.vote_data.target_hash == B256::ZERO { @@ -442,7 +470,7 @@ where pub(crate) fn get_header_by_hash( &self, block_hash: B256, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, ) -> Result { ancestor .and_then(|m| m.get(&block_hash).cloned()) @@ -479,7 +507,7 @@ where let mut new_info = account.account_info().unwrap_or_default(); new_info.code_hash = v.clone().unwrap().hash_slow(); new_info.code = v; - let transition = account.change(new_info, HashMap::new()); + let transition = account.change(new_info, Default::default()); self.state.apply_transition(vec![(k, transition)]); } @@ -659,7 +687,11 @@ where let vote_addrs_map = if vote_addrs.is_empty() { HashMap::new() } else { - validators.iter().copied().zip(vote_addrs).collect::>() + validators + .iter() + .copied() + .zip(vote_addrs) + .collect::>() }; output.current_validators = Some((validators, vote_addrs_map)); @@ -728,7 +760,7 @@ where impl Executor for BscBlockExecutor where EvmConfig: ConfigureEvm
, - DB: Database + std::fmt::Display>, + DB: Database + Display>, P: ParliaProvider, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders, Header>; @@ -745,7 +777,61 @@ where fn execute(mut self, input: Self::Input<'_>) -> Result { let BlockExecutionInput { block, total_difficulty, ancestor_headers } = input; let BscExecuteOutput { receipts, gas_used, snapshot } = - self.execute_and_verify(block, total_difficulty, ancestor_headers)?; + self.execute_without_verification(block, total_difficulty, ancestor_headers)?; + + // NOTE: we need to merge keep the reverts for the bundle retention + self.state.merge_transitions(BundleRetention::Reverts); + + Ok(BlockExecutionOutput { + state: self.state.take_bundle(), + receipts, + requests: Vec::default(), + gas_used, + snapshot, + }) + } + + fn execute_with_state_closure( + mut self, + input: Self::Input<'_>, + mut witness: F, + ) -> Result + where + F: FnMut(&State), + { + let BlockExecutionInput { block, total_difficulty, ancestor_headers } = input; + let BscExecuteOutput { receipts, gas_used, snapshot } = + self.execute_without_verification(block, total_difficulty, ancestor_headers)?; + + // NOTE: we need to merge keep the reverts for the bundle retention + self.state.merge_transitions(BundleRetention::Reverts); + witness(&self.state); + + Ok(BlockExecutionOutput { + state: self.state.take_bundle(), + receipts, + requests: Vec::default(), + gas_used, + snapshot, + }) + } + + fn execute_with_state_hook( + mut self, + input: Self::Input<'_>, + state_hook: F, + ) -> Result + where + F: OnStateHook, + { + let BlockExecutionInput { block, total_difficulty, ancestor_headers } = input; + let BscExecuteOutput { receipts, gas_used, snapshot } = self + .execute_without_verification_with_state_hook( + block, + total_difficulty, + ancestor_headers, + Some(state_hook), + )?; // NOTE: we need to merge keep the reverts for the bundle retention self.state.merge_transitions(BundleRetention::Reverts); @@ -783,7 +869,7 @@ impl BscBatchExecutor { impl BatchExecutor for BscBatchExecutor where EvmConfig: ConfigureEvm
, - DB: Database + std::fmt::Display>, + DB: Database + Display>, P: ParliaProvider, { type Input<'a> = BlockExecutionInput<'a, BlockWithSenders, Header>; @@ -793,7 +879,7 @@ where fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> { let BlockExecutionInput { block, total_difficulty, .. } = input; let BscExecuteOutput { receipts, gas_used: _, snapshot } = - self.executor.execute_and_verify(block, total_difficulty, None)?; + self.executor.execute_without_verification(block, total_difficulty, None)?; validate_block_post_execution(block, self.executor.chain_spec(), &receipts)?; @@ -858,7 +944,7 @@ where pub fn snapshot( &self, header: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, ) -> Result { let mut cache = RECENT_SNAPS.write(); @@ -980,7 +1066,7 @@ where fn get_header_by_hash( &self, block_hash: B256, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, ) -> Result { ancestor .and_then(|m| m.get(&block_hash).cloned()) @@ -997,7 +1083,7 @@ where fn find_ancient_header( &self, header: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, count: u64, ) -> Result { let mut result = header.clone(); diff --git a/crates/bsc/evm/src/lib.rs b/crates/bsc/evm/src/lib.rs index c71e593ec..35a1cf7a0 100644 --- a/crates/bsc/evm/src/lib.rs +++ b/crates/bsc/evm/src/lib.rs @@ -6,6 +6,8 @@ // The `bsc` feature must be enabled to use this crate. #![cfg(feature = "bsc")] +use std::sync::Arc; + use alloy_primitives::{Address, Bytes, U256}; use reth_chainspec::ChainSpec; use reth_ethereum_forks::EthereumHardfork; @@ -20,7 +22,6 @@ use reth_primitives::{ }; use reth_revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector}; use revm_primitives::Env; -use std::sync::Arc; mod config; pub use config::{revm_spec, revm_spec_by_timestamp_after_shanghai}; @@ -28,12 +29,13 @@ mod execute; pub use execute::*; mod error; pub use error::BscBlockExecutionError; + mod patch_hertz; mod post_execution; mod pre_execution; /// Bsc-related EVM configuration. -#[derive(Debug, Default, Clone)] +#[derive(Debug, Clone)] #[non_exhaustive] pub struct BscEvmConfig { chain_spec: Arc, @@ -184,14 +186,13 @@ impl ConfigureEvm for BscEvmConfig { #[cfg(test)] mod tests { - use super::*; use alloy_genesis::Genesis; use reth_chainspec::Chain; - use reth_primitives::{ - revm_primitives::{BlockEnv, CfgEnv}, - }; + use reth_primitives::revm_primitives::{BlockEnv, CfgEnv}; use revm_primitives::SpecId; + use super::*; + #[test] #[ignore] fn test_fill_cfg_and_block_env() { @@ -208,7 +209,7 @@ mod tests { .shanghai_activated() .build(); - BscEvmConfig::default().fill_cfg_and_block_env( + BscEvmConfig::new(Arc::new(chain_spec.clone())).fill_cfg_and_block_env( &mut cfg_env, &mut block_env, &header, diff --git a/crates/bsc/evm/src/patch_hertz.rs b/crates/bsc/evm/src/patch_hertz.rs index 356323498..55116743b 100644 --- a/crates/bsc/evm/src/patch_hertz.rs +++ b/crates/bsc/evm/src/patch_hertz.rs @@ -1,4 +1,3 @@ -use crate::{execute::BscEvmExecutor, BscBlockExecutionError}; use alloy_primitives::{address, b256, Address, B256, U256}; use lazy_static::lazy_static; use reth_errors::ProviderError; @@ -6,9 +5,11 @@ use reth_evm::ConfigureEvm; use reth_primitives::{Header, TransactionSigned}; use reth_revm::{db::states::StorageSlot, State}; use revm_primitives::db::Database; -use std::{collections::HashMap, str::FromStr}; +use std::{collections::HashMap, fmt::Display, str::FromStr}; use tracing::trace; +use crate::{execute::BscEvmExecutor, BscBlockExecutionError}; + struct StoragePatch { address: Address, storage: HashMap, @@ -665,7 +666,7 @@ where transaction: &TransactionSigned, state: &mut State, ) where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let tx_hash = transaction.recalculate_hash(); if let Some(patch) = MAINNET_PATCHES_BEFORE_TX.get(&tx_hash) { @@ -680,7 +681,7 @@ where transaction: &TransactionSigned, state: &mut State, ) where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let tx_hash = transaction.recalculate_hash(); if let Some(patch) = CHAPEL_PATCHES_BEFORE_TX.get(&tx_hash) { @@ -695,7 +696,7 @@ where transaction: &TransactionSigned, state: &mut State, ) where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let tx_hash = transaction.recalculate_hash(); if let Some(patch) = MAINNET_PATCHES_AFTER_TX.get(&tx_hash) { @@ -710,7 +711,7 @@ where transaction: &TransactionSigned, state: &mut State, ) where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let tx_hash = transaction.recalculate_hash(); if let Some(patch) = CHAPEL_PATCHES_AFTER_TX.get(&tx_hash) { @@ -723,7 +724,7 @@ where fn apply_patch(state: &mut State, address: Address, storage: &HashMap) where - DB: Database + std::fmt::Display>, + DB: Database + Display>, { let account = state .load_cache_account(address) diff --git a/crates/bsc/evm/src/post_execution.rs b/crates/bsc/evm/src/post_execution.rs index 6409a9daf..db7b75e1a 100644 --- a/crates/bsc/evm/src/post_execution.rs +++ b/crates/bsc/evm/src/post_execution.rs @@ -1,4 +1,3 @@ -use crate::{BscBlockExecutionError, BscBlockExecutor, SnapshotReader}; use alloy_primitives::{hex, Address, B256, U256}; use bitset::BitSet; use reth_bsc_consensus::{ @@ -6,8 +5,8 @@ use reth_bsc_consensus::{ COLLECT_ADDITIONAL_VOTES_REWARD_RATIO, DEFAULT_TURN_LENGTH, DIFF_INTURN, MAX_SYSTEM_REWARD, SYSTEM_REWARD_PERCENT, }; -use reth_errors::{BlockExecutionError, BlockValidationError, ProviderError}; use reth_bsc_forks::BscHardforks; +use reth_errors::{BlockExecutionError, BlockValidationError, ProviderError}; use reth_evm::ConfigureEvm; use reth_primitives::{ parlia::{Snapshot, VoteAddress, VoteAttestation}, @@ -17,9 +16,11 @@ use reth_primitives::{ use reth_provider::ParliaProvider; use reth_revm::bsc::SYSTEM_ADDRESS; use revm_primitives::{db::Database, EnvWithHandlerCfg}; -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display}; use tracing::debug; +use crate::{BscBlockExecutionError, BscBlockExecutor, SnapshotReader}; + /// Helper type for the input of post execution. #[allow(clippy::type_complexity)] #[derive(Debug, Clone)] @@ -32,7 +33,7 @@ pub(crate) struct PostExecutionInput { impl BscBlockExecutor where EvmConfig: ConfigureEvm
, - DB: Database + std::fmt::Display>, + DB: Database + Display>, P: ParliaProvider, { /// Apply post execution state changes, including system txs and other state change. @@ -41,7 +42,7 @@ where &mut self, block: &BlockWithSenders, parent: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, snap: &Snapshot, post_execution_input: PostExecutionInput, system_txs: &mut Vec, @@ -371,7 +372,7 @@ where fn distribute_finality_reward( &mut self, header: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, system_txs: &mut Vec, receipts: &mut Vec, cumulative_gas_used: &mut u64, @@ -447,8 +448,8 @@ where &self, attestation: &VoteAttestation, parent_header: &Header, - ancestor: Option<&HashMap>, - accumulated_weights: &mut HashMap, + ancestor: Option<&alloy_primitives::map::HashMap>, + accumulated_weights: &mut std::collections::HashMap, ) -> Result<(), BlockExecutionError> { let justified_header = self.get_header_by_hash(attestation.data.target_hash, ancestor)?; let parent = self.get_header_by_hash(justified_header.parent_hash, ancestor)?; diff --git a/crates/bsc/evm/src/pre_execution.rs b/crates/bsc/evm/src/pre_execution.rs index 6ed254894..09f7ec45d 100644 --- a/crates/bsc/evm/src/pre_execution.rs +++ b/crates/bsc/evm/src/pre_execution.rs @@ -6,9 +6,9 @@ use blst::{ BLST_ERROR, }; use reth_bsc_consensus::{DIFF_INTURN, DIFF_NOTURN}; +use reth_bsc_forks::BscHardforks; use reth_errors::{BlockExecutionError, ProviderError}; use reth_ethereum_forks::EthereumHardforks; -use reth_bsc_forks::BscHardforks; use reth_evm::ConfigureEvm; use reth_primitives::{ parlia::{Snapshot, VoteAddress, MAX_ATTESTATION_EXTRA_LENGTH}, @@ -16,14 +16,14 @@ use reth_primitives::{ }; use reth_provider::ParliaProvider; use revm_primitives::db::Database; -use std::collections::HashMap; +use std::fmt::Display; const BLST_DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; impl BscBlockExecutor where EvmConfig: ConfigureEvm
, - DB: Database + std::fmt::Display>, + DB: Database + Display>, P: ParliaProvider, { /// Apply settings and verify headers before a new block is executed. @@ -31,7 +31,7 @@ where &mut self, header: &Header, parent: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, snap: &Snapshot, ) -> Result<(), BlockExecutionError> { // Set state clear flag if the block is after the Spurious Dragon hardfork. @@ -45,7 +45,7 @@ where &self, header: &Header, parent: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, snap: &Snapshot, ) -> Result<(), BlockExecutionError> { self.verify_block_time_for_ramanujan(snap, header, parent)?; @@ -82,7 +82,7 @@ where snap: &Snapshot, header: &Header, parent: &Header, - ancestor: Option<&HashMap>, + ancestor: Option<&alloy_primitives::map::HashMap>, ) -> Result<(), BlockExecutionError> { if !self.chain_spec().is_plato_active_at_block(header.number) { return Ok(()); @@ -226,13 +226,11 @@ where #[cfg(test)] mod tests { - use super::BLST_DST; use alloy_primitives::{b256, hex}; - use blst::min_pk::{PublicKey, Signature}; - use reth_primitives::{ - parlia::{VoteAddress, VoteData, VoteSignature}, - }; + use reth_primitives::parlia::{VoteAddress, VoteData, VoteSignature}; + + use super::BLST_DST; #[test] fn verify_vote_attestation() { diff --git a/crates/bsc/node/Cargo.toml b/crates/bsc/node/Cargo.toml index 589e60569..41995c74c 100644 --- a/crates/bsc/node/Cargo.toml +++ b/crates/bsc/node/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "reth-node-bsc" +name = "reth-bsc-node" version.workspace = true edition.workspace = true rust-version.workspace = true @@ -22,13 +22,16 @@ reth-tracing.workspace = true reth-provider.workspace = true reth-transaction-pool.workspace = true reth-network.workspace = true -reth-evm-bsc.workspace = true -reth-bsc-consensus.workspace = true reth-primitives.workspace = true reth-config.workspace = true reth-rpc.workspace = true reth-node-api.workspace = true +# bsc-reth +reth-bsc-chainspec.workspace = true +reth-bsc-consensus.workspace = true +reth-bsc-evm.workspace = true + # misc eyre.workspace = true @@ -44,12 +47,12 @@ futures.workspace = true tokio.workspace = true futures-util.workspace = true serde_json.workspace = true -reth-evm-bsc.workspace = true +reth-bsc-evm.workspace = true [features] bsc = [ "reth-network/bsc", - "reth-evm-bsc/bsc", + "reth-bsc-evm/bsc", "reth-primitives/bsc", "reth-config/bsc", "reth-bsc-consensus/bsc", diff --git a/crates/bsc/node/src/evm.rs b/crates/bsc/node/src/evm.rs index f65a32a36..dd2e317be 100644 --- a/crates/bsc/node/src/evm.rs +++ b/crates/bsc/node/src/evm.rs @@ -1,6 +1,6 @@ //! BSC EVM support #[doc(inline)] -pub use reth_evm_bsc::BscEvmConfig; +pub use reth_bsc_evm::BscEvmConfig; #[doc(inline)] -pub use reth_evm_bsc::BscExecutorProvider; +pub use reth_bsc_evm::BscExecutorProvider; diff --git a/crates/bsc/node/src/node.rs b/crates/bsc/node/src/node.rs index adfc6b2e5..e0e207b9e 100644 --- a/crates/bsc/node/src/node.rs +++ b/crates/bsc/node/src/node.rs @@ -1,23 +1,25 @@ //! BSC Node types config. use std::sync::Arc; -use crate::EthEngineTypes; + use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig}; +use reth_bsc_chainspec::BscChainSpec; use reth_bsc_consensus::Parlia; use reth_chainspec::ChainSpec; -use reth_ethereum_engine_primitives::{EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, EthereumEngineValidator}; -use reth_evm_bsc::{BscEvmConfig, BscExecutorProvider}; +use reth_ethereum_engine_primitives::{ + EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, EthereumEngineValidator, +}; +use reth_bsc_evm::{BscEvmConfig, BscExecutorProvider}; use reth_network::NetworkHandle; use reth_node_api::{ConfigureEvm, EngineValidator, FullNodeComponents, NodeAddOns}; use reth_node_builder::{ components::{ - ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder, - PayloadServiceBuilder, PoolBuilder, + ComponentsBuilder, ConsensusBuilder, EngineValidatorBuilder, ExecutorBuilder, + NetworkBuilder, PayloadServiceBuilder, PoolBuilder, }, node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine}, BuilderContext, Node, PayloadBuilderConfig, PayloadTypes, }; -use reth_node_builder::components::EngineValidatorBuilder; use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_primitives::Header; use reth_provider::CanonStateSubscriptions; @@ -28,6 +30,8 @@ use reth_transaction_pool::{ TransactionValidationTaskExecutor, }; +use crate::EthEngineTypes; + /// Type configuration for a regular BSC node. #[derive(Debug, Default, Clone, Copy)] #[non_exhaustive] @@ -65,7 +69,7 @@ impl BscNode { impl NodeTypes for BscNode { type Primitives = (); - type ChainSpec = ChainSpec; + type ChainSpec = BscChainSpec; } impl NodeTypesWithEngine for BscNode { @@ -82,7 +86,7 @@ impl NodeAddOns for BSCAddOns { impl Node for BscNode where - Types: NodeTypesWithEngine, + Types: NodeTypesWithEngine, N: FullNodeTypes, { type ComponentsBuilder = ComponentsBuilder< @@ -113,7 +117,7 @@ pub struct BscExecutorBuilder; impl ExecutorBuilder for BscExecutorBuilder where - Types: NodeTypesWithEngine, + Types: NodeTypesWithEngine, Node: FullNodeTypes, { type EVM = BscEvmConfig; @@ -262,7 +266,7 @@ impl BscPayloadBuilder { impl PayloadServiceBuilder for BscPayloadBuilder where - Types: NodeTypesWithEngine, + Types: NodeTypesWithEngine, Node: FullNodeTypes, Pool: TransactionPool + Unpin + 'static, Types::Engine: PayloadTypes< @@ -310,7 +314,7 @@ pub struct BscConsensusBuilder; impl ConsensusBuilder for BscConsensusBuilder where - Node: FullNodeTypes>, + Node: FullNodeTypes>, { type Consensus = Parlia; diff --git a/crates/bsc/rpc/Cargo.toml b/crates/bsc/rpc/Cargo.toml new file mode 100644 index 000000000..b8c8a51ca --- /dev/null +++ b/crates/bsc/rpc/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "reth-bsc-rpc" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +description = "Ethereum RPC implementation for bsc." + +[lints] +workspace = true + +[dependencies] +# reth +reth-evm.workspace = true +reth-primitives.workspace = true +reth-provider.workspace = true +reth-revm.workspace = true +reth-rpc-eth-api.workspace = true +reth-rpc-eth-types.workspace = true +reth-rpc-server-types.workspace = true +reth-tasks = { workspace = true, features = ["rayon"] } +reth-transaction-pool.workspace = true +reth-rpc.workspace = true +reth-node-api.workspace = true +reth-network-api.workspace = true +reth-node-builder.workspace = true +reth-chainspec.workspace = true + +# bsc-reth +reth-bsc-chainspec.workspace = true +reth-bsc-consensus.workspace = true +reth-bsc-evm.workspace = true +reth-bsc-forks.workspace = true + +# ethereum +alloy-eips.workspace = true +alloy-network.workspace = true +alloy-primitives.workspace = true +alloy-rpc-types-eth.workspace = true +alloy-rpc-types.workspace = true +revm.workspace = true + +# async +parking_lot.workspace = true +tokio.workspace = true +reqwest = { workspace = true, features = ["rustls-tls-native-roots"] } + +# rpc +jsonrpsee-types.workspace = true +serde_json.workspace = true + +# misc +thiserror.workspace = true +tracing.workspace = true +derive_more.workspace = true + +[dev-dependencies] +reth-bsc-chainspec.workspace = true + +[features] +bsc = [ + "reth-bsc-evm/bsc", + "reth-primitives/bsc", + "revm/bsc", +] diff --git a/crates/bsc/rpc/src/error.rs b/crates/bsc/rpc/src/error.rs new file mode 100644 index 000000000..41f0b1729 --- /dev/null +++ b/crates/bsc/rpc/src/error.rs @@ -0,0 +1,39 @@ +//! RPC errors specific to BSC. + +use alloy_primitives::Address; +use reth_provider::ProviderError; +use reth_rpc_eth_api::AsEthApiError; +use reth_rpc_eth_types::EthApiError; +use reth_rpc_server_types::result::internal_rpc_err; + +/// Bsc specific errors, that extend [`EthApiError`]. +#[derive(Debug, thiserror::Error)] +pub enum BscEthApiError { + #[error(transparent)] + Eth(#[from] EthApiError), + /// When load account from db failed + #[error("load account failed")] + LoadAccountFailed, + /// Provider error + #[error(transparent)] + Provider(#[from] ProviderError), +} + +impl AsEthApiError for BscEthApiError { + fn as_err(&self) -> Option<&EthApiError> { + match self { + Self::Eth(err) => Some(err), + _ => None, + } + } +} + +impl From for jsonrpsee_types::error::ErrorObject<'static> { + fn from(err: BscEthApiError) -> Self { + match err { + BscEthApiError::Eth(err) => err.into(), + BscEthApiError::LoadAccountFailed => internal_rpc_err(err.to_string()), + BscEthApiError::Provider(err) => err.into(), + } + } +} diff --git a/crates/bsc/rpc/src/eth/call.rs b/crates/bsc/rpc/src/eth/call.rs new file mode 100644 index 000000000..f359cece0 --- /dev/null +++ b/crates/bsc/rpc/src/eth/call.rs @@ -0,0 +1,228 @@ +use crate::{BscEthApi, BscEthApiError}; +use alloy_primitives::{B256, U256}; +use alloy_rpc_types_eth::TransactionInfo; +use reth_chainspec::EthereumHardforks; +use reth_evm::ConfigureEvm; +use reth_node_api::{FullNodeComponents, NodeTypes}; +use reth_primitives::{ + revm_primitives::{ + db::DatabaseRef, BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ResultAndState, + }, + system_contracts::{get_upgrade_system_contracts, is_system_transaction}, + Header, TransactionSignedEcRecovered, +}; +use reth_revm::database::StateProviderDatabase; +use reth_rpc_eth_api::helpers::{ + Call, EthCall, LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, +}; +use reth_rpc_eth_types::{EthApiError, StateCacheDb}; +use revm::{ + bsc::SYSTEM_ADDRESS, + db::{ + AccountState::{NotExisting, Touched}, + CacheDB, + }, +}; +use std::future::Future; + +impl EthCall for BscEthApi +where + Self: Call, + N: FullNodeComponents>, +{ +} + +impl Call for BscEthApi +where + Self: LoadState + SpawnBlocking, + Self::Error: From, + N: FullNodeComponents, +{ + #[inline] + fn call_gas_limit(&self) -> u64 { + self.inner.gas_cap() + } + + #[inline] + fn max_simulate_blocks(&self) -> u64 { + self.inner.max_simulate_blocks() + } + + #[inline] + fn evm_config(&self) -> &impl ConfigureEvm
{ + self.inner.evm_config() + } + + fn spawn_replay_transaction( + &self, + hash: B256, + f: F, + ) -> impl Future, Self::Error>> + Send + where + Self: LoadBlock + LoadPendingBlock + LoadTransaction, + F: FnOnce(TransactionInfo, ResultAndState, StateCacheDb<'_>) -> Result + + Send + + 'static, + R: Send + 'static, + { + async move { + let (transaction, block) = match self.transaction_and_block(hash).await? { + None => return Ok(None), + Some(res) => res, + }; + let (tx, tx_info) = transaction.split(); + + let (cfg, block_env, _) = self.evm_env_at(block.hash().into()).await?; + + // we need to get the state of the parent block because we're essentially replaying the + // block the transaction is included in + let parent_block = block.parent_hash; + let block_txs = block.into_transactions_ecrecovered(); + + let parent_timestamp = self + .block(parent_block.into()) + .await? + .map(|block| block.timestamp) + .ok_or_else(|| EthApiError::UnknownParentBlock)?; + + let this = self.clone(); + self.spawn_with_state_at_block(parent_block.into(), move |state| { + let mut db = CacheDB::new(StateProviderDatabase::new(state)); + + // replay all transactions prior to the targeted transaction + this.replay_transactions_until( + &mut db, + cfg.clone(), + block_env.clone(), + block_txs, + tx.hash, + parent_timestamp, + )?; + + let mut tx_env = Call::evm_config(&this).tx_env(&tx); + if is_system_transaction(&tx, tx.signer(), block_env.coinbase) { + tx_env.bsc.is_system_transaction = Some(true); + }; + + let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env); + + let (res, _) = this.transact(&mut db, env)?; + f(tx_info, res, db) + }) + .await + .map(Some) + } + } + + fn replay_transactions_until( + &self, + db: &mut CacheDB, + cfg: CfgEnvWithHandlerCfg, + block_env: BlockEnv, + transactions: impl IntoIterator, + target_tx_hash: B256, + parent_timestamp: u64, + ) -> Result + where + DB: DatabaseRef, + EthApiError: From, + { + #[allow(clippy::redundant_clone)] + let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env.clone(), Default::default()); + + let mut evm = self.evm_config().evm_with_env(db, env); + let mut index = 0; + let mut before_system_tx = true; + + // try to upgrade system contracts before all txs if feynman is not active + if !self.provider().chain_spec().is_feynman_active_at_timestamp(block_env.timestamp.to()) { + let contracts = get_upgrade_system_contracts( + self.provider().chain_spec().as_ref(), + block_env.number.to(), + block_env.timestamp.to(), + parent_timestamp, + ) + .expect("get upgrade system contracts failed"); + + for (k, v) in contracts { + let account = + evm.db_mut().load_account(k).map_err(|| BscEthApiError::LoadAccountFailed)?; + if account.account_state == NotExisting { + account.account_state = Touched; + } + account.info.code_hash = v.clone().unwrap().hash_slow(); + account.info.code = v; + } + } + + for tx in transactions { + // check if the transaction is a system transaction + // this should be done before return + if before_system_tx && is_system_transaction(&tx, tx.signer(), block_env.coinbase) { + let sys_acc = evm + .db_mut() + .load_account(SYSTEM_ADDRESS) + .map_err(|| BscEthApiError::LoadAccountFailed)?; + let balance = sys_acc.info.balance; + if balance > U256::ZERO { + sys_acc.info.balance = U256::ZERO; + + let val_acc = evm + .db_mut() + .load_account(block_env.coinbase) + .map_err(|| BscEthApiError::LoadAccountFailed)?; + if val_acc.account_state == NotExisting { + val_acc.account_state = Touched; + } + val_acc.info.balance += balance; + } + + // try to upgrade system contracts between normal txs and system txs + // if feynman is active + if !self + .provider() + .chain_spec() + .is_feynman_active_at_timestamp(block_env.timestamp.to()) + { + let contracts = get_upgrade_system_contracts( + self.provider().chain_spec().as_ref(), + block_env.number.to(), + block_env.timestamp.to(), + parent_timestamp, + ) + .expect("get upgrade system contracts failed"); + + for (k, v) in contracts { + let account = evm + .db_mut() + .load_account(k) + .map_err(|| BscEthApiError::LoadAccountFailed)?; + if account.account_state == NotExisting { + account.account_state = Touched; + } + account.info.code_hash = v.clone().unwrap().hash_slow(); + account.info.code = v; + } + } + + before_system_tx = false; + } + + if tx.hash() == target_tx_hash { + // reached the target transaction + break + } + + let sender = tx.signer(); + self.evm_config().fill_tx_env(evm.tx_mut(), &tx.into_signed(), sender); + + if !before_system_tx { + evm.tx_mut().bsc.is_system_transaction = Some(true); + }; + + evm.transact_commit().map_err(BscEthApiError::from)?; + index += 1; + } + Ok(index) + } +} diff --git a/crates/bsc/rpc/src/eth/mod.rs b/crates/bsc/rpc/src/eth/mod.rs new file mode 100644 index 000000000..8c96cd3b0 --- /dev/null +++ b/crates/bsc/rpc/src/eth/mod.rs @@ -0,0 +1,274 @@ +//! Bsc-Reth `eth_` endpoint implementation. + +mod call; +mod trace; + +use std::{fmt, sync::Arc}; + +use crate::BscEthApiError; +use alloy_network::AnyNetwork; +use alloy_primitives::U256; +use derive_more::Deref; +use reth_bsc_forks::BscHardforks; +use reth_chainspec::EthereumHardforks; +use reth_evm::{provider::EvmEnvProvider, ConfigureEvm}; +use reth_network_api::NetworkInfo; +use reth_node_api::{BuilderProvider, FullNodeComponents, FullNodeTypes, NodeTypes}; +use reth_node_builder::EthApiBuilderCtx; +use reth_primitives::Header; +use reth_provider::{ + BlockIdReader, BlockNumReader, BlockReaderIdExt, ChainSpecProvider, HeaderProvider, + StageCheckpointReader, StateProviderFactory, +}; +use reth_rpc::eth::{core::EthApiInner, DevSigner, EthTxBuilder}; +use reth_rpc_eth_api::{ + helpers::{ + AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadBlock, LoadFee, + LoadPendingBlock, LoadState, SpawnBlocking, Trace, + }, + EthApiTypes, +}; +use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle, PendingBlock}; +use reth_tasks::{ + pool::{BlockingTaskGuard, BlockingTaskPool}, + TaskSpawner, +}; +use reth_transaction_pool::TransactionPool; + +/// Adapter for [`EthApiInner`], which holds all the data required to serve core `eth_` API. +pub type EthApiNodeBackend = EthApiInner< + ::Provider, + ::Pool, + ::Network, + ::Evm, +>; + +/// Bsc-Reth `Eth` API implementation. +/// +/// This type provides the functionality for handling `eth_` related requests. +/// +/// This wraps a default `Eth` implementation, and provides additional functionality where the +/// optimism spec deviates from the default (ethereum) spec, e.g. transaction forwarding to the +/// sequencer, receipts, additional RPC fields for transaction receipts. +/// +/// This type implements the [`FullEthApi`](reth_rpc_eth_api::helpers::FullEthApi) by implemented +/// all the `Eth` helper traits and prerequisite traits. +#[derive(Clone, Deref)] +pub struct BscEthApi { + /// Gateway to node's core components. + #[deref] + inner: Arc>, +} + +impl BscEthApi { + /// Creates a new instance for given context. + #[allow(clippy::type_complexity)] + pub fn with_spawner(ctx: &EthApiBuilderCtx) -> Self { + let blocking_task_pool = + BlockingTaskPool::build().expect("failed to build blocking task pool"); + + let inner = EthApiInner::new( + ctx.provider.clone(), + ctx.pool.clone(), + ctx.network.clone(), + ctx.cache.clone(), + ctx.new_gas_price_oracle(), + ctx.config.rpc_gas_cap, + ctx.config.rpc_max_simulate_blocks, + ctx.config.eth_proof_window, + blocking_task_pool, + ctx.new_fee_history_cache(), + ctx.evm_config.clone(), + ctx.executor.clone(), + ctx.config.proof_permits, + ); + + Self { inner: Arc::new(inner) } + } +} + +impl EthApiTypes for BscEthApi +where + Self: Send + Sync, + N: FullNodeComponents, +{ + type Error = BscEthApiError; + // todo: replace with alloy_network::Bsc + type NetworkTypes = AnyNetwork; + type TransactionCompat = EthTxBuilder; +} + +impl EthApiSpec for BscEthApi +where + Self: Send + Sync, + N: FullNodeComponents>, +{ + #[inline] + fn provider( + &self, + ) -> impl ChainSpecProvider + BlockNumReader + StageCheckpointReader + { + self.inner.provider() + } + + #[inline] + fn network(&self) -> impl NetworkInfo { + self.inner.network() + } + + #[inline] + fn starting_block(&self) -> U256 { + self.inner.starting_block() + } + + #[inline] + fn signers(&self) -> &parking_lot::RwLock>> { + self.inner.signers() + } +} + +impl SpawnBlocking for BscEthApi +where + Self: Send + Sync + Clone + 'static, + N: FullNodeComponents, +{ + #[inline] + fn io_task_spawner(&self) -> impl TaskSpawner { + self.inner.task_spawner() + } + + #[inline] + fn tracing_task_pool(&self) -> &BlockingTaskPool { + self.inner.blocking_task_pool() + } + + #[inline] + fn tracing_task_guard(&self) -> &BlockingTaskGuard { + self.inner.blocking_task_guard() + } +} + +impl LoadFee for BscEthApi +where + Self: LoadBlock, + N: FullNodeComponents>, +{ + #[inline] + fn provider( + &self, + ) -> impl BlockIdReader + HeaderProvider + ChainSpecProvider { + self.inner.provider() + } + + #[inline] + fn cache(&self) -> &EthStateCache { + self.inner.cache() + } + + #[inline] + fn gas_oracle(&self) -> &GasPriceOracle { + self.inner.gas_oracle() + } + + #[inline] + fn fee_history_cache(&self) -> &FeeHistoryCache { + self.inner.fee_history_cache() + } +} + +impl LoadPendingBlock for BscEthApi +where + Self: SpawnBlocking, + N: FullNodeComponents>, +{ + #[inline] + fn provider( + &self, + ) -> impl BlockReaderIdExt + + EvmEnvProvider + + ChainSpecProvider + + StateProviderFactory { + self.inner.provider() + } + + #[inline] + fn pool(&self) -> impl TransactionPool { + self.inner.pool() + } + + #[inline] + fn pending_block(&self) -> &tokio::sync::Mutex> { + self.inner.pending_block() + } + + #[inline] + fn evm_config(&self) -> &impl ConfigureEvm
{ + self.inner.evm_config() + } +} + +impl LoadState for BscEthApi +where + Self: Send + Sync + Clone, + N: FullNodeComponents>, +{ + #[inline] + fn provider(&self) -> impl StateProviderFactory + ChainSpecProvider { + self.inner.provider() + } + + #[inline] + fn cache(&self) -> &EthStateCache { + self.inner.cache() + } + + #[inline] + fn pool(&self) -> impl TransactionPool { + self.inner.pool() + } +} + +impl EthState for BscEthApi +where + Self: LoadState + SpawnBlocking, + N: FullNodeComponents, +{ + #[inline] + fn max_proof_window(&self) -> u64 { + self.inner.eth_proof_window() + } +} + +impl EthFees for BscEthApi +where + Self: LoadFee, + N: FullNodeComponents, +{ +} + +impl AddDevSigners for BscEthApi +where + N: FullNodeComponents>, +{ + fn with_dev_accounts(&self) { + *self.signers().write() = DevSigner::random_signers(20) + } +} + +impl BuilderProvider for BscEthApi +where + Self: Send, + N: FullNodeComponents, +{ + type Ctx<'a> = &'a EthApiBuilderCtx; + + fn builder() -> Box Fn(Self::Ctx<'a>) -> Self + Send> { + Box::new(Self::with_spawner) + } +} + +impl fmt::Debug for BscEthApi { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BscEthApi").finish_non_exhaustive() + } +} diff --git a/crates/bsc/rpc/src/eth/trace.rs b/crates/bsc/rpc/src/eth/trace.rs new file mode 100644 index 000000000..3fc741db8 --- /dev/null +++ b/crates/bsc/rpc/src/eth/trace.rs @@ -0,0 +1,96 @@ +use crate::BscEthApi; +use alloy_primitives::B256; +use alloy_rpc_types_eth::TransactionInfo; +use reth_evm::ConfigureEvm; +use reth_node_api::FullNodeComponents; +use reth_primitives::{ + revm_primitives::{db::Database, EnvWithHandlerCfg, ResultAndState}, + system_contracts::is_system_transaction, + Header, +}; +use reth_revm::database::StateProviderDatabase; +use reth_rpc_eth_api::helpers::{ + Call, LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, Trace, +}; +use reth_rpc_eth_types::{cache::db::StateCacheDbRefMutWrapper, EthApiError, StateCacheDb}; +use revm::{db::CacheDB, Inspector}; +use std::future::Future; + +impl Trace for BscEthApi +where + Self: LoadState, + N: FullNodeComponents, +{ + #[inline] + fn evm_config(&self) -> &impl ConfigureEvm
{ + self.inner.evm_config() + } + + fn spawn_trace_transaction_in_block_with_inspector( + &self, + hash: B256, + mut inspector: Insp, + f: F, + ) -> impl Future, Self::Error>> + Send + where + Self: LoadPendingBlock + LoadTransaction + Call, + F: FnOnce( + TransactionInfo, + Insp, + ResultAndState, + StateCacheDb<'_>, + ) -> Result + + Send + + 'static, + Insp: for<'a, 'b> Inspector> + Send + 'static, + R: Send + 'static, + { + async move { + let (transaction, block) = match self.transaction_and_block(hash).await? { + None => return Ok(None), + Some(res) => res, + }; + let (tx, tx_info) = transaction.split(); + + let (cfg, block_env, _) = self.evm_env_at(block.hash().into()).await?; + + // we need to get the state of the parent block because we're essentially replaying the + // block the transaction is included in + let parent_block = block.parent_hash; + let block_txs = block.into_transactions_ecrecovered(); + + let parent_timestamp = LoadState::cache(self) + .get_block(parent_block) + .await? + .map(|block| block.timestamp) + .ok_or_else(|| EthApiError::UnknownParentBlock)?; + + let this = self.clone(); + self.spawn_with_state_at_block(parent_block.into(), move |state| { + let mut db = CacheDB::new(StateProviderDatabase::new(state)); + + // replay all transactions prior to the targeted transaction + this.replay_transactions_until( + &mut db, + cfg.clone(), + block_env.clone(), + block_txs, + tx.hash, + parent_timestamp, + )?; + + let mut tx_env = Call::evm_config(&this).tx_env(&tx); + if is_system_transaction(&tx, tx.signer(), block_env.coinbase) { + tx_env.bsc.is_system_transaction = Some(true); + }; + + let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env); + let (res, _) = + this.inspect(StateCacheDbRefMutWrapper(&mut db), env, &mut inspector)?; + f(tx_info, inspector, res, db) + }) + .await + .map(Some) + } + } +} diff --git a/crates/bsc/rpc/src/lib.rs b/crates/bsc/rpc/src/lib.rs new file mode 100644 index 000000000..e93eafa2c --- /dev/null +++ b/crates/bsc/rpc/src/lib.rs @@ -0,0 +1,12 @@ +//! Bsc-Reth RPC support. + +#![allow(missing_docs)] +#![cfg_attr(all(not(test), feature = "bsc"), warn(unused_crate_dependencies))] +// The `bsc` feature must be enabled to use this crate. +#![cfg(feature = "bsc")] + +pub mod error; +pub mod eth; + +pub use error::BscEthApiError; +pub use eth::BscEthApi; diff --git a/crates/node/core/Cargo.toml b/crates/node/core/Cargo.toml index dfca95ba3..55bfa541c 100644 --- a/crates/node/core/Cargo.toml +++ b/crates/node/core/Cargo.toml @@ -35,7 +35,6 @@ reth-network-peers.workspace = true reth-consensus-common.workspace = true reth-prune-types.workspace = true reth-stages-types.workspace = true -reth-bsc-chainspec = { workspace = true, optional = true } # ethereum alloy-primitives.workspace = true @@ -85,7 +84,6 @@ opbnb = [ ] bsc = [ "reth-primitives/bsc", - "dep:reth-bsc-chainspec", ] # Features for vergen to generate correct env vars diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 1deca4816..d41d84223 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -31,9 +31,6 @@ reth-rpc-server-types.workspace = true reth-network-api.workspace = true reth-trie.workspace = true -# bsc -reth-bsc-forks.workspace = true - # ethereum alloy-eips.workspace = true alloy-dyn-abi = { workspace = true, features = ["eip712"] } @@ -58,7 +55,6 @@ tokio.workspace = true auto_impl.workspace = true dyn-clone.workspace = true tracing.workspace = true -cfg-if = "1.0.0" [features] js-tracer = ["revm-inspectors/js-tracer", "reth-rpc-eth-types/js-tracer"] diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 4635babbc..c6fdf047f 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -13,18 +13,9 @@ use alloy_rpc_types::{ BlockId, Bundle, EthCallResponse, StateContext, TransactionInfo, }; use alloy_rpc_types_eth::transaction::TransactionRequest; -use cfg_if::cfg_if; use futures::Future; -#[cfg(feature = "bsc")] -use reth_bsc_forks::BscHardforks; use reth_chainspec::{EthChainSpec, MIN_TRANSACTION_GAS}; -#[cfg(feature = "bsc")] -use reth_errors::RethError; use reth_evm::{ConfigureEvm, ConfigureEvmEnv}; -#[cfg(feature = "bsc")] -use reth_primitives::system_contracts::get_upgrade_system_contracts; -#[cfg(feature = "bsc")] -use reth_primitives::system_contracts::is_system_transaction; use reth_primitives::{ revm_primitives::{ BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult, HaltReason, @@ -45,10 +36,6 @@ use reth_rpc_eth_types::{ EthApiError, RevertError, RpcInvalidTransactionError, StateCacheDb, }; use reth_rpc_server_types::constants::gas_oracle::{CALL_STIPEND_GAS, ESTIMATE_GAS_ERROR_RATIO}; -#[cfg(feature = "bsc")] -use revm::bsc::SYSTEM_ADDRESS; -#[cfg(feature = "bsc")] -use revm::db::AccountState::{NotExisting, Touched}; use revm::{Database, DatabaseCommit, GetInspector}; use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector}; use tracing::trace; @@ -617,15 +604,7 @@ pub trait Call: LoadState + SpawnBlocking { let parent_block = block.parent_hash; let block_txs = block.into_transactions_ecrecovered(); - cfg_if! { - if #[cfg(feature = "bsc")] { - let parent_timestamp = self.block(parent_block.into()).await? - .map(|block| block.timestamp) - .ok_or_else(|| EthApiError::UnknownParentBlock)?; - } else { - let parent_timestamp = 0; - } - } + let parent_timestamp = 0; let this = self.clone(); self.spawn_with_state_at_block(parent_block.into(), move |state| { @@ -641,16 +620,7 @@ pub trait Call: LoadState + SpawnBlocking { parent_timestamp, )?; - cfg_if! { - if #[cfg(feature = "bsc")] { - let mut tx_env = Call::evm_config(&this).tx_env(&tx); - if is_system_transaction(&tx, tx.signer(), block_env.coinbase) { - tx_env.bsc.is_system_transaction = Some(true); - }; - } else { - let tx_env = Call::evm_config(&this).tx_env(&tx); - } - } + let tx_env = Call::evm_config(&this).tx_env(&tx); let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env); @@ -688,84 +658,8 @@ pub trait Call: LoadState + SpawnBlocking { let mut evm = self.evm_config().evm_with_env(db, env); let mut index = 0; - #[cfg(feature = "bsc")] - let mut before_system_tx = true; - - // try to upgrade system contracts before all txs if feynman is not active - #[cfg(feature = "bsc")] - if !self.provider().chain_spec().is_feynman_active_at_timestamp(block_env.timestamp.to()) { - let contracts = get_upgrade_system_contracts( - self.provider().chain_spec().as_ref(), - block_env.number.to(), - block_env.timestamp.to(), - parent_timestamp, - ) - .expect("get upgrade system contracts failed"); - - for (k, v) in contracts { - let account = evm.db_mut().load_account(k).map_err(|error| { - EthApiError::Internal(RethError::Other("load account failed".into())) - })?; - if account.account_state == NotExisting { - account.account_state = Touched; - } - account.info.code_hash = v.clone().unwrap().hash_slow(); - account.info.code = v; - } - } for tx in transactions { - // check if the transaction is a system transaction - // this should be done before return - #[cfg(feature = "bsc")] - if before_system_tx && is_system_transaction(&tx, tx.signer(), block_env.coinbase) { - let sys_acc = evm.db_mut().load_account(SYSTEM_ADDRESS).map_err(|error| { - EthApiError::Internal(RethError::Other("load account failed".into())) - })?; - let balance = sys_acc.info.balance; - if balance > U256::ZERO { - sys_acc.info.balance = U256::ZERO; - - let val_acc = - evm.db_mut().load_account(block_env.coinbase).map_err(|error| { - EthApiError::Internal(RethError::Other("load account failed".into())) - })?; - if val_acc.account_state == NotExisting { - val_acc.account_state = Touched; - } - val_acc.info.balance += balance; - } - - // try to upgrade system contracts between normal txs and system txs - // if feynman is active - if !self - .provider() - .chain_spec() - .is_feynman_active_at_timestamp(block_env.timestamp.to()) - { - let contracts = get_upgrade_system_contracts( - self.provider().chain_spec().as_ref(), - block_env.number.to(), - block_env.timestamp.to(), - parent_timestamp, - ) - .expect("get upgrade system contracts failed"); - - for (k, v) in contracts { - let account = evm.db_mut().load_account(k).map_err(|error| { - EthApiError::Internal(RethError::Other("load account failed".into())) - })?; - if account.account_state == NotExisting { - account.account_state = Touched; - } - account.info.code_hash = v.clone().unwrap().hash_slow(); - account.info.code = v; - } - } - - before_system_tx = false; - } - if tx.hash() == target_tx_hash { // reached the target transaction break @@ -774,11 +668,6 @@ pub trait Call: LoadState + SpawnBlocking { let sender = tx.signer(); self.evm_config().fill_tx_env(evm.tx_mut(), &tx.into_signed(), sender); - #[cfg(feature = "bsc")] - if !before_system_tx { - evm.tx_mut().bsc.is_system_transaction = Some(true); - }; - evm.transact_commit().map_err(Self::Error::from_evm_err)?; index += 1; } diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index e84dfa74c..ae577855b 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -1,16 +1,11 @@ //! Loads a pending block from database. Helper trait for `eth_` call and trace RPC methods. -#[cfg(feature = "bsc")] -use crate::FromEthApiError; use crate::FromEvmError; use alloy_primitives::B256; use alloy_rpc_types::{BlockId, TransactionInfo}; -use cfg_if::cfg_if; use futures::Future; use reth_chainspec::ChainSpecProvider; use reth_evm::{system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv}; -#[cfg(feature = "bsc")] -use reth_primitives::system_contracts::is_system_transaction; use reth_primitives::Header; use reth_revm::database::StateProviderDatabase; use reth_rpc_eth_types::{ @@ -198,16 +193,7 @@ pub trait Trace: LoadState { let parent_beacon_block_root = block.parent_beacon_block_root; let block_txs = block.into_transactions_ecrecovered(); - cfg_if! { - if #[cfg(feature = "bsc")] { - let parent_timestamp = LoadState::cache(self).get_block(parent_block).await - .map_err(Self::Error::from_eth_err)? - .map(|block| block.timestamp) - .ok_or_else(|| EthApiError::UnknownParentBlock)?; - } else { - let parent_timestamp = 0; - } - } + let parent_timestamp = 0; let this = self.clone(); self.spawn_with_state_at_block(parent_block.into(), move |state| { @@ -241,16 +227,7 @@ pub trait Trace: LoadState { parent_timestamp, )?; - cfg_if! { - if #[cfg(feature = "bsc")] { - let mut tx_env = Call::evm_config(&this).tx_env(&tx); - if is_system_transaction(&tx, tx.signer(), block_env.coinbase) { - tx_env.bsc.is_system_transaction = Some(true); - }; - } else { - let tx_env = Call::evm_config(&this).tx_env(&tx); - } - } + let tx_env = Call::evm_config(&this).tx_env(&tx); let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env); let (res, _) = diff --git a/crates/rpc/rpc-types-compat/src/engine/payload.rs b/crates/rpc/rpc-types-compat/src/engine/payload.rs index e1f2710ce..8820b16e6 100644 --- a/crates/rpc/rpc-types-compat/src/engine/payload.rs +++ b/crates/rpc/rpc-types-compat/src/engine/payload.rs @@ -20,11 +20,6 @@ pub fn try_payload_v1_to_block(payload: ExecutionPayloadV1) -> Result U256::ZERO { - sys_acc.info.balance = U256::ZERO; - - let val_acc = db - .load_account(block_env.coinbase) - .expect("load validator account failed"); - if val_acc.account_state == NotExisting { - val_acc.account_state = Touched; - } - val_acc.info.balance += balance; - } - - // try to upgrade system contracts between normal txs and system txs - // if feynman is active - if is_feynman_active { - let contracts = get_upgrade_system_contracts( - this.inner.provider.chain_spec().as_ref(), - block_env.number.to(), - block_env.timestamp.to(), - parent_timestamp, - ) - .expect("get upgrade system contracts failed"); - - for (k, v) in contracts { - let account = db.load_account(k).map_err(|error| { - EthApiError::Internal(RethError::Other( - "load account failed".into(), - )) - })?; - if account.account_state == NotExisting { - account.account_state = Touched; - } - account.info.code_hash = v.clone().unwrap().hash_slow(); - account.info.code = v; - } - } - - before_system_tx = false; - } - - cfg_if! { - if #[cfg(feature = "bsc")] { - let mut tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); - if !before_system_tx { - tx_env.bsc.is_system_transaction = Some(true); - }; - } else { - let tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); - } - } + let tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); let env = EnvWithHandlerCfg { env: Env::boxed(cfg.cfg_env.clone(), block_env.clone(), tx_env), @@ -265,15 +166,7 @@ where // we trace on top the block's parent block let parent = block.parent_hash; - cfg_if! { - if #[cfg(feature = "bsc")] { - let parent_timestamp = self.eth_api().block(parent.into()).await? - .map(|block| block.timestamp) - .ok_or_else(|| EthApiError::UnknownParentBlock)?; - } else { - let parent_timestamp = 0; - } - } + let parent_timestamp = 0; // Depending on EIP-2 we need to recover the transactions differently let transactions = @@ -327,15 +220,7 @@ where // its parent block's state let state_at = block.parent_hash; - cfg_if! { - if #[cfg(feature = "bsc")] { - let parent_timestamp = self.eth_api().block(state_at.into()).await? - .map(|block| block.timestamp) - .ok_or_else(|| EthApiError::UnknownParentBlock)?; - } else { - let parent_timestamp = 0; - } - } + let parent_timestamp = 0; self.trace_block( state_at.into(), @@ -368,15 +253,7 @@ where let block_hash = block.hash(); let block_txs = block.into_transactions_ecrecovered(); - cfg_if! { - if #[cfg(feature = "bsc")] { - let parent_timestamp = self.eth_api().block(state_at).await? - .map(|block| block.timestamp) - .ok_or_else(|| EthApiError::UnknownParentBlock)?; - } else { - let parent_timestamp = 0; - } - } + let parent_timestamp = 0; let this = self.clone(); self.eth_api() @@ -395,16 +272,7 @@ where parent_timestamp, )?; - cfg_if! { - if #[cfg(feature = "bsc")] { - let mut tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); - if is_system_transaction(&tx, tx.signer(), block_env.coinbase) { - tx_env.bsc.is_system_transaction = Some(true); - }; - } else { - let tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); - } - } + let tx_env = Call::evm_config(this.eth_api()).tx_env(&tx); let env = EnvWithHandlerCfg { env: Env::boxed(cfg.cfg_env.clone(), block_env, tx_env), diff --git a/crates/stages/stages/Cargo.toml b/crates/stages/stages/Cargo.toml index bf6a1b50d..5b58967a6 100644 --- a/crates/stages/stages/Cargo.toml +++ b/crates/stages/stages/Cargo.toml @@ -59,7 +59,7 @@ bincode.workspace = true reth-chainspec.workspace = true reth-primitives = { workspace = true, features = ["test-utils", "arbitrary"] } reth-db = { workspace = true, features = ["test-utils", "mdbx"] } -reth-evm-bsc.workspace = true +reth-bsc-evm.workspace = true reth-evm-ethereum.workspace = true reth-execution-errors.workspace = true reth-consensus = { workspace = true, features = ["test-utils"] } @@ -104,7 +104,7 @@ test-utils = [ "dep:tempfile", ] bsc = [ - "reth-evm-bsc/bsc", + "reth-bsc-evm/bsc", ] [[bench]] diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index f0a6aef1c..f53d25876 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -4,7 +4,6 @@ use std::{ }; use futures_util::TryStreamExt; -use tracing::*; use alloy_primitives::TxNumber; use reth_db::tables; diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index c534a0ddb..441f94583 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -16,7 +16,7 @@ use reth_blockchain_tree_api::{ InsertPayloadOk, }; use reth_chain_state::{ChainInfoTracker, ForkChoiceNotifications, ForkChoiceSubscriptions}; -use reth_chainspec::{ChainInfo, EthereumHardforks}; +use reth_chainspec::{ChainInfo, ChainSpec}; use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_node_types::NodeTypesWithDB; @@ -64,9 +64,9 @@ mod blockchain_provider; pub use blockchain_provider::BlockchainProvider2; /// Helper trait keeping common requirements of providers for [`NodeTypesWithDB`]. -pub trait ProviderNodeTypes: NodeTypesWithDB {} +pub trait ProviderNodeTypes: NodeTypesWithDB {} -impl ProviderNodeTypes for T where T: NodeTypesWithDB {} +impl ProviderNodeTypes for T where T: NodeTypesWithDB {} /// The main type for interacting with the blockchain. ///