Skip to content

Commit

Permalink
Merge pull request #43 from Vid201/feat/reputation
Browse files Browse the repository at this point in the history
Reputation
  • Loading branch information
Vid201 authored Feb 1, 2023
2 parents ae1e715 + 93d95f4 commit 0ad243a
Show file tree
Hide file tree
Showing 18 changed files with 979 additions and 52 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ jobs:
with:
toolchain: stable
components: rustfmt, clippy
- name: Setup third party dependencies
- name: Setup third-party dependencies
run: |
make fetch-thirdparty
make setup-thirdparty
- name: Install Geth and solc
run: |
sudo add-apt-repository ppa:ethereum/ethereum
Expand Down
16 changes: 7 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
build:
make fetch-thirdparty
cd thirdparty/account-abstraction && yarn install && yarn compile && cd ../..
cargo build

run-bundler:
cargo run -- --mnemonic-file ${HOME}/.aa-bundler/0x129D197b2a989C6798601A49D89a4AEC822A17a3 --beneficiary 0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990 --gas-factor 600 --min-balance 1 --entry-points 0x0000000000000000000000000000000000000000 --chain-id 5 --helper 0x0000000000000000000000000000000000000000

run-bundler-uopool:
cargo run --bin bundler-uopool -- --entry-points 0x0000000000000000000000000000000000000000 --chain-id 5
cargo run --bin bundler-uopool -- --entry-points 0x0000000000000000000000000000000000000000 --chain-id 5 --min-stake 1 --min-unstake-delay 0

run-bundler-rpc:
cargo run --bin bundler-rpc

run-create-wallet:
cargo run --bin create-wallet -- --output-path ${HOME}/.aa-bundler

fetch-thirdparty:
git submodule update --init

test:
setup-thirdparty:
git submodule update --init
cd thirdparty/account-abstraction && yarn install && yarn compile && cd ../..
cd thirdparty/bundler && yarn install && yarn preprocess && cd ../..

test:
cargo test

format:
cargo fmt --all

lint:
cd thirdparty/bundler && yarn install && yarn preprocess && cd ../..
cargo fmt --all -- --check
cargo clippy -- -D warnings -A clippy::derive_partial_eq_without_eq -D clippy::unwrap_used
cargo clippy -- -D warnings -A clippy::derive_partial_eq_without_eq -D clippy::unwrap_used -D clippy::uninlined_format_args

clean:
cd thirdparty/account-abstraction && yarn clean && cd ../..
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ For more information: https://hackmd.io/@Vid201/aa-bundler-rust

## How to run?

Set up third-party dependencies (EIP-4337 smart contracts and bundler tests):

```bash
make setup-thirdparty
```

Create wallet for bundler:

```bash
Expand All @@ -32,7 +38,7 @@ cargo run -- --mnemonic-file ${HOME}/.aa-bundler/0x129D197b2a989C6798601A49D89a4
Run only user operation pool:

```bash
cargo run --bin bundler-uopool -- --entry-points 0x0000000000000000000000000000000000000000 --chain-id 5
cargo run --bin bundler-uopool -- --entry-points 0x0000000000000000000000000000000000000000 --chain-id 5 --min-stake 1 --min-unstake-delay 0
```

Run only JSON-RPC API:
Expand Down
13 changes: 12 additions & 1 deletion bin/bundler-rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use jsonrpsee::{core::server::rpc_module::Methods, server::ServerBuilder, tracin
use std::future::pending;

use aa_bundler::{
rpc::{eth::EthApiServerImpl, eth_api::EthApiServer},
rpc::{
debug::DebugApiServerImpl, debug_api::DebugApiServer, eth::EthApiServerImpl,
eth_api::EthApiServer,
},
uopool::server::uopool::uo_pool_client::UoPoolClient,
};

Expand Down Expand Up @@ -34,6 +37,14 @@ async fn main() -> Result<()> {
let mut api = Methods::new();
let uopool_grpc_client =
UoPoolClient::connect(format!("http://{}", opt.uopool_grpc_listen_address)).await?;

#[cfg(debug_assertions)]
api.merge(
DebugApiServerImpl {
uopool_grpc_client: uopool_grpc_client.clone(),
}
.into_rpc(),
)?;
api.merge(
EthApiServerImpl {
call_gas_limit: 100_000_000,
Expand Down
12 changes: 11 additions & 1 deletion bin/bundler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use aa_bundler::{
bundler::Bundler,
models::wallet::Wallet,
rpc::{eth::EthApiServerImpl, eth_api::EthApiServer},
rpc::{
debug::DebugApiServerImpl, debug_api::DebugApiServer, eth::EthApiServerImpl,
eth_api::EthApiServer,
},
uopool::server::uopool::uo_pool_client::UoPoolClient,
utils::{parse_address, parse_u256},
};
Expand Down Expand Up @@ -87,6 +90,13 @@ fn main() -> Result<()> {
))
.await?;

#[cfg(debug_assertions)]
api.merge(
DebugApiServerImpl {
uopool_grpc_client: uopool_grpc_client.clone(),
}
.into_rpc(),
)?;
api.merge(
EthApiServerImpl {
call_gas_limit: 100_000_000,
Expand Down
13 changes: 13 additions & 0 deletions src/proto/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,16 @@ message UserOperation {
bytes paymaster_and_data = 10;
bytes signature = 11;
}

enum ReputationStatus {
OK = 0;
THROTTLED = 1;
BANNED = 2;
}

message ReputationEntry {
types.H160 address = 1;
uint64 uo_seen = 2;
uint64 uo_included = 3;
ReputationStatus status = 4;
}
61 changes: 56 additions & 5 deletions src/proto/uopool/uopool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,68 @@ enum RemoveResult {

message RemoveResponse {
RemoveResult result = 1;
string data = 2;
}

message AllRequest {}
enum GetAllResult {
GOT_ALL = 0;
NOT_GOT_ALL = 1;
}

message GetAllRequest {
types.H160 ep = 1;
}

message GetAllResponse {
GetAllResult result = 1;
repeated types.UserOperation uos = 2;
}

enum ClearResult {
CLEARED = 0;
NOT_CLEARED = 1;
}

message ClearRequest {}

message AllResponse {
repeated types.UserOperation uos = 1;
message ClearResponse {
ClearResult result = 1;
}

enum GetAllReputationResult {
GOT_ALL_REPUTATION = 0;
NOT_GOT_ALL_REPUTATION = 1;
}

message GetAllReputationRequest {
types.H160 ep = 1;
}

message GetAllReputationResponse {
GetAllReputationResult result = 1;
repeated types.ReputationEntry res = 2;
}

enum SetReputationResult {
SET_REPUTATION = 0;
NOT_SET_REPUTATION = 1;
}

message SetReputationRequest {
repeated types.ReputationEntry res = 1;
types.H160 ep = 2;
}

message SetReputationResponse {
SetReputationResult result = 1;
}

service UoPool {
rpc Add(AddRequest) returns (AddResponse);
rpc Remove(RemoveRequest) returns (RemoveResponse);
rpc All(AllRequest) returns (AllResponse);

// debug
rpc GetAll(GetAllRequest) returns (GetAllResponse);
rpc Clear(ClearRequest) returns (ClearResponse);
rpc GetAllReputation(GetAllReputationRequest) returns (GetAllReputationResponse);
rpc SetReputation(SetReputationRequest) returns (SetReputationResponse);
}
113 changes: 113 additions & 0 deletions src/rpc/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use super::debug_api::DebugApiServer;
use crate::{
types::{reputation::ReputationEntry, user_operation::UserOperation},
uopool::server::uopool::{
uo_pool_client::UoPoolClient, ClearRequest, ClearResult, GetAllReputationRequest,
GetAllReputationResult, GetAllRequest, GetAllResult, SetReputationRequest,
SetReputationResult,
},
};
use anyhow::format_err;
use async_trait::async_trait;
use ethers::types::Address;
use jsonrpsee::core::RpcResult;

#[cfg(debug_assertions)]
pub struct DebugApiServerImpl {
pub uopool_grpc_client: UoPoolClient<tonic::transport::Channel>,
}

#[cfg(debug_assertions)]
#[async_trait]
impl DebugApiServer for DebugApiServerImpl {
async fn clear_state(&self) -> RpcResult<()> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

let request = tonic::Request::new(ClearRequest {});

let response = uopool_grpc_client
.clear(request)
.await
.map_err(|status| format_err!("GRPC error (uopool): {}", status.message()))?
.into_inner();

if response.result == ClearResult::Cleared as i32 {
return Ok(());
}

Err(jsonrpsee::core::Error::Custom(
"error clearing state".to_string(),
))
}

async fn dump_mempool(&self, entry_point: Address) -> RpcResult<Vec<UserOperation>> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

let request = tonic::Request::new(GetAllRequest {
ep: Some(entry_point.into()),
});

let response = uopool_grpc_client
.get_all(request)
.await
.map_err(|status| format_err!("GRPC error (uopool): {}", status.message()))?
.into_inner();

if response.result == GetAllResult::GotAll as i32 {
return Ok(response.uos.iter().map(|uo| uo.clone().into()).collect());
}

Err(jsonrpsee::core::Error::Custom(
"error getting mempool".to_string(),
))
}

async fn set_reputation(
&self,
reputation_entries: Vec<ReputationEntry>,
entry_point: Address,
) -> RpcResult<()> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

let request = tonic::Request::new(SetReputationRequest {
res: reputation_entries.iter().map(|re| (*re).into()).collect(),
ep: Some(entry_point.into()),
});

let response = uopool_grpc_client
.set_reputation(request)
.await
.map_err(|status| format_err!("GRPC error (uopool): {}", status.message()))?
.into_inner();

if response.result == SetReputationResult::SetReputation as i32 {
return Ok(());
}

Err(jsonrpsee::core::Error::Custom(
"error setting reputation".to_string(),
))
}

async fn dump_reputation(&self, entry_point: Address) -> RpcResult<Vec<ReputationEntry>> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

let request = tonic::Request::new(GetAllReputationRequest {
ep: Some(entry_point.into()),
});

let response = uopool_grpc_client
.get_all_reputation(request)
.await
.map_err(|status| format_err!("GRPC error (uopool): {}", status.message()))?
.into_inner();

if response.result == GetAllReputationResult::GotAllReputation as i32 {
return Ok(response.res.iter().map(|re| re.clone().into()).collect());
}

Err(jsonrpsee::core::Error::Custom(
"error getting reputation".to_string(),
))
}
}
23 changes: 23 additions & 0 deletions src/rpc/debug_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::types::{reputation::ReputationEntry, user_operation::UserOperation};
use ethers::types::Address;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};

#[cfg(debug_assertions)]
#[rpc(server, namespace = "debug_bundler")]
pub trait DebugApi {
#[method(name = "clearState")]
async fn clear_state(&self) -> RpcResult<()>;

#[method(name = "dumpMempool")]
async fn dump_mempool(&self, entry_point: Address) -> RpcResult<Vec<UserOperation>>;

#[method(name = "setReputation")]
async fn set_reputation(
&self,
reputation_entries: Vec<ReputationEntry>,
entry_point: Address,
) -> RpcResult<()>;

#[method(name = "dumpReputation")]
async fn dump_reputation(&self, entry_point: Address) -> RpcResult<Vec<ReputationEntry>>;
}
4 changes: 4 additions & 0 deletions src/rpc/eth_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,24 @@ pub struct EstimateUserOperationGasResponse {
pub trait EthApi {
#[method(name = "chainId")]
async fn chain_id(&self) -> RpcResult<U64>;

#[method(name = "supportedEntryPoints")]
async fn supported_entry_points(&self) -> RpcResult<Vec<Address>>;

#[method(name = "sendUserOperation")]
async fn send_user_operation(
&self,
user_operation: UserOperation,
entry_point: Address,
) -> RpcResult<UserOperationHash>;

#[method(name = "estimateUserOperationGas")]
async fn estimate_user_operation_gas(
&self,
user_operation: UserOperation,
entry_point: Address,
) -> RpcResult<EstimateUserOperationGasResponse>;

#[method(name = "getUserOperationReceipt")]
async fn get_user_operation_receipt(
&self,
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod debug;
pub mod debug_api;
pub mod eth;
pub mod eth_api;
1 change: 1 addition & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod reputation;
pub mod user_operation;
Loading

0 comments on commit 0ad243a

Please sign in to comment.