├── .github └── workflows │ ├── apisec-scan.yml │ ├── debricked.yml │ ├── devskim.yml │ ├── lint.yml │ └── test.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── bin ├── n42 │ ├── Cargo.toml │ └── src │ │ ├── cli │ │ └── mod.rs │ │ ├── consensus_ext.rs │ │ ├── lib.rs │ │ ├── main.rs │ │ └── ress.rs └── reth │ ├── Cargo.toml │ └── src │ ├── cli │ └── mod.rs │ ├── lib.rs │ ├── main.rs │ └── ress.rs ├── crates ├── chainspec │ ├── Cargo.toml │ ├── res │ │ └── genesis │ │ │ ├── dev.json │ │ │ ├── goerli.json │ │ │ ├── holesky.json │ │ │ ├── hoodi.json │ │ │ ├── mainnet.json │ │ │ ├── n42.json │ │ │ ├── n42_devnet.json │ │ │ └── sepolia.json │ └── src │ │ ├── api.rs │ │ ├── constants.rs │ │ ├── info.rs │ │ ├── lib.rs │ │ └── spec.rs ├── consensus │ ├── common │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── validation.rs │ └── consensus │ │ ├── Cargo.toml │ │ └── src │ │ ├── lib.rs │ │ ├── noop.rs │ │ └── test_utils.rs ├── ethereum │ ├── cli │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── chainspec.rs │ │ │ ├── debug_cmd │ │ │ ├── build_block.rs │ │ │ ├── execution.rs │ │ │ ├── in_memory_merkle.rs │ │ │ ├── merkle.rs │ │ │ └── mod.rs │ │ │ ├── interface.rs │ │ │ └── lib.rs │ ├── evm │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── build.rs │ │ │ ├── config.rs │ │ │ ├── execute.rs │ │ │ ├── lib.rs │ │ │ ├── receipt.rs │ │ │ └── test_utils.rs │ ├── hardforks │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── display.rs │ │ │ ├── hardforks │ │ │ ├── dev.rs │ │ │ ├── mod.rs │ │ │ └── n42.rs │ │ │ └── lib.rs │ └── node │ │ ├── Cargo.toml │ │ ├── src │ │ ├── engine.rs │ │ ├── evm.rs │ │ ├── lib.rs │ │ ├── node.rs │ │ └── payload.rs │ │ └── tests │ │ ├── assets │ │ └── genesis.json │ │ ├── e2e │ │ ├── blobs.rs │ │ ├── dev.rs │ │ ├── eth.rs │ │ ├── main.rs │ │ ├── p2p.rs │ │ ├── pool.rs │ │ ├── rpc.rs │ │ └── utils.rs │ │ └── it │ │ ├── builder.rs │ │ ├── exex.rs │ │ └── main.rs ├── n42 │ ├── alloy-rpc-types-beacon │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ ├── constants.rs │ │ │ ├── events │ │ │ ├── attestation.rs │ │ │ ├── light_client_finality.rs │ │ │ ├── light_client_optimistic.rs │ │ │ └── mod.rs │ │ │ ├── examples │ │ │ ├── relay_builder_block_validation_request_v4.json │ │ │ ├── relay_signed_bid_submission_capella.ssz │ │ │ ├── relay_single_payload.json │ │ │ └── sidecar.json │ │ │ ├── header.rs │ │ │ ├── lib.rs │ │ │ ├── payload.rs │ │ │ ├── relay.rs │ │ │ ├── requests.rs │ │ │ ├── sidecar.rs │ │ │ └── withdrawals.rs │ ├── alloy-rpc-types-engine │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ ├── cancun.rs │ │ │ ├── error.rs │ │ │ ├── forkchoice.rs │ │ │ ├── identification.rs │ │ │ ├── jwt.rs │ │ │ ├── lib.rs │ │ │ ├── payload.rs │ │ │ ├── prague.rs │ │ │ ├── sidecar.rs │ │ │ ├── transition.rs │ │ │ └── version.rs │ ├── clique │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── apos.rs │ │ │ ├── lib.rs │ │ │ └── traits.rs │ ├── consensus-client │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── miner.rs │ ├── engine-primitives │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── attributes.rs │ │ │ └── lib.rs │ ├── engine-types │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── consensus.rs │ │ │ ├── lib.rs │ │ │ ├── network.rs │ │ │ ├── node.rs │ │ │ └── payload.rs │ ├── n42-testing │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── dev.rs │ │ │ ├── main.rs │ │ │ ├── snapshot_test_utils.rs │ │ │ └── utils.rs │ └── primitives │ │ ├── Cargo.toml │ │ └── src │ │ ├── lib.rs │ │ └── snapshot.rs ├── net │ ├── network-api │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── block.rs │ │ │ ├── downloaders.rs │ │ │ ├── error.rs │ │ │ ├── events.rs │ │ │ ├── lib.rs │ │ │ ├── noop.rs │ │ │ └── test_utils │ │ │ ├── mod.rs │ │ │ └── peers_manager.rs │ ├── network │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── benches │ │ │ ├── broadcast.rs │ │ │ └── tx_manager_hash_fetching.rs │ │ ├── docs │ │ │ └── mermaid │ │ │ │ ├── fetch-client.mmd │ │ │ │ ├── network-manager.mmd │ │ │ │ └── swarm.mmd │ │ ├── src │ │ │ ├── budget.rs │ │ │ ├── builder.rs │ │ │ ├── cache.rs │ │ │ ├── config.rs │ │ │ ├── discovery.rs │ │ │ ├── error.rs │ │ │ ├── eth_requests.rs │ │ │ ├── fetch │ │ │ │ ├── client.rs │ │ │ │ └── mod.rs │ │ │ ├── flattened_response.rs │ │ │ ├── import.rs │ │ │ ├── lib.rs │ │ │ ├── listener.rs │ │ │ ├── manager.rs │ │ │ ├── message.rs │ │ │ ├── metrics.rs │ │ │ ├── network.rs │ │ │ ├── peers.rs │ │ │ ├── protocol.rs │ │ │ ├── session │ │ │ │ ├── active.rs │ │ │ │ ├── conn.rs │ │ │ │ ├── counter.rs │ │ │ │ ├── handle.rs │ │ │ │ └── mod.rs │ │ │ ├── state.rs │ │ │ ├── swarm.rs │ │ │ ├── test_utils │ │ │ │ ├── init.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── testnet.rs │ │ │ │ └── transactions.rs │ │ │ ├── transactions │ │ │ │ ├── config.rs │ │ │ │ ├── constants.rs │ │ │ │ ├── fetcher.rs │ │ │ │ ├── mod.rs │ │ │ │ └── validation.rs │ │ │ └── trusted_peers_resolver.rs │ │ └── tests │ │ │ └── it │ │ │ ├── big_pooled_txs_req.rs │ │ │ ├── connect.rs │ │ │ ├── main.rs │ │ │ ├── multiplex.rs │ │ │ ├── requests.rs │ │ │ ├── session.rs │ │ │ ├── startup.rs │ │ │ ├── transaction_hash_fetching.rs │ │ │ └── txgossip.rs │ └── peers │ │ ├── Cargo.toml │ │ └── src │ │ ├── bootnodes │ │ ├── ast.rs │ │ ├── ethereum.rs │ │ ├── mod.rs │ │ └── optimism.rs │ │ ├── lib.rs │ │ ├── node_record.rs │ │ └── trusted_peer.rs ├── node │ ├── builder │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── docs │ │ │ └── mermaid │ │ │ │ └── builder.mmd │ │ └── src │ │ │ ├── aliases.rs │ │ │ ├── builder │ │ │ ├── add_ons.rs │ │ │ ├── mod.rs │ │ │ └── states.rs │ │ │ ├── components │ │ │ ├── builder.rs │ │ │ ├── consensus.rs │ │ │ ├── execute.rs │ │ │ ├── mod.rs │ │ │ ├── network.rs │ │ │ ├── payload.rs │ │ │ └── pool.rs │ │ │ ├── exex.rs │ │ │ ├── handle.rs │ │ │ ├── hooks.rs │ │ │ ├── launch │ │ │ ├── common.rs │ │ │ ├── debug.rs │ │ │ ├── engine.rs │ │ │ ├── exex.rs │ │ │ └── mod.rs │ │ │ ├── lib.rs │ │ │ ├── node.rs │ │ │ ├── rpc.rs │ │ │ └── setup.rs │ └── core │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ ├── args │ │ ├── benchmark_args.rs │ │ ├── database.rs │ │ ├── datadir_args.rs │ │ ├── debug.rs │ │ ├── dev.rs │ │ ├── engine.rs │ │ ├── error.rs │ │ ├── gas_price_oracle.rs │ │ ├── log.rs │ │ ├── mod.rs │ │ ├── network.rs │ │ ├── payload_builder.rs │ │ ├── pruning.rs │ │ ├── ress_args.rs │ │ ├── rpc_server.rs │ │ ├── rpc_state_cache.rs │ │ ├── stage.rs │ │ ├── txpool.rs │ │ └── types.rs │ │ ├── cli │ │ ├── config.rs │ │ └── mod.rs │ │ ├── dirs.rs │ │ ├── exit.rs │ │ ├── lib.rs │ │ ├── node_config.rs │ │ ├── utils.rs │ │ └── version.rs ├── primitives-traits │ ├── Cargo.toml │ └── src │ │ ├── account.rs │ │ ├── block │ │ ├── body.rs │ │ ├── error.rs │ │ ├── header.rs │ │ ├── mod.rs │ │ ├── recovered.rs │ │ └── sealed.rs │ │ ├── constants │ │ ├── gas_units.rs │ │ └── mod.rs │ │ ├── crypto.rs │ │ ├── error.rs │ │ ├── extended.rs │ │ ├── header │ │ ├── clique_utils.rs │ │ ├── error.rs │ │ ├── mod.rs │ │ ├── sealed.rs │ │ └── test_utils.rs │ │ ├── lib.rs │ │ ├── log.rs │ │ ├── node.rs │ │ ├── proofs.rs │ │ ├── receipt.rs │ │ ├── serde_bincode_compat.rs │ │ ├── size.rs │ │ ├── storage.rs │ │ ├── sync.rs │ │ ├── transaction │ │ ├── access_list.rs │ │ ├── error.rs │ │ ├── execute.rs │ │ ├── mod.rs │ │ ├── recover.rs │ │ ├── signature.rs │ │ └── signed.rs │ │ └── withdrawal.rs ├── rpc │ └── rpc-types-compat │ │ ├── Cargo.toml │ │ └── src │ │ ├── block.rs │ │ ├── lib.rs │ │ └── transaction.rs └── storage │ ├── db-api │ ├── Cargo.toml │ └── src │ │ ├── common.rs │ │ ├── cursor.rs │ │ ├── database.rs │ │ ├── database_metrics.rs │ │ ├── lib.rs │ │ ├── mock.rs │ │ ├── models │ │ ├── accounts.rs │ │ ├── blocks.rs │ │ ├── integer_list.rs │ │ ├── mod.rs │ │ ├── sharded_key.rs │ │ ├── snapshot.rs │ │ └── storage_sharded_key.rs │ │ ├── scale.rs │ │ ├── table.rs │ │ ├── tables │ │ ├── codecs │ │ │ ├── fuzz │ │ │ │ ├── inputs.rs │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ └── raw.rs │ │ ├── transaction.rs │ │ ├── unwind.rs │ │ └── utils.rs │ ├── db │ ├── Cargo.toml │ ├── benches │ │ ├── README.md │ │ ├── criterion.rs │ │ ├── get.rs │ │ ├── hash_keys.rs │ │ └── utils.rs │ └── src │ │ ├── implementation │ │ ├── mdbx │ │ │ ├── cursor.rs │ │ │ ├── mod.rs │ │ │ ├── tx.rs │ │ │ └── utils.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── lockfile.rs │ │ ├── mdbx.rs │ │ ├── metrics.rs │ │ ├── static_file │ │ ├── cursor.rs │ │ ├── mask.rs │ │ ├── masks.rs │ │ └── mod.rs │ │ ├── utils.rs │ │ └── version.rs │ ├── provider │ ├── Cargo.toml │ └── src │ │ ├── bundle_state │ │ ├── mod.rs │ │ └── state_reverts.rs │ │ ├── lib.rs │ │ ├── providers │ │ ├── blockchain_provider.rs │ │ ├── consistent.rs │ │ ├── consistent_view.rs │ │ ├── database │ │ │ ├── builder.rs │ │ │ ├── chain.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ └── provider.rs │ │ ├── mod.rs │ │ ├── state │ │ │ ├── historical.rs │ │ │ ├── latest.rs │ │ │ ├── macros.rs │ │ │ └── mod.rs │ │ └── static_file │ │ │ ├── jar.rs │ │ │ ├── manager.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ └── writer.rs │ │ ├── test_utils │ │ ├── blocks.rs │ │ ├── mock.rs │ │ ├── mod.rs │ │ └── noop.rs │ │ ├── traits │ │ ├── full.rs │ │ ├── mod.rs │ │ └── static_file_provider.rs │ │ └── writer │ │ └── mod.rs │ └── storage-api │ ├── Cargo.toml │ └── src │ ├── account.rs │ ├── block.rs │ ├── block_hash.rs │ ├── block_id.rs │ ├── block_indices.rs │ ├── block_writer.rs │ ├── chain.rs │ ├── chain_info.rs │ ├── database_provider.rs │ ├── full.rs │ ├── hashing.rs │ ├── header.rs │ ├── header_sync_gap.rs │ ├── history.rs │ ├── legacy.rs │ ├── lib.rs │ ├── noop.rs │ ├── ommers.rs │ ├── primitives.rs │ ├── prune_checkpoint.rs │ ├── receipts.rs │ ├── snapshot.rs │ ├── stage_checkpoint.rs │ ├── state.rs │ ├── state_writer.rs │ ├── stats.rs │ ├── storage.rs │ ├── transactions.rs │ ├── trie.rs │ └── withdrawals.rs └── update.sh /.github/workflows/devskim.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: DevSkim 7 | 8 | on: 9 | push: 10 | branches: [ "main" ] 11 | pull_request: 12 | branches: [ "main" ] 13 | schedule: 14 | - cron: '38 7 * * 0' 15 | 16 | jobs: 17 | lint: 18 | name: DevSkim 19 | runs-on: ubuntu-latest 20 | permissions: 21 | actions: read 22 | contents: read 23 | security-events: write 24 | steps: 25 | - name: Checkout code 26 | uses: actions/checkout@v4 27 | 28 | - name: Run DevSkim scanner 29 | uses: microsoft/DevSkim-Action@v1 30 | 31 | - name: Upload DevSkim scan results to GitHub Security tab 32 | uses: github/codeql-action/upload-sarif@v3 33 | with: 34 | sarif_file: devskim-results.sarif 35 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Clippy 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] # Or any other branches you want to lint 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | clippy_check: 14 | name: Clippy 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: Swatinem/rust-cache@v2 19 | - uses: dtolnay/rust-toolchain@stable 20 | with: 21 | components: clippy 22 | - name: Run Clippy 23 | #run: cargo clippy --workspace --all-targets -- -D warnings 24 | run: cargo clippy --workspace --lib --bins --all-features 25 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Install Rust toolchain 18 | uses: dtolnay/rust-toolchain@master 19 | with: 20 | toolchain: stable 21 | - name: Cache dependencies 22 | uses: Swatinem/rust-cache@v2 23 | - name: Run cargo check 24 | run: cargo check --verbose 25 | - name: Run tests 26 | run: cargo test -p n42-testing 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | ./debug/ 4 | target/ 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | # MSVC Windows builds of rustc generate these, which store debugging information 10 | *.pdb 11 | 12 | # Generated by Intellij-based IDEs. 13 | .idea 14 | 15 | # Generated by MacOS 16 | .DS_Store 17 | 18 | # Generated test-vectors for DB 19 | testdata/micro/db 20 | 21 | # Generated data for stage benchmarks 22 | crates/stages/testdata 23 | 24 | # Prometheus data dir 25 | data/ 26 | 27 | # Proptest data 28 | proptest-regressions/ 29 | 30 | # Release artifacts 31 | dist/ 32 | 33 | # Database debugging tools 34 | db-tools/ 35 | 36 | # VSCode 37 | .vscode 38 | 39 | # Coverage report 40 | lcov.info 41 | 42 | # Generated by ./etc/generate-jwt.sh 43 | jwttoken/ 44 | 45 | # Cache directory for CCLS, if using it with MDBX sources 46 | .ccls-cache/ 47 | 48 | # Generated by CMake due to MDBX sources 49 | crates/storage/libmdbx-rs/mdbx-sys/libmdbx/cmake-build-debug 50 | 51 | # Rust bug report 52 | rustc-ice-* 53 | /patch/ 54 | 55 | # Vim temporary files 56 | **/.*.swp 57 | **/.*.swo 58 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker.io/docker/dockerfile:1.7-labs 2 | FROM lukemathwalker/cargo-chef:latest-rust-1 as chef 3 | WORKDIR /app 4 | 5 | # Install system dependencies 6 | RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config 7 | 8 | ## Builds a cargo-chef plan 9 | #FROM chef AS planner 10 | #COPY . . 11 | #RUN cargo chef prepare --recipe-path recipe.json 12 | 13 | FROM chef AS builder 14 | #COPY --from=planner /app/recipe.json recipe.json 15 | 16 | # Build profile, release by default 17 | ARG BUILD_PROFILE=release 18 | ENV BUILD_PROFILE=$BUILD_PROFILE 19 | 20 | # Extra Cargo flags 21 | ARG RUSTFLAGS="" 22 | ENV RUSTFLAGS="$RUSTFLAGS" 23 | 24 | # Extra Cargo features 25 | ARG FEATURES="" 26 | ENV FEATURES=$FEATURES 27 | 28 | # Builds dependencies 29 | #RUN cargo chef cook --profile $BUILD_PROFILE --features "$FEATURES" --recipe-path recipe.json 30 | 31 | # Build application 32 | COPY --exclude=target . . 33 | RUN cargo build --profile $BUILD_PROFILE --features "$FEATURES" --locked --bin n42 34 | 35 | # ARG is not resolved in COPY so we have to hack around it by copying the 36 | # binary to a temporary location 37 | RUN cp /app/target/$BUILD_PROFILE/n42 /app/n42 38 | 39 | # Use Ubuntu as the release image 40 | FROM ubuntu AS runtime 41 | WORKDIR /app 42 | 43 | # Copy n42 over from the build stage 44 | COPY --from=builder /app/n42 /usr/local/bin 45 | 46 | # Copy licenses 47 | COPY LICENSE-* ./ 48 | 49 | EXPOSE 30303 30303/udp 9001 8545 8546 50 | ENTRYPOINT ["/usr/local/bin/n42"] 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2025 N42 Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/n42/src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | //! CLI definition and entrypoint to executable 2 | 3 | /// Re-export of the [`reth_node_core`] types specifically in the `cli` module. 4 | /// 5 | /// This is re-exported because the types in `reth_node_core::cli` originally existed in 6 | /// `reth::cli` but were moved to the [`reth_node_core`] crate. This re-export avoids a 7 | /// breaking change. 8 | pub use crate::core::cli::*; 9 | 10 | /// Re-export of the [`reth_ethereum_cli`] types specifically in the `interface` module. 11 | /// 12 | /// This is re-exported because the types in [`reth_ethereum_cli::interface`] originally 13 | /// existed in `reth::cli` but were moved to the [`reth_ethereum_cli`] crate. This re-export 14 | /// avoids a breaking change. 15 | pub use reth_ethereum_cli::interface::*; 16 | -------------------------------------------------------------------------------- /bin/n42/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | #[global_allocator] 4 | static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator(); 5 | 6 | use clap::Parser; 7 | use n42::{args::RessArgs, cli::Cli, ress::install_ress_subprotocol}; 8 | use n42_engine_types::{N42Node}; 9 | use reth_ethereum_cli::chainspec::EthereumChainSpecParser; 10 | use reth_node_builder::NodeHandle; 11 | use reth_node_ethereum::EthereumNode; 12 | use tracing::info; 13 | use n42::consensus_ext::{ConsensusExtApiServer, ConsensusExt}; 14 | 15 | fn main() { 16 | reth_cli_util::sigsegv_handler::install(); 17 | 18 | // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided. 19 | if std::env::var_os("RUST_BACKTRACE").is_none() { 20 | unsafe { std::env::set_var("RUST_BACKTRACE", "1") }; 21 | } 22 | 23 | if let Err(err) = 24 | Cli::::parse().run(async move |builder, ress_args| { 25 | info!(target: "reth::cli", "Launching node"); 26 | let NodeHandle { node, node_exit_future } = 27 | builder.node(N42Node::default()) 28 | .extend_rpc_modules(|ctx| { 29 | 30 | let consensus = ctx.consensus().clone(); 31 | let provider = ctx.provider().clone(); 32 | 33 | let ext = ConsensusExt { consensus, provider }; 34 | 35 | // now we merge our extension namespace into all configured transports 36 | ctx.auth_module.merge_auth_methods(ext.into_rpc())?; 37 | 38 | println!("consensus rpc extension enabled"); 39 | 40 | Ok(()) 41 | }) 42 | .launch_with_debug_capabilities().await?; 43 | 44 | // Install ress subprotocol. 45 | if ress_args.enabled { 46 | install_ress_subprotocol( 47 | ress_args, 48 | node.provider, 49 | node.evm_config, 50 | node.network, 51 | node.task_executor, 52 | node.add_ons_handle.engine_events.new_listener(), 53 | )?; 54 | } 55 | 56 | node_exit_future.await 57 | }) 58 | { 59 | eprintln!("Error: {err:?}"); 60 | std::process::exit(1); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /bin/n42/src/ress.rs: -------------------------------------------------------------------------------- 1 | use crate::network::PeersHandleProvider; 2 | use reth_ethereum_primitives::EthPrimitives; 3 | use reth_evm::ConfigureEvm; 4 | use reth_network::{protocol::IntoRlpxSubProtocol, NetworkProtocols}; 5 | use reth_network_api::FullNetwork; 6 | use reth_node_api::BeaconConsensusEngineEvent; 7 | use reth_node_core::args::RessArgs; 8 | use reth_provider::providers::{BlockchainProvider, ProviderNodeTypes}; 9 | use reth_ress_protocol::{NodeType, ProtocolState, RessProtocolHandler}; 10 | use reth_ress_provider::{maintain_pending_state, PendingState, RethRessProtocolProvider}; 11 | use reth_tasks::TaskExecutor; 12 | use reth_tokio_util::EventStream; 13 | use tokio::sync::mpsc; 14 | use tracing::*; 15 | 16 | /// Install `ress` subprotocol if it's enabled. 17 | pub fn install_ress_subprotocol( 18 | args: RessArgs, 19 | provider: BlockchainProvider

, 20 | evm_config: E, 21 | network: N, 22 | task_executor: TaskExecutor, 23 | engine_events: EventStream>, 24 | ) -> eyre::Result<()> 25 | where 26 | P: ProviderNodeTypes, 27 | E: ConfigureEvm + Clone + 'static, 28 | N: FullNetwork + NetworkProtocols + PeersHandleProvider, 29 | { 30 | info!(target: "reth::cli", "Installing ress subprotocol"); 31 | let pending_state = PendingState::default(); 32 | 33 | // Spawn maintenance task for pending state. 34 | task_executor.spawn(maintain_pending_state( 35 | engine_events, 36 | provider.clone(), 37 | pending_state.clone(), 38 | )); 39 | 40 | let (tx, mut rx) = mpsc::unbounded_channel(); 41 | let provider = RethRessProtocolProvider::new( 42 | provider, 43 | evm_config, 44 | Box::new(task_executor.clone()), 45 | args.max_witness_window, 46 | args.witness_max_parallel, 47 | args.witness_cache_size, 48 | pending_state, 49 | )?; 50 | network.add_rlpx_sub_protocol( 51 | RessProtocolHandler { 52 | provider, 53 | node_type: NodeType::Stateful, 54 | peers_handle: network.peers_handle().clone(), 55 | max_active_connections: args.max_active_connections, 56 | state: ProtocolState::new(tx), 57 | } 58 | .into_rlpx_sub_protocol(), 59 | ); 60 | info!(target: "reth::cli", "Ress subprotocol support enabled"); 61 | 62 | task_executor.spawn(async move { 63 | while let Some(event) = rx.recv().await { 64 | trace!(target: "reth::ress", ?event, "Received ress event"); 65 | } 66 | }); 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /bin/reth/src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | //! CLI definition and entrypoint to executable 2 | 3 | /// Re-export of the [`reth_node_core`] types specifically in the `cli` module. 4 | /// 5 | /// This is re-exported because the types in `reth_node_core::cli` originally existed in 6 | /// `reth::cli` but were moved to the [`reth_node_core`] crate. This re-export avoids a 7 | /// breaking change. 8 | pub use crate::core::cli::*; 9 | 10 | /// Re-export of the [`reth_ethereum_cli`] types specifically in the `interface` module. 11 | /// 12 | /// This is re-exported because the types in [`reth_ethereum_cli::interface`] originally 13 | /// existed in `reth::cli` but were moved to the [`reth_ethereum_cli`] crate. This re-export 14 | /// avoids a breaking change. 15 | pub use reth_ethereum_cli::interface::*; 16 | -------------------------------------------------------------------------------- /bin/reth/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | #[global_allocator] 4 | static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator(); 5 | 6 | use clap::Parser; 7 | use reth::{args::RessArgs, cli::Cli, ress::install_ress_subprotocol}; 8 | use reth_ethereum_cli::chainspec::EthereumChainSpecParser; 9 | use reth_node_builder::NodeHandle; 10 | use reth_node_ethereum::EthereumNode; 11 | use tracing::info; 12 | 13 | fn main() { 14 | reth_cli_util::sigsegv_handler::install(); 15 | 16 | // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided. 17 | if std::env::var_os("RUST_BACKTRACE").is_none() { 18 | unsafe { std::env::set_var("RUST_BACKTRACE", "1") }; 19 | } 20 | 21 | if let Err(err) = 22 | Cli::::parse().run(async move |builder, ress_args| { 23 | info!(target: "reth::cli", "Launching node"); 24 | let NodeHandle { node, node_exit_future } = 25 | builder.node(EthereumNode::default()).launch_with_debug_capabilities().await?; 26 | 27 | // Install ress subprotocol. 28 | if ress_args.enabled { 29 | install_ress_subprotocol( 30 | ress_args, 31 | node.provider, 32 | node.evm_config, 33 | node.network, 34 | node.task_executor, 35 | node.add_ons_handle.engine_events.new_listener(), 36 | )?; 37 | } 38 | 39 | node_exit_future.await 40 | }) 41 | { 42 | eprintln!("Error: {err:?}"); 43 | std::process::exit(1); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /bin/reth/src/ress.rs: -------------------------------------------------------------------------------- 1 | use crate::network::PeersHandleProvider; 2 | use reth_ethereum_primitives::EthPrimitives; 3 | use reth_evm::ConfigureEvm; 4 | use reth_network::{protocol::IntoRlpxSubProtocol, NetworkProtocols}; 5 | use reth_network_api::FullNetwork; 6 | use reth_node_api::BeaconConsensusEngineEvent; 7 | use reth_node_core::args::RessArgs; 8 | use reth_provider::providers::{BlockchainProvider, ProviderNodeTypes}; 9 | use reth_ress_protocol::{NodeType, ProtocolState, RessProtocolHandler}; 10 | use reth_ress_provider::{maintain_pending_state, PendingState, RethRessProtocolProvider}; 11 | use reth_tasks::TaskExecutor; 12 | use reth_tokio_util::EventStream; 13 | use tokio::sync::mpsc; 14 | use tracing::*; 15 | 16 | /// Install `ress` subprotocol if it's enabled. 17 | pub fn install_ress_subprotocol( 18 | args: RessArgs, 19 | provider: BlockchainProvider

, 20 | evm_config: E, 21 | network: N, 22 | task_executor: TaskExecutor, 23 | engine_events: EventStream>, 24 | ) -> eyre::Result<()> 25 | where 26 | P: ProviderNodeTypes, 27 | E: ConfigureEvm + Clone + 'static, 28 | N: FullNetwork + NetworkProtocols + PeersHandleProvider, 29 | { 30 | info!(target: "reth::cli", "Installing ress subprotocol"); 31 | let pending_state = PendingState::default(); 32 | 33 | // Spawn maintenance task for pending state. 34 | task_executor.spawn(maintain_pending_state( 35 | engine_events, 36 | provider.clone(), 37 | pending_state.clone(), 38 | )); 39 | 40 | let (tx, mut rx) = mpsc::unbounded_channel(); 41 | let provider = RethRessProtocolProvider::new( 42 | provider, 43 | evm_config, 44 | Box::new(task_executor.clone()), 45 | args.max_witness_window, 46 | args.witness_max_parallel, 47 | args.witness_cache_size, 48 | pending_state, 49 | )?; 50 | network.add_rlpx_sub_protocol( 51 | RessProtocolHandler { 52 | provider, 53 | node_type: NodeType::Stateful, 54 | peers_handle: network.peers_handle().clone(), 55 | max_active_connections: args.max_active_connections, 56 | state: ProtocolState::new(tx), 57 | } 58 | .into_rlpx_sub_protocol(), 59 | ); 60 | info!(target: "reth::cli", "Ress subprotocol support enabled"); 61 | 62 | task_executor.spawn(async move { 63 | while let Some(event) = rx.recv().await { 64 | trace!(target: "reth::ress", ?event, "Received ress event"); 65 | } 66 | }); 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /crates/chainspec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-chainspec" 3 | version.workspace = true 4 | edition.workspace = true 5 | homepage.workspace = true 6 | license.workspace = true 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | 13 | [dependencies] 14 | # reth 15 | reth-ethereum-forks.workspace = true 16 | reth-network-peers.workspace = true 17 | alloy-trie = { workspace = true, features = ["ethereum"] } 18 | reth-primitives-traits.workspace = true 19 | 20 | # ethereum 21 | alloy-evm.workspace = true 22 | alloy-chains = { workspace = true, features = ["serde", "rlp"] } 23 | alloy-eips = { workspace = true, features = ["serde"] } 24 | alloy-genesis.workspace = true 25 | alloy-primitives = { workspace = true, features = ["rlp"] } 26 | alloy-consensus.workspace = true 27 | 28 | # misc 29 | auto_impl.workspace = true 30 | serde_json.workspace = true 31 | derive_more.workspace = true 32 | 33 | [dev-dependencies] 34 | # eth 35 | alloy-trie = { workspace = true, features = ["arbitrary"] } 36 | alloy-eips = { workspace = true, features = ["arbitrary"] } 37 | alloy-rlp = { workspace = true, features = ["arrayvec"] } 38 | alloy-genesis.workspace = true 39 | 40 | [features] 41 | default = ["std"] 42 | std = [ 43 | "alloy-chains/std", 44 | "alloy-eips/std", 45 | "alloy-genesis/std", 46 | "alloy-primitives/std", 47 | "alloy-trie/std", 48 | "reth-primitives-traits/std", 49 | "alloy-consensus/std", 50 | "alloy-rlp/std", 51 | "reth-ethereum-forks/std", 52 | "derive_more/std", 53 | "reth-network-peers/std", 54 | "serde_json/std", 55 | "alloy-evm/std", 56 | ] 57 | arbitrary = [ 58 | "alloy-chains/arbitrary", 59 | "reth-ethereum-forks/arbitrary", 60 | "reth-primitives-traits/arbitrary", 61 | "alloy-consensus/arbitrary", 62 | "alloy-eips/arbitrary", 63 | "alloy-primitives/arbitrary", 64 | "alloy-trie/arbitrary", 65 | ] 66 | test-utils = [ 67 | "reth-primitives-traits/test-utils", 68 | ] 69 | -------------------------------------------------------------------------------- /crates/chainspec/res/genesis/dev.json: -------------------------------------------------------------------------------- 1 | {"nonce":"0x0","timestamp":"0x6490fdd2","extraData":"0x","gasLimit":"0x1c9c380","difficulty":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494","alloc":{"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266":{"balance":"0xD3C21BCECCEDA1000000"},"0x70997970C51812dc3A010C7d01b50e0d17dc79C8":{"balance":"0xD3C21BCECCEDA1000000"},"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC":{"balance":"0xD3C21BCECCEDA1000000"},"0x90F79bf6EB2c4f870365E785982E1f101E93b906":{"balance":"0xD3C21BCECCEDA1000000"},"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65":{"balance":"0xD3C21BCECCEDA1000000"},"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc":{"balance":"0xD3C21BCECCEDA1000000"},"0x976EA74026E726554dB657fA54763abd0C3a0aa9":{"balance":"0xD3C21BCECCEDA1000000"},"0x14dC79964da2C08b23698B3D3cc7Ca32193d9955":{"balance":"0xD3C21BCECCEDA1000000"},"0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f":{"balance":"0xD3C21BCECCEDA1000000"},"0xa0Ee7A142d267C1f36714E4a8F75612F20a79720":{"balance":"0xD3C21BCECCEDA1000000"},"0xBcd4042DE499D14e55001CcbB24a551F3b954096":{"balance":"0xD3C21BCECCEDA1000000"},"0x71bE63f3384f5fb98995898A86B02Fb2426c5788":{"balance":"0xD3C21BCECCEDA1000000"},"0xFABB0ac9d68B0B445fB7357272Ff202C5651694a":{"balance":"0xD3C21BCECCEDA1000000"},"0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec":{"balance":"0xD3C21BCECCEDA1000000"},"0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097":{"balance":"0xD3C21BCECCEDA1000000"},"0xcd3B766CCDd6AE721141F452C550Ca635964ce71":{"balance":"0xD3C21BCECCEDA1000000"},"0x2546BcD3c84621e976D8185a91A922aE77ECEc30":{"balance":"0xD3C21BCECCEDA1000000"},"0xbDA5747bFD65F08deb54cb465eB87D40e51B197E":{"balance":"0xD3C21BCECCEDA1000000"},"0xdD2FD4581271e230360230F9337D5c0430Bf44C0":{"balance":"0xD3C21BCECCEDA1000000"},"0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199":{"balance":"0xD3C21BCECCEDA1000000"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000"} -------------------------------------------------------------------------------- /crates/chainspec/res/genesis/sepolia.json: -------------------------------------------------------------------------------- 1 | { 2 | "nonce": "0x00", 3 | "timestamp": "0x6159af19", 4 | "extraData": "0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521", 5 | "gasLimit": "0x1c9c380", 6 | "difficulty": "0x20000", 7 | "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 8 | "coinbase": "0x0000000000000000000000000000000000000000", 9 | "stateRoot": "0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494", 10 | "alloc": { 11 | "0xa2A6d93439144FFE4D27c9E088dCD8b783946263": { 12 | "balance": "0xD3C21BCECCEDA1000000" 13 | }, 14 | "0xBc11295936Aa79d594139de1B2e12629414F3BDB": { 15 | "balance": "0xD3C21BCECCEDA1000000" 16 | }, 17 | "0x7cF5b79bfe291A67AB02b393E456cCc4c266F753": { 18 | "balance": "0xD3C21BCECCEDA1000000" 19 | }, 20 | "0xaaec86394441f915bce3e6ab399977e9906f3b69": { 21 | "balance": "0xD3C21BCECCEDA1000000" 22 | }, 23 | "0xF47CaE1CF79ca6758Bfc787dbD21E6bdBe7112B8": { 24 | "balance": "0xD3C21BCECCEDA1000000" 25 | }, 26 | "0xd7eDDB78ED295B3C9629240E8924fb8D8874ddD8": { 27 | "balance": "0xD3C21BCECCEDA1000000" 28 | }, 29 | "0x8b7F0977Bb4f0fBE7076FA22bC24acA043583F5e": { 30 | "balance": "0xD3C21BCECCEDA1000000" 31 | }, 32 | "0xe2e2659028143784d557bcec6ff3a0721048880a": { 33 | "balance": "0xD3C21BCECCEDA1000000" 34 | }, 35 | "0xd9a5179f091d85051d3c982785efd1455cec8699": { 36 | "balance": "0xD3C21BCECCEDA1000000" 37 | }, 38 | "0xbeef32ca5b9a198d27B4e02F4c70439fE60356Cf": { 39 | "balance": "0xD3C21BCECCEDA1000000" 40 | }, 41 | "0x0000006916a87b82333f4245046623b23794c65c": { 42 | "balance": "0x84595161401484A000000" 43 | }, 44 | "0xb21c33de1fab3fa15499c62b59fe0cc3250020d1": { 45 | "balance": "0x52B7D2DCC80CD2E4000000" 46 | }, 47 | "0x10F5d45854e038071485AC9e402308cF80D2d2fE": { 48 | "balance": "0x52B7D2DCC80CD2E4000000" 49 | }, 50 | "0xd7d76c58b3a519e9fA6Cc4D22dC017259BC49F1E": { 51 | "balance": "0x52B7D2DCC80CD2E4000000" 52 | }, 53 | "0x799D329e5f583419167cD722962485926E338F4a": { 54 | "balance": "0xDE0B6B3A7640000" 55 | } 56 | }, 57 | "number": "0x0", 58 | "gasUsed": "0x0", 59 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" 60 | } -------------------------------------------------------------------------------- /crates/chainspec/src/constants.rs: -------------------------------------------------------------------------------- 1 | use crate::spec::DepositContract; 2 | use alloy_eips::eip6110::MAINNET_DEPOSIT_CONTRACT_ADDRESS; 3 | use alloy_primitives::b256; 4 | 5 | /// Gas per transaction not creating a contract. 6 | pub const MIN_TRANSACTION_GAS: u64 = 21_000u64; 7 | 8 | /// Mainnet prune delete limit. 9 | pub const MAINNET_PRUNE_DELETE_LIMIT: usize = 20000; 10 | 11 | /// Deposit contract address: `0x00000000219ab540356cbb839cbe05303d7705fa` 12 | pub(crate) const MAINNET_DEPOSIT_CONTRACT: DepositContract = DepositContract::new( 13 | MAINNET_DEPOSIT_CONTRACT_ADDRESS, 14 | 11052984, 15 | b256!("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"), 16 | ); 17 | -------------------------------------------------------------------------------- /crates/chainspec/src/info.rs: -------------------------------------------------------------------------------- 1 | use alloy_eips::BlockNumHash; 2 | use alloy_primitives::{BlockNumber, B256}; 3 | 4 | /// Current status of the blockchain's head. 5 | #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] 6 | pub struct ChainInfo { 7 | /// The block hash of the highest fully synced block. 8 | pub best_hash: B256, 9 | /// The block number of the highest fully synced block. 10 | pub best_number: BlockNumber, 11 | } 12 | 13 | impl From for BlockNumHash { 14 | fn from(value: ChainInfo) -> Self { 15 | Self { number: value.best_number, hash: value.best_hash } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/consensus/common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-consensus-common" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | 13 | [dependencies] 14 | # reth 15 | reth-chainspec.workspace = true 16 | reth-consensus.workspace = true 17 | 18 | # ethereum 19 | reth-primitives-traits.workspace = true 20 | alloy-consensus.workspace = true 21 | alloy-eips.workspace = true 22 | 23 | [dev-dependencies] 24 | alloy-primitives = { workspace = true, features = ["rand"] } 25 | reth-ethereum-primitives.workspace = true 26 | alloy-consensus.workspace = true 27 | rand.workspace = true 28 | 29 | [features] 30 | default = ["std"] 31 | std = [ 32 | "alloy-consensus/std", 33 | "alloy-eips/std", 34 | "reth-chainspec/std", 35 | "reth-consensus/std", 36 | "reth-primitives-traits/std", 37 | "reth-ethereum-primitives/std", 38 | "alloy-primitives/std", 39 | ] 40 | -------------------------------------------------------------------------------- /crates/consensus/common/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Commonly used consensus methods. 2 | 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 5 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 6 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 7 | )] 8 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 9 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 10 | #![cfg_attr(not(feature = "std"), no_std)] 11 | 12 | /// Collection of consensus validation methods. 13 | pub mod validation; 14 | -------------------------------------------------------------------------------- /crates/consensus/consensus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-consensus" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | 13 | [dependencies] 14 | # reth 15 | reth-execution-types.workspace = true 16 | reth-primitives-traits.workspace = true 17 | 18 | # ethereum 19 | alloy-primitives.workspace = true 20 | alloy-consensus.workspace = true 21 | 22 | # misc 23 | auto_impl.workspace = true 24 | thiserror.workspace = true 25 | 26 | # n42 27 | n42-primitives.workspace = true 28 | 29 | [features] 30 | default = ["std"] 31 | std = [ 32 | "reth-primitives-traits/std", 33 | "alloy-primitives/std", 34 | "alloy-consensus/std", 35 | "reth-primitives-traits/std", 36 | "reth-execution-types/std", 37 | "thiserror/std", 38 | ] 39 | test-utils = [ 40 | "reth-primitives-traits/test-utils", 41 | ] 42 | -------------------------------------------------------------------------------- /crates/consensus/consensus/src/noop.rs: -------------------------------------------------------------------------------- 1 | use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator}; 2 | use alloc::sync::Arc; 3 | use reth_execution_types::BlockExecutionResult; 4 | use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader}; 5 | 6 | /// A Consensus implementation that does nothing. 7 | #[derive(Debug, Copy, Clone, Default)] 8 | #[non_exhaustive] 9 | pub struct NoopConsensus; 10 | 11 | impl NoopConsensus { 12 | /// Creates an Arc instance of Self. 13 | pub fn arc() -> Arc { 14 | Arc::new(Self::default()) 15 | } 16 | } 17 | 18 | impl HeaderValidator for NoopConsensus { 19 | fn validate_header(&self, _header: &SealedHeader) -> Result<(), ConsensusError> { 20 | Ok(()) 21 | } 22 | 23 | fn validate_header_against_parent( 24 | &self, 25 | _header: &SealedHeader, 26 | _parent: &SealedHeader, 27 | ) -> Result<(), ConsensusError> { 28 | Ok(()) 29 | } 30 | } 31 | 32 | impl Consensus for NoopConsensus { 33 | type Error = ConsensusError; 34 | 35 | fn validate_body_against_header( 36 | &self, 37 | _body: &B::Body, 38 | _header: &SealedHeader, 39 | ) -> Result<(), Self::Error> { 40 | Ok(()) 41 | } 42 | 43 | fn validate_block_pre_execution(&self, _block: &SealedBlock) -> Result<(), Self::Error> { 44 | Ok(()) 45 | } 46 | } 47 | 48 | impl FullConsensus for NoopConsensus { 49 | fn validate_block_post_execution( 50 | &self, 51 | _block: &RecoveredBlock, 52 | _result: &BlockExecutionResult, 53 | ) -> Result<(), ConsensusError> { 54 | Ok(()) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/ethereum/cli/src/debug_cmd/mod.rs: -------------------------------------------------------------------------------- 1 | //! `reth debug` command. Collection of various debugging routines. 2 | 3 | use clap::{Parser, Subcommand}; 4 | use reth_chainspec::ChainSpec; 5 | use reth_cli::chainspec::ChainSpecParser; 6 | use reth_cli_commands::common::CliNodeTypes; 7 | use reth_cli_runner::CliContext; 8 | use reth_ethereum_primitives::EthPrimitives; 9 | use reth_node_ethereum::EthEngineTypes; 10 | use std::sync::Arc; 11 | 12 | mod build_block; 13 | mod execution; 14 | mod in_memory_merkle; 15 | mod merkle; 16 | 17 | /// `reth debug` command 18 | #[derive(Debug, Parser)] 19 | pub struct Command { 20 | #[command(subcommand)] 21 | command: Subcommands, 22 | } 23 | 24 | /// `reth debug` subcommands 25 | #[derive(Subcommand, Debug)] 26 | pub enum Subcommands { 27 | /// Debug the roundtrip execution of blocks as well as the generated data. 28 | Execution(execution::Command), 29 | /// Debug the clean & incremental state root calculations. 30 | Merkle(merkle::Command), 31 | /// Debug in-memory state root calculation. 32 | InMemoryMerkle(in_memory_merkle::Command), 33 | /// Debug block building. 34 | BuildBlock(build_block::Command), 35 | } 36 | 37 | impl> Command { 38 | /// Execute `debug` command 39 | pub async fn execute< 40 | N: CliNodeTypes< 41 | Payload = EthEngineTypes, 42 | Primitives = EthPrimitives, 43 | ChainSpec = C::ChainSpec, 44 | >, 45 | >( 46 | self, 47 | ctx: CliContext, 48 | ) -> eyre::Result<()> { 49 | match self.command { 50 | Subcommands::Execution(command) => command.execute::(ctx).await, 51 | Subcommands::Merkle(command) => command.execute::(ctx).await, 52 | Subcommands::InMemoryMerkle(command) => command.execute::(ctx).await, 53 | Subcommands::BuildBlock(command) => command.execute::(ctx).await, 54 | } 55 | } 56 | } 57 | 58 | impl Command { 59 | /// Returns the underlying chain being used to run this command 60 | pub const fn chain_spec(&self) -> Option<&Arc> { 61 | match &self.command { 62 | Subcommands::Execution(command) => command.chain_spec(), 63 | Subcommands::Merkle(command) => command.chain_spec(), 64 | Subcommands::InMemoryMerkle(command) => command.chain_spec(), 65 | Subcommands::BuildBlock(command) => command.chain_spec(), 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /crates/ethereum/cli/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Reth CLI implementation. 2 | 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 5 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 6 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 7 | )] 8 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 9 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 10 | 11 | /// Chain specification parser. 12 | pub mod chainspec; 13 | pub mod debug_cmd; 14 | pub mod interface; 15 | pub use interface::Cli; 16 | 17 | #[cfg(test)] 18 | mod test { 19 | use crate::chainspec::EthereumChainSpecParser; 20 | use clap::Parser; 21 | use reth_chainspec::DEV; 22 | use reth_cli_commands::NodeCommand; 23 | 24 | #[test] 25 | #[ignore = "reth cmd will print op-reth output if optimism feature enabled"] 26 | fn parse_dev() { 27 | let cmd: NodeCommand = NodeCommand::parse_from(["reth", "--dev"]); 28 | let chain = DEV.clone(); 29 | assert_eq!(cmd.chain.chain, chain.chain); 30 | assert_eq!(cmd.chain.genesis_hash(), chain.genesis_hash()); 31 | assert_eq!( 32 | cmd.chain.paris_block_and_final_difficulty, 33 | chain.paris_block_and_final_difficulty 34 | ); 35 | assert_eq!(cmd.chain.hardforks, chain.hardforks); 36 | 37 | assert!(cmd.rpc.http); 38 | assert!(cmd.network.discovery.disable_discovery); 39 | 40 | assert!(cmd.dev.dev); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/ethereum/evm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-evm-ethereum" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | 13 | [dependencies] 14 | # Reth 15 | reth-execution-types.workspace = true 16 | reth-chainspec.workspace = true 17 | reth-ethereum-forks.workspace = true 18 | reth-primitives-traits.workspace = true 19 | reth-ethereum-primitives.workspace = true 20 | revm.workspace = true 21 | reth-evm.workspace = true 22 | 23 | # Alloy 24 | alloy-primitives.workspace = true 25 | alloy-eips.workspace = true 26 | alloy-evm.workspace = true 27 | alloy-consensus.workspace = true 28 | 29 | # Misc 30 | parking_lot = { workspace = true, optional = true } 31 | derive_more = { workspace = true, optional = true } 32 | 33 | [dev-dependencies] 34 | reth-testing-utils.workspace = true 35 | reth-evm = { workspace = true, features = ["test-utils"] } 36 | reth-execution-types.workspace = true 37 | secp256k1.workspace = true 38 | alloy-genesis.workspace = true 39 | 40 | [features] 41 | default = ["std"] 42 | std = [ 43 | "alloy-consensus/std", 44 | "alloy-eips/std", 45 | "alloy-genesis/std", 46 | "alloy-primitives/std", 47 | "secp256k1/std", 48 | "reth-ethereum-forks/std", 49 | "reth-chainspec/std", 50 | "alloy-evm/std", 51 | "reth-execution-types/std", 52 | "reth-evm/std", 53 | "reth-primitives-traits/std", 54 | "revm/std", 55 | "reth-ethereum-primitives/std", 56 | "derive_more?/std", 57 | ] 58 | test-utils = [ 59 | "dep:parking_lot", 60 | "dep:derive_more", 61 | "reth-chainspec/test-utils", 62 | "reth-ethereum-primitives/test-utils", 63 | "reth-evm/test-utils", 64 | "reth-primitives-traits/test-utils", 65 | ] 66 | -------------------------------------------------------------------------------- /crates/ethereum/evm/src/receipt.rs: -------------------------------------------------------------------------------- 1 | use alloy_evm::eth::receipt_builder::{ReceiptBuilder, ReceiptBuilderCtx}; 2 | use reth_ethereum_primitives::{Receipt, TransactionSigned}; 3 | use reth_evm::Evm; 4 | 5 | /// A builder that operates on Reth primitive types, specifically [`TransactionSigned`] and 6 | /// [`Receipt`]. 7 | #[derive(Debug, Clone, Copy, Default)] 8 | #[non_exhaustive] 9 | pub struct RethReceiptBuilder; 10 | 11 | impl ReceiptBuilder for RethReceiptBuilder { 12 | type Transaction = TransactionSigned; 13 | type Receipt = Receipt; 14 | 15 | fn build_receipt( 16 | &self, 17 | ctx: ReceiptBuilderCtx<'_, Self::Transaction, E>, 18 | ) -> Self::Receipt { 19 | let ReceiptBuilderCtx { tx, result, cumulative_gas_used, .. } = ctx; 20 | Receipt { 21 | tx_type: tx.tx_type(), 22 | // Success flag was added in `EIP-658: Embedding transaction status code in 23 | // receipts`. 24 | success: result.is_success(), 25 | cumulative_gas_used, 26 | logs: result.into_logs(), 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/ethereum/hardforks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-ethereum-forks" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | description = "Ethereum fork types used in reth." 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [dependencies] 15 | # ethereum 16 | alloy-hardforks.workspace = true 17 | alloy-eip2124.workspace = true 18 | alloy-primitives = { workspace = true, features = ["serde", "rlp"] } 19 | 20 | # misc 21 | once_cell.workspace = true 22 | rustc-hash = { workspace = true, optional = true } 23 | 24 | # arbitrary utils 25 | arbitrary = { workspace = true, features = ["derive"], optional = true } 26 | auto_impl.workspace = true 27 | 28 | [dev-dependencies] 29 | arbitrary = { workspace = true, features = ["derive"] } 30 | 31 | [features] 32 | default = ["std", "serde", "rustc-hash"] 33 | arbitrary = [ 34 | "dep:arbitrary", 35 | "alloy-primitives/arbitrary", 36 | "alloy-eip2124/arbitrary", 37 | ] 38 | serde = [ 39 | "alloy-primitives/serde", 40 | "alloy-eip2124/serde", 41 | "alloy-hardforks/serde", 42 | ] 43 | std = [ 44 | "alloy-primitives/std", 45 | "rustc-hash/std", 46 | "alloy-eip2124/std", 47 | "once_cell/std", 48 | ] 49 | rustc-hash = ["dep:rustc-hash"] 50 | -------------------------------------------------------------------------------- /crates/ethereum/hardforks/src/hardforks/dev.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec; 2 | 3 | use alloy_primitives::U256; 4 | 5 | use once_cell as _; 6 | #[cfg(not(feature = "std"))] 7 | use once_cell::sync::Lazy as LazyLock; 8 | #[cfg(feature = "std")] 9 | use std::sync::LazyLock; 10 | 11 | use crate::{ChainHardforks, EthereumHardfork, ForkCondition, Hardfork}; 12 | 13 | /// Dev hardforks 14 | pub static DEV_HARDFORKS: LazyLock = LazyLock::new(|| { 15 | ChainHardforks::new(vec![ 16 | (EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)), 17 | (EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)), 18 | (EthereumHardfork::Dao.boxed(), ForkCondition::Block(0)), 19 | (EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)), 20 | (EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)), 21 | (EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)), 22 | (EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)), 23 | (EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)), 24 | (EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)), 25 | (EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)), 26 | (EthereumHardfork::London.boxed(), ForkCondition::Block(0)), 27 | ( 28 | EthereumHardfork::Paris.boxed(), 29 | ForkCondition::TTD { 30 | activation_block_number: 0, 31 | fork_block: None, 32 | total_difficulty: U256::ZERO, 33 | }, 34 | ), 35 | (EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(0)), 36 | (EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(0)), 37 | (EthereumHardfork::Prague.boxed(), ForkCondition::Timestamp(0)), 38 | ]) 39 | }); 40 | -------------------------------------------------------------------------------- /crates/ethereum/hardforks/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Ethereum fork types used in reth. 2 | //! 3 | //! This crate contains Ethereum fork types and helper functions. 4 | //! 5 | //! ## Feature Flags 6 | //! 7 | //! - `arbitrary`: Adds `arbitrary` support for primitive types. 8 | 9 | #![doc( 10 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 11 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 12 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 13 | )] 14 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 15 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 16 | #![cfg_attr(not(feature = "std"), no_std)] 17 | 18 | extern crate alloc; 19 | 20 | /// Re-exported [EIP-2124](https://eips.ethereum.org/EIPS/eip-2124) forkid types. 21 | pub use alloy_eip2124::*; 22 | 23 | mod display; 24 | mod hardforks; 25 | 26 | pub use alloy_hardforks::*; 27 | 28 | pub use display::DisplayHardforks; 29 | pub use hardforks::*; 30 | 31 | #[cfg(any(test, feature = "arbitrary"))] 32 | pub use arbitrary; 33 | -------------------------------------------------------------------------------- /crates/ethereum/node/src/evm.rs: -------------------------------------------------------------------------------- 1 | //! Ethereum EVM support 2 | 3 | #[doc(inline)] 4 | pub use reth_evm_ethereum::execute::EthExecutorProvider; 5 | #[doc(inline)] 6 | pub use reth_evm_ethereum::{EthEvm, EthEvmConfig}; 7 | -------------------------------------------------------------------------------- /crates/ethereum/node/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Standalone crate for ethereum-specific Reth configuration and builder types. 2 | //! 3 | //! # features 4 | //! - `js-tracer`: Enable the `JavaScript` tracer for the `debug_trace` endpoints 5 | 6 | #![doc( 7 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 8 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 9 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 10 | )] 11 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 12 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 13 | 14 | use reth_revm as _; 15 | use revm as _; 16 | 17 | pub use reth_ethereum_engine_primitives::EthEngineTypes; 18 | 19 | pub mod evm; 20 | pub use evm::{EthEvmConfig, EthExecutorProvider}; 21 | 22 | pub use reth_ethereum_consensus as consensus; 23 | pub mod node; 24 | pub use node::{EthereumEthApiBuilder, EthereumNode}; 25 | 26 | pub mod payload; 27 | 28 | pub mod engine; 29 | pub use engine::EthereumEngineValidator; 30 | -------------------------------------------------------------------------------- /crates/ethereum/node/src/payload.rs: -------------------------------------------------------------------------------- 1 | //! Payload component configuration for the Ethereum node. 2 | 3 | use reth_chainspec::{EthChainSpec, EthereumHardforks}; 4 | use reth_ethereum_engine_primitives::{ 5 | EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, 6 | }; 7 | use reth_ethereum_payload_builder::EthereumBuilderConfig; 8 | use reth_ethereum_primitives::EthPrimitives; 9 | use reth_evm::ConfigureEvm; 10 | use reth_node_api::{FullNodeTypes, NodeTypes, PrimitivesTy, TxTy}; 11 | use reth_node_builder::{ 12 | components::PayloadBuilderBuilder, BuilderContext, PayloadBuilderConfig, PayloadTypes, 13 | }; 14 | use reth_transaction_pool::{PoolTransaction, TransactionPool}; 15 | 16 | /// A basic ethereum payload service. 17 | #[derive(Clone, Default, Debug)] 18 | #[non_exhaustive] 19 | pub struct EthereumPayloadBuilder; 20 | 21 | impl PayloadBuilderBuilder for EthereumPayloadBuilder 22 | where 23 | Types: NodeTypes, 24 | Node: FullNodeTypes, 25 | Pool: TransactionPool>> 26 | + Unpin 27 | + 'static, 28 | Evm: ConfigureEvm< 29 | Primitives = PrimitivesTy, 30 | NextBlockEnvCtx = reth_evm::NextBlockEnvAttributes, 31 | > + 'static, 32 | Types::Payload: PayloadTypes< 33 | BuiltPayload = EthBuiltPayload, 34 | PayloadAttributes = EthPayloadAttributes, 35 | PayloadBuilderAttributes = EthPayloadBuilderAttributes, 36 | >, 37 | { 38 | type PayloadBuilder = 39 | reth_ethereum_payload_builder::EthereumPayloadBuilder; 40 | 41 | async fn build_payload_builder( 42 | self, 43 | ctx: &BuilderContext, 44 | pool: Pool, 45 | evm_config: Evm, 46 | ) -> eyre::Result { 47 | let conf = ctx.payload_builder_config(); 48 | let chain = ctx.chain_spec().chain(); 49 | let gas_limit = conf.gas_limit_for(chain); 50 | 51 | Ok(reth_ethereum_payload_builder::EthereumPayloadBuilder::new( 52 | ctx.provider().clone(), 53 | pool, 54 | evm_config, 55 | EthereumBuilderConfig::new().with_gas_limit(gas_limit), 56 | )) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/ethereum/node/tests/assets/genesis.json: -------------------------------------------------------------------------------- 1 | {"config":{"chainId":1,"homesteadBlock":0,"daoForkSupport":true,"eip150Block":0,"eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"berlinBlock":0,"londonBlock":0,"arrowGlacierBlock":0,"grayGlacierBlock":0,"shanghaiTime":0,"cancunTime":0,"terminalTotalDifficulty":"0x0","terminalTotalDifficultyPassed":true},"nonce":"0x0","timestamp":"0x0","extraData":"0x00","gasLimit":"0x1c9c380","difficulty":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","alloc":{"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"balance":"0xd3c21bcecceda1000000"},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"balance":"0xd3c21bcecceda1000000"},"0x1cbd3b2770909d4e10f157cabc84c7264073c9ec":{"balance":"0xd3c21bcecceda1000000"},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"balance":"0xd3c21bcecceda1000000"},"0x2546bcd3c84621e976d8185a91a922ae77ecec30":{"balance":"0xd3c21bcecceda1000000"},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"balance":"0xd3c21bcecceda1000000"},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"balance":"0xd3c21bcecceda1000000"},"0x71be63f3384f5fb98995898a86b02fb2426c5788":{"balance":"0xd3c21bcecceda1000000"},"0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199":{"balance":"0xd3c21bcecceda1000000"},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"balance":"0xd3c21bcecceda1000000"},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"balance":"0xd3c21bcecceda1000000"},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"balance":"0xd3c21bcecceda1000000"},"0x9c41de96b2088cdc640c6182dfcf5491dc574a57":{"balance":"0xd3c21bcecceda1000000"},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"balance":"0xd3c21bcecceda1000000"},"0xbcd4042de499d14e55001ccbb24a551f3b954096":{"balance":"0xd3c21bcecceda1000000"},"0xbda5747bfd65f08deb54cb465eb87d40e51b197e":{"balance":"0xd3c21bcecceda1000000"},"0xcd3b766ccdd6ae721141f452c550ca635964ce71":{"balance":"0xd3c21bcecceda1000000"},"0xdd2fd4581271e230360230f9337d5c0430bf44c0":{"balance":"0xd3c21bcecceda1000000"},"0xdf3e18d64bc6a983f673ab319ccae4f1a57c7097":{"balance":"0xd3c21bcecceda1000000"},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"balance":"0xd3c21bcecceda1000000"},"0xfabb0ac9d68b0b445fb7357272ff202c5651694a":{"balance":"0xd3c21bcecceda1000000"}},"number":"0x0"} 2 | -------------------------------------------------------------------------------- /crates/ethereum/node/tests/e2e/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | mod blobs; 4 | mod dev; 5 | mod eth; 6 | mod p2p; 7 | mod pool; 8 | mod rpc; 9 | mod utils; 10 | 11 | const fn main() {} 12 | -------------------------------------------------------------------------------- /crates/ethereum/node/tests/it/builder.rs: -------------------------------------------------------------------------------- 1 | //! Node builder setup tests. 2 | 3 | use std::sync::Arc; 4 | 5 | use reth_db::{ 6 | test_utils::{create_test_rw_db, TempDatabase}, 7 | DatabaseEnv, 8 | }; 9 | use reth_node_api::NodeTypesWithDBAdapter; 10 | use reth_node_builder::{EngineNodeLauncher, FullNodeComponents, NodeBuilder, NodeConfig}; 11 | use reth_node_ethereum::node::{EthereumAddOns, EthereumNode}; 12 | use reth_provider::providers::BlockchainProvider; 13 | use reth_tasks::TaskManager; 14 | 15 | #[test] 16 | fn test_basic_setup() { 17 | // parse CLI -> config 18 | let config = NodeConfig::test(); 19 | let db = create_test_rw_db(); 20 | let msg = "On components".to_string(); 21 | let _builder = NodeBuilder::new(config) 22 | .with_database(db) 23 | .with_types::() 24 | .with_components(EthereumNode::components()) 25 | .with_add_ons(EthereumAddOns::default()) 26 | .on_component_initialized(move |ctx| { 27 | let _provider = ctx.provider(); 28 | println!("{msg}"); 29 | Ok(()) 30 | }) 31 | .on_node_started(|_full_node| Ok(())) 32 | .on_rpc_started(|_ctx, handles| { 33 | let _client = handles.rpc.http_client(); 34 | Ok(()) 35 | }) 36 | .extend_rpc_modules(|ctx| { 37 | let _ = ctx.config(); 38 | let _ = ctx.node().provider(); 39 | 40 | Ok(()) 41 | }) 42 | .check_launch(); 43 | } 44 | 45 | #[tokio::test] 46 | async fn test_eth_launcher() { 47 | let tasks = TaskManager::current(); 48 | let config = NodeConfig::test(); 49 | let db = create_test_rw_db(); 50 | let _builder = 51 | NodeBuilder::new(config) 52 | .with_database(db) 53 | .with_types_and_provider::>>, 55 | >>() 56 | .with_components(EthereumNode::components()) 57 | .with_add_ons(EthereumAddOns::default()) 58 | .launch_with_fn(|builder| { 59 | let launcher = EngineNodeLauncher::new( 60 | tasks.executor(), 61 | builder.config.datadir(), 62 | Default::default(), 63 | ); 64 | builder.launch_with(launcher) 65 | }); 66 | } 67 | 68 | #[test] 69 | fn test_node_setup() { 70 | let config = NodeConfig::test(); 71 | let db = create_test_rw_db(); 72 | let _builder = 73 | NodeBuilder::new(config).with_database(db).node(EthereumNode::default()).check_launch(); 74 | } 75 | -------------------------------------------------------------------------------- /crates/ethereum/node/tests/it/exex.rs: -------------------------------------------------------------------------------- 1 | use futures::future; 2 | use reth_db::test_utils::create_test_rw_db; 3 | use reth_exex::ExExContext; 4 | use reth_node_api::FullNodeComponents; 5 | use reth_node_builder::{NodeBuilder, NodeConfig}; 6 | use reth_node_ethereum::{node::EthereumAddOns, EthereumNode}; 7 | use std::{ 8 | future::Future, 9 | pin::Pin, 10 | task::{Context, Poll}, 11 | }; 12 | 13 | struct DummyExEx { 14 | _ctx: ExExContext, 15 | } 16 | 17 | impl Future for DummyExEx 18 | where 19 | Node: FullNodeComponents, 20 | { 21 | type Output = eyre::Result<()>; 22 | 23 | fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { 24 | Poll::Pending 25 | } 26 | } 27 | 28 | #[test] 29 | fn basic_exex() { 30 | let config = NodeConfig::test(); 31 | let db = create_test_rw_db(); 32 | let _builder = NodeBuilder::new(config) 33 | .with_database(db) 34 | .with_types::() 35 | .with_components(EthereumNode::components()) 36 | .with_add_ons(EthereumAddOns::default()) 37 | .install_exex("dummy", move |ctx| future::ok(DummyExEx { _ctx: ctx })) 38 | .check_launch(); 39 | } 40 | -------------------------------------------------------------------------------- /crates/ethereum/node/tests/it/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | mod builder; 4 | mod exex; 5 | 6 | const fn main() {} 7 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alloy-rpc-types-beacon" 3 | description = "Types for the Ethereum Beacon Node API" 4 | #version.workspace = true 5 | version = "1.0.5" 6 | edition.workspace = true 7 | rust-version.workspace = true 8 | #authors.workspace = true 9 | license.workspace = true 10 | homepage.workspace = true 11 | repository.workspace = true 12 | exclude.workspace = true 13 | 14 | [package.metadata.docs.rs] 15 | all-features = true 16 | rustdoc-args = [ 17 | "-Zunstable-options", 18 | "--generate-link-to-definition", 19 | "--show-type-layout", 20 | ] 21 | 22 | [lints] 23 | workspace = true 24 | 25 | [dependencies] 26 | # ethereum 27 | alloy-eips = { workspace = true, features = ["serde"] } 28 | alloy-rpc-types-engine = { workspace = true, features = ["serde"] } 29 | alloy-primitives.workspace = true 30 | 31 | # ssz 32 | ethereum_ssz_derive = { workspace = true, optional = true } 33 | ethereum_ssz = { workspace = true, optional = true } 34 | tree_hash = { workspace = true, optional = true } 35 | tree_hash_derive = { workspace = true, optional = true } 36 | 37 | serde.workspace = true 38 | serde_with = { workspace = true, features = ["alloc"] } 39 | 40 | thiserror.workspace = true 41 | 42 | [dev-dependencies] 43 | serde_json.workspace = true 44 | similar-asserts.workspace = true 45 | 46 | [features] 47 | ssz = [ 48 | "dep:ethereum_ssz", 49 | "dep:ethereum_ssz_derive", 50 | "dep:tree_hash", 51 | "dep:tree_hash_derive", 52 | "alloy-rpc-types-engine/ssz", 53 | "alloy-eips/ssz", 54 | ] 55 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/README.md: -------------------------------------------------------------------------------- 1 | # alloy-rpc-types-beacon 2 | 3 | Types for the [Ethereum Beacon Node API][beacon-apis]. 4 | 5 | [beacon-apis]: https://ethereum.github.io/beacon-APIs 6 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/constants.rs: -------------------------------------------------------------------------------- 1 | /// The Domain Separation Tag for hash_to_point in Ethereum beacon chain BLS12-381 signatures. 2 | /// 3 | /// This is also the name of the ciphersuite that defines beacon chain BLS signatures. 4 | /// 5 | /// See: 6 | /// 7 | /// 8 | pub const BLS_DST_SIG: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; 9 | 10 | /// The number of bytes in a BLS12-381 public key. 11 | pub const BLS_PUBLIC_KEY_BYTES_LEN: usize = 48; 12 | 13 | /// The number of bytes in a BLS12-381 secret key. 14 | pub const BLS_SECRET_KEY_BYTES_LEN: usize = 32; 15 | 16 | /// The number of bytes in a BLS12-381 signature. 17 | pub const BLS_SIGNATURE_BYTES_LEN: usize = 96; 18 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/events/attestation.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::B256; 2 | use serde::{Deserialize, Serialize}; 3 | use serde_with::{serde_as, DisplayFromStr}; 4 | 5 | /// Contains data related to an attestation, including slot, index, beacon block root, 6 | /// source, and target information. 7 | #[serde_as] 8 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 9 | pub struct AttestationData { 10 | /// The slot number in which the attestation was included, serialized as a string. 11 | #[serde_as(as = "DisplayFromStr")] 12 | pub slot: u64, 13 | /// The committee index of the attestation, serialized as a string. 14 | #[serde_as(as = "DisplayFromStr")] 15 | pub index: u64, 16 | /// The root of the beacon block being attested to. 17 | pub beacon_block_root: B256, 18 | /// The source checkpoint of the attestation. 19 | pub source: Source, 20 | /// The target checkpoint of the attestation. 21 | pub target: Target, 22 | } 23 | 24 | /// Represents the source checkpoint of an attestation. 25 | #[serde_as] 26 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 27 | pub struct Source { 28 | /// The epoch number of the source checkpoint, serialized as a string. 29 | #[serde_as(as = "DisplayFromStr")] 30 | pub epoch: u64, 31 | /// The root of the source checkpoint. 32 | pub root: B256, 33 | } 34 | 35 | /// Represents the target checkpoint of an attestation. 36 | #[serde_as] 37 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 38 | pub struct Target { 39 | /// The epoch number of the target checkpoint, serialized as a string. 40 | #[serde_as(as = "DisplayFromStr")] 41 | pub epoch: u64, 42 | /// The root of the target checkpoint. 43 | pub root: B256, 44 | } 45 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/events/light_client_optimistic.rs: -------------------------------------------------------------------------------- 1 | use crate::header::BeaconBlockHeader; 2 | use alloy_primitives::Bytes; 3 | use serde::{Deserialize, Serialize}; 4 | use serde_with::{serde_as, DisplayFromStr}; 5 | 6 | /// Contains optimistic data for the light client, including the attested header, 7 | /// sync aggregate, and the signature slot. 8 | #[serde_as] 9 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 10 | pub struct LightClientOptimisticData { 11 | /// The attested header containing a [`BeaconBlockHeader`]. 12 | pub attested_header: AttestedHeader, 13 | /// The sync aggregate which includes the sync committee bits and signature. 14 | pub sync_aggregate: SyncAggregate, 15 | /// The slot in which the signature was included, serialized as a string. 16 | #[serde_as(as = "DisplayFromStr")] 17 | pub signature_slot: u64, 18 | } 19 | 20 | /// Contains the [`BeaconBlockHeader`] that was attested. 21 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 22 | pub struct AttestedHeader { 23 | /// The [`BeaconBlockHeader`] object from the CL spec. 24 | pub beacon: BeaconBlockHeader, 25 | } 26 | 27 | /// Contains the sync committee bits and signature. 28 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 29 | pub struct SyncAggregate { 30 | /// The bits representing the sync committee's participation. 31 | pub sync_committee_bits: Bytes, 32 | /// The aggregated signature of the sync committee. 33 | pub sync_committee_signature: Bytes, 34 | } 35 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/examples/relay_signed_bid_submission_capella.ssz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n42blockchain/N42-rs/a2cef84273d15e99b25d227942620231eb1fb23f/crates/n42/alloy-rpc-types-beacon/src/examples/relay_signed_bid_submission_capella.ssz -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc( 3 | html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", 4 | html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" 5 | )] 6 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 7 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 8 | 9 | use alloy_primitives::FixedBytes; 10 | use constants::{BLS_PUBLIC_KEY_BYTES_LEN, BLS_SIGNATURE_BYTES_LEN}; 11 | 12 | /// Constants used in the Beacon API. 13 | pub mod constants; 14 | 15 | /// Beacon API events support. 16 | pub mod events; 17 | 18 | /// Types and functions related to the beacon block header. 19 | pub mod header; 20 | 21 | /// Types and functions related to the beacon block payload. 22 | pub mod payload; 23 | 24 | /// Types and functions related to the relay mechanism. 25 | pub mod relay; 26 | 27 | /// Types and functions related to execution requests. 28 | pub mod requests; 29 | 30 | /// Types and functions related to the sidecar. 31 | pub mod sidecar; 32 | 33 | /// Types and functions related to withdrawals. 34 | pub mod withdrawals; 35 | 36 | /// BLS signature type 37 | pub type BlsSignature = FixedBytes; 38 | 39 | /// BLS public key type 40 | pub type BlsPublicKey = FixedBytes; 41 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-beacon/src/withdrawals.rs: -------------------------------------------------------------------------------- 1 | use alloy_eips::eip4895::Withdrawal; 2 | use alloy_primitives::Address; 3 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 4 | use serde_with::{serde_as, DeserializeAs, DisplayFromStr, SerializeAs}; 5 | 6 | /// Same as [Withdrawal] but respects the Beacon API format which uses snake-case and quoted 7 | /// decimals. 8 | #[serde_as] 9 | #[derive(Serialize, Deserialize, Clone)] 10 | pub(crate) struct BeaconWithdrawal { 11 | #[serde_as(as = "DisplayFromStr")] 12 | index: u64, 13 | #[serde_as(as = "DisplayFromStr")] 14 | validator_index: u64, 15 | address: Address, 16 | #[serde_as(as = "DisplayFromStr")] 17 | amount: u64, 18 | } 19 | 20 | impl SerializeAs for BeaconWithdrawal { 21 | fn serialize_as(source: &Withdrawal, serializer: S) -> Result 22 | where 23 | S: Serializer, 24 | { 25 | beacon_withdrawals::serialize(source, serializer) 26 | } 27 | } 28 | 29 | impl<'de> DeserializeAs<'de, Withdrawal> for BeaconWithdrawal { 30 | fn deserialize_as(deserializer: D) -> Result 31 | where 32 | D: Deserializer<'de>, 33 | { 34 | beacon_withdrawals::deserialize(deserializer) 35 | } 36 | } 37 | 38 | /// A helper serde module to convert from/to the Beacon API which uses quoted decimals rather than 39 | /// big-endian hex. 40 | pub mod beacon_withdrawals { 41 | use super::*; 42 | 43 | /// Serialize the payload attributes for the beacon API. 44 | pub fn serialize(payload_attributes: &Withdrawal, serializer: S) -> Result 45 | where 46 | S: Serializer, 47 | { 48 | let withdrawal = BeaconWithdrawal { 49 | index: payload_attributes.index, 50 | validator_index: payload_attributes.validator_index, 51 | address: payload_attributes.address, 52 | amount: payload_attributes.amount, 53 | }; 54 | withdrawal.serialize(serializer) 55 | } 56 | 57 | /// Deserialize the payload attributes for the beacon API. 58 | pub fn deserialize<'de, D>(deserializer: D) -> Result 59 | where 60 | D: Deserializer<'de>, 61 | { 62 | let withdrawal = BeaconWithdrawal::deserialize(deserializer)?; 63 | Ok(Withdrawal { 64 | index: withdrawal.index, 65 | validator_index: withdrawal.validator_index, 66 | address: withdrawal.address, 67 | amount: withdrawal.amount, 68 | }) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-engine/README.md: -------------------------------------------------------------------------------- 1 | # alloy-rpc-types-engine 2 | 3 | Types for the `engine` Ethereum JSON-RPC namespace. 4 | 5 | Engine API types: 6 | 7 | and , 8 | following the execution specs . 9 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-engine/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc( 3 | html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", 4 | html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" 5 | )] 6 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 7 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 8 | #![cfg_attr(not(feature = "std"), no_std)] 9 | 10 | #[macro_use] 11 | extern crate alloc; 12 | 13 | mod cancun; 14 | pub use cancun::*; 15 | mod prague; 16 | pub use prague::*; 17 | mod sidecar; 18 | pub use sidecar::*; 19 | 20 | mod forkchoice; 21 | pub use forkchoice::*; 22 | 23 | mod version; 24 | pub use version::ForkchoiceUpdateVersion; 25 | 26 | mod identification; 27 | pub use identification::*; 28 | 29 | #[cfg(feature = "jwt")] 30 | mod jwt; 31 | #[cfg(feature = "jwt")] 32 | pub use jwt::*; 33 | 34 | pub mod payload; 35 | pub use payload::*; 36 | 37 | mod error; 38 | pub use error::*; 39 | 40 | mod transition; 41 | pub use transition::*; 42 | 43 | #[doc(inline)] 44 | pub use alloy_eips::eip4844::BlobAndProofV1; 45 | 46 | /// The list of all supported Engine capabilities available over the engine endpoint. 47 | /// 48 | /// Latest spec: Prague 49 | pub const CAPABILITIES: &[&str] = &[ 50 | "engine_forkchoiceUpdatedV1", 51 | "engine_forkchoiceUpdatedV2", 52 | "engine_forkchoiceUpdatedV3", 53 | "engine_exchangeTransitionConfigurationV1", 54 | "engine_getClientVersionV1", 55 | "engine_getPayloadV1", 56 | "engine_getPayloadV2", 57 | "engine_getPayloadV3", 58 | "engine_getPayloadV4", 59 | "engine_newPayloadV1", 60 | "engine_newPayloadV2", 61 | "engine_newPayloadV3", 62 | "engine_newPayloadV4", 63 | "engine_getPayloadBodiesByHashV1", 64 | "engine_getPayloadBodiesByRangeV1", 65 | ]; 66 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-engine/src/transition.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::{B256, U256}; 2 | 3 | /// This structure contains configurable settings of the transition process. 4 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] 5 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 6 | #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] 7 | #[doc(alias = "TxConfiguration")] 8 | pub struct TransitionConfiguration { 9 | /// Maps on the TERMINAL_TOTAL_DIFFICULTY parameter of EIP-3675 10 | pub terminal_total_difficulty: U256, 11 | /// Maps on TERMINAL_BLOCK_HASH parameter of EIP-3675 12 | pub terminal_block_hash: B256, 13 | /// Maps on TERMINAL_BLOCK_NUMBER parameter of EIP-3675 14 | #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] 15 | pub terminal_block_number: u64, 16 | } 17 | -------------------------------------------------------------------------------- /crates/n42/alloy-rpc-types-engine/src/version.rs: -------------------------------------------------------------------------------- 1 | //! Versions for the engine api. 2 | 3 | /// The version of the engine api. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 5 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 6 | #[repr(u32)] 7 | pub enum ForkchoiceUpdateVersion { 8 | /// Version 1 of the engine api. 9 | V1 = 1, 10 | /// Version 2 of the engine api. 11 | V2 = 2, 12 | /// Version 3 of the engine api. 13 | V3 = 3, 14 | /// Version 4 of the engine api. 15 | V4 = 4, 16 | } 17 | -------------------------------------------------------------------------------- /crates/n42/clique/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "n42-clique" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | exclude.workspace = true 10 | 11 | [dependencies] 12 | once_cell.workspace = true 13 | unexpected = "0.1" 14 | 15 | hash-db = "0.16.0" 16 | keccak-hash = "0.10.0" 17 | itertools.workspace = true 18 | derive_more.workspace = true 19 | lazy_static = "1.4" 20 | 21 | parking_lot.workspace = true 22 | primitive-types = "0.3.0" 23 | hex-literal = "0.3" 24 | num-bigint = "0.4" 25 | tiny-keccak = "2.0" 26 | uint = "0.9" 27 | sled = "0.34.7" 28 | 29 | 30 | rlp = "0.4" 31 | alloy-rlp.workspace = true 32 | alloy-genesis.workspace = true 33 | alloy-primitives.workspace = true 34 | alloy-signer-local.workspace = true 35 | alloy-signer.workspace = true 36 | k256.workspace = true 37 | rand.workspace = true 38 | blst.workspace = true 39 | secp256k1 = { workspace = true, features = ["recovery"] } 40 | sha2.workspace = true 41 | sha3 = "0.10.5" 42 | # n42 43 | n42-primitives.workspace = true 44 | 45 | alloy-serde.workspace = true 46 | # serde 47 | bytes.workspace = true 48 | serde.workspace = true 49 | 50 | schnellru.workspace = true 51 | #lru-cache = "0.1" 52 | #lru = "0.7" 53 | tracing.workspace = true 54 | #log = "0.4" 55 | 56 | #reth 57 | reth-execution-types.workspace = true 58 | reth-node-api.workspace = true 59 | #reth-rpc.workspace = true 60 | #reth-rpc-eth-api.workspace = true 61 | reth-primitives-traits.workspace = true 62 | #reth-testing-utils.workspace = true 63 | reth-provider.workspace = true 64 | #reth-blockchain-tree.workspace = true 65 | reth-storage-api.workspace=true 66 | reth-primitives = { workspace = true, default-features = false, features = ["std", "reth-codec", "arbitrary"] } 67 | reth-consensus.workspace = true 68 | #reth-beacon-consensus.workspace = true 69 | #reth-ethereum-consensus.workspace = true 70 | reth-chainspec.workspace = true 71 | #reth-engine-primitives.workspace = true 72 | #reth-transaction-pool = { workspace = true, features = ["test-utils"] } 73 | #reth-evm = { workspace = true, features = ["test-utils"] } 74 | #reth-db = { workspace = true, features = ["test-utils"] } 75 | #reth-db-common.workspace = true 76 | #reth-network.workspace = true 77 | eyre.workspace = true 78 | 79 | # arbitrary utils 80 | arbitrary = { workspace = true, features = ["derive"], optional = true } 81 | hex = "0.4.3" 82 | 83 | [lints] 84 | workspace = true 85 | 86 | -------------------------------------------------------------------------------- /crates/n42/clique/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! clique consensus 2 | 3 | mod apos; 4 | pub use apos::*; 5 | -------------------------------------------------------------------------------- /crates/n42/clique/src/traits.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Debug, Formatter}; 2 | use std::time::{SystemTime}; 3 | use reth_consensus::{Consensus, ConsensusError}; 4 | use crate::apos::{AposError,APos,EXTRA_VANITY,NONCE_AUTH_VOTE,NONCE_DROP_VOTE,DIFF_IN_TURN,DIFF_NO_TURN}; 5 | use reth_primitives::{ 6 | proofs, Block, BlockBody, BlockWithSenders, Header, SealedBlock, SealedHeader, 7 | }; 8 | use alloy_primitives::{U256}; 9 | use reth_chainspec::{EthChainSpec, EthereumHardforks}; 10 | use reth_evm::provider::EvmEnvProvider; 11 | use reth_storage_api::{BlockReader, HeaderProvider, SnapshotProvider, SnapshotProviderWriter, StateProviderFactory}; 12 | 13 | -------------------------------------------------------------------------------- /crates/n42/consensus-client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "consensus-client" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | exclude.workspace = true 10 | 11 | [dependencies] 12 | # reth 13 | #reth-beacon-consensus.workspace = true 14 | reth-chainspec.workspace = true 15 | reth-consensus.workspace = true 16 | reth-engine-primitives.workspace = true 17 | reth-engine-service.workspace = true 18 | reth-engine-tree.workspace = true 19 | reth-evm.workspace = true 20 | reth-ethereum-engine-primitives.workspace = true 21 | reth-ethereum-primitives.workspace = true 22 | reth-payload-builder.workspace = true 23 | reth-payload-primitives.workspace = true 24 | reth-primitives.workspace = true 25 | reth-payload-validator.workspace = true 26 | reth-provider.workspace = true 27 | reth-prune.workspace = true 28 | reth-rpc-types-compat.workspace = true 29 | reth-transaction-pool.workspace = true 30 | reth-stages-api.workspace = true 31 | reth-network.workspace = true 32 | reth-eth-wire-types.workspace = true 33 | reth-network-api.workspace = true 34 | reth-tokio-util.workspace = true 35 | reth-node-types.workspace = true 36 | reth-node-api.workspace = true 37 | reth-network-p2p.workspace = true 38 | reth-primitives-traits.workspace = true 39 | 40 | # alloy 41 | alloy-primitives.workspace = true 42 | alloy-rpc-types-engine.workspace = true 43 | alloy-eips.workspace = true 44 | alloy-consensus.workspace = true 45 | 46 | # async 47 | tokio.workspace = true 48 | tokio-stream.workspace = true 49 | futures-util.workspace = true 50 | 51 | # misc 52 | nix.workspace = true 53 | eyre.workspace = true 54 | tracing.workspace = true 55 | schnellru.workspace = true 56 | itertools.workspace = true 57 | 58 | op-alloy-rpc-types-engine = { workspace = true, optional = true } 59 | 60 | [lints] 61 | workspace = true 62 | -------------------------------------------------------------------------------- /crates/n42/consensus-client/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Consensus client 2 | 3 | pub mod miner; 4 | -------------------------------------------------------------------------------- /crates/n42/engine-primitives/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "n42-engine-primitives" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | exclude.workspace = true 10 | 11 | [dependencies] 12 | 13 | reth-ethereum-engine-primitives.workspace = true 14 | #reth-engine-primitives.workspace = true 15 | reth-primitives.workspace = true 16 | reth-node-api.workspace = true 17 | reth-chainspec.workspace = true 18 | reth-payload-primitives.workspace = true 19 | 20 | # alloy 21 | alloy-primitives.workspace = true 22 | alloy-rpc-types-engine.workspace = true 23 | alloy-rpc-types = { workspace = true, features = ["engine"] } 24 | 25 | #misc 26 | eyre.workspace = true 27 | thiserror.workspace = true 28 | serde.workspace = true 29 | 30 | [lints] 31 | workspace = true 32 | -------------------------------------------------------------------------------- /crates/n42/engine-primitives/src/attributes.rs: -------------------------------------------------------------------------------- 1 | //! The implementation of the [`PayloadAttributesBuilder`] for the N42 engine service 2 | 3 | use alloy_primitives::{Address, B256}; 4 | use reth_chainspec::EthereumHardforks; 5 | use reth_ethereum_engine_primitives::EthPayloadAttributes; 6 | use reth_payload_primitives::PayloadAttributesBuilder; 7 | use std::sync::Arc; 8 | 9 | /// The attributes builder for N42 Ethereum payload. 10 | #[derive(Debug)] 11 | #[non_exhaustive] 12 | pub struct N42PayloadAttributesBuilder { 13 | chain_spec: Arc, 14 | signer_address: Option

, 15 | } 16 | 17 | impl N42PayloadAttributesBuilder { 18 | /// Creates a new instance of the builder. 19 | pub const fn new(chain_spec: Arc) -> Self { 20 | Self { chain_spec, signer_address: None } 21 | } 22 | 23 | /// Creates a new instance of the builder with an optional signer address 24 | pub const fn new_add_signer(chain_spec: Arc, signer_address: Option
) -> Self { 25 | Self { chain_spec, signer_address } 26 | } 27 | } 28 | 29 | impl PayloadAttributesBuilder 30 | for N42PayloadAttributesBuilder 31 | where 32 | ChainSpec: Send + Sync + EthereumHardforks + 'static, 33 | { 34 | fn build(&self, timestamp: u64) -> EthPayloadAttributes { 35 | EthPayloadAttributes { 36 | timestamp, 37 | prev_randao: B256::ZERO, 38 | suggested_fee_recipient: self.signer_address.unwrap_or(Address::ZERO), 39 | withdrawals: self 40 | .chain_spec 41 | .is_shanghai_active_at_timestamp(timestamp) 42 | .then(Default::default), 43 | parent_beacon_block_root: self 44 | .chain_spec 45 | .is_cancun_active_at_timestamp(timestamp) 46 | .then(Default::default), 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /crates/n42/engine-primitives/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! n42 engine primitives 2 | 3 | mod attributes; 4 | pub use attributes::N42PayloadAttributesBuilder; 5 | //pub use attributes::N42PayloadAttributes; 6 | //pub use attributes::N42PayloadBuilderAttributes; 7 | -------------------------------------------------------------------------------- /crates/n42/engine-types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "n42-engine-types" 3 | version = "0.0.0" 4 | publish = false 5 | edition.workspace = true 6 | license.workspace = true 7 | 8 | [dependencies] 9 | #n42 10 | n42-engine-primitives.workspace = true 11 | n42-clique.workspace = true 12 | #reth 13 | reth-evm.workspace = true 14 | reth-evm-ethereum.workspace = true 15 | reth-errors.workspace = true 16 | reth-trie.workspace = true 17 | reth-execution-types.workspace = true 18 | reth-chain-state.workspace = true 19 | reth-chainspec.workspace = true 20 | reth-node-api.workspace = true 21 | reth-node-core.workspace = true 22 | reth-node-builder.workspace = true 23 | reth-network.workspace = true 24 | reth-rpc.workspace = true 25 | reth-rpc-server-types.workspace = true 26 | reth-ethereum-engine-primitives.workspace = true 27 | reth-rpc-api.workspace = true 28 | reth-rpc-builder.workspace = true 29 | reth-rpc-eth-types.workspace = true 30 | reth-transaction-pool.workspace = true 31 | reth-consensus.workspace = true 32 | #reth-auto-seal-consensus.workspace = true 33 | reth-revm.workspace = true 34 | reth-tasks.workspace = true 35 | reth-primitives.workspace = true 36 | reth-primitives-traits.workspace = true 37 | reth-storage-api.workspace = true 38 | reth-ethereum-primitives.workspace = true 39 | reth-payload-builder.workspace = true 40 | reth-payload-builder-primitives.workspace = true 41 | reth-payload-primitives.workspace = true 42 | reth-basic-payload-builder.workspace = true 43 | reth-ethereum-payload-builder.workspace = true 44 | reth-node-ethereum = { workspace = true, features = ["test-utils"] } 45 | reth-tracing.workspace = true 46 | reth-trie-db.workspace = true 47 | alloy-genesis.workspace = true 48 | alloy-rpc-types-eth.workspace = true 49 | alloy-rpc-types = { workspace = true, features = ["engine"] } 50 | reth-provider.workspace = true 51 | 52 | 53 | eyre.workspace = true 54 | tokio.workspace = true 55 | thiserror.workspace = true 56 | serde.workspace = true 57 | futures-core = "0.3.31" 58 | futures-util = "0.3.31" 59 | tracing = "0.1.41" 60 | 61 | # ethereum 62 | alloy-rlp.workspace = true 63 | alloy-primitives.workspace = true 64 | alloy-consensus.workspace = true 65 | alloy-eips.workspace = true 66 | revm.workspace = true 67 | 68 | # metrics 69 | reth-metrics.workspace = true 70 | metrics.workspace = true 71 | 72 | 73 | -------------------------------------------------------------------------------- /crates/n42/engine-types/src/consensus.rs: -------------------------------------------------------------------------------- 1 | use reth_consensus::{ConsensusError, FullConsensus}; 2 | use reth_ethereum_primitives::{EthPrimitives, PooledTransaction}; 3 | use std::sync::Arc; 4 | use reth_node_api::FullNodeTypes; 5 | use n42_clique::APos; 6 | use reth_chainspec::ChainSpec; 7 | use reth_node_builder::components::ConsensusBuilder; 8 | use reth_node_builder::{BuilderContext, NodeTypes}; 9 | 10 | /// A basic ethereum consensus builder. 11 | #[derive(Debug, Default, Clone, Copy)] 12 | pub struct N42ConsensusBuilder { 13 | // TODO add closure to modify consensus 14 | } 15 | 16 | impl ConsensusBuilder for N42ConsensusBuilder 17 | where 18 | Node: FullNodeTypes>, 19 | { 20 | type Consensus = Arc>; 21 | 22 | async fn build_consensus(self, ctx: &BuilderContext) -> eyre::Result { 23 | //Ok(Arc::new(EthBeaconConsensus::new(ctx.chain_spec()))) 24 | Ok(Arc::new(APos::new(ctx.provider().clone(), ctx.chain_spec(), ctx.config().dev.consensus_signer_private_key.map(|v|v.to_string())))) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /crates/n42/engine-types/src/lib.rs: -------------------------------------------------------------------------------- 1 | //mod addons; 2 | //pub use addons::N42NodeAddOns; 3 | 4 | //mod engine_type; 5 | //pub use engine_type::N42EngineTypes; 6 | 7 | // mod attributes; 8 | // pub use attributes::N42PayloadAttributes; 9 | // pub use attributes::N42PayloadBuilderAttributes; 10 | 11 | //mod engine_validator; 12 | //pub use engine_validator::N42EngineValidator; 13 | 14 | mod node; 15 | pub use node::N42Node; 16 | 17 | mod payload; 18 | //mod job_generator; 19 | //mod job; 20 | //mod metrics; 21 | mod network; 22 | mod consensus; 23 | 24 | pub use payload::EthereumPayloadBuilderWrapper; 25 | pub use payload::N42PayloadServiceBuilder; 26 | 27 | 28 | 29 | 30 | 31 | // 32 | // #[tokio::main] 33 | // async fn main() -> eyre::Result<()> { 34 | // let _guard = RethTracer::new().init()?; 35 | // 36 | // let tasks = TaskManager::current(); 37 | // 38 | // // create optimism genesis with canyon at block 2 39 | // let spec = ChainSpec::builder() 40 | // .chain(Chain::mainnet()) 41 | // .genesis(Genesis::default()) 42 | // .london_activated() 43 | // .paris_activated() 44 | // .shanghai_activated() 45 | // .build(); 46 | // 47 | // // create node config 48 | // let node_config = 49 | // NodeConfig::test().with_rpc(RpcServerArgs::default().with_http()).with_chain(spec); 50 | // 51 | // let handle = NodeBuilder::new(node_config) 52 | // .testing_node(tasks.executor()) 53 | // .launch_node(MyCustomNode::default()) 54 | // .await 55 | // .unwrap(); 56 | // 57 | // println!("Node started"); 58 | // 59 | // handle.node_exit_future.await 60 | // } 61 | -------------------------------------------------------------------------------- /crates/n42/engine-types/src/network.rs: -------------------------------------------------------------------------------- 1 | use reth_network::config::NetworkMode; 2 | use reth_network::{EthNetworkPrimitives, NetworkManager, NetworkHandle, PeersInfo}; 3 | use reth_node_api::{AddOnsContext, FullNodeComponents, NodeAddOns, TxTy}; 4 | use reth_ethereum_primitives::{EthPrimitives, PooledTransaction}; 5 | use reth_chainspec::{ChainSpec, EthChainSpec}; 6 | use reth_node_builder::{ 7 | components::{ 8 | NetworkBuilder, PoolBuilder, 9 | }, 10 | node::{FullNodeTypes, NodeTypes}, 11 | BuilderContext, 12 | }; 13 | use reth_transaction_pool::{ 14 | EthTransactionPool, PoolTransaction, TransactionPool, TransactionValidationTaskExecutor, 15 | }; 16 | use reth_tracing::tracing::{debug, info}; 17 | 18 | /// A basic ethereum payload service. 19 | #[derive(Debug, Default, Clone, Copy)] 20 | pub struct N42NetworkBuilder { 21 | // TODO add closure to modify network 22 | } 23 | 24 | impl NetworkBuilder for N42NetworkBuilder 25 | where 26 | Node: FullNodeTypes>, 27 | Pool: TransactionPool< 28 | Transaction: PoolTransaction, Pooled = PooledTransaction>, 29 | > + Unpin 30 | + 'static, 31 | { 32 | type Network = NetworkHandle; 33 | 34 | async fn build_network( 35 | self, 36 | ctx: &BuilderContext, 37 | pool: Pool, 38 | ) -> eyre::Result { 39 | let network_config_builder = ctx.network_config_builder()?.network_mode(NetworkMode::Work); 40 | let network_config = ctx.build_network_config(network_config_builder); 41 | let network = NetworkManager::builder(network_config).await?; 42 | let handle = ctx.start_network(network, pool); 43 | info!(target: "n42::cli", enode=%handle.local_node_record(), "P2P networking initialized"); 44 | Ok(handle) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /crates/n42/n42-testing/src/main.rs: -------------------------------------------------------------------------------- 1 | mod dev; 2 | mod utils; 3 | mod snapshot_test_utils; 4 | 5 | #[tokio::main] 6 | async fn main() { 7 | println!("main starts"); 8 | } 9 | -------------------------------------------------------------------------------- /crates/n42/n42-testing/src/snapshot_test_utils.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Keccak, Hasher}; 2 | use secp256k1::{PublicKey, Secp256k1}; 3 | use alloy_primitives::Address; 4 | use std::{str::FromStr, collections::HashMap}; 5 | use reth_network::config::SecretKey; 6 | 7 | #[cfg(test)] 8 | pub struct TesterAccountPool { 9 | pub accounts: HashMap, 10 | } 11 | 12 | #[cfg(test)] 13 | impl TesterAccountPool { 14 | pub fn new() -> Self { 15 | Self { 16 | accounts: HashMap::new(), 17 | } 18 | } 19 | 20 | // Returns the Ethereum address for a given signer label 21 | pub fn address(&mut self, account: &str) -> Address { 22 | if account.is_empty() { 23 | return Address::from_str("0x0000000000000000000000000000000000000000").unwrap(); 24 | } 25 | if !self.accounts.contains_key(account) { 26 | let secret_key = SecretKey::new(&mut secp256k1::rand::thread_rng()); 27 | self.accounts.insert(account.to_string(), secret_key); 28 | } 29 | // Initialize secp256k1 context 30 | let secp = Secp256k1::new(); 31 | 32 | // Get the corresponding public key 33 | let secret_key = self.accounts.get(account).unwrap(); 34 | let public_key = PublicKey::from_secret_key(&secp, secret_key); 35 | 36 | // Serialize the public key in uncompressed format (65 bytes) 37 | let public_key_uncompressed = public_key.serialize_uncompressed(); 38 | 39 | // Hash the last 64 bytes of the uncompressed public key 40 | let mut keccak = Keccak::v256(); 41 | keccak.update(&public_key_uncompressed[1..]); // Skip the first byte (0x04) 42 | let mut output = [0u8; 32]; 43 | keccak.finalize(&mut output); 44 | 45 | // Take the last 20 bytes as the address 46 | let address = &output[12..]; 47 | Address::from_slice(address) 48 | } 49 | 50 | pub fn secret_key(&mut self, account: &str) -> SecretKey { 51 | if !self.accounts.contains_key(account) { 52 | let secret_key = SecretKey::new(&mut secp256k1::rand::thread_rng()); 53 | self.accounts.insert(account.to_string(), secret_key); 54 | } 55 | *self.accounts.get(account).unwrap() 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /crates/n42/n42-testing/src/utils.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::{Address, B256}; 2 | use reth::rpc::types::engine::PayloadAttributes; 3 | use reth_payload_builder::EthPayloadBuilderAttributes; 4 | 5 | #[cfg(test)] 6 | pub(crate) fn n42_payload_attributes(timestamp: u64, parent_hash: B256, eth_signer_address: Address) -> EthPayloadBuilderAttributes { 7 | let attributes = PayloadAttributes { 8 | timestamp, 9 | prev_randao: B256::ZERO, 10 | suggested_fee_recipient: eth_signer_address, 11 | withdrawals: None, 12 | 13 | // for chains that has cancun fork, parent_beacon_block_root must be set to Some, otherwise 14 | // tests will fail: "failed to resolve pending payload err=EIP-4788 parent beacon block 15 | // root missing for active Cancun block" 16 | parent_beacon_block_root: Some(B256::ZERO), 17 | //parent_beacon_block_root: None, 18 | }; 19 | EthPayloadBuilderAttributes::new(parent_hash, attributes) 20 | } 21 | -------------------------------------------------------------------------------- /crates/n42/primitives/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "n42-primitives" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | exclude.workspace = true 10 | 11 | [dependencies] 12 | serde_json.workspace=true 13 | #reth 14 | reth-primitives = { workspace = true, default-features = false, features = ["std","arbitrary"] } 15 | reth-primitives-traits.workspace = true 16 | alloy-rlp.workspace = true 17 | alloy-primitives.workspace = true 18 | reth-codecs.workspace = true 19 | 20 | # arbitrary utils 21 | # arbitrary = { workspace = true, features = ["derive"], optional = true } 22 | # arbitrary.workspace=true 23 | # serde 24 | serde.workspace = true 25 | # log 26 | tracing.workspace = true 27 | # 28 | schnellru.workspace = true 29 | 30 | bytes.workspace=true 31 | 32 | secp256k1.workspace=true 33 | [lints] 34 | workspace = true 35 | -------------------------------------------------------------------------------- /crates/n42/primitives/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! n42 primitives 2 | 3 | mod snapshot; 4 | pub use snapshot::Snapshot; 5 | pub use snapshot::APosConfig; 6 | -------------------------------------------------------------------------------- /crates/net/network-api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-network-api" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | description = "Network interfaces and commonly used types" 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [dependencies] 15 | # reth 16 | reth-network-peers.workspace = true 17 | reth-network-types.workspace = true 18 | reth-network-p2p.workspace = true 19 | reth-eth-wire-types.workspace = true 20 | reth-tokio-util.workspace = true 21 | reth-ethereum-forks.workspace = true 22 | reth-consensus.workspace = true 23 | reth-errors.workspace = true 24 | 25 | # ethereum 26 | alloy-primitives = { workspace = true, features = ["getrandom"] } 27 | alloy-rpc-types-admin.workspace = true 28 | enr = { workspace = true, default-features = false, features = ["rust-secp256k1"] } 29 | 30 | # async 31 | futures.workspace = true 32 | tokio-stream.workspace = true 33 | 34 | # misc 35 | thiserror.workspace = true 36 | serde = { workspace = true, features = ["derive"], optional = true } 37 | tokio = { workspace = true, features = ["sync"] } 38 | auto_impl.workspace = true 39 | derive_more.workspace = true 40 | 41 | [features] 42 | serde = [ 43 | "dep:serde", 44 | "reth-eth-wire-types/serde", 45 | "reth-network-types/serde", 46 | "alloy-primitives/serde", 47 | "enr/serde", 48 | "reth-ethereum-forks/serde", 49 | ] 50 | -------------------------------------------------------------------------------- /crates/net/network-api/src/block.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use alloy_primitives::{BlockHash, TxHash, B256}; 3 | use derive_more::Error; 4 | use reth_errors::BlockExecutionError; 5 | use reth_eth_wire_types::NewBlock; 6 | use reth_tokio_util::EventStream; 7 | use reth_consensus::ConsensusError; 8 | 9 | /// block import error. 10 | #[derive(Debug, Clone)] 11 | pub struct N42BlockImportOutcome { 12 | /// The block hash that caused the error. 13 | pub hash: BlockHash, 14 | 15 | /// The result after validating the block 16 | pub result: Result, N42BlockImportError> 17 | } 18 | 19 | 20 | /// Represents the specific error type within a block error. 21 | #[derive(Debug, Clone, thiserror::Error)] 22 | pub enum N42BlockImportError { 23 | /// The block encountered a validation error. 24 | #[error(transparent)] 25 | Validation(#[from] ConsensusError), 26 | // The block encountered an execution error. 27 | // #[error(transparent)] 28 | // Execution(#[from] BlockExecutionError), 29 | } 30 | 31 | 32 | /// Provides client for downloading blocks. 33 | #[auto_impl::auto_impl(&, Arc)] 34 | pub trait BlockAnnounceProvider { 35 | type Block; 36 | /// Announce a block over devp2p 37 | fn announce_block(&self, block: NewBlock, hash: B256); 38 | 39 | /// subscribe a new [`NewBlock`] listener channel. 40 | fn subscribe_block(&self) -> EventStream>; 41 | 42 | fn validated_block(&self, result: N42BlockImportOutcome); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /crates/net/network-api/src/downloaders.rs: -------------------------------------------------------------------------------- 1 | //! API related to syncing blocks. 2 | 3 | use std::fmt::Debug; 4 | 5 | use futures::Future; 6 | use reth_network_p2p::BlockClient; 7 | use tokio::sync::oneshot; 8 | 9 | /// Provides client for downloading blocks. 10 | #[auto_impl::auto_impl(&, Arc)] 11 | pub trait BlockDownloaderProvider { 12 | /// The client this type can provide. 13 | type Client: BlockClient + Send + Sync + Clone + 'static; 14 | 15 | /// Returns a new [`BlockClient`], used for fetching blocks from peers. 16 | /// 17 | /// The client is the entrypoint for sending block requests to the network. 18 | fn fetch_client( 19 | &self, 20 | ) -> impl Future> + Send; 21 | } 22 | -------------------------------------------------------------------------------- /crates/net/network-api/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | use tokio::sync::{mpsc, oneshot}; 3 | 4 | /// Network Errors 5 | #[derive(Error, Debug, Clone, PartialEq, Eq)] 6 | pub enum NetworkError { 7 | /// Indicates that the sender has been dropped. 8 | #[error("sender has been dropped")] 9 | ChannelClosed, 10 | } 11 | 12 | impl From> for NetworkError { 13 | fn from(_: mpsc::error::SendError) -> Self { 14 | Self::ChannelClosed 15 | } 16 | } 17 | 18 | impl From for NetworkError { 19 | fn from(_: oneshot::error::RecvError) -> Self { 20 | Self::ChannelClosed 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/net/network-api/src/test_utils/mod.rs: -------------------------------------------------------------------------------- 1 | //! API for integration testing network components. 2 | 3 | pub mod peers_manager; 4 | 5 | pub use peers_manager::{PeerCommand, PeersHandle, PeersHandleProvider}; 6 | -------------------------------------------------------------------------------- /crates/net/network/README.md: -------------------------------------------------------------------------------- 1 | # RETH network implementation -------------------------------------------------------------------------------- /crates/net/network/docs/mermaid/fetch-client.mmd: -------------------------------------------------------------------------------- 1 | sequenceDiagram 2 | participant Client as FetchClient 3 | participant Fetcher as StateFetcher 4 | participant State as NetworkState 5 | participant Session as Active Peer Session 6 | participant Peers as PeerManager 7 | loop Send Request, retry if retriable and remaining retries 8 | Client->>Fetcher: DownloadRequest{GetHeaders, GetBodies} 9 | Note over Client,Fetcher: Request and oneshot Sender sent via `request_tx` channel 10 | loop Process buffered requests 11 | State->>Fetcher: poll action 12 | Fetcher->>Fetcher: Select Available Peer 13 | Note over Fetcher: Peer is available if it's currently idle, no inflight requests 14 | Fetcher->>State: FetchAction::BlockDownloadRequest 15 | State->>Session: Delegate Request 16 | Note over State,Session: Request and oneshot Sender sent via `to_session_tx` channel 17 | end 18 | Session->>Session: Send Request to remote 19 | Session->>Session: Enforce Request timeout 20 | Session-->>State: Send Response Result via channel 21 | State->>Fetcher: Delegate Response 22 | Fetcher-->>Client: Send Response via channel 23 | opt Bad Response 24 | Client->>Peers: Penalize Peer 25 | end 26 | Peers->>Peers: Apply Reputation Change 27 | opt reputation dropped below threshold 28 | Peers->>State: Disconnect Session 29 | State->>Session: Delegate Disconnect 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /crates/net/network/docs/mermaid/network-manager.mmd: -------------------------------------------------------------------------------- 1 | graph TB 2 | handle(NetworkHandle) 3 | events(NetworkEvents) 4 | transactions(Transactions Task) 5 | ethrequest(ETH Request Task) 6 | discovery(Discovery Task) 7 | subgraph NetworkManager 8 | direction LR 9 | subgraph Swarm 10 | direction TB 11 | B1[(Session Manager)] 12 | B2[(Connection Lister)] 13 | B3[(Network State)] 14 | end 15 | end 16 | handle <--> |request response channel| NetworkManager 17 | NetworkManager --> |Network events| events 18 | transactions <--> |transactions| NetworkManager 19 | ethrequest <--> |ETH request handing| NetworkManager 20 | discovery --> |Discovered peers| NetworkManager 21 | -------------------------------------------------------------------------------- /crates/net/network/docs/mermaid/swarm.mmd: -------------------------------------------------------------------------------- 1 | graph TB 2 | connections(TCP Listener) 3 | Discovery[(Discovery)] 4 | fetchRequest(Client Interfaces) 5 | Sessions[(SessionManager)] 6 | SessionTask[(Peer Session)] 7 | State[(State)] 8 | StateFetch[(State Fetcher)] 9 | connections --> |incoming| Sessions 10 | State --> |initiate outgoing| Sessions 11 | Discovery --> |update peers| State 12 | Sessions --> |spawns| SessionTask 13 | SessionTask <--> |handle state requests| State 14 | fetchRequest --> |request Headers, Bodies| StateFetch 15 | State --> |poll pending requests| StateFetch 16 | -------------------------------------------------------------------------------- /crates/net/network/src/flattened_response.rs: -------------------------------------------------------------------------------- 1 | use futures::Future; 2 | use pin_project::pin_project; 3 | use std::{ 4 | pin::Pin, 5 | task::{Context, Poll}, 6 | }; 7 | use tokio::sync::oneshot::{error::RecvError, Receiver}; 8 | 9 | /// Flatten a [Receiver] message in order to get rid of the [RecvError] result 10 | #[derive(Debug)] 11 | #[pin_project] 12 | pub struct FlattenedResponse { 13 | #[pin] 14 | receiver: Receiver, 15 | } 16 | 17 | impl Future for FlattenedResponse> 18 | where 19 | E: From, 20 | { 21 | type Output = Result; 22 | 23 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 24 | let this = self.project(); 25 | 26 | this.receiver.poll(cx).map(|r| r.unwrap_or_else(|err| Err(err.into()))) 27 | } 28 | } 29 | 30 | impl From> for FlattenedResponse { 31 | fn from(value: Receiver) -> Self { 32 | Self { receiver: value } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crates/net/network/src/test_utils/init.rs: -------------------------------------------------------------------------------- 1 | use enr::{k256::ecdsa::SigningKey, Enr, EnrPublicKey}; 2 | use reth_network_peers::PeerId; 3 | use std::net::SocketAddr; 4 | 5 | /// Obtains a `PeerId` from an ENR. In this case, the `PeerId` represents the public key contained 6 | /// in the ENR. 7 | pub fn enr_to_peer_id(enr: Enr) -> PeerId { 8 | // In the following tests, methods which accept a public key expect it to contain the public 9 | // key in its 64-byte encoded (uncompressed) form. 10 | enr.public_key().encode_uncompressed().into() 11 | } 12 | 13 | // copied from ethers-rs 14 | /// A bit of hack to find an unused TCP port. 15 | /// 16 | /// Does not guarantee that the given port is unused after the function exists, just that it was 17 | /// unused before the function started (i.e., it does not reserve a port). 18 | pub fn unused_port() -> u16 { 19 | unused_tcp_addr().port() 20 | } 21 | 22 | /// Finds an unused tcp address 23 | pub fn unused_tcp_addr() -> SocketAddr { 24 | let listener = std::net::TcpListener::bind("127.0.0.1:0") 25 | .expect("Failed to create TCP listener to find unused port"); 26 | listener.local_addr().expect("Failed to read TCP listener local_addr to find unused port") 27 | } 28 | 29 | /// Finds an unused udp port 30 | pub fn unused_udp_port() -> u16 { 31 | unused_udp_addr().port() 32 | } 33 | /// Finds an unused udp address 34 | pub fn unused_udp_addr() -> SocketAddr { 35 | let udp_listener = std::net::UdpSocket::bind("127.0.0.1:0") 36 | .expect("Failed to create UDP listener to find unused port"); 37 | udp_listener.local_addr().expect("Failed to read UDP listener local_addr to find unused port") 38 | } 39 | 40 | /// Finds a single port that is unused for both TCP and UDP. 41 | pub fn unused_tcp_and_udp_port() -> u16 { 42 | loop { 43 | let port = unused_port(); 44 | if std::net::UdpSocket::bind(format!("127.0.0.1:{port}")).is_ok() { 45 | return port 46 | } 47 | } 48 | } 49 | 50 | /// Creates two unused `SocketAddrs`, intended for use as the p2p (TCP) and discovery ports (UDP) 51 | /// for new reth instances. 52 | pub fn unused_tcp_udp() -> (SocketAddr, SocketAddr) { 53 | (unused_tcp_addr(), unused_udp_addr()) 54 | } 55 | -------------------------------------------------------------------------------- /crates/net/network/src/test_utils/mod.rs: -------------------------------------------------------------------------------- 1 | //! Common helpers for network testing. 2 | 3 | mod init; 4 | mod testnet; 5 | pub mod transactions; 6 | 7 | pub use init::{ 8 | enr_to_peer_id, unused_port, unused_tcp_addr, unused_tcp_and_udp_port, unused_tcp_udp, 9 | unused_udp_addr, unused_udp_port, 10 | }; 11 | pub use testnet::{NetworkEventStream, Peer, PeerConfig, PeerHandle, Testnet, TestnetHandle}; 12 | pub use transactions::{buffer_hash_to_tx_fetcher, new_mock_session, new_tx_manager}; 13 | -------------------------------------------------------------------------------- /crates/net/network/tests/it/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | mod big_pooled_txs_req; 4 | mod connect; 5 | mod multiplex; 6 | mod requests; 7 | mod session; 8 | mod startup; 9 | mod transaction_hash_fetching; 10 | mod txgossip; 11 | 12 | const fn main() {} 13 | -------------------------------------------------------------------------------- /crates/net/network/tests/it/transaction_hash_fetching.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::U256; 2 | use reth_network::{ 3 | test_utils::Testnet, 4 | transactions::{TransactionPropagationMode::Max, TransactionsManagerConfig}, 5 | }; 6 | use reth_provider::test_utils::{ExtendedAccount, MockEthProvider}; 7 | use reth_tracing::init_test_tracing; 8 | use reth_transaction_pool::{test_utils::TransactionGenerator, PoolTransaction, TransactionPool}; 9 | use tokio::time::Duration; 10 | 11 | #[tokio::test(flavor = "multi_thread")] 12 | #[ignore] 13 | async fn transaction_hash_fetching() { 14 | init_test_tracing(); 15 | 16 | let mut config = TransactionsManagerConfig { propagation_mode: Max(0), ..Default::default() }; 17 | config.transaction_fetcher_config.max_inflight_requests = 1; 18 | 19 | let provider = MockEthProvider::default(); 20 | let num_peers = 10; 21 | let net = Testnet::create_with(num_peers, provider.clone()).await; 22 | 23 | // install request handlers 24 | let net = net.with_eth_pool_config(config); 25 | let handle = net.spawn(); 26 | 27 | // connect all the peers first 28 | handle.connect_peers().await; 29 | 30 | let listening_peer = &handle.peers()[num_peers - 1]; 31 | let mut listening_peer_tx_listener = 32 | listening_peer.pool().unwrap().pending_transactions_listener(); 33 | 34 | let num_tx_per_peer = 10; 35 | 36 | // Generate transactions for peers 37 | for i in 1..num_peers { 38 | let peer = &handle.peers()[i]; 39 | let peer_pool = peer.pool().unwrap(); 40 | 41 | for _ in 0..num_tx_per_peer { 42 | let mut tx_gen = TransactionGenerator::new(rand::rng()); 43 | let tx = tx_gen.gen_eip1559_pooled(); 44 | let sender = tx.sender(); 45 | provider.add_account(sender, ExtendedAccount::new(0, U256::from(100_000_000))); 46 | peer_pool.add_external_transaction(tx).await.unwrap(); 47 | } 48 | } 49 | 50 | // Total expected transactions 51 | let total_expected_tx = num_tx_per_peer * (num_peers - 1); 52 | let mut received_tx = 0; 53 | 54 | loop { 55 | tokio::select! { 56 | Some(_) = listening_peer_tx_listener.recv() => { 57 | received_tx += 1; 58 | if received_tx >= total_expected_tx { 59 | break; 60 | } 61 | } 62 | _ = tokio::time::sleep(Duration::from_secs(10)) => { 63 | panic!("Timed out waiting for transactions. Received {received_tx}/{total_expected_tx}"); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /crates/net/peers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-network-peers" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | description = "Network peer types and utils" 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [dependencies] 15 | # eth 16 | alloy-primitives = { workspace = true, features = ["rlp"] } 17 | alloy-rlp = { workspace = true, features = ["derive", "core-net", "core-error"] } 18 | enr = { workspace = true, optional = true } 19 | 20 | # crypto 21 | 22 | secp256k1 = { workspace = true, optional = true } 23 | # misc 24 | serde_with.workspace = true 25 | thiserror.workspace = true 26 | url.workspace = true 27 | tokio = { workspace = true, optional = true } 28 | 29 | [dev-dependencies] 30 | alloy-primitives = { workspace = true, features = ["rand"] } 31 | rand.workspace = true 32 | secp256k1 = { workspace = true, features = ["rand"] } 33 | serde_json.workspace = true 34 | enr.workspace = true 35 | tokio = { workspace = true, features = ["net", "macros", "rt"] } 36 | rand_08.workspace = true 37 | 38 | [features] 39 | default = ["std"] 40 | std = [ 41 | "alloy-primitives/std", 42 | "alloy-rlp/std", 43 | "secp256k1?/std", 44 | "serde_with/std", 45 | "thiserror/std", 46 | "url/std", 47 | "serde_json/std", 48 | ] 49 | secp256k1 = ["dep:secp256k1", "enr/secp256k1"] 50 | net = ["std", "dep:tokio", "tokio?/net"] 51 | -------------------------------------------------------------------------------- /crates/net/peers/src/bootnodes/ast.rs: -------------------------------------------------------------------------------- 1 | pub(super) static N42_BOOTNODES : [&str; 1] = [ 2 | "enode://9342cbfe9c986eb17487ffff7d138890c7de3e06f56c2ac335ee14f6dd481db8edc6038139fab38c5cf25dcbe78ae58f3f119c8fa67a8b0b1a8ae1f7c46923c4@127.0.0.1:12345", 3 | ]; 4 | 5 | pub(super) static N42_TESTNET_BOOTNODES : [&str; 2] = [ 6 | "enode://6f7655869fe8be864b1621f7df44334235845fb0b4c9113716b1373e7d7130cc0ff4d1296f742824eb5ecb75b5d50d04aed0d8677fa433be796fa36666395331@5.161.199.154:30303", 7 | "enode://e0a232e3cf5d4cd17f4296b85da907dc475a0e7c27d52245f6d8863f46de321955cf286804cd2f14b35623697417925719589ad6d947cbae549c96332cf65cdc@188.245.191.239:30303", 8 | ]; 9 | -------------------------------------------------------------------------------- /crates/net/peers/src/bootnodes/mod.rs: -------------------------------------------------------------------------------- 1 | //! Bootnodes for the network 2 | 3 | use crate::NodeRecord; 4 | use alloc::vec::Vec; 5 | 6 | mod ethereum; 7 | pub use ethereum::*; 8 | 9 | mod optimism; 10 | mod ast; 11 | 12 | pub use optimism::*; 13 | use crate::bootnodes::ast::{N42_BOOTNODES, N42_TESTNET_BOOTNODES}; 14 | 15 | /// Returns parsed ast nodes 16 | pub fn n42_nodes() -> Vec { 17 | parse_nodes(&N42_BOOTNODES[..]) 18 | } 19 | 20 | /// Returns parsed n42 testnet nodes 21 | pub fn n42_testnet_nodes() -> Vec { 22 | parse_nodes(&N42_TESTNET_BOOTNODES[..]) 23 | } 24 | 25 | /// Returns parsed mainnet nodes 26 | pub fn mainnet_nodes() -> Vec { 27 | parse_nodes(&MAINNET_BOOTNODES[..]) 28 | } 29 | 30 | /// Returns parsed sepolia nodes 31 | pub fn sepolia_nodes() -> Vec { 32 | parse_nodes(&SEPOLIA_BOOTNODES[..]) 33 | } 34 | 35 | /// Returns parsed holesky nodes 36 | pub fn holesky_nodes() -> Vec { 37 | parse_nodes(&HOLESKY_BOOTNODES[..]) 38 | } 39 | 40 | /// Returns parsed hoodi nodes 41 | pub fn hoodi_nodes() -> Vec { 42 | parse_nodes(&HOODI_BOOTNODES[..]) 43 | } 44 | 45 | /// Returns parsed op-stack mainnet nodes 46 | pub fn op_nodes() -> Vec { 47 | parse_nodes(OP_BOOTNODES) 48 | } 49 | 50 | /// Returns parsed op-stack testnet nodes 51 | pub fn op_testnet_nodes() -> Vec { 52 | parse_nodes(OP_TESTNET_BOOTNODES) 53 | } 54 | 55 | /// Returns parsed op-stack base mainnet nodes 56 | pub fn base_nodes() -> Vec { 57 | parse_nodes(OP_BOOTNODES) 58 | } 59 | 60 | /// Returns parsed op-stack base testnet nodes 61 | pub fn base_testnet_nodes() -> Vec { 62 | parse_nodes(OP_TESTNET_BOOTNODES) 63 | } 64 | 65 | /// Parses all the nodes 66 | pub fn parse_nodes(nodes: impl IntoIterator>) -> Vec { 67 | nodes.into_iter().map(|s| s.as_ref().parse().unwrap()).collect() 68 | } 69 | -------------------------------------------------------------------------------- /crates/node/builder/README.md: -------------------------------------------------------------------------------- 1 | ## reth-node-builder 2 | 3 | A declarative way to configure a reth ethereum node. 4 | 5 | ### Examples 6 | 7 | The [examples](../../../examples) folder contains various examples of how to use the builder to configure a reth node. -------------------------------------------------------------------------------- /crates/node/builder/docs/mermaid/builder.mmd: -------------------------------------------------------------------------------- 1 | graph TD; 2 | CLI::parse-->NodeCommand 3 | NodeCommand--execute-->NodeBuilder 4 | subgraph "Builder" 5 | NodeBuilder--"with_types"-->NodeBuilderT 6 | NodeBuilderT("NodeBuilder(Types)")--"with_components"-->NodeBuilderC 7 | NodeBuilderC("NodeBuilder(Types, Components)")--"extend_rpc_modules"-->NodeBuilderC 8 | NodeBuilderC--"on_rpc_started"-->NodeBuilderC 9 | end 10 | NodeBuilderC--"launch"-->launch 11 | subgraph launch 12 | database("database init")-->tree("blockchain provider init") 13 | tree--BuilderContext-->components{"build_components"} 14 | subgraph components 15 | ComponentsBuilder--"first creates"-->Pool 16 | Pool--"then creates"-->PayloadService 17 | Pool--"then creates"-->Network 18 | end 19 | components--"launch rpc"-->RpcContext 20 | RpcContext--invokes-->extend_rpc_modules 21 | RpcContext--invokes-->on_rpc_started 22 | end 23 | launch--"FullNode"-->NodeHandle 24 | -------------------------------------------------------------------------------- /crates/node/builder/src/aliases.rs: -------------------------------------------------------------------------------- 1 | use reth_network::NetworkPrimitives; 2 | use reth_node_api::BlockBody; 3 | use reth_provider::BlockReader; 4 | 5 | /// This is a type alias to make type bounds simpler, when we have a [`NetworkPrimitives`] and need 6 | /// a [`BlockReader`] whose associated types match the [`NetworkPrimitives`] associated types. 7 | pub trait BlockReaderFor: 8 | BlockReader< 9 | Block = N::Block, 10 | Header = N::BlockHeader, 11 | Transaction = ::Transaction, 12 | Receipt = N::Receipt, 13 | > 14 | { 15 | } 16 | 17 | impl BlockReaderFor for T 18 | where 19 | N: NetworkPrimitives, 20 | T: BlockReader< 21 | Block = N::Block, 22 | Header = N::BlockHeader, 23 | Transaction = ::Transaction, 24 | Receipt = N::Receipt, 25 | >, 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /crates/node/builder/src/builder/add_ons.rs: -------------------------------------------------------------------------------- 1 | //! Node add-ons. Depend on core [`NodeComponents`](crate::NodeComponents). 2 | 3 | use reth_node_api::{FullNodeComponents, NodeAddOns}; 4 | 5 | use crate::{exex::BoxedLaunchExEx, hooks::NodeHooks}; 6 | 7 | /// Additional node extensions. 8 | /// 9 | /// At this point we consider all necessary components defined. 10 | pub struct AddOns> { 11 | /// Additional `NodeHooks` that are called at specific points in the node's launch lifecycle. 12 | pub hooks: NodeHooks, 13 | /// The `ExExs` (execution extensions) of the node. 14 | pub exexs: Vec<(String, Box>)>, 15 | /// Additional captured addons. 16 | pub add_ons: AddOns, 17 | } 18 | -------------------------------------------------------------------------------- /crates/node/builder/src/components/consensus.rs: -------------------------------------------------------------------------------- 1 | //! Consensus component for the node builder. 2 | use reth_consensus::{ConsensusError, FullConsensus}; 3 | use reth_node_api::PrimitivesTy; 4 | 5 | use crate::{BuilderContext, FullNodeTypes}; 6 | use std::future::Future; 7 | 8 | /// A type that knows how to build the consensus implementation. 9 | pub trait ConsensusBuilder: Send { 10 | /// The consensus implementation to build. 11 | type Consensus: FullConsensus, Error = ConsensusError> 12 | + Clone 13 | + Unpin 14 | + 'static; 15 | 16 | /// Creates the consensus implementation. 17 | fn build_consensus( 18 | self, 19 | ctx: &BuilderContext, 20 | ) -> impl Future> + Send; 21 | } 22 | 23 | impl ConsensusBuilder for F 24 | where 25 | Node: FullNodeTypes, 26 | Consensus: 27 | FullConsensus, Error = ConsensusError> + Clone + Unpin + 'static, 28 | F: FnOnce(&BuilderContext) -> Fut + Send, 29 | Fut: Future> + Send, 30 | { 31 | type Consensus = Consensus; 32 | 33 | fn build_consensus( 34 | self, 35 | ctx: &BuilderContext, 36 | ) -> impl Future> { 37 | self(ctx) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/node/builder/src/components/execute.rs: -------------------------------------------------------------------------------- 1 | //! EVM component for the node builder. 2 | use crate::{BuilderContext, ConfigureEvm, FullNodeTypes}; 3 | use reth_node_api::PrimitivesTy; 4 | use std::future::Future; 5 | 6 | /// A type that knows how to build the executor types. 7 | pub trait ExecutorBuilder: Send { 8 | /// The EVM config to use. 9 | /// 10 | /// This provides the node with the necessary configuration to configure an EVM. 11 | type EVM: ConfigureEvm> + 'static; 12 | 13 | /// Creates the EVM config. 14 | fn build_evm( 15 | self, 16 | ctx: &BuilderContext, 17 | ) -> impl Future> + Send; 18 | } 19 | 20 | impl ExecutorBuilder for F 21 | where 22 | Node: FullNodeTypes, 23 | EVM: ConfigureEvm> + 'static, 24 | F: FnOnce(&BuilderContext) -> Fut + Send, 25 | Fut: Future> + Send, 26 | { 27 | type EVM = EVM; 28 | 29 | fn build_evm( 30 | self, 31 | ctx: &BuilderContext, 32 | ) -> impl Future> { 33 | self(ctx) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /crates/node/builder/src/components/network.rs: -------------------------------------------------------------------------------- 1 | //! Network component for the node builder. 2 | 3 | use crate::{BuilderContext, FullNodeTypes}; 4 | use reth_network::types::NetPrimitivesFor; 5 | use reth_network_api::FullNetwork; 6 | use reth_node_api::PrimitivesTy; 7 | use reth_transaction_pool::TransactionPool; 8 | use std::future::Future; 9 | 10 | /// A type that knows how to build the network implementation. 11 | pub trait NetworkBuilder: Send { 12 | /// The network built. 13 | type Network: FullNetwork>>; 14 | 15 | /// Launches the network implementation and returns the handle to it. 16 | fn build_network( 17 | self, 18 | ctx: &BuilderContext, 19 | pool: Pool, 20 | ) -> impl Future> + Send; 21 | } 22 | 23 | impl NetworkBuilder for F 24 | where 25 | Node: FullNodeTypes, 26 | Net: FullNetwork>>, 27 | Pool: TransactionPool, 28 | F: Fn(&BuilderContext, Pool) -> Fut + Send, 29 | Fut: Future> + Send, 30 | { 31 | type Network = Net; 32 | 33 | fn build_network( 34 | self, 35 | ctx: &BuilderContext, 36 | pool: Pool, 37 | ) -> impl Future> + Send { 38 | self(ctx, pool) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/node/builder/src/exex.rs: -------------------------------------------------------------------------------- 1 | //! Types for launching execution extensions (ExEx). 2 | 3 | use std::future::Future; 4 | 5 | use futures::{future::BoxFuture, FutureExt}; 6 | use reth_exex::ExExContext; 7 | use reth_node_api::FullNodeComponents; 8 | 9 | /// A trait for launching an `ExEx`. 10 | pub trait LaunchExEx: Send { 11 | /// Launches the `ExEx`. 12 | /// 13 | /// The `ExEx` should be able to run independently and emit events on the channels provided in 14 | /// the [`ExExContext`]. 15 | fn launch( 16 | self, 17 | ctx: ExExContext, 18 | ) -> impl Future> + Send>> + Send; 19 | } 20 | 21 | /// A boxed exex future. 22 | pub type BoxExEx = BoxFuture<'static, eyre::Result<()>>; 23 | 24 | /// A version of [`LaunchExEx`] that returns a boxed future. Makes the trait object-safe. 25 | pub trait BoxedLaunchExEx: Send { 26 | /// Launches the `ExEx` and returns a boxed future. 27 | fn launch(self: Box, ctx: ExExContext) 28 | -> BoxFuture<'static, eyre::Result>; 29 | } 30 | 31 | /// Implements [`BoxedLaunchExEx`] for any [`LaunchExEx`] that is [Send] and `'static`. 32 | /// 33 | /// Returns a [`BoxFuture`] that resolves to a [`BoxExEx`]. 34 | impl BoxedLaunchExEx for E 35 | where 36 | E: LaunchExEx + Send + 'static, 37 | Node: FullNodeComponents, 38 | { 39 | fn launch( 40 | self: Box, 41 | ctx: ExExContext, 42 | ) -> BoxFuture<'static, eyre::Result> { 43 | async move { 44 | let exex = LaunchExEx::launch(*self, ctx).await?; 45 | Ok(Box::pin(exex) as BoxExEx) 46 | } 47 | .boxed() 48 | } 49 | } 50 | 51 | /// Implements `LaunchExEx` for any closure that takes an [`ExExContext`] and returns a future 52 | /// resolving to an `ExEx`. 53 | impl LaunchExEx for F 54 | where 55 | Node: FullNodeComponents, 56 | F: FnOnce(ExExContext) -> Fut + Send, 57 | Fut: Future> + Send, 58 | E: Future> + Send, 59 | { 60 | fn launch( 61 | self, 62 | ctx: ExExContext, 63 | ) -> impl Future> + Send>> + Send 64 | { 65 | self(ctx) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /crates/node/builder/src/handle.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use reth_node_api::FullNodeComponents; 4 | use reth_node_core::exit::NodeExitFuture; 5 | 6 | use crate::{node::FullNode, rpc::RethRpcAddOns}; 7 | 8 | /// A Handle to the launched node. 9 | #[must_use = "Needs to await the node exit future"] 10 | pub struct NodeHandle> { 11 | /// All node components. 12 | pub node: FullNode, 13 | /// The exit future of the node. 14 | pub node_exit_future: NodeExitFuture, 15 | } 16 | 17 | impl NodeHandle 18 | where 19 | Node: FullNodeComponents, 20 | AddOns: RethRpcAddOns, 21 | { 22 | /// Waits for the node to exit, if it was configured to exit. 23 | pub async fn wait_for_node_exit(self) -> eyre::Result<()> { 24 | self.node_exit_future.await 25 | } 26 | } 27 | 28 | impl fmt::Debug for NodeHandle 29 | where 30 | Node: FullNodeComponents, 31 | AddOns: RethRpcAddOns, 32 | { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | f.debug_struct("NodeHandle") 35 | .field("node", &"...") 36 | .field("node_exit_future", &self.node_exit_future) 37 | .finish() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/node/builder/src/launch/mod.rs: -------------------------------------------------------------------------------- 1 | //! Abstraction for launching a node. 2 | 3 | pub mod common; 4 | mod exex; 5 | 6 | pub(crate) mod debug; 7 | pub(crate) mod engine; 8 | 9 | pub use common::LaunchContext; 10 | pub use exex::ExExLauncher; 11 | 12 | use std::future::Future; 13 | 14 | /// A general purpose trait that launches a new node of any kind. 15 | /// 16 | /// Acts as a node factory that targets a certain node configuration and returns a handle to the 17 | /// node. 18 | /// 19 | /// This is essentially the launch logic for a node. 20 | /// 21 | /// See also [`EngineNodeLauncher`](crate::EngineNodeLauncher) and 22 | /// [`NodeBuilderWithComponents::launch_with`](crate::NodeBuilderWithComponents) 23 | pub trait LaunchNode { 24 | /// The node type that is created. 25 | type Node; 26 | 27 | /// Create and return a new node asynchronously. 28 | fn launch_node(self, target: Target) -> impl Future>; 29 | } 30 | 31 | impl LaunchNode for F 32 | where 33 | F: FnOnce(Target) -> Fut + Send, 34 | Fut: Future> + Send, 35 | { 36 | type Node = Node; 37 | 38 | fn launch_node(self, target: Target) -> impl Future> { 39 | self(target) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/node/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Standalone crate for Reth configuration and builder types. 2 | //! 3 | //! # features 4 | //! - `js-tracer`: Enable the `JavaScript` tracer for the `debug_trace` endpoints 5 | 6 | #![doc( 7 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 8 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 9 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 10 | )] 11 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 12 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 13 | 14 | /// Node event hooks. 15 | pub mod hooks; 16 | 17 | /// Support for configuring the higher level node types. 18 | pub mod node; 19 | pub use node::*; 20 | 21 | /// Support for configuring the components of a node. 22 | pub mod components; 23 | pub use components::{NodeComponents, NodeComponentsBuilder}; 24 | 25 | mod builder; 26 | pub use builder::{add_ons::AddOns, *}; 27 | 28 | mod launch; 29 | pub use launch::{ 30 | debug::{DebugNode, DebugNodeLauncher}, 31 | engine::EngineNodeLauncher, 32 | *, 33 | }; 34 | 35 | mod handle; 36 | pub use handle::NodeHandle; 37 | 38 | pub mod rpc; 39 | 40 | pub mod setup; 41 | 42 | /// Type aliases for traits that are often used together 43 | pub mod aliases; 44 | pub use aliases::*; 45 | 46 | /// Support for installing the ExExs (execution extensions) in a node. 47 | pub mod exex; 48 | 49 | /// Re-export the core configuration traits. 50 | pub use reth_node_core::cli::config::{ 51 | PayloadBuilderConfig, RethNetworkConfig, RethTransactionPoolConfig, 52 | }; 53 | 54 | // re-export the core config for convenience 55 | pub use reth_node_core::node_config::NodeConfig; 56 | 57 | // re-export API types for convenience 58 | pub use reth_node_api::*; 59 | 60 | use aquamarine as _; 61 | 62 | use reth_rpc as _; 63 | -------------------------------------------------------------------------------- /crates/node/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-node-core" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | 13 | [dependencies] 14 | # reth 15 | reth-chainspec.workspace = true 16 | reth-consensus.workspace = true 17 | reth-primitives-traits = { workspace = true, features = ["rayon"] } 18 | reth-cli-util.workspace = true 19 | reth-db = { workspace = true, features = ["mdbx"] } 20 | reth-storage-errors.workspace = true 21 | reth-storage-api = { workspace = true, features = ["std", "db-api"] } 22 | reth-network = { workspace = true, features = ["serde"] } 23 | reth-network-p2p.workspace = true 24 | reth-rpc-eth-types.workspace = true 25 | reth-rpc-server-types.workspace = true 26 | reth-rpc-types-compat.workspace = true 27 | reth-transaction-pool.workspace = true 28 | reth-tracing.workspace = true 29 | reth-config = { workspace = true, features = ["serde"] } 30 | reth-discv4.workspace = true 31 | reth-discv5.workspace = true 32 | reth-net-nat.workspace = true 33 | reth-network-peers.workspace = true 34 | reth-prune-types.workspace = true 35 | reth-stages-types.workspace = true 36 | reth-ethereum-forks.workspace = true 37 | reth-engine-primitives.workspace = true 38 | 39 | # ethereum 40 | alloy-primitives.workspace = true 41 | alloy-rpc-types-engine = { workspace = true, features = ["std", "jwt"] } 42 | alloy-consensus.workspace = true 43 | alloy-eips.workspace = true 44 | 45 | # misc 46 | eyre.workspace = true 47 | clap = { workspace = true, features = ["derive", "env"] } 48 | humantime.workspace = true 49 | rand.workspace = true 50 | derive_more.workspace = true 51 | toml.workspace = true 52 | serde.workspace = true 53 | strum = { workspace = true, features = ["derive"] } 54 | thiserror.workspace = true 55 | 56 | # io 57 | dirs-next.workspace = true 58 | shellexpand.workspace = true 59 | 60 | # tracing 61 | tracing.workspace = true 62 | 63 | # crypto 64 | secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } 65 | 66 | # async 67 | futures.workspace = true 68 | 69 | [dev-dependencies] 70 | # test vectors generation 71 | proptest.workspace = true 72 | tokio.workspace = true 73 | 74 | [features] 75 | # Features for vergen to generate correct env vars 76 | jemalloc = ["reth-cli-util/jemalloc"] 77 | asm-keccak = ["alloy-primitives/asm-keccak"] 78 | 79 | [build-dependencies] 80 | vergen = { workspace = true, features = ["build", "cargo", "emit_and_set"] } 81 | vergen-git2.workspace = true 82 | -------------------------------------------------------------------------------- /crates/node/core/src/args/benchmark_args.rs: -------------------------------------------------------------------------------- 1 | //! clap [Args](clap::Args) for benchmark configuration 2 | 3 | use clap::Args; 4 | use std::path::PathBuf; 5 | 6 | /// Parameters for benchmark configuration 7 | #[derive(Debug, Args, PartialEq, Eq, Default, Clone)] 8 | #[command(next_help_heading = "Benchmark")] 9 | pub struct BenchmarkArgs { 10 | /// Run the benchmark from a specific block. 11 | #[arg(long, verbatim_doc_comment)] 12 | pub from: Option, 13 | 14 | /// Run the benchmark to a specific block. 15 | #[arg(long, verbatim_doc_comment)] 16 | pub to: Option, 17 | 18 | /// Path to a JWT secret to use for the authenticated engine-API RPC server. 19 | /// 20 | /// This will perform JWT authentication for all requests to the given engine RPC url. 21 | /// 22 | /// If no path is provided, a secret will be generated and stored in the datadir under 23 | /// `//jwt.hex`. For mainnet this would be `~/.reth/mainnet/jwt.hex` by default. 24 | #[arg(long = "jwtsecret", value_name = "PATH", global = true, required = false)] 25 | pub auth_jwtsecret: Option, 26 | 27 | /// The RPC url to use for sending engine requests. 28 | #[arg( 29 | long, 30 | value_name = "ENGINE_RPC_URL", 31 | verbatim_doc_comment, 32 | default_value = "http://localhost:8551" 33 | )] 34 | pub engine_rpc_url: String, 35 | 36 | /// The path to the output directory for granular benchmark results. 37 | #[arg(long, short, value_name = "BENCHMARK_OUTPUT", verbatim_doc_comment)] 38 | pub output: Option, 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | use clap::Parser; 45 | 46 | /// A helper type to parse Args more easily 47 | #[derive(Parser)] 48 | struct CommandParser { 49 | #[command(flatten)] 50 | args: T, 51 | } 52 | 53 | #[test] 54 | fn test_parse_benchmark_args() { 55 | let default_args = BenchmarkArgs { 56 | engine_rpc_url: "http://localhost:8551".to_string(), 57 | ..Default::default() 58 | }; 59 | let args = CommandParser::::parse_from(["reth-bench"]).args; 60 | assert_eq!(args, default_args); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crates/node/core/src/args/datadir_args.rs: -------------------------------------------------------------------------------- 1 | //! clap [Args](clap::Args) for datadir config 2 | 3 | use crate::dirs::{ChainPath, DataDirPath, MaybePlatformPath}; 4 | use clap::Args; 5 | use reth_chainspec::Chain; 6 | use std::path::PathBuf; 7 | 8 | /// Parameters for datadir configuration 9 | #[derive(Debug, Args, PartialEq, Eq, Default, Clone)] 10 | #[command(next_help_heading = "Datadir")] 11 | pub struct DatadirArgs { 12 | /// The path to the data dir for all reth files and subdirectories. 13 | /// 14 | /// Defaults to the OS-specific data directory: 15 | /// 16 | /// - Linux: `$XDG_DATA_HOME/reth/` or `$HOME/.local/share/reth/` 17 | /// - Windows: `{FOLDERID_RoamingAppData}/reth/` 18 | /// - macOS: `$HOME/Library/Application Support/reth/` 19 | #[arg(long, value_name = "DATA_DIR", verbatim_doc_comment, default_value_t)] 20 | pub datadir: MaybePlatformPath, 21 | 22 | /// The absolute path to store static files in. 23 | #[arg( 24 | long = "datadir.static-files", 25 | alias = "datadir.static_files", 26 | value_name = "PATH", 27 | verbatim_doc_comment 28 | )] 29 | pub static_files_path: Option, 30 | } 31 | 32 | impl DatadirArgs { 33 | /// Resolves the final datadir path. 34 | pub fn resolve_datadir(self, chain: Chain) -> ChainPath { 35 | let datadir = self.datadir.clone(); 36 | datadir.unwrap_or_chain_default(chain, self) 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | use clap::Parser; 44 | 45 | /// A helper type to parse Args more easily 46 | #[derive(Parser)] 47 | struct CommandParser { 48 | #[command(flatten)] 49 | args: T, 50 | } 51 | 52 | #[test] 53 | fn test_parse_datadir_args() { 54 | let default_args = DatadirArgs::default(); 55 | let args = CommandParser::::parse_from(["reth"]).args; 56 | assert_eq!(args, default_args); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/node/core/src/args/error.rs: -------------------------------------------------------------------------------- 1 | use std::num::ParseIntError; 2 | 3 | /// Error while parsing a `ReceiptsLogPruneConfig` 4 | #[derive(thiserror::Error, Debug)] 5 | #[expect(clippy::enum_variant_names)] 6 | pub(crate) enum ReceiptsLogError { 7 | /// The format of the filter is invalid. 8 | #[error("invalid filter format: {0}")] 9 | InvalidFilterFormat(String), 10 | /// Address is invalid. 11 | #[error("address is invalid: {0}")] 12 | InvalidAddress(String), 13 | /// The prune mode is not one of full, distance, before. 14 | #[error("prune mode is invalid: {0}")] 15 | InvalidPruneMode(String), 16 | /// The distance value supplied is invalid. 17 | #[error("distance is invalid: {0}")] 18 | InvalidDistance(ParseIntError), 19 | /// The block number supplied is invalid. 20 | #[error("block number is invalid: {0}")] 21 | InvalidBlockNumber(ParseIntError), 22 | } 23 | -------------------------------------------------------------------------------- /crates/node/core/src/args/mod.rs: -------------------------------------------------------------------------------- 1 | //! Parameters for configuring the rpc more granularity via CLI 2 | 3 | /// NetworkArg struct for configuring the network 4 | mod network; 5 | pub use network::{DiscoveryArgs, NetworkArgs}; 6 | 7 | /// RpcServerArg struct for configuring the RPC 8 | mod rpc_server; 9 | pub use rpc_server::RpcServerArgs; 10 | 11 | /// `RpcStateCacheArgs` struct for configuring RPC state cache 12 | mod rpc_state_cache; 13 | pub use rpc_state_cache::RpcStateCacheArgs; 14 | 15 | /// DebugArgs struct for debugging purposes 16 | mod debug; 17 | pub use debug::{DebugArgs, InvalidBlockHookType, InvalidBlockSelection}; 18 | 19 | /// DatabaseArgs struct for configuring the database 20 | mod database; 21 | pub use database::DatabaseArgs; 22 | 23 | /// LogArgs struct for configuring the logger 24 | mod log; 25 | pub use log::{ColorMode, LogArgs, Verbosity}; 26 | 27 | /// `PayloadBuilderArgs` struct for configuring the payload builder 28 | mod payload_builder; 29 | pub use payload_builder::PayloadBuilderArgs; 30 | 31 | /// Stage related arguments 32 | mod stage; 33 | pub use stage::StageEnum; 34 | 35 | /// Gas price oracle related arguments 36 | mod gas_price_oracle; 37 | pub use gas_price_oracle::GasPriceOracleArgs; 38 | 39 | /// TxPoolArgs for configuring the transaction pool 40 | mod txpool; 41 | pub use txpool::TxPoolArgs; 42 | 43 | /// DevArgs for configuring the dev testnet 44 | mod dev; 45 | pub use dev::DevArgs; 46 | 47 | /// PruneArgs for configuring the pruning and full node 48 | mod pruning; 49 | pub use pruning::PruningArgs; 50 | 51 | /// DatadirArgs for configuring data storage paths 52 | mod datadir_args; 53 | pub use datadir_args::DatadirArgs; 54 | 55 | /// BenchmarkArgs struct for configuring the benchmark to run 56 | mod benchmark_args; 57 | pub use benchmark_args::BenchmarkArgs; 58 | 59 | /// EngineArgs for configuring the engine 60 | mod engine; 61 | pub use engine::EngineArgs; 62 | 63 | /// `RessArgs` for configuring ress subprotocol. 64 | mod ress_args; 65 | pub use ress_args::RessArgs; 66 | 67 | mod error; 68 | pub mod types; 69 | -------------------------------------------------------------------------------- /crates/node/core/src/args/ress_args.rs: -------------------------------------------------------------------------------- 1 | use clap::Args; 2 | 3 | /// The default number of maximum active connections. 4 | const MAX_ACTIVE_CONNECTIONS_DEFAULT: u64 = 5; 5 | 6 | /// The default maximum witness lookback window. 7 | const MAX_WITNESS_WINDOW_DEFAULT: u64 = 1024; 8 | 9 | /// The default maximum number of witnesses to generate in parallel. 10 | const WITNESS_MAX_PARALLEL_DEFAULT: usize = 5; 11 | 12 | /// The default witness cache size. 13 | const WITNESS_CACHE_SIZE_DEFAULT: u32 = 10; 14 | 15 | /// Parameters for configuring the `ress` subprotocol. 16 | #[derive(Debug, Clone, Args, PartialEq, Eq)] 17 | #[command(next_help_heading = "Ress")] 18 | pub struct RessArgs { 19 | /// Enable support for `ress` subprotocol. 20 | #[arg(long = "ress.enable", default_value_t = false)] 21 | pub enabled: bool, 22 | 23 | /// The maximum number of active connections for `ress` subprotocol. 24 | #[arg(long = "ress.max-active-connections", default_value_t = MAX_ACTIVE_CONNECTIONS_DEFAULT)] 25 | pub max_active_connections: u64, 26 | 27 | /// The maximum witness lookback window. 28 | #[arg(long = "ress.max-witness-window", default_value_t = MAX_WITNESS_WINDOW_DEFAULT)] 29 | pub max_witness_window: u64, 30 | 31 | /// The maximum number of witnesses to generate in parallel. 32 | #[arg(long = "ress.witness-max-parallel", default_value_t = WITNESS_MAX_PARALLEL_DEFAULT)] 33 | pub witness_max_parallel: usize, 34 | 35 | /// Witness cache size. 36 | #[arg(long = "ress.witness-cache-size", default_value_t = WITNESS_CACHE_SIZE_DEFAULT)] 37 | pub witness_cache_size: u32, 38 | } 39 | 40 | impl Default for RessArgs { 41 | fn default() -> Self { 42 | Self { 43 | enabled: false, 44 | max_active_connections: MAX_ACTIVE_CONNECTIONS_DEFAULT, 45 | max_witness_window: MAX_WITNESS_WINDOW_DEFAULT, 46 | witness_max_parallel: WITNESS_MAX_PARALLEL_DEFAULT, 47 | witness_cache_size: WITNESS_CACHE_SIZE_DEFAULT, 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /crates/node/core/src/args/rpc_state_cache.rs: -------------------------------------------------------------------------------- 1 | use clap::Args; 2 | use reth_rpc_server_types::constants::cache::{ 3 | DEFAULT_BLOCK_CACHE_MAX_LEN, DEFAULT_CONCURRENT_DB_REQUESTS, DEFAULT_HEADER_CACHE_MAX_LEN, 4 | DEFAULT_RECEIPT_CACHE_MAX_LEN, 5 | }; 6 | 7 | /// Parameters to configure RPC state cache. 8 | #[derive(Debug, Clone, Args, PartialEq, Eq)] 9 | #[command(next_help_heading = "RPC State Cache")] 10 | pub struct RpcStateCacheArgs { 11 | /// Max number of blocks in cache. 12 | #[arg( 13 | long = "rpc-cache.max-blocks", 14 | default_value_t = DEFAULT_BLOCK_CACHE_MAX_LEN, 15 | )] 16 | pub max_blocks: u32, 17 | 18 | /// Max number receipts in cache. 19 | #[arg( 20 | long = "rpc-cache.max-receipts", 21 | default_value_t = DEFAULT_RECEIPT_CACHE_MAX_LEN, 22 | )] 23 | pub max_receipts: u32, 24 | 25 | /// Max number of headers in cache. 26 | #[arg( 27 | long = "rpc-cache.max-headers", 28 | alias = "rpc-cache.max-envs", 29 | default_value_t = DEFAULT_HEADER_CACHE_MAX_LEN, 30 | )] 31 | pub max_headers: u32, 32 | 33 | /// Max number of concurrent database requests. 34 | #[arg( 35 | long = "rpc-cache.max-concurrent-db-requests", 36 | default_value_t = DEFAULT_CONCURRENT_DB_REQUESTS, 37 | )] 38 | pub max_concurrent_db_requests: usize, 39 | } 40 | 41 | impl RpcStateCacheArgs { 42 | /// Sets the Cache sizes to zero, effectively disabling caching. 43 | pub const fn set_zero_lengths(&mut self) { 44 | self.max_blocks = 0; 45 | self.max_receipts = 0; 46 | self.max_headers = 0; 47 | } 48 | } 49 | 50 | impl Default for RpcStateCacheArgs { 51 | fn default() -> Self { 52 | Self { 53 | max_blocks: DEFAULT_BLOCK_CACHE_MAX_LEN, 54 | max_receipts: DEFAULT_RECEIPT_CACHE_MAX_LEN, 55 | max_headers: DEFAULT_HEADER_CACHE_MAX_LEN, 56 | max_concurrent_db_requests: DEFAULT_CONCURRENT_DB_REQUESTS, 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/node/core/src/args/stage.rs: -------------------------------------------------------------------------------- 1 | //! Shared arguments related to stages 2 | use derive_more::Display; 3 | 4 | /// Represents a specific stage within the data pipeline. 5 | /// 6 | /// Different stages within the pipeline have dedicated functionalities and operations. 7 | #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, clap::ValueEnum, Display)] 8 | pub enum StageEnum { 9 | /// The headers stage within the pipeline. 10 | /// 11 | /// This stage handles operations related to block headers. 12 | Headers, 13 | /// The bodies stage within the pipeline. 14 | /// 15 | /// This stage deals with block bodies and their associated data. 16 | Bodies, 17 | /// The senders stage within the pipeline. 18 | /// 19 | /// Responsible for sender-related processes and data recovery. 20 | Senders, 21 | /// The execution stage within the pipeline. 22 | /// 23 | /// Handles the execution of transactions and contracts. 24 | Execution, 25 | /// The account hashing stage within the pipeline. 26 | /// 27 | /// Manages operations related to hashing account data. 28 | AccountHashing, 29 | /// The storage hashing stage within the pipeline. 30 | /// 31 | /// Manages operations related to hashing storage data. 32 | StorageHashing, 33 | /// The account and storage hashing stages within the pipeline. 34 | /// 35 | /// Covers general data hashing operations. 36 | Hashing, 37 | /// The merkle stage within the pipeline. 38 | /// 39 | /// Handles Merkle tree-related computations and data processing. 40 | Merkle, 41 | /// The transaction lookup stage within the pipeline. 42 | /// 43 | /// Deals with the retrieval and processing of transactions. 44 | TxLookup, 45 | /// The account history stage within the pipeline. 46 | /// 47 | /// Manages historical data related to accounts. 48 | AccountHistory, 49 | /// The storage history stage within the pipeline. 50 | /// 51 | /// Manages historical data related to storage. 52 | StorageHistory, 53 | } 54 | -------------------------------------------------------------------------------- /crates/node/core/src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | //! Additional CLI configuration support. 2 | 3 | pub mod config; 4 | -------------------------------------------------------------------------------- /crates/node/core/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The core of the Ethereum node. Collection of utilities and libraries that are used by the node. 2 | 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 5 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 6 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 7 | )] 8 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 9 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 10 | 11 | pub mod args; 12 | pub mod cli; 13 | pub mod dirs; 14 | pub mod exit; 15 | pub mod node_config; 16 | pub mod utils; 17 | pub mod version; 18 | 19 | /// Re-exported primitive types 20 | pub mod primitives { 21 | pub use reth_ethereum_forks::*; 22 | pub use reth_primitives_traits::*; 23 | } 24 | 25 | /// Re-export of `reth_rpc_*` crates. 26 | pub mod rpc { 27 | /// Re-exported from `reth_rpc::rpc`. 28 | pub mod result { 29 | pub use reth_rpc_server_types::result::*; 30 | } 31 | 32 | /// Re-exported from `reth_rpc::eth`. 33 | pub mod compat { 34 | pub use reth_rpc_types_compat::*; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/block/error.rs: -------------------------------------------------------------------------------- 1 | //! Error types for the `block` module. 2 | 3 | use crate::transaction::signed::RecoveryError; 4 | 5 | /// Type alias for [`BlockRecoveryError`] with a [`SealedBlock`](crate::SealedBlock) value. 6 | pub type SealedBlockRecoveryError = BlockRecoveryError>; 7 | 8 | /// Error when recovering a block from [`SealedBlock`](crate::SealedBlock) to 9 | /// [`RecoveredBlock`](crate::RecoveredBlock). 10 | /// 11 | /// This error is returned when the block recovery fails and contains the erroneous block, because 12 | /// recovering a block takes ownership of the block. 13 | #[derive(Debug, Clone, thiserror::Error)] 14 | #[error("Failed to recover the block")] 15 | pub struct BlockRecoveryError(pub T); 16 | 17 | impl BlockRecoveryError { 18 | /// Create a new error. 19 | pub const fn new(inner: T) -> Self { 20 | Self(inner) 21 | } 22 | 23 | /// Unwrap the error and return the original value. 24 | pub fn into_inner(self) -> T { 25 | self.0 26 | } 27 | } 28 | 29 | impl From> for RecoveryError 30 | where 31 | T: core::fmt::Debug + Send + Sync + 'static, 32 | { 33 | fn from(err: BlockRecoveryError) -> Self { 34 | Self::from_source(err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/block/header.rs: -------------------------------------------------------------------------------- 1 | //! Block header data primitive. 2 | 3 | use crate::{InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat}; 4 | use alloy_primitives::Sealable; 5 | use core::{fmt, hash::Hash}; 6 | 7 | /// Re-exported alias 8 | pub use alloy_consensus::BlockHeader as AlloyBlockHeader; 9 | 10 | /// Helper trait that unifies all behaviour required by block header to support full node 11 | /// operations. 12 | pub trait FullBlockHeader: BlockHeader + MaybeCompact {} 13 | 14 | impl FullBlockHeader for T where T: BlockHeader + MaybeCompact {} 15 | 16 | /// Abstraction of a block header. 17 | pub trait BlockHeader: 18 | Send 19 | + Sync 20 | + Unpin 21 | + Clone 22 | + Hash 23 | + Default 24 | + fmt::Debug 25 | + PartialEq 26 | + Eq 27 | + alloy_rlp::Encodable 28 | + alloy_rlp::Decodable 29 | + alloy_consensus::BlockHeader 30 | + Sealable 31 | + InMemorySize 32 | + MaybeSerde 33 | + MaybeSerdeBincodeCompat 34 | + AsRef 35 | + 'static 36 | { 37 | } 38 | 39 | impl BlockHeader for alloy_consensus::Header {} 40 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/constants/mod.rs: -------------------------------------------------------------------------------- 1 | //! Ethereum protocol-related constants 2 | 3 | /// Gas units, for example [`GIGAGAS`]. 4 | pub mod gas_units; 5 | pub use gas_units::{GIGAGAS, KILOGAS, MEGAGAS}; 6 | 7 | use alloy_primitives::{b256, B256}; 8 | /// n42 block gas limit 9 | pub const N42_BLOCK_GAS_LIMIT: u64 = 9_223_372_036_854_775_807; 10 | 11 | /// The n42 mainnet genesis hash: 12 | /// `0x138734b7044254e5ecbabf8056f5c2b73cd0847aaa5acac7345507cbeab387b8` 13 | pub const N42_GENESIS_HASH: B256 = 14 | b256!("138734b7044254e5ecbabf8056f5c2b73cd0847aaa5acac7345507cbeab387b8"); 15 | 16 | /// The client version: `reth/v{major}.{minor}.{patch}` 17 | pub const RETH_CLIENT_VERSION: &str = concat!("reth/v", env!("CARGO_PKG_VERSION")); 18 | 19 | /// Minimum gas limit allowed for transactions. 20 | pub const MINIMUM_GAS_LIMIT: u64 = 5000; 21 | 22 | /// Maximum gas limit allowed for block. 23 | /// In hex this number is `0x7fffffffffffffff` 24 | pub const MAXIMUM_GAS_LIMIT_BLOCK: u64 = 2u64.pow(63) - 1; 25 | 26 | /// The bound divisor of the gas limit, used in update calculations. 27 | pub const GAS_LIMIT_BOUND_DIVISOR: u64 = 1024; 28 | 29 | /// The number of blocks to unwind during a reorg that already became a part of canonical chain. 30 | /// 31 | /// In reality, the node can end up in this particular situation very rarely. It would happen only 32 | /// if the node process is abruptly terminated during ongoing reorg and doesn't boot back up for 33 | /// long period of time. 34 | /// 35 | /// Unwind depth of `3` blocks significantly reduces the chance that the reorged block is kept in 36 | /// the database. 37 | pub const BEACON_CONSENSUS_REORG_UNWIND_DEPTH: u64 = 3; 38 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/crypto.rs: -------------------------------------------------------------------------------- 1 | //! Crypto utilities. 2 | 3 | pub use alloy_consensus::crypto::*; 4 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/error.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use core::ops::{Deref, DerefMut}; 3 | 4 | /// A pair of values, one of which is expected and one of which is actual. 5 | #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)] 6 | #[error("got {got}, expected {expected}")] 7 | pub struct GotExpected { 8 | /// The actual value. 9 | pub got: T, 10 | /// The expected value. 11 | pub expected: T, 12 | } 13 | 14 | impl From<(T, T)> for GotExpected { 15 | #[inline] 16 | fn from((got, expected): (T, T)) -> Self { 17 | Self::new(got, expected) 18 | } 19 | } 20 | 21 | impl GotExpected { 22 | /// Creates a new error from a pair of values. 23 | #[inline] 24 | pub const fn new(got: T, expected: T) -> Self { 25 | Self { got, expected } 26 | } 27 | } 28 | 29 | /// A pair of values, one of which is expected and one of which is actual. 30 | /// 31 | /// Same as [`GotExpected`], but [`Box`]ed for smaller size. 32 | /// 33 | /// Prefer instantiating using [`GotExpected`], and then using `.into()` to convert to this type. 34 | #[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error, Debug)] 35 | #[error(transparent)] 36 | pub struct GotExpectedBoxed(pub Box>); 37 | 38 | impl Deref for GotExpectedBoxed { 39 | type Target = GotExpected; 40 | 41 | #[inline(always)] 42 | fn deref(&self) -> &Self::Target { 43 | &self.0 44 | } 45 | } 46 | 47 | impl DerefMut for GotExpectedBoxed { 48 | #[inline(always)] 49 | fn deref_mut(&mut self) -> &mut Self::Target { 50 | &mut self.0 51 | } 52 | } 53 | 54 | impl From<(T, T)> for GotExpectedBoxed { 55 | #[inline] 56 | fn from(value: (T, T)) -> Self { 57 | Self(Box::new(GotExpected::from(value))) 58 | } 59 | } 60 | 61 | impl From> for GotExpectedBoxed { 62 | #[inline] 63 | fn from(value: GotExpected) -> Self { 64 | Self(Box::new(value)) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/header/error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can occur during header sanity checks. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub enum HeaderError { 4 | /// Represents an error when the block difficulty is too large. 5 | LargeDifficulty, 6 | /// Represents an error when the block extra data is too large. 7 | LargeExtraData, 8 | } 9 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/header/mod.rs: -------------------------------------------------------------------------------- 1 | mod sealed; 2 | pub use sealed::{Header, SealedHeader, SealedHeaderFor}; 3 | 4 | mod error; 5 | pub use error::HeaderError; 6 | 7 | #[cfg(any(test, feature = "test-utils", feature = "arbitrary"))] 8 | pub mod test_utils; 9 | 10 | pub mod clique_utils; 11 | 12 | /// Bincode-compatible header type serde implementations. 13 | #[cfg(feature = "serde-bincode-compat")] 14 | pub mod serde_bincode_compat { 15 | pub use super::sealed::serde_bincode_compat::SealedHeader; 16 | } 17 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/log.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use alloy_primitives::{Address, Bytes, Log as AlloyLog, B256}; 4 | use alloy_rlp::{RlpDecodable, RlpEncodable}; 5 | use proptest::proptest; 6 | use proptest_arbitrary_interop::arb; 7 | use reth_codecs::{add_arbitrary_tests, Compact}; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// This type is kept for compatibility tests after the codec support was added to 11 | /// alloy-primitives Log type natively 12 | #[derive( 13 | Clone, 14 | Debug, 15 | PartialEq, 16 | Eq, 17 | RlpDecodable, 18 | RlpEncodable, 19 | Default, 20 | Serialize, 21 | Deserialize, 22 | Compact, 23 | )] 24 | #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] 25 | #[add_arbitrary_tests(compact, rlp)] 26 | struct Log { 27 | /// Contract that emitted this log. 28 | address: Address, 29 | /// Topics of the log. The number of logs depends on what `LOG` opcode is used. 30 | topics: Vec, 31 | /// Arbitrary length data. 32 | data: Bytes, 33 | } 34 | 35 | impl From for Log { 36 | fn from(mut log: AlloyLog) -> Self { 37 | Self { 38 | address: log.address, 39 | topics: std::mem::take(log.data.topics_mut_unchecked()), 40 | data: log.data.data, 41 | } 42 | } 43 | } 44 | 45 | impl From for AlloyLog { 46 | fn from(log: Log) -> Self { 47 | Self::new_unchecked(log.address, log.topics, log.data) 48 | } 49 | } 50 | 51 | proptest! { 52 | #[test] 53 | fn test_roundtrip_conversion_between_log_and_alloy_log(log in arb::()) { 54 | // Convert log to buffer and then create alloy_log from buffer and compare 55 | let mut compacted_log = Vec::::new(); 56 | let len = log.to_compact(&mut compacted_log); 57 | 58 | let alloy_log = AlloyLog::from_compact(&compacted_log, len).0; 59 | assert_eq!(log, alloy_log.into()); 60 | 61 | // Create alloy_log from log and then convert it to buffer and compare compacted_alloy_log and compacted_log 62 | let alloy_log = AlloyLog::new_unchecked(log.address, log.topics, log.data); 63 | let mut compacted_alloy_log = Vec::::new(); 64 | let alloy_len = alloy_log.to_compact(&mut compacted_alloy_log); 65 | assert_eq!(len, alloy_len); 66 | assert_eq!(compacted_log, compacted_alloy_log); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/receipt.rs: -------------------------------------------------------------------------------- 1 | //! Receipt abstraction 2 | 3 | use crate::{InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat}; 4 | use alloc::vec::Vec; 5 | use alloy_consensus::{ 6 | Eip2718EncodableReceipt, RlpDecodableReceipt, RlpEncodableReceipt, TxReceipt, Typed2718, 7 | }; 8 | use core::fmt; 9 | 10 | /// Helper trait that unifies all behaviour required by receipt to support full node operations. 11 | pub trait FullReceipt: Receipt + MaybeCompact {} 12 | 13 | impl FullReceipt for T where T: Receipt + MaybeCompact {} 14 | 15 | /// Abstraction of a receipt. 16 | #[auto_impl::auto_impl(&, Arc)] 17 | pub trait Receipt: 18 | Send 19 | + Sync 20 | + Unpin 21 | + Clone 22 | + fmt::Debug 23 | + TxReceipt 24 | + RlpEncodableReceipt 25 | + RlpDecodableReceipt 26 | + Eip2718EncodableReceipt 27 | + Typed2718 28 | + MaybeSerde 29 | + InMemorySize 30 | + MaybeSerdeBincodeCompat 31 | { 32 | } 33 | 34 | /// Retrieves gas spent by transactions as a vector of tuples (transaction index, gas used). 35 | pub fn gas_spent_by_transactions(receipts: I) -> Vec<(u64, u64)> 36 | where 37 | I: IntoIterator, 38 | T: TxReceipt, 39 | { 40 | receipts 41 | .into_iter() 42 | .enumerate() 43 | .map(|(id, receipt)| (id as u64, receipt.cumulative_gas_used())) 44 | .collect() 45 | } 46 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/storage.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::{B256, U256}; 2 | 3 | /// Account storage entry. 4 | /// 5 | /// `key` is the subkey when used as a value in the `StorageChangeSets` table. 6 | #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 7 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 8 | #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] 9 | #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] 10 | pub struct StorageEntry { 11 | /// Storage key. 12 | pub key: B256, 13 | /// Value on storage key. 14 | pub value: U256, 15 | } 16 | 17 | impl StorageEntry { 18 | /// Create a new `StorageEntry` with given key and value. 19 | pub const fn new(key: B256, value: U256) -> Self { 20 | Self { key, value } 21 | } 22 | } 23 | 24 | impl From<(B256, U256)> for StorageEntry { 25 | fn from((key, value): (B256, U256)) -> Self { 26 | Self { key, value } 27 | } 28 | } 29 | 30 | // NOTE: Removing reth_codec and manually encode subkey 31 | // and compress second part of the value. If we have compression 32 | // over whole value (Even SubKey) that would mess up fetching of values with seek_by_key_subkey 33 | #[cfg(any(test, feature = "reth-codec"))] 34 | impl reth_codecs::Compact for StorageEntry { 35 | fn to_compact(&self, buf: &mut B) -> usize 36 | where 37 | B: bytes::BufMut + AsMut<[u8]>, 38 | { 39 | // for now put full bytes and later compress it. 40 | buf.put_slice(&self.key[..]); 41 | self.value.to_compact(buf) + 32 42 | } 43 | 44 | fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { 45 | let key = B256::from_slice(&buf[..32]); 46 | let (value, out) = U256::from_compact(&buf[32..], len - 32); 47 | (Self { key, value }, out) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/sync.rs: -------------------------------------------------------------------------------- 1 | //! Lock synchronization primitives 2 | 3 | use once_cell as _; 4 | 5 | #[cfg(not(feature = "std"))] 6 | pub use once_cell::sync::{Lazy as LazyLock, OnceCell as OnceLock}; 7 | 8 | #[cfg(feature = "std")] 9 | pub use std::sync::{LazyLock, OnceLock}; 10 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/transaction/execute.rs: -------------------------------------------------------------------------------- 1 | //! Abstraction of an executable transaction. 2 | 3 | use alloy_primitives::Address; 4 | 5 | /// Loads transaction into execution environment. 6 | pub trait FillTxEnv { 7 | /// Fills `TxEnv` with an [`Address`] and transaction. 8 | fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address); 9 | } 10 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/transaction/mod.rs: -------------------------------------------------------------------------------- 1 | //! Transaction abstraction 2 | 3 | pub mod execute; 4 | pub mod signature; 5 | pub mod signed; 6 | 7 | pub mod error; 8 | pub mod recover; 9 | 10 | pub use alloy_consensus::transaction::{SignerRecoverable, TransactionInfo, TransactionMeta}; 11 | 12 | use crate::{InMemorySize, MaybeCompact, MaybeSerde}; 13 | use core::{fmt, hash::Hash}; 14 | 15 | #[cfg(test)] 16 | mod access_list; 17 | 18 | /// Helper trait that unifies all behaviour required by transaction to support full node operations. 19 | pub trait FullTransaction: Transaction + MaybeCompact {} 20 | 21 | impl FullTransaction for T where T: Transaction + MaybeCompact {} 22 | 23 | /// Abstraction of a transaction. 24 | pub trait Transaction: 25 | Send 26 | + Sync 27 | + Unpin 28 | + Clone 29 | + fmt::Debug 30 | + Eq 31 | + PartialEq 32 | + Hash 33 | + alloy_consensus::Transaction 34 | + InMemorySize 35 | + MaybeSerde 36 | { 37 | } 38 | 39 | impl Transaction for T where 40 | T: Send 41 | + Sync 42 | + Unpin 43 | + Clone 44 | + fmt::Debug 45 | + Eq 46 | + PartialEq 47 | + Hash 48 | + alloy_consensus::Transaction 49 | + InMemorySize 50 | + MaybeSerde 51 | { 52 | } 53 | -------------------------------------------------------------------------------- /crates/primitives-traits/src/transaction/signature.rs: -------------------------------------------------------------------------------- 1 | //! Signature types and helpers 2 | 3 | /// Re-exported signature type 4 | pub use alloy_primitives::Signature; 5 | 6 | #[cfg(test)] 7 | mod tests { 8 | use crate::crypto::secp256k1::recover_signer; 9 | use alloy_primitives::{address, Signature, B256, U256}; 10 | use std::str::FromStr; 11 | 12 | #[test] 13 | fn test_recover_signer() { 14 | let signature = Signature::new( 15 | U256::from_str( 16 | "18515461264373351373200002665853028612451056578545711640558177340181847433846", 17 | ) 18 | .unwrap(), 19 | U256::from_str( 20 | "46948507304638947509940763649030358759909902576025900602547168820602576006531", 21 | ) 22 | .unwrap(), 23 | false, 24 | ); 25 | let hash = 26 | B256::from_str("daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53") 27 | .unwrap(); 28 | let signer = recover_signer(&signature, hash).unwrap(); 29 | let expected = address!("0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"); 30 | assert_eq!(expected, signer); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/rpc/rpc-types-compat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reth-rpc-types-compat" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | homepage.workspace = true 8 | repository.workspace = true 9 | description = "Compatibility layer for reth-primitives and ethereum RPC types" 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [dependencies] 15 | # reth 16 | reth-primitives-traits.workspace = true 17 | 18 | # ethereum 19 | alloy-primitives.workspace = true 20 | alloy-rpc-types-eth = { workspace = true, default-features = false, features = ["serde"] } 21 | alloy-consensus.workspace = true 22 | 23 | # io 24 | serde.workspace = true 25 | jsonrpsee-types.workspace = true 26 | -------------------------------------------------------------------------------- /crates/rpc/rpc-types-compat/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Reth compatibility and utils for RPC types 2 | //! 3 | //! This crate various helper functions to convert between reth primitive types and rpc types. 4 | 5 | #![doc( 6 | html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", 7 | html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", 8 | issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" 9 | )] 10 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 11 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 12 | 13 | pub mod block; 14 | pub mod transaction; 15 | pub use transaction::TransactionCompat; 16 | -------------------------------------------------------------------------------- /crates/rpc/rpc-types-compat/src/transaction.rs: -------------------------------------------------------------------------------- 1 | //! Compatibility functions for rpc `Transaction` type. 2 | 3 | use alloy_consensus::transaction::Recovered; 4 | use alloy_rpc_types_eth::{request::TransactionRequest, TransactionInfo}; 5 | use core::error; 6 | use serde::{Deserialize, Serialize}; 7 | use std::fmt; 8 | 9 | /// Builds RPC transaction w.r.t. network. 10 | pub trait TransactionCompat: Send + Sync + Unpin + Clone + fmt::Debug { 11 | /// RPC transaction response type. 12 | type Transaction: Serialize 13 | + for<'de> Deserialize<'de> 14 | + Send 15 | + Sync 16 | + Unpin 17 | + Clone 18 | + fmt::Debug; 19 | 20 | /// RPC transaction error type. 21 | type Error: error::Error + Into>; 22 | 23 | /// Wrapper for `fill()` with default `TransactionInfo` 24 | /// Create a new rpc transaction result for a _pending_ signed transaction, setting block 25 | /// environment related fields to `None`. 26 | fn fill_pending(&self, tx: Recovered) -> Result { 27 | self.fill(tx, TransactionInfo::default()) 28 | } 29 | 30 | /// Create a new rpc transaction result for a mined transaction, using the given block hash, 31 | /// number, and tx index fields to populate the corresponding fields in the rpc result. 32 | /// 33 | /// The block hash, number, and tx index fields should be from the original block where the 34 | /// transaction was mined. 35 | fn fill( 36 | &self, 37 | tx: Recovered, 38 | tx_inf: TransactionInfo, 39 | ) -> Result; 40 | 41 | /// Builds a fake transaction from a transaction request for inclusion into block built in 42 | /// `eth_simulateV1`. 43 | fn build_simulate_v1_transaction(&self, request: TransactionRequest) -> Result; 44 | 45 | /// Truncates the input of a transaction to only the first 4 bytes. 46 | // todo: remove in favour of using constructor on `TransactionResponse` or similar 47 | // . 48 | fn otterscan_api_truncate_input(tx: &mut Self::Transaction); 49 | } 50 | -------------------------------------------------------------------------------- /crates/storage/db-api/src/common.rs: -------------------------------------------------------------------------------- 1 | use crate::{table::*, DatabaseError}; 2 | 3 | /// A key-value pair for table `T`. 4 | pub type KeyValue = (::Key, ::Value); 5 | 6 | /// A fallible key-value pair that may or may not exist. 7 | /// 8 | /// The `Result` represents that the operation might fail, while the `Option` represents whether or 9 | /// not the entry exists. 10 | pub type PairResult = Result>, DatabaseError>; 11 | 12 | /// A key-value pair coming from an iterator. 13 | /// 14 | /// The `Result` represents that the operation might fail, while the `Option` represents whether or 15 | /// not there is another entry. 16 | pub type IterPairResult = Option, DatabaseError>>; 17 | 18 | /// A value only result for table `T`. 19 | pub type ValueOnlyResult = Result::Value>, DatabaseError>; 20 | -------------------------------------------------------------------------------- /crates/storage/db-api/src/database.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | table::TableImporter, 3 | transaction::{DbTx, DbTxMut}, 4 | DatabaseError, 5 | }; 6 | use std::{fmt::Debug, sync::Arc}; 7 | 8 | /// Main Database trait that can open read-only and read-write transactions. 9 | /// 10 | /// Sealed trait which cannot be implemented by 3rd parties, exposed only for consumption. 11 | pub trait Database: Send + Sync + Debug { 12 | /// Read-Only database transaction 13 | type TX: DbTx + Send + Sync + Debug + 'static; 14 | /// Read-Write database transaction 15 | type TXMut: DbTxMut + DbTx + TableImporter + Send + Sync + Debug + 'static; 16 | 17 | /// Create read only transaction. 18 | #[track_caller] 19 | fn tx(&self) -> Result; 20 | 21 | /// Create read write transaction only possible if database is open with write access. 22 | #[track_caller] 23 | fn tx_mut(&self) -> Result; 24 | 25 | /// Takes a function and passes a read-only transaction into it, making sure it's closed in the 26 | /// end of the execution. 27 | fn view(&self, f: F) -> Result 28 | where 29 | F: FnOnce(&Self::TX) -> T, 30 | { 31 | let tx = self.tx()?; 32 | 33 | let res = f(&tx); 34 | tx.commit()?; 35 | 36 | Ok(res) 37 | } 38 | 39 | /// Takes a function and passes a write-read transaction into it, making sure it's committed in 40 | /// the end of the execution. 41 | fn update(&self, f: F) -> Result 42 | where 43 | F: FnOnce(&Self::TXMut) -> T, 44 | { 45 | let tx = self.tx_mut()?; 46 | 47 | let res = f(&tx); 48 | tx.commit()?; 49 | 50 | Ok(res) 51 | } 52 | } 53 | 54 | impl Database for Arc { 55 | type TX = ::TX; 56 | type TXMut = ::TXMut; 57 | 58 | fn tx(&self) -> Result { 59 | ::tx(self) 60 | } 61 | 62 | fn tx_mut(&self) -> Result { 63 | ::tx_mut(self) 64 | } 65 | } 66 | 67 | impl Database for &DB { 68 | type TX = ::TX; 69 | type TXMut = ::TXMut; 70 | 71 | fn tx(&self) -> Result { 72 | ::tx(self) 73 | } 74 | 75 | fn tx_mut(&self) -> Result { 76 | ::tx_mut(self) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /crates/storage/db-api/src/database_metrics.rs: -------------------------------------------------------------------------------- 1 | use metrics::{counter, gauge, histogram, Label}; 2 | use std::sync::Arc; 3 | 4 | /// Represents a type that can report metrics, used mainly with the database. The `report_metrics` 5 | /// method can be used as a prometheus hook. 6 | pub trait DatabaseMetrics { 7 | /// Reports metrics for the database. 8 | fn report_metrics(&self) { 9 | for (name, value, labels) in self.gauge_metrics() { 10 | gauge!(name, labels).set(value); 11 | } 12 | 13 | for (name, value, labels) in self.counter_metrics() { 14 | counter!(name, labels).increment(value); 15 | } 16 | 17 | for (name, value, labels) in self.histogram_metrics() { 18 | histogram!(name, labels).record(value); 19 | } 20 | } 21 | 22 | /// Returns a list of [Gauge](metrics::Gauge) metrics for the database. 23 | fn gauge_metrics(&self) -> Vec<(&'static str, f64, Vec