Skip to content

Commit

Permalink
reth-ethereum-forks crate (paradigmxyz#5621)
Browse files Browse the repository at this point in the history
Co-authored-by: root <root@Arindam>
Co-authored-by: Matthias Seitz <[email protected]>
  • Loading branch information
3 people authored Dec 1, 2023
1 parent 1067bb3 commit 2144b97
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 198 deletions.
237 changes: 160 additions & 77 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
"crates/consensus/auto-seal/",
"crates/consensus/beacon/",
"crates/consensus/common/",
"crates/ethereum-forks/",
"crates/interfaces/",
"crates/metrics/",
"crates/metrics/metrics-derive/",
Expand Down Expand Up @@ -102,6 +103,7 @@ reth-dns-discovery = { path = "crates/net/dns" }
reth-downloaders = { path = "crates/net/downloaders" }
reth-ecies = { path = "crates/net/ecies" }
reth-eth-wire = { path = "crates/net/eth-wire" }
reth-ethereum-forks = { path = "crates/ethereum-forks" }
reth-interfaces = { path = "crates/interfaces" }
reth-ipc = { path = "crates/rpc/ipc" }
reth-libmdbx = { path = "crates/storage/libmdbx-rs" }
Expand Down
41 changes: 41 additions & 0 deletions crates/ethereum-forks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[package]
name = "reth-ethereum-forks"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
description = "Ethereum fork types used in reth."

[dependencies]
# reth
reth-codecs.workspace = true

# ethereum
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
alloy-rlp = { workspace = true, features = ["arrayvec"] }

# used for forkid
crc = "3"

# misc
serde.workspace = true
thiserror.workspace = true


# arbitrary utils
arbitrary = { workspace = true, features = ["derive"], optional = true }
proptest = { workspace = true, optional = true }
proptest-derive = { workspace = true, optional = true }

[dev-dependencies]
rand.workspace = true
arbitrary = { workspace = true, features = ["derive"] }
proptest.workspace = true
proptest-derive.workspace = true


[features]
arbitrary = ["dep:arbitrary", "dep:proptest", "dep:proptest-derive"]
optimism = ["reth-codecs/optimism"]
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
//!
//! Previously version of Apache licenced [`ethereum-forkid`](https://crates.io/crates/ethereum-forkid).
#![deny(missing_docs)]

use crate::{hex, BlockNumber, Head, B256};
use crate::Head;
use alloy_primitives::{hex, BlockNumber, B256};
use alloy_rlp::*;
use crc::*;
use reth_codecs::derive_arbitrary;
Expand Down Expand Up @@ -72,10 +71,12 @@ where
}
}

// TODO: Move
/// How to filter forks.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum ForkFilterKey {
/// By block number activation.
Block(BlockNumber),
/// By timestamp activation.
Time(u64),
}

Expand Down Expand Up @@ -379,7 +380,7 @@ impl Cache {
#[cfg(test)]
mod tests {
use super::*;
use crate::{hex_literal::hex, revm_primitives::b256};
use alloy_primitives::b256;

const GENESIS_HASH: B256 =
b256!("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use serde::{Deserialize, Serialize};

use crate::{ChainSpec, ForkCondition, ForkFilter, ForkId};
use std::{fmt::Display, str::FromStr};

/// The name of an Ethereum hardfork.
Expand Down Expand Up @@ -52,25 +51,6 @@ pub enum Hardfork {
Cancun,
}

impl Hardfork {
/// Get the [ForkId] for this hardfork in the given spec, if the fork is activated at any point.
pub fn fork_id(&self, spec: &ChainSpec) -> Option<ForkId> {
match spec.fork(*self) {
ForkCondition::Never => None,
_ => Some(spec.fork_id(&spec.satisfy(spec.fork(*self)))),
}
}

/// Get the [ForkFilter] for this hardfork in the given spec, if the fork is activated at any
/// point.
pub fn fork_filter(&self, spec: &ChainSpec) -> Option<ForkFilter> {
match spec.fork(*self) {
ForkCondition::Never => None,
_ => Some(spec.fork_filter(spec.satisfy(spec.fork(*self)))),
}
}
}

impl FromStr for Hardfork {
type Err = String;

Expand Down Expand Up @@ -115,8 +95,6 @@ impl Display for Hardfork {
#[cfg(test)]
mod tests {
use super::*;
use crate::{Chain, Genesis};
use std::collections::BTreeMap;

#[test]
fn check_hardfork_from_str() {
Expand Down Expand Up @@ -181,34 +159,4 @@ mod tests {
fn check_nonexistent_hardfork_from_str() {
assert!(Hardfork::from_str("not a hardfork").is_err());
}

#[test]
fn check_fork_id_chainspec_with_fork_condition_never() {
let spec = ChainSpec {
chain: Chain::mainnet(),
genesis: Genesis::default(),
genesis_hash: None,
hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]),
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
};

assert_eq!(Hardfork::Frontier.fork_id(&spec), None);
}

#[test]
fn check_fork_filter_chainspec_with_fork_condition_never() {
let spec = ChainSpec {
chain: Chain::mainnet(),
genesis: Genesis::default(),
genesis_hash: None,
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]),
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
};

assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None);
}
}
24 changes: 24 additions & 0 deletions crates/ethereum-forks/src/head.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use alloy_primitives::{BlockNumber, B256, U256};
use serde::{Deserialize, Serialize};

/// Describes the current head block.
///
/// The head block is the highest fully synced block.
///
/// Note: This is a slimmed down version of Header, primarily for communicating the highest block
/// with the P2P network and the RPC.
#[derive(
Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct Head {
/// The number of the head block.
pub number: BlockNumber,
/// The hash of the head block.
pub hash: B256,
/// The difficulty of the head block.
pub difficulty: U256,
/// The total difficulty at the head block.
pub total_difficulty: U256,
/// The timestamp of the head block.
pub timestamp: u64,
}
28 changes: 28 additions & 0 deletions crates/ethereum-forks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Ethereum fork types used in reth.
//!
//! This crate contains Ethereum fork types and helper functions.
//!
//! ## Feature Flags
//!
//! - `arbitrary`: Adds `proptest` and `arbitrary` support for primitive types.
#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
)]
#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)]
#![deny(unused_must_use, rust_2018_idioms, unused_crate_dependencies)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![allow(clippy::non_canonical_clone_impl)]

mod forkid;
mod hardfork;
mod head;

pub use forkid::{ForkFilter, ForkFilterKey, ForkHash, ForkId, ForkTransition, ValidationError};
pub use hardfork::Hardfork;
pub use head::Head;

#[cfg(any(test, feature = "arbitrary"))]
pub use arbitrary;
2 changes: 1 addition & 1 deletion crates/net/dns/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ mod tests {

let mut builder = EnrBuilder::new("v4");
let mut buf = Vec::new();
let fork_id = Hardfork::Frontier.fork_id(&MAINNET).unwrap();
let fork_id = MAINNET.hardfork_fork_id(Hardfork::Frontier).unwrap();
fork_id.encode(&mut buf);
builder.ip4(Ipv4Addr::LOCALHOST).udp4(30303).tcp4(30303).add_value(b"eth", &buf);
let enr = builder.build(&secret_key).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions crates/net/eth-wire/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use reth_primitives::{Chain, ForkId, B256, U256};
/// .total_difficulty(U256::from(100))
/// .blockhash(B256::from(MAINNET_GENESIS_HASH))
/// .genesis(B256::from(MAINNET_GENESIS_HASH))
/// .forkid(Hardfork::Paris.fork_id(&MAINNET).unwrap())
/// .forkid(MAINNET.hardfork_fork_id(Hardfork::Paris).unwrap())
/// .build();
///
/// assert_eq!(
Expand All @@ -28,7 +28,7 @@ use reth_primitives::{Chain, ForkId, B256, U256};
/// total_difficulty: U256::from(100),
/// blockhash: B256::from(MAINNET_GENESIS_HASH),
/// genesis: B256::from(MAINNET_GENESIS_HASH),
/// forkid: Hardfork::Paris.fork_id(&MAINNET).unwrap(),
/// forkid: MAINNET.hardfork_fork_id(Hardfork::Paris).unwrap(),
/// }
/// );
/// ```
Expand Down
4 changes: 2 additions & 2 deletions crates/net/eth-wire/src/types/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ impl Default for Status {
total_difficulty: U256::from(17_179_869_184u64),
blockhash: mainnet_genesis,
genesis: mainnet_genesis,
forkid: Hardfork::Frontier
.fork_id(&MAINNET)
forkid: MAINNET
.hardfork_fork_id(Hardfork::Frontier)
.expect("The Frontier hardfork should always exist"),
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/net/network/src/session/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,8 @@ mod tests {
secret_key,
local_peer_id,
status: StatusBuilder::default().build(),
fork_filter: Hardfork::Frontier
.fork_filter(&MAINNET)
fork_filter: MAINNET
.hardfork_fork_filter(Hardfork::Frontier)
.expect("The Frontier fork filter should exist on mainnet"),
bandwidth_meter: BandwidthMeter::default(),
}
Expand Down
54 changes: 31 additions & 23 deletions crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
name = "reth-primitives"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
description = "Commonly used types in reth."

[dependencies]
# reth
reth-codecs.workspace = true
reth-ethereum-forks.workspace = true
reth-rpc-types.workspace = true
revm-primitives.workspace = true
revm.workspace = true
revm-primitives.workspace = true

# ethereum
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
Expand All @@ -33,28 +34,28 @@ crc = "3"
tracing.workspace = true

# misc
bytes.workspace = true
byteorder = "1"
bytes.workspace = true
clap = { workspace = true, features = ["derive"], optional = true }
derive_more = "0.99"
itertools = "0.11"
modular-bitfield = "0.11.2"
num_enum = "0.7"
once_cell.workspace = true
rayon.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_with = "3.3.0"
thiserror.workspace = true
sha2 = "0.10.7"
sucds = "~0.6"
modular-bitfield = "0.11.2"
derive_more = "0.99"
tempfile.workspace = true
thiserror.workspace = true
url = "2.3"
once_cell.workspace = true
zstd = { version = "0.12", features = ["experimental"] }
rayon.workspace = true
tempfile.workspace = true
sha2 = "0.10.7"
itertools = "0.11"
num_enum = "0.7"

# `test-utils` feature
plain_hasher = { version = "0.2", optional = true }
hash-db = { version = "~0.15", optional = true }
plain_hasher = { version = "0.2", optional = true }

# arbitrary utils
arbitrary = { workspace = true, features = ["derive"], optional = true }
Expand All @@ -63,32 +64,39 @@ proptest-derive = { workspace = true, optional = true }
strum = { workspace = true, features = ["derive"] }

[dev-dependencies]
serde_json.workspace = true
test-fuzz = "4"
rand.workspace = true
revm-primitives = { workspace = true, features = ["arbitrary"] }
arbitrary = { workspace = true, features = ["derive"] }
assert_matches.workspace = true
proptest.workspace = true
proptest-derive.workspace = true
assert_matches.workspace = true
rand.workspace = true
revm-primitives = { workspace = true, features = ["arbitrary"] }
serde_json.workspace = true
test-fuzz = "4"
toml.workspace = true
triehash = "0.8"

plain_hasher = "0.2"
hash-db = "~0.15"
plain_hasher = "0.2"

# necessary so we don't hit a "undeclared 'std'":
# https://github.com/paradigmxyz/reth/pull/177#discussion_r1021172198
secp256k1.workspace = true
criterion.workspace = true
pprof = { workspace = true, features = ["flamegraph", "frame-pointer", "criterion"] }
secp256k1.workspace = true

[features]
default = ["c-kzg"]
arbitrary = ["revm-primitives/arbitrary", "reth-rpc-types/arbitrary", "dep:arbitrary", "dep:proptest", "dep:proptest-derive"]
arbitrary = [
"revm-primitives/arbitrary",
"reth-rpc-types/arbitrary",
"reth-ethereum-forks/arbitrary",
"dep:arbitrary",
"dep:proptest",
"dep:proptest-derive",
]
c-kzg = ["dep:c-kzg", "revm/c-kzg", "revm-primitives/c-kzg"]
clap = ["dep:clap"]
optimism = ["reth-codecs/optimism", "revm-primitives/optimism", "revm/optimism"]
optimism = ["reth-codecs/optimism", "revm-primitives/optimism", "reth-ethereum-forks/optimism", "revm/optimism"]
test-utils = ["dep:plain_hasher", "dep:hash-db", "dep:ethers-core"]

[[bench]]
Expand Down
Loading

0 comments on commit 2144b97

Please sign in to comment.