Skip to content

Commit

Permalink
feat: make NetworkConfigBuilder independent of concrete ChainSpec (
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr committed Sep 26, 2024
1 parent f2a508d commit 65f2664
Show file tree
Hide file tree
Showing 21 changed files with 130 additions and 84 deletions.
2 changes: 1 addition & 1 deletion crates/chainspec/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use reth_primitives_traits::Header;

/// Trait representing type configuring a chain spec.
#[auto_impl::auto_impl(&, Arc)]
pub trait EthChainSpec: Send + Sync + Unpin + Debug + 'static {
pub trait EthChainSpec: Send + Sync + Unpin + Debug {
// todo: make chain spec type generic over hardfork
//type Hardfork: Clone + Copy + 'static;

Expand Down
19 changes: 14 additions & 5 deletions crates/chainspec/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,7 @@ impl ChainSpec {

/// Returns the hardfork display helper.
pub fn display_hardforks(&self) -> DisplayHardforks {
DisplayHardforks::new(
&self.hardforks,
self.paris_block_and_final_difficulty.map(|(block, _)| block),
)
DisplayHardforks::new(&self, self.paris_block_and_final_difficulty.map(|(block, _)| block))
}

/// Get the fork id for the given hardfork.
Expand Down Expand Up @@ -613,6 +610,18 @@ impl Hardforks for ChainSpec {
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
self.hardforks.forks_iter()
}

fn fork_id(&self, head: &Head) -> ForkId {
self.fork_id(head)
}

fn latest_fork_id(&self) -> ForkId {
self.latest_fork_id()
}

fn fork_filter(&self, head: Head) -> ForkFilter {
self.fork_filter(head)
}
}

impl EthereumHardforks for ChainSpec {
Expand Down Expand Up @@ -820,7 +829,7 @@ fn into_optimism_chain_spec(genesis: Genesis) -> ChainSpec {
#[auto_impl::auto_impl(&, Arc)]
pub trait ChainSpecProvider: Send + Sync {
/// The chain spec type.
type ChainSpec: EthChainSpec;
type ChainSpec: EthChainSpec + 'static;

/// Get an [`Arc`] to the [`ChainSpec`].
fn chain_spec(&self) -> Arc<Self::ChainSpec>;
Expand Down
3 changes: 1 addition & 2 deletions crates/cli/commands/src/p2p/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,12 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let net = NetworkConfigBuilder::new(p2p_secret_key)
.peer_config(config.peers_config_with_basic_nodes_from_file(None))
.external_ip_resolver(self.network.nat)
.chain_spec(self.chain.clone())
.disable_discv4_discovery_if(self.chain.chain.is_optimism())
.boot_nodes(boot_nodes.clone())
.apply(|builder| {
self.network.discovery.apply_to_builder(builder, rlpx_socket, boot_nodes)
})
.build_with_noop_provider()
.build_with_noop_provider(self.chain)
.manager()
.await?;
let network = net.handle().clone();
Expand Down
2 changes: 1 addition & 1 deletion crates/consensus/auto-seal/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ where
Pool: TransactionPool + Unpin + 'static,
Engine: EngineTypes,
Executor: BlockExecutorProvider,
ChainSpec: EthChainSpec + EthereumHardforks,
ChainSpec: EthChainSpec + EthereumHardforks + 'static,
{
type Output = ();

Expand Down
21 changes: 10 additions & 11 deletions crates/ethereum-forks/src/hardforks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
mod ethereum;
pub use ethereum::EthereumHardforks;

use crate::{ForkCondition, Hardfork};
use crate::{ForkCondition, ForkFilter, ForkId, Hardfork, Head};
#[cfg(feature = "std")]
use rustc_hash::FxHashMap;
#[cfg(feature = "std")]
Expand Down Expand Up @@ -31,6 +31,15 @@ pub trait Hardforks: Clone {
fn is_fork_active_at_block<H: Hardfork>(&self, fork: H, block_number: u64) -> bool {
self.fork(fork).active_at_block(block_number)
}

/// Compute the [`ForkId`] for the given [`Head`] following eip-6122 spec
fn fork_id(&self, head: &Head) -> ForkId;

/// Returns the [`ForkId`] for the last fork.
fn latest_fork_id(&self) -> ForkId;

/// Creates a [`ForkFilter`] for the block described by [Head].
fn fork_filter(&self, head: Head) -> ForkFilter;
}

/// Ordered list of a chain hardforks that implement [`Hardfork`].
Expand Down Expand Up @@ -129,16 +138,6 @@ impl ChainHardforks {
}
}

impl Hardforks for ChainHardforks {
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
self.fork(fork)
}

fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
self.forks_iter()
}
}

impl core::fmt::Debug for ChainHardforks {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ChainHardforks")
Expand Down
10 changes: 5 additions & 5 deletions crates/net/discv5/src/network_stack_id.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Keys of ENR [`ForkId`](reth_ethereum_forks::ForkId) kv-pair. Identifies which network stack a
//! node belongs to.

use reth_chainspec::ChainSpec;
use reth_chainspec::EthChainSpec;

/// Identifies which Ethereum network stack a node belongs to, on the discovery network.
#[derive(Debug)]
Expand All @@ -21,11 +21,11 @@ impl NetworkStackId {
pub const OPSTACK: &'static [u8] = b"opstack";

#[allow(clippy::missing_const_for_fn)]
/// Returns the [`NetworkStackId`] that matches the given [`ChainSpec`].
pub fn id(chain: &ChainSpec) -> Option<&'static [u8]> {
if chain.is_optimism() {
/// Returns the [`NetworkStackId`] that matches the given chain spec.
pub fn id(chain: impl EthChainSpec) -> Option<&'static [u8]> {
if chain.chain().is_optimism() {
return Some(Self::OPEL)
} else if chain.is_ethereum() {
} else if chain.chain().is_ethereum() {
return Some(Self::ETH)
}

Expand Down
9 changes: 6 additions & 3 deletions crates/net/eth-wire-types/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use alloy_chains::{Chain, NamedChain};
use alloy_genesis::Genesis;
use alloy_primitives::{hex, B256, U256};
use alloy_rlp::{RlpDecodable, RlpEncodable};
use reth_chainspec::{ChainSpec, MAINNET};
use reth_chainspec::{ChainSpec, EthChainSpec, Hardforks, MAINNET};
use reth_codecs_derive::add_arbitrary_tests;
use reth_primitives::{EthereumHardfork, ForkId, Head};
use std::fmt::{Debug, Display};
Expand Down Expand Up @@ -75,9 +75,12 @@ impl Status {
///
/// Sets the `chain` and `genesis`, `blockhash`, and `forkid` fields based on the [`ChainSpec`]
/// and head.
pub fn spec_builder(spec: &ChainSpec, head: &Head) -> StatusBuilder {
pub fn spec_builder<Spec>(spec: Spec, head: &Head) -> StatusBuilder
where
Spec: EthChainSpec + Hardforks,
{
Self::builder()
.chain(spec.chain)
.chain(spec.chain())
.genesis(spec.genesis_hash())
.blockhash(head.hash)
.total_difficulty(head.total_difficulty)
Expand Down
56 changes: 31 additions & 25 deletions crates/net/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

use std::{collections::HashSet, net::SocketAddr, sync::Arc};

use reth_chainspec::{ChainSpec, MAINNET};
use reth_chainspec::{ChainSpecProvider, EthChainSpec, Hardforks};
use reth_discv4::{Discv4Config, Discv4ConfigBuilder, NatResolver, DEFAULT_DISCOVERY_ADDRESS};
use reth_discv5::NetworkStackId;
use reth_dns_discovery::DnsDiscoveryConfig;
use reth_eth_wire::{HelloMessage, HelloMessageWithProtocols, Status};
use reth_network_peers::{mainnet_nodes, pk2id, sepolia_nodes, PeerId, TrustedPeer};
use reth_network_types::{PeersConfig, SessionsConfig};
use reth_primitives::{ForkFilter, Head};
use reth_storage_api::{BlockNumReader, BlockReader, HeaderProvider};
use reth_storage_api::{noop::NoopBlockReader, BlockNumReader, BlockReader, HeaderProvider};
use reth_tasks::{TaskSpawner, TokioTaskExecutor};
use secp256k1::SECP256K1;

Expand Down Expand Up @@ -56,8 +56,8 @@ pub struct NetworkConfig<C> {
pub peers_config: PeersConfig,
/// How to configure the [`SessionManager`](crate::session::SessionManager).
pub sessions_config: SessionsConfig,
/// The chain spec
pub chain_spec: Arc<ChainSpec>,
/// The chain id
pub chain_id: u64,
/// The [`ForkFilter`] to use at launch for authenticating sessions.
///
/// See also <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2124.md#stale-software-examples>
Expand Down Expand Up @@ -99,7 +99,10 @@ impl NetworkConfig<()> {

impl<C> NetworkConfig<C> {
/// Create a new instance with all mandatory fields set, rest is field with defaults.
pub fn new(client: C, secret_key: SecretKey) -> Self {
pub fn new(client: C, secret_key: SecretKey) -> Self
where
C: ChainSpecProvider<ChainSpec: Hardforks>,
{
NetworkConfig::builder(secret_key).build(client)
}

Expand Down Expand Up @@ -170,8 +173,6 @@ pub struct NetworkConfigBuilder {
peers_config: Option<PeersConfig>,
/// How to configure the sessions manager
sessions_config: Option<SessionsConfig>,
/// The network's chain spec
chain_spec: Arc<ChainSpec>,
/// The default mode of the network.
network_mode: NetworkMode,
/// The executor to use for spawning tasks.
Expand Down Expand Up @@ -211,7 +212,6 @@ impl NetworkConfigBuilder {
listener_addr: None,
peers_config: None,
sessions_config: None,
chain_spec: MAINNET.clone(),
network_mode: Default::default(),
executor: None,
hello_message: None,
Expand Down Expand Up @@ -241,12 +241,6 @@ impl NetworkConfigBuilder {
&self.secret_key
}

/// Sets the chain spec.
pub fn chain_spec(mut self, chain_spec: Arc<ChainSpec>) -> Self {
self.chain_spec = chain_spec;
self
}

/// Sets the [`NetworkMode`].
pub const fn network_mode(mut self, network_mode: NetworkMode) -> Self {
self.network_mode = network_mode;
Expand Down Expand Up @@ -461,10 +455,14 @@ impl NetworkConfigBuilder {

/// Convenience function for creating a [`NetworkConfig`] with a noop provider that does
/// nothing.
pub fn build_with_noop_provider(
pub fn build_with_noop_provider<ChainSpec>(
self,
) -> NetworkConfig<reth_storage_api::noop::NoopBlockReader> {
self.build(Default::default())
chain_spec: Arc<ChainSpec>,
) -> NetworkConfig<NoopBlockReader<ChainSpec>>
where
ChainSpec: EthChainSpec + Hardforks + 'static,
{
self.build(NoopBlockReader::new(chain_spec))
}

/// Consumes the type and creates the actual [`NetworkConfig`]
Expand All @@ -473,8 +471,12 @@ impl NetworkConfigBuilder {
/// The given client is to be used for interacting with the chain, for example fetching the
/// corresponding block for a given block hash we receive from a peer in the status message when
/// establishing a connection.
pub fn build<C>(self, client: C) -> NetworkConfig<C> {
pub fn build<C>(self, client: C) -> NetworkConfig<C>
where
C: ChainSpecProvider<ChainSpec: Hardforks>,
{
let peer_id = self.get_peer_id();
let chain_spec = client.chain_spec();
let Self {
secret_key,
mut dns_discovery_config,
Expand All @@ -485,7 +487,6 @@ impl NetworkConfigBuilder {
listener_addr,
peers_config,
sessions_config,
chain_spec,
network_mode,
executor,
hello_message,
Expand Down Expand Up @@ -514,9 +515,9 @@ impl NetworkConfigBuilder {
let head = head.unwrap_or_else(|| Head {
hash: chain_spec.genesis_hash(),
number: 0,
timestamp: chain_spec.genesis.timestamp,
difficulty: chain_spec.genesis.difficulty,
total_difficulty: chain_spec.genesis.difficulty,
timestamp: chain_spec.genesis().timestamp,
difficulty: chain_spec.genesis().difficulty,
total_difficulty: chain_spec.genesis().difficulty,
});

// set the status
Expand All @@ -525,6 +526,9 @@ impl NetworkConfigBuilder {
// set a fork filter based on the chain spec and head
let fork_filter = chain_spec.fork_filter(head);

// get the chain id
let chain_id = chain_spec.chain().id();

// If default DNS config is used then we add the known dns network to bootstrap from
if let Some(dns_networks) =
dns_discovery_config.as_mut().and_then(|c| c.bootstrap_dns_networks.as_mut())
Expand All @@ -547,7 +551,7 @@ impl NetworkConfigBuilder {
listener_addr,
peers_config: peers_config.unwrap_or_default(),
sessions_config: sessions_config.unwrap_or_default(),
chain_spec,
chain_id,
block_import: block_import.unwrap_or_else(|| Box::<ProofOfStakeBlockImport>::default()),
network_mode,
executor: executor.unwrap_or_else(|| Box::<TokioTaskExecutor>::default()),
Expand Down Expand Up @@ -587,9 +591,11 @@ impl NetworkMode {

#[cfg(test)]
mod tests {
use std::sync::Arc;

use super::*;
use rand::thread_rng;
use reth_chainspec::Chain;
use reth_chainspec::{Chain, MAINNET};
use reth_dns_discovery::tree::LinkEntry;
use reth_primitives::ForkHash;
use reth_provider::test_utils::NoopProvider;
Expand Down Expand Up @@ -622,7 +628,7 @@ mod tests {
let genesis_fork_hash = ForkHash::from(chain_spec.genesis_hash());

// enforce that the fork_id set in the status is consistent with the generated fork filter
let config = builder().chain_spec(chain_spec).build(NoopProvider::default());
let config = builder().build_with_noop_provider(chain_spec);

let status = config.status;
let fork_filter = config.fork_filter;
Expand Down
4 changes: 2 additions & 2 deletions crates/net/network/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl NetworkManager {
listener_addr,
peers_config,
sessions_config,
chain_spec,
chain_id,
block_import,
network_mode,
boot_nodes,
Expand Down Expand Up @@ -264,7 +264,7 @@ impl NetworkManager {
local_peer_id,
peers_handle,
network_mode,
Arc::new(AtomicU64::new(chain_spec.chain.id())),
Arc::new(AtomicU64::new(chain_id)),
tx_gossip_disabled,
discv4,
discv5,
Expand Down
Loading

0 comments on commit 65f2664

Please sign in to comment.