Skip to content

Commit

Permalink
feat(trait): use ProviderLike and EntryPointLike
Browse files Browse the repository at this point in the history
  • Loading branch information
0xfourzerofour committed Aug 24, 2023
1 parent b6fc431 commit e146839
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 123 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
run: sudo apt-get install -y protobuf-compiler
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.71.0
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
Expand All @@ -35,6 +37,7 @@ jobs:
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
toolchain: 1.71.0
- name: Install toolchain (nightly)
run: rustup toolchain add nightly --component rustfmt --profile minimal
- uses: Swatinem/rust-cache@v2
Expand Down
20 changes: 10 additions & 10 deletions src/builder/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use std::{
};

use anyhow::{bail, Context};
use ethers::{
providers::{Http, Provider, RetryClient},
types::{transaction::eip2718::TypedTransaction, Address, H256, U256},
};
use ethers::types::{transaction::eip2718::TypedTransaction, Address, H256, U256};
use tokio::{join, sync::broadcast, time};
use tonic::{async_trait, transport::Channel, Request, Response, Status};
use tracing::{debug, error, info, trace, warn};
Expand All @@ -36,7 +33,7 @@ use crate::{
self, op_pool_client::OpPoolClient, RemoveEntitiesRequest, RemoveOpsRequest,
},
},
types::{Entity, EntryPointLike, ExpectedStorage, UserOperation},
types::{Entity, EntryPointLike, ExpectedStorage, ProviderLike, UserOperation},
},
};

Expand All @@ -50,9 +47,10 @@ pub struct Settings {
}

#[derive(Debug)]
pub struct BuilderImpl<P, E, T>
pub struct BuilderImpl<P, PL, E, T>
where
P: BundleProposer,
PL: ProviderLike,
E: EntryPointLike,
T: TransactionTracker,
{
Expand All @@ -65,7 +63,7 @@ where
entry_point: E,
transaction_tracker: T,
// TODO: Figure out what we really want to do for detecting new blocks.
provider: Arc<Provider<RetryClient<Http>>>,
provider: Arc<PL>,
settings: Settings,
event_sender: broadcast::Sender<WithEntryPoint<BuilderEvent>>,
}
Expand Down Expand Up @@ -93,9 +91,10 @@ enum SendBundleResult {
Error(anyhow::Error),
}

impl<P, E, T> BuilderImpl<P, E, T>
impl<P, PL, E, T> BuilderImpl<P, PL, E, T>
where
P: BundleProposer,
PL: ProviderLike,
E: EntryPointLike,
T: TransactionTracker,
{
Expand All @@ -108,7 +107,7 @@ where
proposer: P,
entry_point: E,
transaction_tracker: T,
provider: Arc<Provider<RetryClient<Http>>>,
provider: Arc<PL>,
settings: Settings,
event_sender: broadcast::Sender<WithEntryPoint<BuilderEvent>>,
) -> Self {
Expand Down Expand Up @@ -442,9 +441,10 @@ where
}

#[async_trait]
impl<P, E, T> Builder for Arc<BuilderImpl<P, E, T>>
impl<P, PL, E, T> Builder for Arc<BuilderImpl<P, PL, E, T>>
where
P: BundleProposer,
PL: ProviderLike,
E: EntryPointLike,
T: TransactionTracker,
{
Expand Down
6 changes: 4 additions & 2 deletions src/builder/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,15 @@ impl Task for BuilderTask {
};
let op_pool =
Self::connect_client_with_shutdown(&self.args.pool_url, shutdown_token.clone()).await?;

let entry_point = IEntryPoint::new(self.args.entry_point_address, Arc::clone(&provider));
let simulator = SimulatorImpl::new(
Arc::clone(&provider),
self.args.entry_point_address,
entry_point.clone(),
self.args.sim_settings,
self.args.mempool_configs.clone(),
);
let entry_point = IEntryPoint::new(self.args.entry_point_address, Arc::clone(&provider));

let proposer = BundleProposerImpl::new(
op_pool.clone(),
simulator,
Expand Down
57 changes: 19 additions & 38 deletions src/common/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ use std::{
sync::Arc,
};

use anyhow::Context;
use ethers::{
abi::AbiDecode,
contract::ContractError,
providers::{JsonRpcClient, Provider},
types::{Address, BlockId, Bytes, Opcode, H256, U256},
};
use indexmap::IndexSet;
Expand All @@ -18,20 +15,18 @@ use mockall::automock;
use tonic::async_trait;

use super::{
contracts::i_entry_point::FailedOp,
mempool::{match_mempools, MempoolMatchResult},
tracer::parse_combined_tracer_str,
types::EntryPointLike,
};
use crate::common::{
contracts::{
i_aggregator::IAggregator,
i_entry_point::{FailedOp, IEntryPoint},
},
eth,
mempool::MempoolConfig,
tracer,
tracer::{AssociatedSlotsByAddress, StorageAccess, TracerOutput},
types::{
Entity, EntityType, ExpectedStorage, ProviderLike, StakeInfo, UserOperation,
AggregatorOut, Entity, EntityType, ExpectedStorage, ProviderLike, StakeInfo, UserOperation,
ValidTimeRange, ValidationOutput, ValidationReturnInfo, ViolationError,
},
};
Expand Down Expand Up @@ -82,24 +77,24 @@ pub trait Simulator: Send + Sync + 'static {
}

#[derive(Debug)]
pub struct SimulatorImpl<T: JsonRpcClient> {
provider: Arc<Provider<T>>,
entry_point: IEntryPoint<Provider<T>>,
pub struct SimulatorImpl<P: ProviderLike, E: EntryPointLike> {
provider: Arc<P>,
entry_point: E,
sim_settings: Settings,
mempool_configs: HashMap<H256, MempoolConfig>,
}

impl<T> SimulatorImpl<T>
impl<P, E> SimulatorImpl<P, E>
where
T: JsonRpcClient + 'static,
P: ProviderLike,
E: EntryPointLike,
{
pub fn new(
provider: Arc<Provider<T>>,
entry_point_address: Address,
provider: Arc<P>,
entry_point: E,
sim_settings: Settings,
mempool_configs: HashMap<H256, MempoolConfig>,
) -> Self {
let entry_point = IEntryPoint::new(entry_point_address, provider.clone());
Self {
provider,
entry_point,
Expand All @@ -124,6 +119,7 @@ where
let paymaster_address = op.paymaster();
let tracer_out = tracer::trace_simulate_validation(
&self.entry_point,
Arc::clone(&self.provider),
op.clone(),
block_id,
self.sim_settings.max_verification_gas,
Expand Down Expand Up @@ -193,20 +189,11 @@ where
let Some(aggregator_address) = aggregator_address else {
return Ok(AggregatorOut::NotNeeded);
};
let aggregator = IAggregator::new(aggregator_address, Arc::clone(&self.provider));
match aggregator
.validate_user_op_signature(op)
.gas(gas_cap)
.call()

self.provider
.clone()
.validate_user_op_signature(aggregator_address, op, gas_cap)
.await
{
Ok(sig) => Ok(AggregatorOut::SuccessWithInfo(AggregatorSimOut {
address: aggregator_address,
signature: sig,
})),
Err(ContractError::Revert(_)) => Ok(AggregatorOut::ValidationReverted),
Err(error) => Err(error).context("should call aggregator to validate signature")?,
}
}

// Parse the output from tracing and return a list of violations.
Expand Down Expand Up @@ -406,9 +393,10 @@ where
}

#[async_trait]
impl<T> Simulator for SimulatorImpl<T>
impl<P, E> Simulator for SimulatorImpl<P, E>
where
T: JsonRpcClient + 'static,
P: ProviderLike,
E: EntryPointLike,
{
async fn simulate_validation(
&self,
Expand Down Expand Up @@ -558,13 +546,6 @@ struct ValidationContext {
accessed_addresses: HashSet<Address>,
}

#[derive(Debug)]
enum AggregatorOut {
NotNeeded,
SuccessWithInfo(AggregatorSimOut),
ValidationReverted,
}

#[derive(Clone, Copy, Debug)]
struct EntityInfo {
pub address: Address,
Expand Down
38 changes: 15 additions & 23 deletions src/common/tracer.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
use std::{
collections::{BTreeSet, HashMap},
fmt::Debug,
sync::Arc,
};

use anyhow::Context;
use ethers::{
providers::{JsonRpcClient, Middleware, Provider},
types::{transaction::eip2718::TypedTransaction, Address, BlockId, U256},
};
use ethers::types::{transaction::eip2718::TypedTransaction, Address, BlockId, U256};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::common::{
use super::{
context::LogWithContext,
contracts::i_entry_point::IEntryPoint,
types::{ExpectedStorage, UserOperation},
types::{EntryPointLike, ProviderLike},
};
use crate::common::types::{ExpectedStorage, UserOperation};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -67,34 +65,28 @@ impl AssociatedSlotsByAddress {

/// Runs the bundler's custom tracer on the entry point's `simulateValidation`
/// method for the provided user operation.
pub async fn trace_simulate_validation(
entry_point: &IEntryPoint<impl Middleware>,
pub async fn trace_simulate_validation<E: EntryPointLike, P: ProviderLike>(
entry_point: &E,
provider: Arc<P>,
op: UserOperation,
block_id: BlockId,
max_validation_gas: u64,
) -> anyhow::Result<TracerOutput> {
let pvg = op.pre_verification_gas;
let tx = entry_point
.simulate_validation(op)
.gas(U256::from(max_validation_gas) + pvg)
.tx;
trace_call(
entry_point.client().provider(),
tx,
block_id,
validation_tracer_js(),
)
.await
.simulate_validation(op, max_validation_gas)
.await?;

trace_call(provider, tx, block_id, validation_tracer_js()).await
}

async fn trace_call<T>(
provider: &Provider<impl JsonRpcClient>,
async fn trace_call<T, P: ProviderLike>(
provider: Arc<P>,
tx: TypedTransaction,
block_id: BlockId,
tracer_code: &str,
) -> anyhow::Result<T>
where
T: Debug + DeserializeOwned + Serialize + Send,
T: Debug + DeserializeOwned + Serialize + Send + 'static,
{
let out = provider
.request(
Expand Down
21 changes: 21 additions & 0 deletions src/common/types/entry_point_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ pub trait EntryPointLike: Send + Sync + 'static {

async fn get_deposit(&self, address: Address, block_hash: H256) -> anyhow::Result<U256>;

async fn simulate_validation(
&self,
user_op: UserOperation,
max_validation_gas: u64,
) -> anyhow::Result<TypedTransaction>;

async fn call_spoofed_simulate_op(
&self,
op: UserOperation,
Expand Down Expand Up @@ -80,6 +86,21 @@ where
self.deref().address()
}

async fn simulate_validation(
&self,
user_op: UserOperation,
max_validation_gas: u64,
) -> anyhow::Result<TypedTransaction> {
let pvg = user_op.pre_verification_gas;

let tx = self
.simulate_validation(user_op)
.gas(U256::from(max_validation_gas) + pvg)
.tx;

Ok(tx)
}

async fn call_handle_ops(
&self,
ops_per_aggregator: Vec<UserOpsPerAggregator>,
Expand Down
Loading

0 comments on commit e146839

Please sign in to comment.