Skip to content

Commit

Permalink
doc: rpc crate Rustdoc comments
Browse files Browse the repository at this point in the history
  • Loading branch information
da-bao-jian committed Aug 7, 2023
1 parent efa98ef commit f74efe3
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 0 deletions.
1 change: 1 addition & 0 deletions crates/primitives/src/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! A `Wallet` is a wrapper around an ethers wallet with an optional field for Flashbots bundle identifier
use crate::UserOperation;
use ethers::{
prelude::{k256::ecdsa::SigningKey, rand},
Expand Down
31 changes: 31 additions & 0 deletions crates/rpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Silius RPC

Silius RPC crate provides an interface for handling RPC methods according to the [ERC-4337 specs](https://eips.ethereum.org/EIPS/eip-4337#rpc-methods-eth-namespace).

## Supported RPC Methods
### `eth` name space
* `eth_sendUserOperation`
* submits a UserOperation to the client's [UserOperation alternative mempools](https://eips.ethereum.org/EIPS/eip-4337#alternative-mempools). The client must validate the UserOperation, and return a result accordingly.
* `eth_estimateUserOperationGas`
* estimates the gas values for a UserOperation. Given UserOperation optionally without gas limits and gas prices, return the needed gas limits. The signature field is ignored by the wallet, so that the operation will not require user’s approval.
* `eth_getUserOperationReceipt`
* returns a UserOperation receipt based on a hash (`userOpHash`) returned by `eth_sendUserOperation`.
* `eth_supportedEntryPoints`
* returns an array of the `entryPoint` addresses supported by the client.
* `eth_getUserOperationByHash`
* returns a UserOperation based on a hash (`userOpHash`) returned by `eth_sendUserOperation`.
* `eth_chainId`
* returns [EIP-155](https://eips.ethereum.org/EIPS/eip-155) Chain ID.
### `debug` name space
* `debug_clearState`
* clears the bundler's [alternative mempool](https://eips.ethereum.org/EIPS/eip-4337#alternative-mempools) and reputation data of paymasters/accounts/factories/aggregators.
* `debug_dumpMempool`
* dumps the current UserOperations mempool.
* `debug_setReputation`
* sets reputation of given addresses.
* `debug_dumpReputation`
* returns the reputation data of all observed addresses.
* `debug_setBundlingMode`
* sets the bundling mode. After setting mode to `manual`, an explicit call to `debug_sendBundleNow` is required to send a bundle.
* `debug_sendBundleNow`
* forces the bundler to build and execute a bundle from the mempool as [`handleOps()`](https://github.com/eth-infinitism/account-abstraction/blob/12be13e2e97b763e1ef294602b3f2072bc301443/contracts/core/EntryPoint.sol#L92) transaction.
43 changes: 43 additions & 0 deletions crates/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ use silius_primitives::{
};
use tonic::Request;

/// DebugApiServerImpl implements the ERC-4337 `debug` namespace rpc methods trait [DebugApiServer](DebugApiServer).
pub struct DebugApiServerImpl {
pub uopool_grpc_client: UoPoolClient<tonic::transport::Channel>,
pub bundler_grpc_client: BundlerClient<tonic::transport::Channel>,
}

#[async_trait]
impl DebugApiServer for DebugApiServerImpl {
/// Clears the bundler mempool
///
///
/// # Returns
/// * `RpcResult<()>` - None if no error
async fn clear_state(&self) -> RpcResult<()> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -33,6 +39,14 @@ impl DebugApiServer for DebugApiServerImpl {
Ok(())
}

/// Sending an [GetAllRequest](GetAllRequest) to the UoPool gRPC server
/// to get all of the [UserOperation](UserOperation) in the mempool.
///
/// # Arguments
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<Vec<UserOperation>>` - An array of [UserOperation](UserOperation)
async fn dump_mempool(&self, ep: Address) -> RpcResult<Vec<UserOperation>> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -51,6 +65,15 @@ impl DebugApiServer for DebugApiServerImpl {
Ok(uos)
}

/// Set the reputations for the given array of [ReputationEntry](ReputationEntry)
/// and send it to the UoPool gRPC service through the [SetReputationRequest](SetReputationRequest).
///
/// # Arguments
/// * `reputation_entries: Vec<ReputationEntry>` - The [ReputationEntry](ReputationEntry) to be set.
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<()>` - None if no error
async fn set_reputation(&self, entries: Vec<ReputationEntry>, ep: Address) -> RpcResult<()> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -76,6 +99,13 @@ impl DebugApiServer for DebugApiServerImpl {
))
}

/// Return the all of [ReputationEntries](ReputationEntry) in the mempool via the [GetAllReputationRequest](GetAllReputationRequest).
///
/// # Arguments
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<Vec<ReputationEntry>>` - An array of [ReputationEntries](ReputationEntry)
async fn dump_reputation(&self, ep: Address) -> RpcResult<Vec<ReputationEntry>> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -92,6 +122,13 @@ impl DebugApiServer for DebugApiServerImpl {
Ok(res.rep.iter().map(|re| re.clone().into()).collect())
}

/// Set the bundling mode.
///
/// # Arguments
/// * `mode: BundlerMode` - The [BundlingMode](BundlingMode) to be set.
///
/// # Returns
/// * `RpcResult<()>` - None if no error
async fn set_bundling_mode(&self, mode: BundlerMode) -> RpcResult<()> {
let mut bundler_grpc_client = self.bundler_grpc_client.clone();

Expand All @@ -106,6 +143,12 @@ impl DebugApiServer for DebugApiServerImpl {
}
}

/// Immediately send the current bundle of user operations.
/// This is useful for testing or in situations where waiting for the next scheduled bundle is not desirable.
///
///
/// # Returns
/// * `RpcResult<H256>` - The hash of the bundle that was sent.
async fn send_bundle_now(&self) -> RpcResult<H256> {
let mut bundler_grpc_client = self.bundler_grpc_client.clone();

Expand Down
41 changes: 41 additions & 0 deletions crates/rpc/src/debug_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,68 @@ use ethers::types::{Address, H256};
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use silius_primitives::{reputation::ReputationEntry, BundlerMode, UserOperation};

/// The ERC-4337 `debug` namespace RPC methods trait
#[rpc(server, namespace = "debug_bundler")]
pub trait DebugApi {
/// Clears the bundler mempool
///
///
/// # Returns
/// * `RpcResult<()>` - None
#[method(name = "clearState")]
async fn clear_state(&self) -> RpcResult<()>;

/// Get all [UserOperations](UserOperation) of the mempool
///
/// # Arguments
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<Vec<UserOperation>>` - A vector of [UserOperations](UserOperation) returned
#[method(name = "dumpMempool")]
async fn dump_mempool(&self, entry_point: Address) -> RpcResult<Vec<UserOperation>>;

/// Set the reputations for the given array of [ReputationEntry](ReputationEntry)
///
/// # Arguments
/// * `reputation_entries: Vec<ReputationEntry>` - The [ReputationEntry](ReputationEntry) to be set.
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<()>` - None
#[method(name = "setReputation")]
async fn set_reputation(
&self,
reputation_entries: Vec<ReputationEntry>,
entry_point: Address,
) -> RpcResult<()>;

/// Return the all of [ReputationEntries](ReputationEntry) in the mempool.
///
/// # Arguments
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<Vec<ReputationEntry>>` - An array of [ReputationEntry](ReputationEntry)
#[method(name = "dumpReputation")]
async fn dump_reputation(&self, entry_point: Address) -> RpcResult<Vec<ReputationEntry>>;

/// Set the bundling mode.
///
/// # Arguments
/// * `mode: BundlerMode` - The [BundlingMode](BundlingMode) to be set.
///
/// # Returns
/// * `RpcResult<()>` - None
#[method(name = "setBundlingMode")]
async fn set_bundling_mode(&self, mode: BundlerMode) -> RpcResult<()>;

/// Immediately send the current bundle of user operations.
/// This is useful for testing or in situations where waiting for the next scheduled bundle is not desirable.
///
///
/// # Returns
/// * `RpcResult<H256>` - The hash of the bundle that was sent.
#[method(name = "sendBundleNow")]
async fn send_bundle_now(&self) -> RpcResult<H256>;
}
8 changes: 8 additions & 0 deletions crates/rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ use silius_primitives::{
uopool::ValidationError,
};

/// A wrapper for the [ErrorObjectOwned](ErrorObjectOwned) type.
pub struct JsonRpcError(pub ErrorObjectOwned);

impl From<JsonRpcError> for ErrorObjectOwned {
/// Convert a [JsonRpcError](JsonRpcError) to a [ErrorObjectOwned](ErrorObjectOwned).
fn from(err: JsonRpcError) -> Self {
err.0
}
}

impl From<SanityCheckError> for JsonRpcError {
/// Convert a [SanityCheckError](SanityCheckError) to a [JsonRpcError](JsonRpcError).
fn from(err: SanityCheckError) -> Self {
JsonRpcError(
match err {
Expand Down Expand Up @@ -139,6 +142,7 @@ impl From<SanityCheckError> for JsonRpcError {
}

impl From<SimulationCheckError> for JsonRpcError {
/// Convert a [SimulationCheckError](SimulationCheckError) to a [JsonRpcError](JsonRpcError).
fn from(err: SimulationCheckError) -> Self {
JsonRpcError(match err {
SimulationCheckError::Signature {} => ErrorObject::owned(
Expand Down Expand Up @@ -204,6 +208,7 @@ impl From<SimulationCheckError> for JsonRpcError {
}

impl From<ReputationError> for JsonRpcError {
/// Convert a [ReputationError](ReputationError) to a [JsonRpcError](JsonRpcError).
fn from(err: ReputationError) -> Self {
JsonRpcError(
match err {
Expand Down Expand Up @@ -255,6 +260,7 @@ impl From<ReputationError> for JsonRpcError {
}

impl From<ValidationError> for JsonRpcError {
/// Convert a [ValidationError](ValidationError) to a [JsonRpcError](JsonRpcError).
fn from(err: ValidationError) -> Self {
match err {
ValidationError::Sanity(err) => err.into(),
Expand All @@ -264,6 +270,7 @@ impl From<ValidationError> for JsonRpcError {
}

impl From<tonic::Status> for JsonRpcError {
/// Convert a tonic status to a [JsonRpcError](JsonRpcError).
fn from(s: tonic::Status) -> Self {
JsonRpcError(ErrorObject::owned(
ErrorCode::InternalError.code(),
Expand All @@ -274,6 +281,7 @@ impl From<tonic::Status> for JsonRpcError {
}

impl From<serde_json::Error> for JsonRpcError {
/// Convert a [serde_json error](serde_json::Error) to a [JsonRpcError](JsonRpcError).
fn from(err: serde_json::Error) -> Self {
JsonRpcError(ErrorObject::owned(
ErrorCode::ParseError.code(),
Expand Down
43 changes: 43 additions & 0 deletions crates/rpc/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ use silius_primitives::{
use std::str::FromStr;
use tonic::Request;

/// EthApiServer implements the ERC-4337 `eth` namespace RPC methods trait [EthApiServer](EthApiServer).
pub struct EthApiServerImpl {
/// The [UoPool gRPC client](UoPoolClient).
pub uopool_grpc_client: UoPoolClient<tonic::transport::Channel>,
}

#[async_trait]
impl EthApiServer for EthApiServerImpl {
/// Retrieve the current [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
///
/// # Returns
/// * `RpcResult<U64>` - The chain ID as a U64.
async fn chain_id(&self) -> RpcResult<U64> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -35,6 +41,10 @@ impl EthApiServer for EthApiServerImpl {
return Ok(res.chain_id.into());
}

/// Get the supported entry points for [UserOperations](UserOperation).
///
/// # Returns
/// * `RpcResult<Vec<String>>` - A array of the entry point addresses as strings.
async fn supported_entry_points(&self) -> RpcResult<Vec<String>> {
let mut uopool_grpc_client = self.uopool_grpc_client.clone();

Expand All @@ -51,6 +61,14 @@ impl EthApiServer for EthApiServerImpl {
.collect());
}

/// Send a user operation via the [AddRequest](AddRequest).
///
/// # Arguments
/// * `user_operation: UserOperation` - The user operation to be sent.
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<UserOperationHash>` - The hash of the sent user operation.
async fn send_user_operation(
&self,
uo: UserOperation,
Expand Down Expand Up @@ -81,6 +99,16 @@ impl EthApiServer for EthApiServerImpl {
.0)
}

/// Estimate the gas required for a [UserOperation](UserOperation) via the [EstimateUserOperationGasRequest](EstimateUserOperationGasRequest).
/// This allows you to gauge the computational cost of the operation.
/// See [How ERC-4337 Gas Estimation Works](https://www.alchemy.com/blog/erc-4337-gas-estimation).
///
/// # Arguments
/// * `user_operation: [UserOperationPartial](UserOperationPartial)` - The partial user operation for which to estimate the gas.
/// * `entry_point: Address` - The address of the entry point.
///
/// # Returns
/// * `RpcResult<UserOperationGasEstimation>` - The [UserOperationGasEstimation](UserOperationGasEstimation) for the user operation.
async fn estimate_user_operation_gas(
&self,
uo: UserOperationPartial,
Expand Down Expand Up @@ -111,6 +139,13 @@ impl EthApiServer for EthApiServerImpl {
.0)
}

/// Retrieve the receipt of a [UserOperation](UserOperation).
///
/// # Arguments
/// * `user_operation_hash: String` - The hash of the user operation.
///
/// # Returns
/// * `RpcResult<Option<UserOperationReceipt>>` - The [UserOperationReceipt] of the user operation.
async fn get_user_operation_receipt(
&self,
uo_hash: String,
Expand Down Expand Up @@ -164,6 +199,14 @@ impl EthApiServer for EthApiServerImpl {
}
}

/// Retrieve a [UserOperation](UserOperation) by its hash via [UserOperationHashRequest](UserOperationHashRequest).
/// The hash serves as a unique identifier for the [UserOperation](UserOperation).
///
/// # Arguments
/// * `user_operation_hash: String` - The hash of a [UserOperation](UserOperation).
///
/// # Returns
/// * `RpcResult<Option<UserOperationByHash>>` - The [UserOperation](UserOperation) associated with the hash, or None if it does not exist.
async fn get_user_operation_by_hash(
&self,
uo_hash: String,
Expand Down
Loading

0 comments on commit f74efe3

Please sign in to comment.