Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add p2p crate #151

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add p2p crate
zsluedem committed Nov 2, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 0ec1d267762feb874f859995f2ee149a9a8fa91a
2,691 changes: 2,294 additions & 397 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ members = [
"crates/bundler",
"crates/contracts",
"crates/grpc",
"crates/p2p",
"crates/primitives",
"crates/rpc",
"crates/uopool",
@@ -27,14 +28,18 @@ rust-version = "1.73.0"
[workspace.dependencies]
async-stream = "0.3.5"
async-trait = "0.1"
discv5 = { version = "0.3.0", features = ["libp2p"] }
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "fa3017715a298728d9fb341933818a5d0d84c2dc", features = [
"ws",
] }
expanded-pathbuf = "0.1"
eyre = "0.6.8"
futures-util = "0.3.28"
lazy_static = "1.4.0"
parking_lot = "0.12"
serde_json = "1"
ssz_rs = { git = "https://github.com/ralexstokes/ssz-rs.git", rev = "8640128ec83071094d24fb4511147d6b9dd029bb" }
ssz_rs_derive = { git = "https://github.com/ralexstokes/ssz-rs.git", rev = "8640128ec83071094d24fb4511147d6b9dd029bb" }
tokio = { version = "1.18", features = ["full"] }
tracing = "0.1"

20 changes: 20 additions & 0 deletions P2P.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Prerequirements for building

1. Install rust
2. make fetch-thirdparty
3. make setup-thirdparty

# How to run silius with p2p enabled

## Run silius with bootnodes

```
cargo run -- bundler --eth-client-address http://localhost:8545 --mnemonic-file ./bundler-spec-tests/keys/0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --beneficiary 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --entry-points 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 --http --http.port 4000 --eth-client-proxy-address http://localhost:8545 --p2p-broadcast-address 127.0.0.1 --bootnodes "enr:-Iu4QBh2tesC8BokO61v1w43MnbfHF5H95ZJNHVEQaRq_MjFFuxmeVQnoEXxUDk5qKJCHM944gC72Xg4dYwRkGt9zA4BgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKRdyIA8OvArCcZbt3hoJHu4nVe6CblqjO0CnrbGACi-IN0Y3CCEPGDdWRwghDx" --enable-p2p --tcp4-port 4338 --udp4-port 4338 --datadir ./.local/data
```


## Run silius as bootnodes

```
cargo run -- bundler --eth-client-address http://localhost:8545 --mnemonic-file ./bundler-spec-tests/keys/0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --beneficiary 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --entry-points 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 --http --http.port 4000 --eth-client-proxy-address http://localhost:8545 --p2p-broadcast-address 127.0.0.1 --enable-p2p
```
2 changes: 2 additions & 0 deletions bin/silius/Cargo.toml
Original file line number Diff line number Diff line change
@@ -13,13 +13,15 @@ AA (ERC-4337) bundler - Silius
[dependencies]
clap = { version = "4", features = ["derive"] }
dirs = "4.0"
discv5 = { workspace = true }
ethers = { workspace = true }
expanded-pathbuf = { workspace = true }
eyre = { workspace = true }
log = "0.4.19"
pin-utils = "0.1"
silius-bundler = { path = "../../crates/bundler" }
silius-grpc = { path = "../../crates/grpc" }
silius-p2p = { path = "../../crates/p2p" }
silius-primitives = { path = "../../crates/primitives" }
silius-rpc = { path = "../../crates/rpc" }
tokio = { workspace = true }
3 changes: 3 additions & 0 deletions bin/silius/src/bundler.rs
Original file line number Diff line number Diff line change
@@ -165,6 +165,9 @@ where
args.min_priority_fee_per_gas,
args.whitelist,
args.uopool_mode,
args.p2p_opts.enable_p2p,
args.p2p_opts.to_config(),
args.p2p_opts.bootnodes,
)
.await?;

91 changes: 90 additions & 1 deletion bin/silius/src/cli/args.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use crate::utils::{parse_address, parse_send_bundle_mode, parse_u256, parse_uopool_mode};
use crate::utils::{
parse_address, parse_enr, parse_send_bundle_mode, parse_u256, parse_uopool_mode,
};
use clap::Parser;
use discv5::Enr;
use ethers::types::{Address, U256};
use expanded_pathbuf::ExpandedPathBuf;
use silius_p2p::config::{Config, ListenAddr};
use silius_primitives::{
bundler::SendBundleMode,
chain::SUPPORTED_CHAINS,
@@ -88,6 +92,9 @@ pub struct UoPoolArgs {
/// User operation mempool mode
#[clap(long, default_value = "standard", value_parser=parse_uopool_mode)]
pub uopool_mode: UoPoolMode,

#[clap(flatten)]
pub p2p_opts: P2POpts,
}

/// Common CLI args for bundler and uopool
@@ -211,8 +218,53 @@ pub struct CreateWalletArgs {
pub flashbots_key: bool,
}

#[derive(Clone, Debug, Parser, PartialEq)]
pub struct P2POpts {
/// enable p2p
#[clap(long)]
pub enable_p2p: bool,

/// Sets the p2p listen address.
#[clap(long, default_value = "0.0.0.0")]
pub p2p_listen_address: Ipv4Addr,

/// The ipv4 address to broadcast to peers about which address we are listening on.
#[clap(long)]
pub p2p_broadcast_address: Option<Ipv4Addr>,

/// The udp4 port to broadcast to peers in order to reach back for discovery.
#[clap(long, default_value = "4337")]
pub udp4_port: u16,

#[clap(long, default_value = "4337")]
pub tcp4_port: u16,

#[clap(long, value_delimiter = ',', value_parser=parse_enr)]
pub bootnodes: Vec<Enr>,
}

impl P2POpts {
pub fn to_config(&self) -> Config {
// TODO: support ipv6
Config {
listen_addr: silius_p2p::config::ListenAddress::Ipv4(ListenAddr {
addr: self.p2p_listen_address,
udp_port: self.udp4_port,
tcp_port: self.tcp4_port,
}),
ipv4_addr: self.p2p_broadcast_address,
ipv6_addr: None,
enr_udp4_port: Some(self.udp4_port),
enr_tcp4_port: Some(self.tcp4_port),
enr_udp6_port: None,
enr_tcp6_port: None,
}
}
}
#[cfg(test)]
mod tests {
use discv5::enr::{CombinedKey, EnrBuilder};

use super::*;
use std::{
net::{IpAddr, Ipv4Addr},
@@ -512,4 +564,41 @@ mod tests {
false
);
}

#[test]
fn p2p_opts() {
let key = CombinedKey::secp256k1_from_bytes([1; 32].as_mut()).unwrap();
let enr = EnrBuilder::new("v4")
.ip4(Ipv4Addr::new(8, 8, 8, 8))
.tcp4(4337)
.udp4(4337)
.build(&key)
.unwrap();
let binding = enr.clone().to_base64();
let args = vec![
"p2popts",
"--enable-p2p",
"--p2p-listen-address",
"0.0.0.0",
"--p2p-broadcast-address",
"127.0.0.1",
"--tcp4-port",
"4337",
"--udp4-port",
"4337",
"--bootnodes",
&binding,
];
assert_eq!(
P2POpts {
enable_p2p: true,
p2p_listen_address: Ipv4Addr::new(0, 0, 0, 0),
p2p_broadcast_address: Some(Ipv4Addr::new(127, 0, 0, 1)),
tcp4_port: 4337,
udp4_port: 4337,
bootnodes: vec![enr]
},
P2POpts::try_parse_from(args).unwrap()
)
}
}
12 changes: 4 additions & 8 deletions bin/silius/src/cli/commands.rs
Original file line number Diff line number Diff line change
@@ -31,8 +31,7 @@ impl BundlerCommand {
pub async fn execute(self) -> eyre::Result<()> {
if self.common.eth_client_address.clone().starts_with("http") {
let eth_client = Arc::new(create_http_provider(&self.common.eth_client_address).await?);
let block_streams =
create_http_block_streams(eth_client.clone(), self.common.entry_points.len()).await;
let block_streams = create_http_block_streams(eth_client.clone(), 1).await;
launch_bundler(
self.bundler,
self.uopool,
@@ -44,8 +43,7 @@ impl BundlerCommand {
.await?;
} else {
let eth_client = Arc::new(create_ws_provider(&self.common.eth_client_address).await?);
let block_streams =
create_ws_block_streams(eth_client.clone(), self.common.entry_points.len()).await;
let block_streams = create_ws_block_streams(eth_client.clone(), 1).await;
launch_bundler(
self.bundler,
self.uopool,
@@ -123,8 +121,7 @@ impl UoPoolCommand {
pub async fn execute(self) -> eyre::Result<()> {
if self.common.eth_client_address.clone().starts_with("http") {
let eth_client = Arc::new(create_http_provider(&self.common.eth_client_address).await?);
let block_streams =
create_http_block_streams(eth_client.clone(), self.common.entry_points.len()).await;
let block_streams = create_http_block_streams(eth_client.clone(), 1).await;
launch_uopool(
self.uopool,
eth_client,
@@ -135,8 +132,7 @@ impl UoPoolCommand {
.await?;
} else {
let eth_client = Arc::new(create_ws_provider(&self.common.eth_client_address).await?);
let block_streams =
create_ws_block_streams(eth_client.clone(), self.common.entry_points.len()).await;
let block_streams = create_ws_block_streams(eth_client.clone(), 1).await;
launch_uopool(
self.uopool,
eth_client,
6 changes: 6 additions & 0 deletions bin/silius/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use dirs::home_dir;
use discv5::Enr;
use ethers::types::{Address, U256};
use expanded_pathbuf::ExpandedPathBuf;
use pin_utils::pin_mut;
@@ -38,6 +39,11 @@ pub fn parse_uopool_mode(s: &str) -> Result<UoPoolMode, String> {
UoPoolMode::from_str(s).map_err(|_| format!("String {s} is not a valid UoPoolMode"))
}

/// Parse ENR record
pub fn parse_enr(enr: &str) -> Result<Enr, String> {
Enr::from_str(enr).map_err(|_| format!("Enr {enr} is not a valid enr."))
}

/// Runs the future to completion or until:
/// - `ctrl-c` is received.
/// - `SIGTERM` is received (unix only).
3 changes: 2 additions & 1 deletion crates/contracts/Cargo.toml
Original file line number Diff line number Diff line change
@@ -11,9 +11,10 @@ AA (ERC-4337) bundler smart contract interfaces
"""

[dependencies]

ethers = { workspace = true }
eyre = { workspace = true }
lazy_static = "1.4.0"
lazy_static = { workspace = true }
regex = "1.9.6"
serde = "1"
serde_json = "1"
8 changes: 8 additions & 0 deletions crates/contracts/src/entry_point.rs
Original file line number Diff line number Diff line change
@@ -451,4 +451,12 @@ mod tests {
);
Ok(())
}

#[test]
fn deserialize_failedop() -> eyre::Result<()> {
let err_msg = Bytes::from_str("0x220266b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e41413430206f76657220766572696669636174696f6e4761734c696d69740000")?;
let res = EntryPointAPIErrors::decode(err_msg)?;
println!("res: {:?}", res);
Ok(())
}
}
4 changes: 2 additions & 2 deletions crates/contracts/src/tracer.rs
Original file line number Diff line number Diff line change
@@ -19,8 +19,8 @@ impl TryFrom<GethTrace> for JsTracerFrame {
fn try_from(val: GethTrace) -> Result<Self, Self::Error> {
match val {
GethTrace::Known(val) => Err(format_err!("Invalid geth trace: {val:?}")),
GethTrace::Unknown(val) => serde_json::from_value(val)
.map_err(|error| format_err!("Failed to parse geth trace: {error}")),
GethTrace::Unknown(val) => serde_json::from_value(val.clone())
.map_err(|error| format_err!("Failed to parse geth trace: {error}, {val:#}")),
}
}
}
4 changes: 4 additions & 0 deletions crates/grpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -14,14 +14,18 @@ AA (ERC-4337) bundler gRPC interfaces
arrayref = "0.3"
async-trait = { workspace = true }
dashmap = "5.4.0"
discv5 = { workspace = true }
ethers = { workspace = true }
expanded-pathbuf = { workspace = true }
eyre = { workspace = true }
futures = "0.3.28"
libp2p-identity = "0.2.3"
parking_lot = { workspace = true }
prost = "0.11"
serde_json = { workspace = true }
silius-bundler = { path = "../bundler" }
silius-contracts = { path = "../contracts" }
silius-p2p = { path = "../p2p" }
silius-primitives = { path = "../primitives" }
silius-uopool = { path = "../uopool" }
tokio = { workspace = true }
31 changes: 31 additions & 0 deletions crates/grpc/src/network.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use ethers::providers::Middleware;
use silius_p2p::network::Network;
use silius_primitives::reputation::ReputationEntry;
use silius_uopool::{Mempool, Reputation, VecCh, VecUo};

use crate::builder::UoPoolBuilder;

/// The Integrator is for the integrations between p2p network and the uopool
pub struct NetworkIntegrator<M, P, R, E>
where
M: Middleware + Clone + 'static,
P: Mempool<UserOperations = VecUo, CodeHashes = VecCh, Error = E> + Send + Sync,
R: Reputation<ReputationEntries = Vec<ReputationEntry>, Error = E> + Send + Sync,
{
network: Network,
uopool_builder: UoPoolBuilder<M, P, R, E>,
}

impl<M, P, R, E> NetworkIntegrator<M, P, R, E>
where
M: Middleware + Clone + 'static,
P: Mempool<UserOperations = VecUo, CodeHashes = VecCh, Error = E> + Send + Sync,
R: Reputation<ReputationEntries = Vec<ReputationEntry>, Error = E> + Send + Sync,
{
pub fn new(network: Network, uopool_builder: UoPoolBuilder<M, P, R, E>) -> Self {
Self {
network,
uopool_builder,
}
}
}
Loading