-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### Description Sets up a `net` crate based off of paradigmxyz/reth-exex-examples#15. ### Metadata Makes progress on #6
- Loading branch information
Showing
22 changed files
with
2,904 additions
and
176 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[package] | ||
name = "op-net" | ||
description = "Networking library for OP Stack Consensus" | ||
version = "0.0.0" | ||
edition.workspace = true | ||
authors.workspace = true | ||
license.workspace = true | ||
keywords.workspace = true | ||
repository.workspace = true | ||
categories.workspace = true | ||
rust-version.workspace = true | ||
|
||
[dependencies] | ||
# Alloy | ||
alloy.workspace = true | ||
alloy-rlp.workspace = true | ||
|
||
# Kona | ||
kona-primitives.workspace = true | ||
|
||
# Networking | ||
ssz_rs.workspace = true | ||
snap.workspace = true | ||
futures.workspace = true | ||
discv5.workspace = true | ||
libp2p.workspace = true | ||
openssl.workspace = true | ||
libp2p-identity.workspace = true | ||
|
||
# Misc | ||
eyre.workspace = true | ||
tokio.workspace = true | ||
tracing.workspace = true | ||
lazy_static.workspace = true | ||
unsigned-varint.workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## Network Library | ||
|
||
Contains a gossipsub driver to run discv5 peer discovery and block gossip. | ||
|
||
## Acknowledgements | ||
|
||
Largely based off [magi][https://github.com/a16z/magi]'s [p2p module](https://github.com/a16z/magi/tree/master/src/network). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
//! Network Builder Module. | ||
use alloy::primitives::Address; | ||
use eyre::Result; | ||
use std::net::SocketAddr; | ||
use tokio::sync::watch::channel; | ||
|
||
use libp2p::{ | ||
gossipsub::ConfigBuilder, noise::Config as NoiseConfig, tcp::Config as TcpConfig, | ||
yamux::Config as YamuxConfig, Multiaddr, SwarmBuilder, | ||
}; | ||
use libp2p_identity::Keypair; | ||
|
||
use crate::{ | ||
discovery::builder::DiscoveryBuilder, | ||
driver::NetworkDriver, | ||
gossip::{behaviour::Behaviour, config, driver::GossipDriver, handler::BlockHandler}, | ||
types::address::NetworkAddress, | ||
}; | ||
|
||
/// Constructs a [NetworkDriver] for Optimism's consensus-layer. | ||
#[derive(Default)] | ||
pub struct NetworkDriverBuilder { | ||
/// The chain ID of the network. | ||
chain_id: Option<u64>, | ||
/// The unsafe block signer. | ||
unsafe_block_signer: Option<Address>, | ||
/// The socket address that the service is listening on. | ||
socket: Option<SocketAddr>, | ||
/// The [ConfigBuilder] constructs the config for `gossipsub`. | ||
inner: Option<ConfigBuilder>, | ||
/// The [Keypair] for the node. | ||
keypair: Option<Keypair>, | ||
/// The [TcpConfig] for the swarm. | ||
tcp_config: Option<TcpConfig>, | ||
// /// The [NoiseConfig] for the swarm. | ||
// noise_config: Option<NoiseConfig>, | ||
/// The [YamuxConfig] for the swarm. | ||
yamux_config: Option<YamuxConfig>, | ||
} | ||
|
||
impl NetworkDriverBuilder { | ||
/// Creates a new [NetworkDriverBuilder]. | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Specifies the chain ID of the network. | ||
pub fn with_chain_id(&mut self, chain_id: u64) -> &mut Self { | ||
self.chain_id = Some(chain_id); | ||
self | ||
} | ||
|
||
/// Specifies the unsafe block signer. | ||
pub fn with_unsafe_block_signer(&mut self, unsafe_block_signer: Address) -> &mut Self { | ||
self.unsafe_block_signer = Some(unsafe_block_signer); | ||
self | ||
} | ||
|
||
/// Specifies the socket address that the service is listening on. | ||
pub fn with_socket(&mut self, socket: SocketAddr) -> &mut Self { | ||
self.socket = Some(socket); | ||
self | ||
} | ||
|
||
/// Specifies the keypair for the node. | ||
pub fn with_keypair(&mut self, keypair: Keypair) -> &mut Self { | ||
self.keypair = Some(keypair); | ||
self | ||
} | ||
|
||
/// Specifies the [TcpConfig] for the swarm. | ||
pub fn with_tcp_config(&mut self, tcp_config: TcpConfig) -> &mut Self { | ||
self.tcp_config = Some(tcp_config); | ||
self | ||
} | ||
|
||
// /// Specifies the [NoiseConfig] for the swarm. | ||
// pub fn with_noise_config(&mut self, noise_config: NoiseConfig) -> &mut Self { | ||
// self.noise_config = Some(noise_config); | ||
// self | ||
// } | ||
|
||
/// Specifies the [YamuxConfig] for the swarm. | ||
pub fn with_yamux_config(&mut self, yamux_config: YamuxConfig) -> &mut Self { | ||
self.yamux_config = Some(yamux_config); | ||
self | ||
} | ||
|
||
// TODO: extend builder with [ConfigBuilder] methods. | ||
|
||
/// Specifies the [ConfigBuilder] for the `gossipsub` configuration. | ||
pub fn with_gossip_config(&mut self, inner: ConfigBuilder) -> &mut Self { | ||
self.inner = Some(inner); | ||
self | ||
} | ||
|
||
/// Builds the [NetworkDriver]. | ||
pub fn build(self) -> Result<NetworkDriver> { | ||
// Build the config for gossipsub. | ||
let config = self.inner.unwrap_or(config::default_config_builder()).build()?; | ||
let unsafe_block_signer = | ||
self.unsafe_block_signer.ok_or_else(|| eyre::eyre!("unsafe block signer not set"))?; | ||
let chain_id = self.chain_id.ok_or_else(|| eyre::eyre!("chain ID not set"))?; | ||
|
||
// Create the block handler. | ||
let (unsafe_block_signer_sender, unsafe_block_signer_recv) = channel(unsafe_block_signer); | ||
let (handler, unsafe_block_recv) = BlockHandler::new(chain_id, unsafe_block_signer_recv); | ||
|
||
// Construct the gossipsub behaviour. | ||
let behaviour = Behaviour::new(config, &[Box::new(handler.clone())])?; | ||
|
||
// Build the swarm. | ||
let keypair = self.keypair.unwrap_or(Keypair::generate_secp256k1()); | ||
let swarm = SwarmBuilder::with_existing_identity(keypair) | ||
.with_tokio() | ||
.with_tcp(self.tcp_config.unwrap_or_default(), NoiseConfig::new, || { | ||
self.yamux_config.unwrap_or_default() | ||
})? | ||
.with_behaviour(|_| behaviour)? | ||
.build(); | ||
let addr = self.socket.ok_or_else(|| eyre::eyre!("socket address not set"))?; | ||
let addr = NetworkAddress::try_from(addr)?; | ||
let swarm_addr = Multiaddr::from(addr); | ||
let swarm = GossipDriver::new(swarm, swarm_addr); | ||
|
||
// Build the discovery service | ||
let discovery = | ||
DiscoveryBuilder::new().with_address(addr).with_chain_id(chain_id).build()?; | ||
|
||
Ok(NetworkDriver { | ||
unsafe_block_recv, | ||
unsafe_block_signer_sender, | ||
handler, | ||
swarm, | ||
discovery, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
//! Bootnodes for consensus network discovery. | ||
use discv5::enr::{CombinedKey, Enr}; | ||
use lazy_static::lazy_static; | ||
use std::str::FromStr; | ||
|
||
lazy_static! { | ||
/// Default bootnodes to use. | ||
pub static ref BOOTNODES: Vec<Enr<CombinedKey>> = [ | ||
// Optimism Mainnet Bootnodes | ||
Enr::from_str("enr:-J64QBbwPjPLZ6IOOToOLsSjtFUjjzN66qmBZdUexpO32Klrc458Q24kbty2PdRaLacHM5z-cZQr8mjeQu3pik6jPSOGAYYFIqBfgmlkgnY0gmlwhDaRWFWHb3BzdGFja4SzlAUAiXNlY3AyNTZrMaECmeSnJh7zjKrDSPoNMGXoopeDF4hhpj5I0OsQUUt4u8uDdGNwgiQGg3VkcIIkBg").unwrap(), | ||
Enr::from_str("enr:-J64QAlTCDa188Hl1OGv5_2Kj2nWCsvxMVc_rEnLtw7RPFbOfqUOV6khXT_PH6cC603I2ynY31rSQ8sI9gLeJbfFGaWGAYYFIrpdgmlkgnY0gmlwhANWgzCHb3BzdGFja4SzlAUAiXNlY3AyNTZrMaECkySjcg-2v0uWAsFsZZu43qNHppGr2D5F913Qqs5jDCGDdGNwgiQGg3VkcIIkBg").unwrap(), | ||
Enr::from_str("enr:-J24QGEzN4mJgLWNTUNwj7riVJ2ZjRLenOFccl2dbRFxHHOCCZx8SXWzgf-sLzrGs6QgqSFCvGXVgGPBkRkfOWlT1-iGAYe6Cu93gmlkgnY0gmlwhCJBEUSHb3BzdGFja4OkAwCJc2VjcDI1NmsxoQLuYIwaYOHg3CUQhCkS-RsSHmUd1b_x93-9yQ5ItS6udIN0Y3CCIyuDdWRwgiMr").unwrap(), | ||
|
||
// Base Mainnet Bootnodes | ||
Enr::from_str("enr:-J24QNz9lbrKbN4iSmmjtnr7SjUMk4zB7f1krHZcTZx-JRKZd0kA2gjufUROD6T3sOWDVDnFJRvqBBo62zuF-hYCohOGAYiOoEyEgmlkgnY0gmlwhAPniryHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQKNVFlCxh_B-716tTs-h1vMzZkSs1FTu_OYTNjgufplG4N0Y3CCJAaDdWRwgiQG").unwrap(), | ||
Enr::from_str("enr:-J24QH-f1wt99sfpHy4c0QJM-NfmsIfmlLAMMcgZCUEgKG_BBYFc6FwYgaMJMQN5dsRBJApIok0jFn-9CS842lGpLmqGAYiOoDRAgmlkgnY0gmlwhLhIgb2Hb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJ9FTIv8B9myn1MWaC_2lJ-sMoeCDkusCsk4BYHjjCq04N0Y3CCJAaDdWRwgiQG").unwrap(), | ||
Enr::from_str("enr:-J24QDXyyxvQYsd0yfsN0cRr1lZ1N11zGTplMNlW4xNEc7LkPXh0NAJ9iSOVdRO95GPYAIc6xmyoCCG6_0JxdL3a0zaGAYiOoAjFgmlkgnY0gmlwhAPckbGHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJwoS7tzwxqXSyFL7g0JM-KWVbgvjfB8JA__T7yY_cYboN0Y3CCJAaDdWRwgiQG").unwrap(), | ||
Enr::from_str("enr:-J24QHmGyBwUZXIcsGYMaUqGGSl4CFdx9Tozu-vQCn5bHIQbR7On7dZbU61vYvfrJr30t0iahSqhc64J46MnUO2JvQaGAYiOoCKKgmlkgnY0gmlwhAPnCzSHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQINc4fSijfbNIiGhcgvwjsjxVFJHUstK9L1T8OTKUjgloN0Y3CCJAaDdWRwgiQG").unwrap(), | ||
Enr::from_str("enr:-J24QG3ypT4xSu0gjb5PABCmVxZqBjVw9ca7pvsI8jl4KATYAnxBmfkaIuEqy9sKvDHKuNCsy57WwK9wTt2aQgcaDDyGAYiOoGAXgmlkgnY0gmlwhDbGmZaHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQIeAK_--tcLEiu7HvoUlbV52MspE0uCocsx1f_rYvRenIN0Y3CCJAaDdWRwgiQG").unwrap(), | ||
].to_vec(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
//! Contains a builder for the discovery service. | ||
use crate::{ | ||
discovery::driver::DiscoveryDriver, | ||
types::{address::NetworkAddress, enr::OpStackEnr}, | ||
}; | ||
use discv5::{ | ||
enr::{CombinedKey, Enr}, | ||
ConfigBuilder, Discv5, ListenConfig, | ||
}; | ||
use eyre::Result; | ||
|
||
use crate::types::enr::OP_CL_KEY; | ||
|
||
/// Discovery service builder. | ||
#[derive(Debug, Default, Clone)] | ||
pub struct DiscoveryBuilder { | ||
/// The discovery service address. | ||
address: Option<NetworkAddress>, | ||
/// The chain ID of the network. | ||
chain_id: Option<u64>, | ||
} | ||
|
||
impl DiscoveryBuilder { | ||
/// Creates a new discovery builder. | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Sets the discovery service address. | ||
pub fn with_address(mut self, address: NetworkAddress) -> Self { | ||
self.address = Some(address); | ||
self | ||
} | ||
|
||
/// Sets the chain ID of the network. | ||
pub fn with_chain_id(mut self, chain_id: u64) -> Self { | ||
self.chain_id = Some(chain_id); | ||
self | ||
} | ||
|
||
/// Builds a [DiscoveryDriver]. | ||
pub fn build(self) -> Result<DiscoveryDriver> { | ||
let addr = self.address.ok_or_else(|| eyre::eyre!("address not set"))?; | ||
let chain_id = self.chain_id.ok_or_else(|| eyre::eyre!("chain ID not set"))?; | ||
let opstack = OpStackEnr::new(chain_id, 0); | ||
let opstack_data: Vec<u8> = opstack.into(); | ||
|
||
let key = CombinedKey::generate_secp256k1(); | ||
let enr = Enr::builder().add_value_rlp(OP_CL_KEY, opstack_data.into()).build(&key)?; | ||
let listen_config = ListenConfig::from_ip(addr.ip.into(), addr.port); | ||
let config = ConfigBuilder::new(listen_config).build(); | ||
|
||
let disc = Discv5::new(enr, key, config) | ||
.map_err(|_| eyre::eyre!("could not create disc service"))?; | ||
|
||
Ok(DiscoveryDriver::new(disc, chain_id)) | ||
} | ||
} |
Oops, something went wrong.