Skip to content

Commit

Permalink
feat(network): start network impl and rpc handling
Browse files Browse the repository at this point in the history
  • Loading branch information
dancoombs committed Oct 11, 2023
1 parent c43c845 commit 0eb3059
Show file tree
Hide file tree
Showing 19 changed files with 1,951 additions and 43 deletions.
278 changes: 254 additions & 24 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions bin/tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@ Rundler tools
[dependencies]
rundler-dev = { path = "../../crates/dev" }
rundler-rpc = { path = "../../crates/rpc" }
rundler-network = { path = "../../crates/network" }

anyhow = "1.0.70"
clap = { version = "4.2.4", features = ["derive", "env"] }
dotenv = "0.15.0"
ethers = "2.0.8"
ethers-signers = {version = "2.0.8", features = ["aws"] }
hex = "0.4.3"
rusoto_core = { version = "0.48.0", default-features = false, features = ["rustls"] }
rusoto_kms = { version = "0.48.0", default-features = false, features = ["rustls"] }
serde_json = "1.0.96"
tokio.workspace = true
futures.workspace = true
enr = { version = "*", features = ["serde", "k256"] }
discv5 = { version = "0.3.1", features = ["libp2p"] }
env_logger = "0.10.0"

[dependencies.libp2p]
version = "0.52.3"
default-features = false
features = ["tokio", "identify", "noise", "macros", "ping", "tcp", "identify", "yamux", "secp256k1"]
77 changes: 77 additions & 0 deletions bin/tools/src/bin/network.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// This file is part of Rundler.
//
// Rundler is free software: you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later version.
//
// Rundler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

use std::{net::SocketAddr, time::Duration};

use clap::Parser;
use ethers::types::H256;
use rundler_network::{Config as NetworkConfig, ConnectionConfig, Network};
use tokio::sync::mpsc;

const PRIVATE_KEY: &str = "b0ddfec7d365b4599ff8367e960f8c4890364f99e2151beac352338cc0cfe1bc";

#[tokio::main]
async fn main() -> anyhow::Result<()> {
env_logger::init();

let cli = Cli::parse();

let private_key = if cli.bootnode.is_none() {
println!("Starting as a bootnode");
PRIVATE_KEY.into()
} else {
println!("Starting as a regular node");
let enr_key = discv5::enr::CombinedKey::generate_secp256k1();
hex::encode(enr_key.encode())
};

let bootnodes = cli
.bootnode
.map(|b| vec![b.parse().expect("invalid bootnode")])
.unwrap_or_default();
let listen_address: SocketAddr = format!("127.0.0.1:{}", cli.port).parse()?;

let config = NetworkConfig {
private_key,
listen_address,
bootnodes,
network_config: ConnectionConfig {
max_chunk_size: 1048576,
request_timeout: Duration::from_secs(10),
ttfb_timeout: Duration::from_secs(5),
},
supported_mempools: vec![H256::random()],
metadata_seq_number: 0,
};

let (_, action_recv) = mpsc::unbounded_channel();
let (event_send, _) = mpsc::unbounded_channel();

println!("Config: {:?}", config);
let network = Network::new(config, event_send, action_recv).await?;
println!("ENR: {}", network.enr());

network.run().await?;
Ok(())
}

#[derive(Debug, Parser)]
#[clap(name = "rundler network tester")]
struct Cli {
/// The port used to listen on all interfaces
#[clap(short)]
port: u16,

#[clap(short)]
bootnode: Option<String>,
}
7 changes: 7 additions & 0 deletions crates/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ ethereum_ssz_derive = "0.5.3"
ethers.workspace = true
snap = "1.1.0"
ssz_types = "0.5.4"
discv5 = { version = "0.3.1", features = ["libp2p"] }
futures.workspace = true
hex = "0.4.3"
libp2p-mplex = "0.40.0"
tokio.workspace = true
tokio-io-timeout = "1.2.0"
tokio-util = { workspace = true, features = ["codec", "compat"] }
thiserror.workspace = true
tracing.workspace = true
Expand All @@ -26,3 +32,4 @@ features = ["tokio", "noise", "macros", "tcp", "identify", "yamux", "secp256k1"]

[dev-dependencies]
rand.workspace = true
tracing-test = { version = "0.2.4", features = ["no-env-filter"] }
29 changes: 29 additions & 0 deletions crates/network/src/behaviour.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of Rundler.
//
// Rundler is free software: you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later version.
//
// Rundler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

use libp2p::{
identify,
swarm::{keep_alive, NetworkBehaviour},
};

use crate::rpc;

#[derive(NetworkBehaviour)]
pub(crate) struct Behaviour {
// TODO(danc): temp, remove when not needed
pub(crate) keep_alive: keep_alive::Behaviour,
// Request/response protocol
pub(crate) rpc: rpc::Behaviour,
// Identity protocol
pub(crate) identify: identify::Behaviour,
}
98 changes: 98 additions & 0 deletions crates/network/src/enr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// This file is part of Rundler.
//
// Rundler is free software: you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later version.
//
// Rundler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

// Adapted from https://github.com/sigp/lighthouse/blob/stable/beacon_node/lighthouse_network/src/discovery/enr_ext.rs

use discv5::{
enr::{k256, CombinedKey, CombinedPublicKey, EnrBuilder},
Enr,
};
use libp2p::{
identity::{ed25519, secp256k1, PublicKey},
multiaddr::Protocol,
Multiaddr, PeerId,
};

use crate::Config;

pub(crate) fn build_enr(config: &Config) -> (Enr, CombinedKey) {
let enr_key: CombinedKey =
k256::ecdsa::SigningKey::from_slice(&hex::decode(&config.private_key).unwrap())
.unwrap()
.into();

let enr = EnrBuilder::new("v4")
.ip(config.listen_address.ip())
.tcp4(config.listen_address.port())
.udp4(config.listen_address.port() + 1)
.build(&enr_key)
.unwrap();

(enr, enr_key)
}

pub(crate) trait EnrExt {
fn multiaddr(&self) -> Vec<Multiaddr>;

fn peer_id(&self) -> PeerId;
}

impl EnrExt for Enr {
fn multiaddr(&self) -> Vec<Multiaddr> {
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(ip) = self.ip4() {
if let Some(udp) = self.udp4() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Udp(udp));
multiaddrs.push(multiaddr);
}
if let Some(tcp) = self.tcp4() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Tcp(tcp));
multiaddrs.push(multiaddr);
}
}
multiaddrs
}

fn peer_id(&self) -> PeerId {
self.public_key().as_peer_id()
}
}

pub(crate) trait CombinedKeyPublicExt {
/// Converts the publickey into a peer id, without consuming the key.
fn as_peer_id(&self) -> PeerId;
}

impl CombinedKeyPublicExt for CombinedPublicKey {
/// Converts the publickey into a peer id, without consuming the key.
fn as_peer_id(&self) -> PeerId {
match self {
Self::Secp256k1(pk) => {
let pk_bytes = pk.to_sec1_bytes();
let libp2p_pk: PublicKey = secp256k1::PublicKey::try_from_bytes(&pk_bytes)
.expect("valid public key")
.into();
PeerId::from_public_key(&libp2p_pk)
}
Self::Ed25519(pk) => {
let pk_bytes = pk.to_bytes();
let libp2p_pk: PublicKey = ed25519::PublicKey::try_from_bytes(&pk_bytes)
.expect("valid public key")
.into();
PeerId::from_public_key(&libp2p_pk)
}
}
}
}
19 changes: 19 additions & 0 deletions crates/network/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This file is part of Rundler.
//
// Rundler is free software: you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later version.
//
// Rundler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

/// Network errors
#[derive(thiserror::Error, Debug)]
pub enum Error {}

/// Network result
pub type Result<T> = std::result::Result<T, Error>;
21 changes: 19 additions & 2 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@
//! Lots of inspiration for the components of this implementation were taken from the Lighthouse implementation
//! of the Ethereum consensus layer p2p protocol. See [here](https://github.com/sigp/lighthouse/) for more details.
// TODO(danc): remove this before release
#[allow(dead_code)]
mod rpc;
pub use rpc::{
message::{
ErrorKind as ResponseErrorKind, PooledUserOpHashesRequest, PooledUserOpHashesResponse,
PooledUserOpsByHashRequest, PooledUserOpsByHashResponse, MAX_OPS_PER_REQUEST,
},
ConnectionConfig,
};

mod behaviour;

mod network;
pub use network::{
Action, AppRequest, AppRequestId, AppResponse, AppResponseResult, Config, Event, Network,
};

mod enr;

mod error;
pub use error::{Error, Result};
Loading

0 comments on commit 0eb3059

Please sign in to comment.