diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00a9a876..f8fc126a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,7 @@ jobs: with: name: silius path: silius-artifact + - run: mv silius-artifact/silius /usr/local/bin/ - run: chmod a+x /usr/local/bin/silius - run: chmod a+x silius/bundler-spec-tests/launcher.sh diff --git a/Cargo.lock b/Cargo.lock index bfbe4399..6616e04a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5380,6 +5380,7 @@ dependencies = [ "async-trait", "dashmap", "ethers 2.0.8", + "expanded-pathbuf", "parking_lot", "prost", "prost-build", diff --git a/Cargo.toml b/Cargo.toml index 148e19c3..18b88b6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ rust-version = "1.71.1" anyhow = "1" async-trait = "0.1" ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "fa3017715a298728d9fb341933818a5d0d84c2dc" } +expanded-pathbuf = "0.1" parking_lot = "0.12" serde_json = "1" tokio = { version = "1.18", features = ["full"] } diff --git a/bin/silius/Cargo.toml b/bin/silius/Cargo.toml index 636eae41..a0139f75 100644 --- a/bin/silius/Cargo.toml +++ b/bin/silius/Cargo.toml @@ -17,7 +17,7 @@ anyhow = { workspace = true } clap = { version = "4", features = ["derive"] } dirs = "4.0" ethers = { workspace = true } -expanded-pathbuf = "0.1" +expanded-pathbuf = { workspace = true } log = "0.4.19" pin-utils = "0.1" silius-bundler = { path = "../../crates/bundler" } diff --git a/bin/silius/src/cli.rs b/bin/silius/src/cli.rs index bb383794..c3d964d3 100644 --- a/bin/silius/src/cli.rs +++ b/bin/silius/src/cli.rs @@ -1,14 +1,18 @@ use crate::utils::{parse_address, parse_u256, parse_uopool_mode}; use clap::Parser; use ethers::types::{Address, U256}; +use expanded_pathbuf::ExpandedPathBuf; use silius_primitives::UoPoolMode; use std::net::SocketAddr; -#[derive(Clone, Debug, Parser, PartialEq)] +#[derive(Clone, Debug, Parser)] pub struct UoPoolServiceOpts { #[clap(long, default_value = "127.0.0.1:3001")] pub uopool_grpc_listen_address: SocketAddr, + #[clap(long)] + pub datadir: Option, + #[clap(long, value_parser=parse_u256, default_value = "1")] pub min_stake: U256, diff --git a/bin/silius/src/create-wallet.rs b/bin/silius/src/create-wallet.rs index fe02f2b0..d08b8f09 100644 --- a/bin/silius/src/create-wallet.rs +++ b/bin/silius/src/create-wallet.rs @@ -1,9 +1,8 @@ use anyhow::Result; use clap::Parser; -use dirs::home_dir; use ethers::types::U256; use expanded_pathbuf::ExpandedPathBuf; -use silius::utils::parse_u256; +use silius::utils::{parse_u256, unwrap_path_or_home}; use silius_primitives::Wallet; use tracing::info; @@ -28,14 +27,7 @@ fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let path = if let Some(output_path) = opt.output_path { - output_path - } else { - home_dir() - .map(|h| h.join(".silius")) - .ok_or_else(|| anyhow::anyhow!("Get Home directory error")) - .map(ExpandedPathBuf)? - }; + let path = unwrap_path_or_home(opt.output_path)?; if opt.build_fb_wallet == Some(true) { let wallet = Wallet::build_random(path, &opt.chain_id, true)?; diff --git a/bin/silius/src/silius-uopool.rs b/bin/silius/src/silius-uopool.rs index db69abd2..33b9540a 100644 --- a/bin/silius/src/silius-uopool.rs +++ b/bin/silius/src/silius-uopool.rs @@ -6,7 +6,7 @@ use ethers::{ }; use silius::{ cli::UoPoolServiceOpts, - utils::{parse_address, parse_u256}, + utils::{parse_address, parse_u256, unwrap_path_or_home}, }; use silius_grpc::uopool_service_run; use silius_primitives::{chain::SUPPORTED_CHAINS, Chain}; @@ -62,10 +62,13 @@ async fn main() -> Result<()> { } } + let datadir = unwrap_path_or_home(opt.uopool_opts.datadir)?; + info!("Starting uopool gRPC service..."); uopool_service_run( opt.uopool_opts.uopool_grpc_listen_address, + datadir, opt.entry_points, eth_client, chain, diff --git a/bin/silius/src/silius.rs b/bin/silius/src/silius.rs index 2b128967..0656f9f0 100644 --- a/bin/silius/src/silius.rs +++ b/bin/silius/src/silius.rs @@ -7,7 +7,7 @@ use ethers::{ use expanded_pathbuf::ExpandedPathBuf; use silius::{ cli::{BundlerServiceOpts, RpcServiceOpts, UoPoolServiceOpts}, - utils::{parse_address, parse_u256, run_until_ctrl_c}, + utils::{parse_address, parse_u256, run_until_ctrl_c, unwrap_path_or_home}, }; use silius_grpc::{ bundler_client::BundlerClient, bundler_service_run, uo_pool_client::UoPoolClient, @@ -114,9 +114,12 @@ fn main() -> Result<()> { if !opt.no_uopool { + let datadir = unwrap_path_or_home(opt.uopool_opts.datadir)?; + info!("Starting uopool gRPC service..."); uopool_service_run( opt.uopool_opts.uopool_grpc_listen_address, + datadir, opt.entry_points.clone(), eth_client, chain, diff --git a/bin/silius/src/utils.rs b/bin/silius/src/utils.rs index cc54fc4d..950a705b 100644 --- a/bin/silius/src/utils.rs +++ b/bin/silius/src/utils.rs @@ -1,9 +1,23 @@ +use dirs::home_dir; use ethers::types::{Address, U256}; +use expanded_pathbuf::ExpandedPathBuf; use pin_utils::pin_mut; use silius_primitives::UoPoolMode; use std::{future::Future, str::FromStr}; use tracing::info; +/// Unwrap path or returns home directory +pub fn unwrap_path_or_home(path: Option) -> anyhow::Result { + if let Some(path) = path { + Ok(path) + } else { + home_dir() + .map(|h| h.join(".silius")) + .ok_or_else(|| anyhow::anyhow!("Get Home directory error")) + .map(ExpandedPathBuf) + } +} + /// Parses address from string pub fn parse_address(s: &str) -> Result { Address::from_str(s).map_err(|_| format!("String {s} is not a valid address")) diff --git a/crates/grpc/Cargo.toml b/crates/grpc/Cargo.toml index 2a1c6ec6..a2be058d 100644 --- a/crates/grpc/Cargo.toml +++ b/crates/grpc/Cargo.toml @@ -16,6 +16,7 @@ arrayref = "0.3" async-trait = { workspace = true } dashmap = "5.4.0" ethers = { workspace = true } +expanded-pathbuf = { workspace = true } parking_lot = { workspace = true } prost = "0.11" serde_json = { workspace = true } diff --git a/crates/grpc/src/builder.rs b/crates/grpc/src/builder.rs index 49679849..1a938338 100644 --- a/crates/grpc/src/builder.rs +++ b/crates/grpc/src/builder.rs @@ -1,5 +1,4 @@ -use std::sync::Arc; - +use crate::uopool::{GAS_INCREASE_PERC, MAX_UOS_PER_UNSTAKED_SENDER}; use ethers::{ providers::Middleware, types::{Address, U256}, @@ -13,14 +12,14 @@ use silius_uopool::{ validate::validator::StandardUserOperationValidator, Mempool, MempoolBox, Reputation, ReputationBox, UoPool, VecCh, VecUo, }; +use std::fmt::{Debug, Display}; +use std::sync::Arc; -use crate::uopool::{GAS_INCREASE_PERC, MAX_UOS_PER_UNSTAKED_SENDER}; - -pub struct UoPoolBuilder +pub struct UoPoolBuilder where M: Middleware + Clone + 'static, - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { is_unsafe: bool, eth_client: Arc, @@ -31,15 +30,16 @@ where min_unstake_delay: U256, min_priority_fee_per_gas: U256, whitelist: Vec
, - mempool: MempoolBox, - reputation: ReputationBox, R>, + mempool: MempoolBox, + reputation: ReputationBox, R, E>, } -impl UoPoolBuilder +impl UoPoolBuilder where M: Middleware + Clone + 'static, - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { #[allow(clippy::too_many_arguments)] pub fn new( @@ -55,8 +55,8 @@ where mempool: P, reputation: R, ) -> Self { - let mempool = MempoolBox::::new(mempool); - let mut reputation = ReputationBox::, R>::new(reputation); + let mempool = MempoolBox::::new(mempool); + let mut reputation = ReputationBox::, R, E>::new(reputation); reputation.init( MIN_INCLUSION_RATE_DENOMINATOR, THROTTLING_SLACK, @@ -82,7 +82,7 @@ where } } - pub fn uo_pool(&self) -> UoPool, P, R> { + pub fn uo_pool(&self) -> UoPool, P, R, E> { let entry_point = EntryPoint::::new(self.eth_client.clone(), self.entrypoint_addr); let validator = if self.is_unsafe { @@ -105,7 +105,7 @@ where ) }; - UoPool::, P, R>::new( + UoPool::, P, R, E>::new( entry_point, validator, self.mempool.clone(), diff --git a/crates/grpc/src/uopool.rs b/crates/grpc/src/uopool.rs index 40bd16c3..87ed08d2 100644 --- a/crates/grpc/src/uopool.rs +++ b/crates/grpc/src/uopool.rs @@ -11,14 +11,18 @@ use ethers::{ providers::{Http, Middleware, Provider}, types::{Address, U256}, }; +use expanded_pathbuf::ExpandedPathBuf; use silius_contracts::entry_point::EntryPointErr; use silius_primitives::reputation::ReputationEntry; use silius_primitives::{uopool::AddError, Chain, UoPoolMode}; use silius_uopool::{ - mempool_id, validate::validator::StandardUserOperationValidator, MemoryMempool, - MemoryReputation, MempoolId, Reputation, UoPool as UserOperationPool, + init_env, DBError, DatabaseMempool, DatabaseReputation, Mempool, VecCh, VecUo, WriteMap, }; -use silius_uopool::{Mempool, VecCh, VecUo}; +use silius_uopool::{ + mempool_id, validate::validator::StandardUserOperationValidator, MempoolId, Reputation, + UoPool as UserOperationPool, +}; +use std::fmt::{Debug, Display}; use std::{net::SocketAddr, sync::Arc, time::Duration}; use tonic::{Code, Request, Response, Status}; use tracing::{info, warn}; @@ -26,30 +30,31 @@ use tracing::{info, warn}; pub const MAX_UOS_PER_UNSTAKED_SENDER: usize = 4; pub const GAS_INCREASE_PERC: u64 = 10; -type StandardUserPool = - UserOperationPool, P, R>; +type StandardUserPool = + UserOperationPool, P, R, E>; -pub struct UoPoolService +pub struct UoPoolService where M: Middleware + Clone + 'static, - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { - pub uo_pools: Arc>>, + pub uo_pools: Arc>>, pub chain: Chain, } -impl UoPoolService +impl UoPoolService where M: Middleware + Clone + 'static, - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { - pub fn new(uo_pools: Arc>>, chain: Chain) -> Self { + pub fn new(uo_pools: Arc>>, chain: Chain) -> Self { Self { uo_pools, chain } } - fn get_uo_pool(&self, ep: &Address) -> tonic::Result> { + fn get_uo_pool(&self, ep: &Address) -> tonic::Result> { let m_id = mempool_id(ep, &U256::from(self.chain.id())); self.uo_pools .get(&m_id) @@ -62,18 +67,13 @@ where } #[async_trait] -impl uo_pool_server::UoPool for UoPoolService +impl uo_pool_server::UoPool for UoPoolService where EntryPointErr: From<::Error>, M: Middleware + Clone + 'static, - P: Mempool - + Send - + Sync - + 'static, - R: Reputation, Error = anyhow::Error> - + Send - + Sync - + 'static, + P: Mempool + Send + Sync + 'static, + R: Reputation, Error = E> + Send + Sync + 'static, + E: Debug + Display + 'static, { async fn add(&self, req: Request) -> Result, Status> { let req = req.into_inner(); @@ -347,6 +347,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn uopool_service_run( grpc_listen_address: SocketAddr, + datadir: ExpandedPathBuf, eps: Vec
, eth_client: Arc>, chain: Chain, @@ -362,9 +363,18 @@ pub async fn uopool_service_run( let m_map = Arc::new(DashMap::< MempoolId, - UoPoolBuilder, MemoryMempool, MemoryReputation>, + UoPoolBuilder< + Provider, + DatabaseMempool, + DatabaseReputation, + DBError, + >, >::new()); + let env = Arc::new(init_env::(datadir.join("db")).expect("Init mdbx failed")); + env.create_tables() + .expect("Create mdbx database tables failed"); + for ep in eps { let id = mempool_id(&ep, &U256::from(chain.id())); let builder = UoPoolBuilder::new( @@ -377,16 +387,17 @@ pub async fn uopool_service_run( min_unstake_delay, min_priority_fee_per_gas, whitelist.clone(), - MemoryMempool::default(), - MemoryReputation::default(), + DatabaseMempool::new(env.clone()), + DatabaseReputation::new(env.clone()), ); m_map.insert(id, builder); } let svc = uo_pool_server::UoPoolServer::new(UoPoolService::< Provider, - MemoryMempool, - MemoryReputation, + DatabaseMempool, + DatabaseReputation, + DBError, >::new(m_map.clone(), chain)); tokio::spawn(async move { diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index d2be851a..1c6cc7ea 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -14,7 +14,7 @@ AA (ERC-4337) bundler commonly used types anyhow = { workspace = true } educe = { version = "0.4", features = ["Debug", "Default"] } ethers = { workspace = true } -expanded-pathbuf = "0.1" +expanded-pathbuf = { workspace = true } lazy_static = "1.4.0" rustc-hex = "^2.0.1" serde = "1" diff --git a/crates/uopool/src/database/env.rs b/crates/uopool/src/database/env.rs index ff2002e6..748644a1 100644 --- a/crates/uopool/src/database/env.rs +++ b/crates/uopool/src/database/env.rs @@ -8,7 +8,7 @@ use reth_db::{ }, Error, TableType, }; -use std::{fmt::Display, path::PathBuf}; +use std::{fmt::Display, fs, path::PathBuf}; // Code adapted from: https://github.com/paradigmxyz/reth/blob/main/crates/storage/db/src/implementation/mdbx/mod.rs #[derive(Debug)] @@ -74,6 +74,8 @@ fn default_page_size() -> usize { impl Env { /// Sets up the database environment pub fn open(path: PathBuf) -> anyhow::Result { + fs::create_dir_all(&path)?; + let env = Environment::new() .set_max_dbs(TABLES.len()) .set_geometry(Geometry { diff --git a/crates/uopool/src/database/mod.rs b/crates/uopool/src/database/mod.rs index 73ee511f..f9ff798a 100644 --- a/crates/uopool/src/database/mod.rs +++ b/crates/uopool/src/database/mod.rs @@ -1,6 +1,8 @@ //! The database implementation of the [Mempool](crate::mempool::Mempool) trait. Primarily used for storing mempool information in a local database. +pub use self::env::DBError; use self::env::Env; use reth_libmdbx::EnvironmentKind; +pub use reth_libmdbx::WriteMap; use std::path::PathBuf; mod env; diff --git a/crates/uopool/src/lib.rs b/crates/uopool/src/lib.rs index f0e928a5..1174133e 100644 --- a/crates/uopool/src/lib.rs +++ b/crates/uopool/src/lib.rs @@ -9,7 +9,9 @@ mod uopool; mod utils; pub mod validate; -pub use database::mempool::DatabaseMempool; +pub use database::{ + init_env, mempool::DatabaseMempool, reputation::DatabaseReputation, DBError, WriteMap, +}; pub use memory::{mempool::MemoryMempool, reputation::MemoryReputation}; pub use mempool::{mempool_id, Mempool, MempoolBox, MempoolId}; pub use reputation::{Reputation, ReputationBox}; diff --git a/crates/uopool/src/mempool.rs b/crates/uopool/src/mempool.rs index 69fbc8f4..beac8d56 100644 --- a/crates/uopool/src/mempool.rs +++ b/crates/uopool/src/mempool.rs @@ -13,16 +13,16 @@ pub type MempoolId = H256; /// /// The Mempool box provide a RwLock for the inner Mempool which could be multi-thread accessed #[derive(Debug)] -pub struct MempoolBox +pub struct MempoolBox where - P: Mempool + Send + Sync, + P: Mempool + Send + Sync, { inner: Arc>, } -impl Clone for MempoolBox +impl Clone for MempoolBox where - P: Mempool + Send + Sync, + P: Mempool + Send + Sync, { fn clone(&self) -> Self { Self { @@ -31,9 +31,9 @@ where } } -impl MempoolBox +impl MempoolBox where - P: Mempool + Send + Sync, + P: Mempool + Send + Sync, { pub fn new(inner: P) -> Self { Self { @@ -42,14 +42,15 @@ where } } -impl Mempool for MempoolBox +impl Mempool for MempoolBox where T: Debug + IntoIterator, U: Debug + IntoIterator, - M: Mempool + Send + Sync, + M: Mempool + Send + Sync, + E: Debug, { type CodeHashes = U; - type Error = anyhow::Error; + type Error = E; type UserOperations = T; fn get_all(&self) -> T { @@ -65,7 +66,7 @@ where uo: UserOperation, ep: &Address, chain_id: &U256, - ) -> Result { + ) -> Result { self.inner.write().add(uo, ep, chain_id) } @@ -73,7 +74,7 @@ where &mut self, uo_hash: &UserOperationHash, hashes: &U, - ) -> Result<(), anyhow::Error> { + ) -> Result<(), Self::Error> { self.inner.write().set_code_hashes(uo_hash, hashes) } diff --git a/crates/uopool/src/reputation.rs b/crates/uopool/src/reputation.rs index 2bb1e0ad..d975ea5c 100644 --- a/crates/uopool/src/reputation.rs +++ b/crates/uopool/src/reputation.rs @@ -7,16 +7,16 @@ use silius_primitives::{ use std::{fmt::Debug, ops::Deref, sync::Arc}; #[derive(Debug)] -pub struct ReputationBox +pub struct ReputationBox where - R: Reputation + Send + Sync + Debug, + R: Reputation + Send + Sync + Debug, { inner: Arc>, } -impl Clone for ReputationBox +impl Clone for ReputationBox where - R: Reputation + Send + Sync + Debug, + R: Reputation + Send + Sync + Debug, { fn clone(&self) -> Self { Self { @@ -25,9 +25,9 @@ where } } -impl ReputationBox +impl ReputationBox where - R: Reputation + Send + Sync + Debug, + R: Reputation + Send + Sync + Debug, { pub fn new(inner: R) -> Self { Self { @@ -36,13 +36,15 @@ where } } -impl Reputation for ReputationBox +impl Reputation for ReputationBox where T: Debug + IntoIterator, - R: Reputation + Send + Sync, + R: Reputation + Send + Sync, + E: Debug, { - type Error = anyhow::Error; type ReputationEntries = T; + type Error = E; + fn add_blacklist(&mut self, addr: &Address) -> bool { self.inner.write().add_blacklist(addr) } diff --git a/crates/uopool/src/uopool.rs b/crates/uopool/src/uopool.rs index b67e73c5..bc50a798 100644 --- a/crates/uopool/src/uopool.rs +++ b/crates/uopool/src/uopool.rs @@ -28,6 +28,7 @@ use silius_primitives::{ UserOperationReceipt, }; use std::collections::{HashMap, HashSet}; +use std::fmt::{Debug, Display}; use tracing::trace; pub type VecUo = Vec; @@ -37,10 +38,11 @@ const LATEST_SCAN_DEPTH: u64 = 1000; /// The alternative mempool pool implementation that provides functionalities to add, remove, validate, and serves data requests from the [RPC API](EthApiServer). /// Architecturally, the [UoPool](UoPool) is the backend service managed by the [UoPoolService](UoPoolService) and serves requests from the [RPC API](EthApiServer). -pub struct UoPool, P, R> +pub struct UoPool, P, R, E> where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug, { /// The unique ID of the mempool pub id: MempoolId, @@ -49,19 +51,20 @@ where /// The [UserOperationValidator](UserOperationValidator) object pub validator: V, /// The [MempoolBox](MempoolBox) is a [Boxed pointer](https://doc.rust-lang.org/std/boxed/struct.Box.html) to a [Mempool](Mempool) object - pub mempool: MempoolBox, + pub mempool: MempoolBox, /// The [ReputationBox](ReputationBox) is a [Boxed pointer](https://doc.rust-lang.org/std/boxed/struct.Box.html) to a [ReputationEntry](ReputationEntry) object - pub reputation: ReputationBox, R>, + pub reputation: ReputationBox, R, E>, // The maximum gas limit for [UserOperation](UserOperation) gas verification. pub max_verification_gas: U256, // The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID pub chain: Chain, } -impl, P, R> UoPool +impl, P, R, E> UoPool where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { /// Creates a new [UoPool](UoPool) object /// @@ -80,8 +83,8 @@ where pub fn new( entry_point: EntryPoint, validator: V, - mempool: MempoolBox, - reputation: ReputationBox, R>, + mempool: MempoolBox, + reputation: ReputationBox, R, E>, max_verification_gas: U256, chain: Chain, ) -> Self { @@ -127,7 +130,7 @@ where /// /// # Returns /// `()` - Returns nothing - pub fn set_reputation(&mut self, reputation: Vec) -> anyhow::Result<()> { + pub fn set_reputation(&mut self, reputation: Vec) -> Result<(), E> { self.reputation.set_entities(reputation) } @@ -228,7 +231,7 @@ where /// /// # Returns /// `Result, anyhow::Error>` - The sorted [UserOperations](UserOperation) - pub fn get_sorted_user_operations(&self) -> anyhow::Result> { + pub fn get_sorted_user_operations(&self) -> Result, E> { self.mempool.get_sorted() } @@ -607,12 +610,18 @@ where match event { EntryPointAPIEvents::UserOperationEventFilter(uo_event) => { self.remove_user_operation(&uo_event.user_op_hash.into()); - self.reputation.increment_included(&uo_event.sender)?; - self.reputation.increment_included(&uo_event.paymaster)?; + self.reputation + .increment_included(&uo_event.sender) + .map_err(|err| anyhow::anyhow!(err.to_string()))?; + self.reputation + .increment_included(&uo_event.paymaster) + .map_err(|err| anyhow::anyhow!(err.to_string()))?; // TODO: include event aggregator } EntryPointAPIEvents::AccountDeployedFilter(event) => { - self.reputation.increment_included(&event.factory)?; + self.reputation + .increment_included(&event.factory) + .map_err(|err| anyhow::anyhow!(err.to_string()))?; } _ => (), } diff --git a/crates/uopool/src/validate/mod.rs b/crates/uopool/src/validate/mod.rs index ac7dfac8..c32c59ad 100644 --- a/crates/uopool/src/validate/mod.rs +++ b/crates/uopool/src/validate/mod.rs @@ -48,44 +48,44 @@ pub enum UserOperationValidatorMode { /// The [UserOperation](UserOperation) validator trait. /// The [UserOperationValidator](UserOperationValidator) is a composable trait that allows bundler to choose validation rules(sanity, simultation, simulation trace) to apply. #[async_trait::async_trait] -pub trait UserOperationValidator: Send + Sync +pub trait UserOperationValidator: Send + Sync where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { async fn validate_user_operation( &self, uo: &UserOperation, - mempool: &MempoolBox, - reputation: &ReputationBox, R>, + mempool: &MempoolBox, + reputation: &ReputationBox, R, E>, mode: EnumSet, ) -> Result where - P: Mempool + Send + Sync; + P: Mempool + Send + Sync; } /// The [UserOperation](UserOperation) sanity check helper trait. -pub struct SanityHelper<'a, M: Middleware + 'static, P, R> +pub struct SanityHelper<'a, M: Middleware + 'static, P, R, E> where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { - mempool: &'a MempoolBox, - reputation: &'a ReputationBox, R>, + mempool: &'a MempoolBox, + reputation: &'a ReputationBox, R, E>, entry_point: EntryPoint, chain: Chain, } #[async_trait::async_trait] -pub trait SanityCheck: Send + Sync +pub trait SanityCheck: Send + Sync where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError>; } @@ -104,13 +104,13 @@ pub trait SimulationCheck: Send + Sync { } /// The [UserOperation](UserOperation) simulation trace check helper trait. -pub struct SimulationTraceHelper<'a, M: Middleware + 'static, P, R> +pub struct SimulationTraceHelper<'a, M: Middleware + 'static, P, R, E> where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { - mempool: &'a MempoolBox, - reputation: &'a ReputationBox, R>, + mempool: &'a MempoolBox, + reputation: &'a ReputationBox, R, E>, entry_point: EntryPoint, chain: Chain, simulate_validation_result: &'a SimulateValidationResult, @@ -120,14 +120,14 @@ where } #[async_trait::async_trait] -pub trait SimulationTraceCheck: Send + Sync +pub trait SimulationTraceCheck: Send + Sync where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { async fn check_user_operation( &self, uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError>; } diff --git a/crates/uopool/src/validate/sanity/call_gas.rs b/crates/uopool/src/validate/sanity/call_gas.rs index 770ca8e1..66081182 100644 --- a/crates/uopool/src/validate/sanity/call_gas.rs +++ b/crates/uopool/src/validate/sanity/call_gas.rs @@ -12,10 +12,10 @@ use silius_primitives::{reputation::ReputationEntry, sanity::SanityCheckError, U pub struct CallGas; #[async_trait::async_trait] -impl SanityCheck for CallGas +impl SanityCheck for CallGas where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The `check_user_operation` method implementation for the `CallGas` sanity check. /// @@ -28,7 +28,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError> { let exec_res = match helper.entry_point.simulate_handle_op(uo.clone()).await { Ok(res) => res, diff --git a/crates/uopool/src/validate/sanity/max_fee.rs b/crates/uopool/src/validate/sanity/max_fee.rs index 5196c38e..385f806a 100644 --- a/crates/uopool/src/validate/sanity/max_fee.rs +++ b/crates/uopool/src/validate/sanity/max_fee.rs @@ -15,10 +15,10 @@ pub struct MaxFee { } #[async_trait::async_trait] -impl SanityCheck for MaxFee +impl SanityCheck for MaxFee where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that checks the max fee /// @@ -31,7 +31,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError> { if uo.max_priority_fee_per_gas > uo.max_fee_per_gas { return Err(SanityCheckError::HighMaxPriorityFeePerGas { diff --git a/crates/uopool/src/validate/sanity/paymaster.rs b/crates/uopool/src/validate/sanity/paymaster.rs index feb5e1fe..e96493b6 100644 --- a/crates/uopool/src/validate/sanity/paymaster.rs +++ b/crates/uopool/src/validate/sanity/paymaster.rs @@ -11,14 +11,16 @@ use silius_primitives::{ sanity::SanityCheckError, UserOperation, }; +use std::fmt::Debug; pub struct Paymaster; #[async_trait::async_trait] -impl SanityCheck for Paymaster +impl SanityCheck for Paymaster where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug, { /// The [check_user_operation] method implementation that performs the sanity check on the paymaster. /// @@ -31,7 +33,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError> { if !uo.paymaster_and_data.is_empty() { if let Some(addr) = get_address(&uo.paymaster_and_data) { diff --git a/crates/uopool/src/validate/sanity/sender.rs b/crates/uopool/src/validate/sanity/sender.rs index 5b6466da..094d9277 100644 --- a/crates/uopool/src/validate/sanity/sender.rs +++ b/crates/uopool/src/validate/sanity/sender.rs @@ -10,10 +10,10 @@ use silius_primitives::{reputation::ReputationEntry, sanity::SanityCheckError, U pub struct SenderOrInitCode; #[async_trait::async_trait] -impl SanityCheck for SenderOrInitCode +impl SanityCheck for SenderOrInitCode where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that performs the check whether the [UserOperation](UserOperation) is a deployment or a transaction. /// @@ -26,7 +26,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError> { let code = helper .entry_point diff --git a/crates/uopool/src/validate/sanity/sender_uos.rs b/crates/uopool/src/validate/sanity/sender_uos.rs index 05e8ffe3..a9726bd1 100644 --- a/crates/uopool/src/validate/sanity/sender_uos.rs +++ b/crates/uopool/src/validate/sanity/sender_uos.rs @@ -12,6 +12,7 @@ use silius_primitives::{ sanity::SanityCheckError, UserOperation, }; +use std::fmt::Debug; pub struct SenderUos { pub max_uos_per_unstaked_sender: usize, @@ -19,10 +20,11 @@ pub struct SenderUos { } #[async_trait::async_trait] -impl SanityCheck for SenderUos +impl SanityCheck for SenderUos where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug, { /// The [check_user_operation] method implementation that performs the sanity check on the [UserOperation](UserOperation) sender. /// @@ -35,7 +37,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &SanityHelper, + helper: &SanityHelper, ) -> Result<(), SanityCheckError> { if helper.mempool.get_number_by_sender(&uo.sender) == 0 { return Ok(()); diff --git a/crates/uopool/src/validate/sanity/verification_gas.rs b/crates/uopool/src/validate/sanity/verification_gas.rs index 6ea404ed..eef3037b 100644 --- a/crates/uopool/src/validate/sanity/verification_gas.rs +++ b/crates/uopool/src/validate/sanity/verification_gas.rs @@ -12,10 +12,10 @@ pub struct VerificationGas { } #[async_trait::async_trait] -impl SanityCheck for VerificationGas +impl SanityCheck for VerificationGas where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that performs the check on verification gas. /// @@ -28,7 +28,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - _helper: &SanityHelper, + _helper: &SanityHelper, ) -> Result<(), SanityCheckError> { if uo.verification_gas_limit > self.max_verification_gas { return Err(SanityCheckError::HighVerificationGasLimit { diff --git a/crates/uopool/src/validate/simulation_trace/call_stack.rs b/crates/uopool/src/validate/simulation_trace/call_stack.rs index cb70f74b..f91c3dff 100644 --- a/crates/uopool/src/validate/simulation_trace/call_stack.rs +++ b/crates/uopool/src/validate/simulation_trace/call_stack.rs @@ -18,6 +18,7 @@ use silius_primitives::{ }, UserOperation, }; +use std::fmt::Debug; pub struct CallStack; @@ -94,10 +95,11 @@ impl CallStack { } #[async_trait::async_trait] -impl SimulationTraceCheck for CallStack +impl SimulationTraceCheck for CallStack where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug, { /// The [check_user_operation] method implementation that performs the call stack trace check. /// @@ -110,7 +112,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { if helper.stake_info.is_none() { helper.stake_info = Some(extract_stake_info(uo, helper.simulate_validation_result)); diff --git a/crates/uopool/src/validate/simulation_trace/code_hashes.rs b/crates/uopool/src/validate/simulation_trace/code_hashes.rs index 5e868e72..6c39db3e 100644 --- a/crates/uopool/src/validate/simulation_trace/code_hashes.rs +++ b/crates/uopool/src/validate/simulation_trace/code_hashes.rs @@ -15,6 +15,7 @@ use silius_primitives::{ simulation::{CodeHash, SimulationCheckError}, UserOperation, }; +use std::fmt::{Debug, Display}; use std::sync::Arc; use tokio::task::JoinSet; @@ -68,10 +69,11 @@ impl CodeHashes { } #[async_trait::async_trait] -impl SimulationTraceCheck for CodeHashes +impl SimulationTraceCheck for CodeHashes where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { /// The [check_user_operation] method implementation that checks the code hashes /// @@ -84,7 +86,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { let addrs = helper .js_trace diff --git a/crates/uopool/src/validate/simulation_trace/external_contracts.rs b/crates/uopool/src/validate/simulation_trace/external_contracts.rs index 28f87e31..8e158578 100644 --- a/crates/uopool/src/validate/simulation_trace/external_contracts.rs +++ b/crates/uopool/src/validate/simulation_trace/external_contracts.rs @@ -16,15 +16,15 @@ use silius_primitives::{ pub struct ExternalContracts; #[async_trait::async_trait] -impl SimulationTraceCheck for ExternalContracts +impl SimulationTraceCheck for ExternalContracts where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { async fn check_user_operation( &self, uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { for call_info in helper.js_trace.calls_from_entry_point.iter() { let level = SELECTORS_INDICES diff --git a/crates/uopool/src/validate/simulation_trace/gas.rs b/crates/uopool/src/validate/simulation_trace/gas.rs index 1861f3c2..864b9419 100644 --- a/crates/uopool/src/validate/simulation_trace/gas.rs +++ b/crates/uopool/src/validate/simulation_trace/gas.rs @@ -12,10 +12,10 @@ use silius_primitives::{ pub struct Gas; #[async_trait::async_trait] -impl SimulationTraceCheck for Gas +impl SimulationTraceCheck for Gas where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that checks if the user operation runs out of gas /// @@ -28,7 +28,7 @@ where async fn check_user_operation( &self, _uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { for call_info in helper.js_trace.calls_from_entry_point.iter() { if call_info.oog.unwrap_or(false) { diff --git a/crates/uopool/src/validate/simulation_trace/opcodes.rs b/crates/uopool/src/validate/simulation_trace/opcodes.rs index ebf1da83..d783753a 100644 --- a/crates/uopool/src/validate/simulation_trace/opcodes.rs +++ b/crates/uopool/src/validate/simulation_trace/opcodes.rs @@ -14,10 +14,10 @@ use silius_primitives::{ pub struct Opcodes; #[async_trait::async_trait] -impl SimulationTraceCheck for Opcodes +impl SimulationTraceCheck for Opcodes where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that checks the use of forbidden opcodes /// @@ -30,7 +30,7 @@ where async fn check_user_operation( &self, _uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { for call_info in helper.js_trace.calls_from_entry_point.iter() { let level = SELECTORS_INDICES diff --git a/crates/uopool/src/validate/simulation_trace/storage_access.rs b/crates/uopool/src/validate/simulation_trace/storage_access.rs index d9cc3da3..7b344e80 100644 --- a/crates/uopool/src/validate/simulation_trace/storage_access.rs +++ b/crates/uopool/src/validate/simulation_trace/storage_access.rs @@ -97,10 +97,10 @@ impl StorageAccess { } #[async_trait::async_trait] -impl SimulationTraceCheck for StorageAccess +impl SimulationTraceCheck for StorageAccess where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [check_user_operation] method implementation that checks if the user operation access storage other than the one associated with itself. /// @@ -113,7 +113,7 @@ where async fn check_user_operation( &self, uo: &UserOperation, - helper: &mut SimulationTraceHelper, + helper: &mut SimulationTraceHelper, ) -> Result<(), SimulationCheckError> { if helper.stake_info.is_none() { helper.stake_info = Some(extract_stake_info(uo, helper.simulate_validation_result)); diff --git a/crates/uopool/src/validate/validator.rs b/crates/uopool/src/validate/validator.rs index 4893eb02..352c183f 100644 --- a/crates/uopool/src/validate/validator.rs +++ b/crates/uopool/src/validate/validator.rs @@ -33,29 +33,31 @@ use silius_primitives::{ reputation::ReputationEntry, simulation::SimulationCheckError, uopool::ValidationError, Chain, UserOperation, }; +use std::fmt::{Debug, Display}; /// Standard implementation of [UserOperationValidator](UserOperationValidator). -pub struct StandardUserOperationValidator +pub struct StandardUserOperationValidator where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, { /// The [EntryPoint](EntryPoint) object. entry_point: EntryPoint, /// A [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID. chain: Chain, /// An array of [SanityChecks](SanityCheck). - sanity_checks: Vec>>, + sanity_checks: Vec>>, /// An array of [SimulationCheck](SimulationCheck). simulation_checks: Vec>, /// An array of [SimulationTraceChecks](SimulationTraceCheck). - simulation_trace_checks: Vec>>, + simulation_trace_checks: Vec>>, } -impl StandardUserOperationValidator +impl StandardUserOperationValidator where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { /// Creates a new [StandardUserOperationValidator](StandardUserOperationValidator). /// @@ -219,7 +221,10 @@ where /// /// # Returns /// A reference to [self](StandardUserOperationValidator). - pub fn with_sanity_check(mut self, sanity_check: impl SanityCheck + 'static) -> Self { + pub fn with_sanity_check( + mut self, + sanity_check: impl SanityCheck + 'static, + ) -> Self { self.sanity_checks.push(Box::new(sanity_check)); self } @@ -241,7 +246,7 @@ where pub fn with_simulation_trace_check( mut self, - simulation_trace_check: impl SimulationTraceCheck + 'static, + simulation_trace_check: impl SimulationTraceCheck + 'static, ) -> Self { self.simulation_trace_checks .push(Box::new(simulation_trace_check)); @@ -250,11 +255,12 @@ where } #[async_trait::async_trait] -impl UserOperationValidator - for StandardUserOperationValidator +impl UserOperationValidator + for StandardUserOperationValidator where - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug + Display, { /// Validates a [UserOperation](UserOperation) via the [simulate_validation](crate::entry_point::EntryPoint::simulate_validation) method of the [entry_point](crate::entry_point::EntryPoint). /// The function also optionally performs sanity checks and simulation checks if the [UserOperationValidatorMode](UserOperationValidatorMode) contains the respective flags. @@ -270,8 +276,8 @@ where async fn validate_user_operation( &self, uo: &UserOperation, - mempool: &MempoolBox, - reputation: &ReputationBox, R>, + mempool: &MempoolBox, + reputation: &ReputationBox, R, E>, mode: EnumSet, ) -> Result { let mut out: UserOperationValidationOutcome = Default::default(); diff --git a/examples/simple_account/create.rs b/examples/simple_account/create.rs index 262e5c5b..1a1c4f6d 100644 --- a/examples/simple_account/create.rs +++ b/examples/simple_account/create.rs @@ -1,5 +1,3 @@ -use std::{env, sync::Arc, time::Duration}; - use ethers::{ prelude::{MiddlewareBuilder, SignerMiddleware}, providers::{Http, Middleware, Provider}, @@ -12,6 +10,7 @@ use silius_primitives::consts::entry_point::ADDRESS; use silius_primitives::UserOperation; use silius_primitives::Wallet as UoWallet; use silius_tests::common::gen::SimpleAccountFactory; +use std::{env, sync::Arc, time::Duration}; // stackup simple account factory const SIMPLE_ACCOUNT_FACTORY: &str = "0x9406Cc6185a346906296840746125a0E44976454"; diff --git a/examples/simple_account/deposit.rs b/examples/simple_account/deposit.rs index 9af0ac88..c22276ec 100644 --- a/examples/simple_account/deposit.rs +++ b/examples/simple_account/deposit.rs @@ -1,5 +1,3 @@ -use std::{env, sync::Arc, time::Duration}; - use ethers::{ prelude::{gas_oracle::ProviderOracle, MiddlewareBuilder, SignerMiddleware}, providers::{Http, Middleware, Provider}, @@ -10,6 +8,7 @@ use ethers::{ use silius_contracts::entry_point::EntryPointAPI; use silius_primitives::consts::entry_point::ADDRESS; use silius_tests::common::gen::SimpleAccountFactory; +use std::{env, sync::Arc, time::Duration}; // stackup simple account factory const SIMPLE_ACCOUNT_FACTORY: &str = "0x9406Cc6185a346906296840746125a0E44976454"; diff --git a/examples/simple_account/transfer.rs b/examples/simple_account/transfer.rs index aed1445f..841f0982 100644 --- a/examples/simple_account/transfer.rs +++ b/examples/simple_account/transfer.rs @@ -1,5 +1,3 @@ -use std::{env, str::FromStr, sync::Arc, time::Duration}; - use ethers::{ prelude::{MiddlewareBuilder, SignerMiddleware}, providers::{Http, Middleware, Provider}, @@ -13,6 +11,7 @@ use silius_primitives::consts::entry_point::ADDRESS; use silius_primitives::UserOperation; use silius_primitives::Wallet as UoWallet; use silius_tests::common::gen::SimpleAccountFactory; +use std::{env, str::FromStr, sync::Arc, time::Duration}; // stackup simple account factory const SIMPLE_ACCOUNT_FACTORY: &str = "0x9406Cc6185a346906296840746125a0E44976454"; diff --git a/tests/src/simulation_tests.rs b/tests/src/simulation_tests.rs index 258bfb88..23927cfd 100644 --- a/tests/src/simulation_tests.rs +++ b/tests/src/simulation_tests.rs @@ -47,17 +47,19 @@ use silius_uopool::{ UoPool, VecCh, VecUo, }; use std::collections::HashMap; +use std::fmt::Debug; use std::ops::Deref; use std::sync::Arc; const MAX_UOS_PER_UNSTAKED_SENDER: usize = 4; const GAS_INCREASE_PERC: u64 = 10; -struct TestContext +struct TestContext where - V: UserOperationValidator + 'static, - P: Mempool + Send + Sync, - R: Reputation, Error = anyhow::Error> + Send + Sync, + V: UserOperationValidator + 'static, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, + E: Debug, { pub client: Arc, pub _geth: GethInstance, @@ -67,14 +69,15 @@ where pub storage_factory: DeployedContract>, pub _rules_factory: DeployedContract>, pub storage_account: DeployedContract>, - pub uopool: UoPool, + pub uopool: UoPool, } type Context = TestContext< ClientType, - StandardUserOperationValidator, MemoryMempool, MemoryReputation>, + StandardUserOperationValidator, MemoryMempool, MemoryReputation, anyhow::Error>, MemoryMempool, MemoryReputation, + anyhow::Error, >; async fn setup() -> anyhow::Result { @@ -147,9 +150,15 @@ async fn setup() -> anyhow::Result { let pool = UoPool::< ClientType, - StandardUserOperationValidator, MemoryMempool, MemoryReputation>, + StandardUserOperationValidator< + Provider, + MemoryMempool, + MemoryReputation, + anyhow::Error, + >, MemoryMempool, MemoryReputation, + anyhow::Error, >::new( entry_point, validator,