From e491cf851ba3133d75474bc745d4ce128b48c041 Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Sun, 29 Jan 2023 00:11:40 +0100 Subject: [PATCH] feat: implement debug reputation endpoints --- src/proto/types/types.proto | 13 ++++++++ src/proto/uopool/uopool.proto | 27 ++++++++++++++++ src/rpc/debug.rs | 51 +++++++++++++++++++++++++---- src/rpc/debug_api.rs | 8 +++-- src/uopool/server.rs | 45 ++++++++++++++++++++++++++ src/uopool/services/uopool.rs | 61 ++++++++++++++++++++++++++++------- 6 files changed, 185 insertions(+), 20 deletions(-) diff --git a/src/proto/types/types.proto b/src/proto/types/types.proto index 6d1b2bbd..4b8a0b12 100644 --- a/src/proto/types/types.proto +++ b/src/proto/types/types.proto @@ -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; +} \ No newline at end of file diff --git a/src/proto/uopool/uopool.proto b/src/proto/uopool/uopool.proto index 7540c5ec..26b3d18b 100644 --- a/src/proto/uopool/uopool.proto +++ b/src/proto/uopool/uopool.proto @@ -57,6 +57,31 @@ message ClearResponse { ClearResult result = 1; } +enum GetAllReputationResult { + GOT_ALL_REPUTATION = 0; + NOT_GOT_ALL_REPUTATION = 1; +} + +message GetAllReputationRequest {} + +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; +} + +message SetReputationResponse { + SetReputationResult result = 1; +} + service UoPool { rpc Add(AddRequest) returns (AddResponse); rpc Remove(RemoveRequest) returns (RemoveResponse); @@ -64,4 +89,6 @@ service UoPool { // debug rpc GetAll(GetAllRequest) returns (GetAllResponse); rpc Clear(ClearRequest) returns (ClearResponse); + rpc GetAllReputation(GetAllReputationRequest) returns (GetAllReputationResponse); + rpc SetReputation(SetReputationRequest) returns (SetReputationResponse); } diff --git a/src/rpc/debug.rs b/src/rpc/debug.rs index 50befbca..e3b22752 100644 --- a/src/rpc/debug.rs +++ b/src/rpc/debug.rs @@ -2,8 +2,9 @@ use super::debug_api::DebugApiServer; use crate::{ types::{reputation::ReputationEntry, user_operation::UserOperation}, uopool::server::uopool::{ - uo_pool_client::UoPoolClient, ClearRequest, ClearResult, GetAllRequest, - GetAllResult, + uo_pool_client::UoPoolClient, ClearRequest, ClearResult, GetAllReputationRequest, + GetAllReputationResult, GetAllRequest, GetAllResult, SetReputationRequest, + SetReputationResult, }, }; use anyhow::format_err; @@ -61,11 +62,49 @@ impl DebugApiServer for DebugApiServerImpl { )) } - async fn set_reputation(&self, _reputation_entries: Vec) -> RpcResult<()> { - todo!() + async fn set_reputation( + &self, + reputation_entries: Vec, + _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(), + }); + + 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) -> RpcResult> { - todo!() + async fn dump_reputation(&self, _entry_point: Address) -> RpcResult> { + let mut uopool_grpc_client = self.uopool_grpc_client.clone(); + + let request = tonic::Request::new(GetAllReputationRequest {}); + + 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(), + )) } } diff --git a/src/rpc/debug_api.rs b/src/rpc/debug_api.rs index 6370ac17..976c7092 100644 --- a/src/rpc/debug_api.rs +++ b/src/rpc/debug_api.rs @@ -12,8 +12,12 @@ pub trait DebugApi { async fn dump_mempool(&self, entry_point: Address) -> RpcResult>; #[method(name = "setReputation")] - async fn set_reputation(&self, reputation_entries: Vec) -> RpcResult<()>; + async fn set_reputation( + &self, + reputation_entries: Vec, + entry_point: Address, + ) -> RpcResult<()>; #[method(name = "dumpReputation")] - async fn dump_reputation(&self) -> RpcResult>; + async fn dump_reputation(&self, entry_point: Address) -> RpcResult>; } diff --git a/src/uopool/server.rs b/src/uopool/server.rs index bfb30b80..5ba22b90 100644 --- a/src/uopool/server.rs +++ b/src/uopool/server.rs @@ -112,6 +112,51 @@ pub mod types { } } } + + impl From for ReputationEntry { + fn from(reputation_entry: crate::types::reputation::ReputationEntry) -> Self { + Self { + address: Some(reputation_entry.address.into()), + uo_seen: reputation_entry.uo_seen, + uo_included: reputation_entry.uo_included, + status: match reputation_entry.status { + crate::types::reputation::ReputationStatus::OK => ReputationStatus::Ok, + crate::types::reputation::ReputationStatus::THROTTLED => { + ReputationStatus::Throttled + } + crate::types::reputation::ReputationStatus::BANNED => ReputationStatus::Banned, + } as i32, + } + } + } + + impl From for crate::types::reputation::ReputationEntry { + fn from(reputation_entry: ReputationEntry) -> Self { + Self { + address: { + if let Some(address) = reputation_entry.address { + address.into() + } else { + Address::zero() + } + }, + uo_seen: reputation_entry.uo_seen, + uo_included: reputation_entry.uo_included, + status: match reputation_entry.status { + _ if reputation_entry.status == ReputationStatus::Ok as i32 => { + crate::types::reputation::ReputationStatus::OK + } + _ if reputation_entry.status == ReputationStatus::Throttled as i32 => { + crate::types::reputation::ReputationStatus::THROTTLED + } + _ if reputation_entry.status == ReputationStatus::Banned as i32 => { + crate::types::reputation::ReputationStatus::BANNED + } + _ => crate::types::reputation::ReputationStatus::OK, + }, + } + } + } } pub mod uopool { diff --git a/src/uopool/services/uopool.rs b/src/uopool/services/uopool.rs index 8bfb9336..5a75fdb2 100644 --- a/src/uopool/services/uopool.rs +++ b/src/uopool/services/uopool.rs @@ -3,8 +3,9 @@ use crate::{ uopool::{ server::uopool::{ uo_pool_server::UoPool, AddRequest, AddResponse, AddResult, ClearRequest, - ClearResponse, ClearResult, GetAllRequest, GetAllResponse, GetAllResult, RemoveRequest, - RemoveResponse, + ClearResponse, ClearResult, GetAllReputationRequest, GetAllReputationResponse, + GetAllReputationResult, GetAllRequest, GetAllResponse, GetAllResult, RemoveRequest, + RemoveResponse, SetReputationRequest, SetReputationResponse, SetReputationResult, }, MempoolBox, MempoolId, ReputationBox, }, @@ -86,6 +87,22 @@ impl UoPool for UoPoolService { Err(tonic::Status::unimplemented("todo")) } + #[cfg(debug_assertions)] + async fn clear( + &self, + _request: tonic::Request, + ) -> Result, tonic::Status> { + for mempool in self.mempools.write().values_mut() { + mempool.clear(); + } + + self.reputation.write().clear(); + + Ok(tonic::Response::new(ClearResponse { + result: ClearResult::Cleared as i32, + })) + } + #[cfg(debug_assertions)] async fn get_all( &self, @@ -123,18 +140,38 @@ impl UoPool for UoPoolService { } #[cfg(debug_assertions)] - async fn clear( + async fn set_reputation( &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - for mempool in self.mempools.write().values_mut() { - mempool.clear(); - } + request: tonic::Request, + ) -> Result, tonic::Status> { + let req = request.into_inner(); + let mut res = SetReputationResponse::default(); - self.reputation.write().clear(); + self.reputation + .write() + .set(req.res.iter().map(|re| re.clone().into()).collect()); - Ok(tonic::Response::new(ClearResponse { - result: ClearResult::Cleared as i32, - })) + res.result = SetReputationResult::SetReputation as i32; + + Ok(tonic::Response::new(res)) + } + + #[cfg(debug_assertions)] + async fn get_all_reputation( + &self, + _request: tonic::Request, + ) -> Result, tonic::Status> { + let res = GetAllReputationResponse { + result: GetAllReputationResult::GotAllReputation as i32, + res: self + .reputation + .read() + .get_all() + .iter() + .map(|re| (*re).into()) + .collect(), + }; + + Ok(tonic::Response::new(res)) } }