From 704fd22f50f71cb5a0971ca5ba0383d84b8e9838 Mon Sep 17 00:00:00 2001 From: Will Qiu Date: Thu, 31 Aug 2023 08:47:27 +0800 Subject: [PATCH] WIP --- Cargo.lock | 49 +++++++++- Cargo.toml | 2 + crates/p2p/Cargo.toml | 11 ++- crates/p2p/src/behaviour.rs | 13 +-- crates/p2p/src/gossipsub.rs | 32 +++--- crates/p2p/src/network.rs | 124 +++++++++++++----------- crates/p2p/src/reqrep/mod.rs | 10 +- crates/p2p/src/tests/mod.rs | 2 + crates/p2p/src/tests/swarm.rs | 94 +++++++++++------- crates/primitives/Cargo.toml | 4 +- crates/primitives/src/lib.rs | 2 + crates/primitives/src/p2p.rs | 19 ++++ crates/primitives/src/user_operation.rs | 25 ++--- 13 files changed, 246 insertions(+), 141 deletions(-) create mode 100644 crates/primitives/src/p2p.rs diff --git a/Cargo.lock b/Cargo.lock index 69fdd3b9..1f21d8c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,8 +19,10 @@ dependencies = [ "anyhow", "async-trait", "discv5", + "env_logger", "ethereum_ssz", "ethereum_ssz_derive", + "ethers 2.0.8", "futures", "lazy_static", "libp2p", @@ -30,8 +32,10 @@ dependencies = [ "snap", "ssz_rs", "ssz_rs_derive", + "test-log", "tokio", "tracing", + "tracing-subscriber", ] [[package]] @@ -1902,6 +1906,19 @@ dependencies = [ "syn 2.0.29", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -3284,6 +3301,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -7197,8 +7220,7 @@ dependencies = [ [[package]] name = "ssz_rs" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057291e5631f280978fa9c8009390663ca4613359fc1318e36a8c24c392f6d1f" +source = "git+https://github.com/ralexstokes/ssz-rs.git?rev=8640128ec83071094d24fb4511147d6b9dd029bb#8640128ec83071094d24fb4511147d6b9dd029bb" dependencies = [ "bitvec", "hex", @@ -7211,8 +7233,7 @@ dependencies = [ [[package]] name = "ssz_rs_derive" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" +source = "git+https://github.com/ralexstokes/ssz-rs.git?rev=8640128ec83071094d24fb4511147d6b9dd029bb#8640128ec83071094d24fb4511147d6b9dd029bb" dependencies = [ "proc-macro2", "quote", @@ -7466,6 +7487,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-log" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9601d162c1d77e62c1ea0bc8116cd1caf143ce3af947536c3c9052a1677fe0c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "thiserror" version = "1.0.47" diff --git a/Cargo.toml b/Cargo.toml index 6b2115f2..1e2ce974 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "fa3017715a298728 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" diff --git a/crates/p2p/Cargo.toml b/crates/p2p/Cargo.toml index d7d29ccd..2d92eaa1 100644 --- a/crates/p2p/Cargo.toml +++ b/crates/p2p/Cargo.toml @@ -21,8 +21,8 @@ lazy_static = { workspace = true } snap = "1" silius-primitives = { path = "../primitives" } silius-uopool = {path = "../uopool"} -ssz_rs = "0.9.0" -ssz_rs_derive = "0.9.0" +ssz_rs = { workspace = true } +ssz_rs_derive = { workspace = true } discv5 = {version = "0.3.0", features = ["libp2p"]} tokio = { workspace = true } tracing = { workspace = true } @@ -33,3 +33,10 @@ libp2p-mplex = {path = "/chain/eth/rust-libp2p/muxers/mplex"} path = "/chain/eth/rust-libp2p/libp2p" # version = "0.52.3" features = [ "identify", "yamux","noise", "gossipsub", "dns", "tcp", "tokio", "secp256k1", "macros", "request-response"] + +[dev-dependencies] +ethers = { workspace=true } +test-log = "0.2.12" +env_logger = "*" +tracing = {version = "0.1", default-features = false} +tracing-subscriber = {version = "0.3", default-features = false, features = ["env-filter", "fmt"]} diff --git a/crates/p2p/src/behaviour.rs b/crates/p2p/src/behaviour.rs index 2ad0bf0b..f6848393 100644 --- a/crates/p2p/src/behaviour.rs +++ b/crates/p2p/src/behaviour.rs @@ -1,13 +1,13 @@ use crate::config::Config; use crate::discovery::{self, Discovery}; use crate::enr::build_enr; -use crate::gossipsub::Gossipsub; +use crate::gossipsub::{create_gossisub, Gossipsub}; use crate::reqrep::{BundlerCodec, BundlerRequestResponse, Request, Response}; use discv5::enr::CombinedKey; use libp2p::gossipsub; -use libp2p::gossipsub::ConfigBuilder; use libp2p::request_response; use libp2p::swarm::NetworkBehaviour; +use silius_uopool::MempoolId; #[derive(NetworkBehaviour)] #[behaviour(to_swarm = "Event", event_process = false)] @@ -18,14 +18,9 @@ pub struct Behaviour { } impl Behaviour { - pub fn new(key: CombinedKey, config: Config) -> anyhow::Result { + pub fn new(key: CombinedKey, config: Config, mempool_ids: MempoolId) -> anyhow::Result { let enr = build_enr(&key, &config)?; - let gossipsub_config = ConfigBuilder::default() - .validation_mode(gossipsub::ValidationMode::Anonymous) - .build() - .map_err(|e| anyhow::anyhow!(e))?; - let gossipsub = Gossipsub::new(gossipsub::MessageAuthenticity::Anonymous, gossipsub_config) - .map_err(|e| anyhow::anyhow!(e))?; + let gossipsub = create_gossisub(mempool_ids).map_err(|e| anyhow::anyhow!(e))?; let reqrep = BundlerRequestResponse::new(BundlerCodec {}, request_response::Config::default()); let discovery = Discovery::new(enr, key, config)?; diff --git a/crates/p2p/src/gossipsub.rs b/crates/p2p/src/gossipsub.rs index 11b92b52..387381b2 100644 --- a/crates/p2p/src/gossipsub.rs +++ b/crates/p2p/src/gossipsub.rs @@ -5,7 +5,7 @@ use std::{ use libp2p::gossipsub::{ Behaviour, ConfigBuilder, DataTransform, IdentTopic, Message, MessageAuthenticity, RawMessage, - TopicHash, WhitelistSubscriptionFilter, + TopicHash, ValidationMode, WhitelistSubscriptionFilter, }; use silius_uopool::MempoolId; use snap::raw::{decompress_len, Decoder, Encoder}; @@ -82,24 +82,34 @@ impl DataTransform for SnappyTransform { } } -pub fn create_whitelist_filter(mempool_ids: &[MempoolId]) -> WhitelistSubscriptionFilter { +pub fn create_whitelist_filter(mempool_id: MempoolId) -> WhitelistSubscriptionFilter { let mut possible_hashes: HashSet = HashSet::new(); - for mempool_id in mempool_ids.iter() { - let topic = IdentTopic::new(format!("/{TOPIC_PREFIX:}/{mempool_id:}/{USER_OPS_WITH_ENTRY_POINT_TOPIC:}/{SSZ_SNAPPY_ENCODING:}")); - possible_hashes.insert(topic.into()); - } + let topic = topic(&mempool_id); + possible_hashes.insert(topic.into()); WhitelistSubscriptionFilter(possible_hashes) } -pub fn create_gossisub(mempool_ids: &[MempoolId]) -> Result { - let filter = create_whitelist_filter(mempool_ids); - let gs_config = ConfigBuilder::default().build()?; +pub fn topic(mempool_id: &MempoolId) -> IdentTopic { + IdentTopic::new(format!( + "/{TOPIC_PREFIX:}/{mempool_id:x}/{USER_OPS_WITH_ENTRY_POINT_TOPIC:}/{SSZ_SNAPPY_ENCODING:}" + )) +} + +pub fn create_gossisub(mempool_id: MempoolId) -> Result { + let filter = create_whitelist_filter(mempool_id); + let gs_config = ConfigBuilder::default() + .validation_mode(ValidationMode::Anonymous) + .build()?; let snappy_transform = SnappyTransform::new(MAX_GOSSIP_SNAP_SIZE); - Gossipsub::new_with_subscription_filter_and_transform( + let mut gossipsub = Gossipsub::new_with_subscription_filter_and_transform( MessageAuthenticity::Anonymous, gs_config, None, filter, snappy_transform, - ) + )?; + let _ = gossipsub + .subscribe(&topic(&mempool_id)) + .map_err(|_| "subscribe error")?; + Ok(gossipsub) } diff --git a/crates/p2p/src/network.rs b/crates/p2p/src/network.rs index 458406cd..2878ece1 100644 --- a/crates/p2p/src/network.rs +++ b/crates/p2p/src/network.rs @@ -11,18 +11,23 @@ use libp2p::{ upgrade, }, futures::StreamExt, + gossipsub::{MessageId, PublishError, TopicHash}, identity::Keypair, noise, - swarm::SwarmBuilder, + swarm::{dial_opts::DialOpts, DialError, SwarmBuilder}, Multiaddr, PeerId, Swarm, Transport, TransportError, }; use libp2p_mplex::{MaxBufferBehaviour, MplexConfig}; +use silius_primitives::UserOperationsWithEntryPoint; +use silius_uopool::MempoolId; +use ssz_rs::Serialize; use tracing::info; use crate::{ behaviour::Behaviour, config::Config, enr::{build_enr, keypair_to_combine, CombineKeyPubExt}, + gossipsub::topic, }; struct TokioExecutor; @@ -32,9 +37,14 @@ impl libp2p::swarm::Executor for TokioExecutor { } } +pub enum NetworkEvent { + NewListenAddr(Multiaddr), +} + pub struct Network { swarm: Swarm, name: String, + mempool_id: MempoolId, } impl From for Swarm { @@ -44,16 +54,25 @@ impl From for Swarm { } impl Network { - pub fn new(key: Keypair, config: Config, name: String) -> anyhow::Result { + pub fn new( + key: Keypair, + config: Config, + name: String, + mempool_id: MempoolId, + ) -> anyhow::Result { let transport = Self::build_transport(key.clone())?; let combine_key = keypair_to_combine(key)?; let enr = build_enr(&combine_key, &config)?; - let behaviour = Behaviour::new(combine_key, config)?; + let behaviour = Behaviour::new(combine_key, config, mempool_id)?; let peer_id = enr.public_key().to_peer_id()?; let swarm = SwarmBuilder::with_executor(transport, behaviour, peer_id, TokioExecutor).build(); - Ok(Self { swarm, name }) + Ok(Self { + swarm, + name, + mempool_id, + }) } fn build_transport(private_key: Keypair) -> std::io::Result> { @@ -74,71 +93,37 @@ impl Network { .expect("signing can fail only once during starting a node"); // Authentication Ok(transport - .upgrade(upgrade::Version::V1) + .upgrade(upgrade::Version::V1Lazy) .authenticate(noise_config) .multiplex(upgrade::SelectUpgrade::new(yamux_config, mplex_config)) .timeout(Duration::from_secs(10)) .boxed()) } - pub fn poll_network(&mut self, cx: &mut Context) -> Poll<()> { + pub fn poll_network(&mut self, cx: &mut Context) -> Poll { while let Poll::Ready(Some(swarm_event)) = self.swarm.poll_next_unpin(cx) { info!("Swarm event: {:?}", swarm_event); - match swarm_event { - libp2p::swarm::SwarmEvent::Behaviour(_) => println!("behaviour {}", self.name), - libp2p::swarm::SwarmEvent::ConnectionEstablished { - peer_id, - connection_id, - endpoint, - num_established, - concurrent_dial_errors, - established_in, - } => println!("connection established {}, {peer_id}, {connection_id}, {endpoint:?}, {num_established}, {concurrent_dial_errors:?}, {established_in:?}", self.name), - libp2p::swarm::SwarmEvent::ConnectionClosed { - peer_id, - connection_id, - endpoint, - num_established, - cause, - } => println!("connection closed {}", self.name), - libp2p::swarm::SwarmEvent::IncomingConnection { - connection_id, - local_addr, - send_back_addr, - } => println!("incomming connection {}", self.name), - libp2p::swarm::SwarmEvent::IncomingConnectionError { - connection_id, - local_addr, - send_back_addr, - error, - } => println!("incoming connection error {}", self.name), - libp2p::swarm::SwarmEvent::OutgoingConnectionError { - connection_id, - peer_id, - error, - } => { - println!("outgoing connection error {}", self.name) + let event_opt = match swarm_event { + libp2p::swarm::SwarmEvent::Behaviour(e) => { + println!("behaviour {} {e:?}", self.name); + None } + libp2p::swarm::SwarmEvent::NewListenAddr { listener_id, address, - } => println!("new listenaddr {}", self.name), - libp2p::swarm::SwarmEvent::ExpiredListenAddr { - listener_id, - address, - } => println!("expire listen addr {}", self.name), - libp2p::swarm::SwarmEvent::ListenerClosed { - listener_id, - addresses, - reason, - } => println!("listener closed {}", self.name), - libp2p::swarm::SwarmEvent::ListenerError { listener_id, error } => { - println!("listen error {}", self.name) + } => { + println!("new listenaddr {}, {listener_id:?}", self.name); + Some(NetworkEvent::NewListenAddr(address)) + } + + event => { + println!("comming event {}: {event:?}", self.name); + None } - libp2p::swarm::SwarmEvent::Dialing { - peer_id, - connection_id, - } => println!("dialing {}", self.name), + }; + if let Some(event) = event_opt { + return Poll::Ready(event); } } Poll::Pending @@ -148,7 +133,32 @@ impl Network { self.swarm.listen_on(addr) } - pub async fn next_event(&mut self) -> () { + pub async fn next_event(&mut self) -> NetworkEvent { futures::future::poll_fn(|cx| self.poll_network(cx)).await } + + fn topic_hash(&self) -> TopicHash { + topic(&self.mempool_id).into() + } + + pub fn publish( + &mut self, + user_ops: UserOperationsWithEntryPoint, + ) -> Result { + let mut buf = Vec::new(); + let _ = user_ops.serialize(&mut buf).unwrap(); + let topic_hash = self.topic_hash(); + self.swarm + .behaviour_mut() + .gossipsub + .publish(topic_hash, buf) + } + + pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { + self.swarm.dial(opts) + } + + pub fn listened_addrs(&self) -> Vec<&Multiaddr> { + self.swarm.listeners().collect() + } } diff --git a/crates/p2p/src/reqrep/mod.rs b/crates/p2p/src/reqrep/mod.rs index a8cf1a51..cc6b0c1d 100644 --- a/crates/p2p/src/reqrep/mod.rs +++ b/crates/p2p/src/reqrep/mod.rs @@ -8,7 +8,7 @@ use libp2p::{ request_response::{self, Codec, ProtocolSupport}, }; use silius_primitives::UserOperation; -use ssz_rs::{Bitvector, Deserialize, DeserializeError, List, Serialize, Sized, Vector}; +use ssz_rs::{Bitvector, Deserialize, DeserializeError, List, Serialize, Vector}; use self::protocol::{Protocol, ProtocolId, SUPPORTED_PROTOCOL}; @@ -235,12 +235,12 @@ pub struct PooledUserOpHashesReq { offset: u64, } -#[derive(ssz_rs_derive::SimpleSerialize, Clone, Debug, PartialEq, Default)] +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] pub struct PooledUserOpsByHashReq { hashes: List, 1024>, } -#[derive(ssz_rs_derive::SimpleSerialize, Clone, Debug, PartialEq, Default)] +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] pub struct MetaData { seq_number: u64, mempool_nets: Bitvector<32>, @@ -276,14 +276,14 @@ impl Response { } } -#[derive(ssz_rs_derive::SimpleSerialize, Clone, Debug, PartialEq, Default)] +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] pub struct PooledUserOpHashes { more_flag: u64, hashes: List<[u8; 32], 1024>, } -#[derive(ssz_rs_derive::SimpleSerialize, Clone, Debug, PartialEq, Default)] +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] pub struct PooledUserOpsByHash { hashes: List, } diff --git a/crates/p2p/src/tests/mod.rs b/crates/p2p/src/tests/mod.rs index 28993e04..6dbb89a2 100644 --- a/crates/p2p/src/tests/mod.rs +++ b/crates/p2p/src/tests/mod.rs @@ -18,3 +18,5 @@ pub fn get_available_port() -> Option { } Some(unused_port) } + +pub fn build_node_pair() {} diff --git a/crates/p2p/src/tests/swarm.rs b/crates/p2p/src/tests/swarm.rs index 0c26a173..677763d4 100644 --- a/crates/p2p/src/tests/swarm.rs +++ b/crates/p2p/src/tests/swarm.rs @@ -1,19 +1,23 @@ -use std::{net::Ipv4Addr, time::Duration}; +use std::{net::Ipv4Addr, str::FromStr, time::Duration}; +use ethers::types::{Address, U256}; use libp2p::{gossipsub::TopicHash, identity::Keypair, Swarm}; +use silius_primitives::consts::entry_point; +use silius_uopool::mempool_id; use crate::{ behaviour::Behaviour, config::{Config, ListenAddr}, - network::Network, + network::{Network, NetworkEvent}, }; use super::get_available_port; +use test_log::test; -#[tokio::test] -async fn req_rep() -> anyhow::Result<()> { - let key1 = Keypair::generate_secp256k1(); - let config1 = Config { +fn build_p2p_instance(name: String) -> anyhow::Result { + let mempool_id = mempool_id(&Address::from_str(entry_point::ADDRESS)?, &U256::from(5)); + let key = Keypair::generate_secp256k1(); + let config = Config { listen_addr: crate::config::ListenAddress::Ipv4(ListenAddr { addr: Ipv4Addr::LOCALHOST, udp_port: get_available_port().unwrap(), @@ -26,46 +30,66 @@ async fn req_rep() -> anyhow::Result<()> { enr_udp6_port: None, enr_tcp6_port: None, }; - let peer1_listen_addr = config1.listen_addr.to_multi_addr().first().unwrap().clone(); - let mut peer1: Swarm = Network::new(key1, config1, "peer1".to_string())?.into(); - println!("listening peer1 {peer1_listen_addr:?}"); + let listen_addr = config.listen_addr.to_multi_addr().first().unwrap().clone(); + let mut network = Network::new(key, config, name, mempool_id.clone())?; + network.listen_on(listen_addr); + Ok(network) +} - peer1.listen_on(peer1_listen_addr)?; - let key2 = Keypair::generate_secp256k1(); - let config2 = Config { - listen_addr: crate::config::ListenAddress::Ipv4(ListenAddr { - addr: Ipv4Addr::LOCALHOST, - udp_port: get_available_port().unwrap(), - tcp_port: get_available_port().unwrap(), - }), - ipv4_addr: Some(Ipv4Addr::LOCALHOST), - ipv6_addr: None, - enr_udp4_port: get_available_port(), - enr_tcp4_port: None, - enr_udp6_port: None, - enr_tcp6_port: None, +pub async fn build_connnected_p2p_pair() -> anyhow::Result<(Network, Network)> { + let mut peer1 = build_p2p_instance("peer1".to_string())?; + let mut peer2 = build_p2p_instance("peer2".to_string())?; + // let the two nodes set up listeners + let peer1_fut = async { + loop { + if let NetworkEvent::NewListenAddr(_) = peer1.next_event().await { + return; + } + } }; - let peer2_listen_addr = config2.listen_addr.to_multi_addr().first().unwrap().clone(); - let mut peer2 = Network::new(key2, config2, "peer2".to_string())?; - peer2.listen_on(peer2_listen_addr.clone())?; - println!("listening peer2 {peer2_listen_addr:?}"); + let peer2_fut = async { + loop { + if let NetworkEvent::NewListenAddr(_) = peer2.next_event().await { + return; + } + } + }; + + let joined = futures::future::join(peer1_fut, peer2_fut); + + // wait for either both nodes to listen or a timeout + tokio::select! { + _ = tokio::time::sleep(Duration::from_millis(500)) => {} + _ = joined => {} + } + let peer2_listened_addr = *peer2.listened_addrs().first().unwrap(); + peer1.dial(peer2_listened_addr.clone())?; + Ok((peer1, peer2)) +} + +#[test(tokio::test)] +async fn swarm() -> anyhow::Result<()> { + let (peer1, peer2) = build_connnected_p2p_pair().await?; + tokio::spawn(async move { loop { println!("peer2 poll event"); - peer2.next_event().await + peer2.next_event().await; } }); peer1.dial(peer2_listen_addr)?; println!("peer1 dial peer2"); - tokio::time::sleep(Duration::from_secs(2)).await; - - peer1 - .behaviour_mut() - .gossipsub - .publish(TopicHash::from_raw("test"), "hello world")?; + tokio::spawn(async move { + println!("peer1 poll event"); + peer1.next_event().await; + peer1.publish(Default::default()).unwrap(); + loop { + println!("peer1 poll event"); + peer1.next_event().await; + } + }); println!("peer1 publish"); tokio::time::sleep(Duration::from_secs(10)).await; - Ok(()) } diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index c06afc58..069140ec 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -19,8 +19,8 @@ lazy_static = { workspace = true } rustc-hex = "^2.0.1" serde = "1" serde_json = { workspace = true } -ssz_rs = "0.9.0" -ssz_rs_derive = "0.9.0" +ssz_rs = { workspace = true } +ssz_rs_derive = { workspace = true } strum = "0.24" strum_macros = "0.24" tokio = { workspace = true } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 1b2c8dd8..bdb2725d 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -3,6 +3,7 @@ pub mod bundler; pub mod chain; pub mod consts; +mod p2p; pub mod reputation; pub mod sanity; pub mod simulation; @@ -13,6 +14,7 @@ mod wallet; pub use bundler::Mode as BundlerMode; pub use chain::Chain; +pub use p2p::{PooledUserOps, UserOperationsWithEntryPoint}; pub use uopool::Mode as UoPoolMode; pub use user_operation::{ UserOperation, UserOperationByHash, UserOperationGasEstimation, UserOperationHash, diff --git a/crates/primitives/src/p2p.rs b/crates/primitives/src/p2p.rs new file mode 100644 index 00000000..f873b7a7 --- /dev/null +++ b/crates/primitives/src/p2p.rs @@ -0,0 +1,19 @@ +use ssz_rs::{List, Vector, U256}; +use ssz_rs_derive::Serializable; + +use crate::UserOperation; + +#[derive(Clone, Debug, Default, Serializable)] +pub struct UserOperationsWithEntryPoint { + entrypoint_contract: U256, + verified_at_block_hash: U256, + chain_id: U256, + user_operations: List, +} + +#[derive(Clone, Debug, Default, Serializable)] +pub struct PooledUserOps { + mempool_id: Vector, + more_flag: u64, + user_operations: List, +} diff --git a/crates/primitives/src/user_operation.rs b/crates/primitives/src/user_operation.rs index 31056daf..236e650d 100644 --- a/crates/primitives/src/user_operation.rs +++ b/crates/primitives/src/user_operation.rs @@ -7,7 +7,7 @@ use ethers::{ }; use rustc_hex::FromHexError; use serde::{Deserialize, Serialize}; -use ssz_rs::{List, Sized}; +use ssz_rs::List; use std::{ops::Deref, slice::Windows, str::FromStr}; const BYTES_PER_LENGTH_OFFSET: usize = 4; /// This could be increased if we found bigger bytes, the propper value is not sure right now. @@ -415,15 +415,6 @@ fn btyes_to_list( .map_err(|(data, _)| ssz_rs::SerializeError::MaximumEncodedLengthReached(data.len())) } -impl ssz_rs::Sized for UserOperation { - fn is_variable_size() -> bool { - true - } - fn size_hint() -> usize { - 0 - } -} - impl ssz_rs::Serialize for UserOperation { fn serialize(&self, buffer: &mut Vec) -> Result { let mut serializer = ssz_rs::__internal::Serializer::default(); @@ -490,7 +481,7 @@ impl ssz_rs::Deserialize for UserOperation { let mut container = Self::default(); let byte_read = { - let encoded_length = <[u8; 20] as ssz_rs::Sized>::size_hint(); + let encoded_length = <[u8; 20] as ssz_rs::Serializable>::size_hint(); let end = start + encoded_length; let target = encoding @@ -583,13 +574,15 @@ impl ssz_rs::Deserialize for UserOperation { } } -impl ssz_rs::Merkleized for UserOperation { - fn hash_tree_root(&mut self) -> Result { - unimplemented!() +impl ssz_rs::Serializable for UserOperation { + fn is_variable_size() -> bool { + true } -} -impl ssz_rs::SimpleSerialize for UserOperation {} + fn size_hint() -> usize { + 0 + } +} #[cfg(test)] mod tests {