From 4653ac58849c81b6ab993a1d23f061a97962524b Mon Sep 17 00:00:00 2001 From: hinto-janai Date: Thu, 5 Sep 2024 11:53:16 -0400 Subject: [PATCH] rpc/interface: separate `RpcHandler` into 3 `tower::Service`s (#266) * apply diff * cleanup * fix test --- rpc/interface/README.md | 16 +- rpc/interface/src/lib.rs | 6 +- rpc/interface/src/route/bin.rs | 9 +- rpc/interface/src/route/json_rpc.rs | 28 ++-- rpc/interface/src/route/other.rs | 10 +- rpc/interface/src/rpc_handler.rs | 49 +++--- rpc/interface/src/rpc_handler_dummy.rs | 210 +++++++++++++++---------- rpc/interface/src/rpc_request.rs | 33 ---- rpc/interface/src/rpc_response.rs | 33 ---- rpc/interface/src/rpc_service.rs | 52 ++++++ 10 files changed, 227 insertions(+), 219 deletions(-) delete mode 100644 rpc/interface/src/rpc_request.rs delete mode 100644 rpc/interface/src/rpc_response.rs create mode 100644 rpc/interface/src/rpc_service.rs diff --git a/rpc/interface/README.md b/rpc/interface/README.md index 3a63ac46..eb878643 100644 --- a/rpc/interface/README.md +++ b/rpc/interface/README.md @@ -17,7 +17,7 @@ CLIENT ─► ROUTE ─► REQUEST ─► HANDLER ─► RESPONSE ─► CLIENT Everything coming _in_ from a client is handled by this crate. -This is where your [`RpcHandler`] turns this [`RpcRequest`] into a [`RpcResponse`]. +This is where your [`RpcHandler`] turns this `Request` into a `Response`. You hand this `Response` back to `cuprate-rpc-interface` and it will take care of sending it back to the client. @@ -42,16 +42,18 @@ The proper usage of this crate is to: 3. Do whatever with it # The [`RpcHandler`] -This is your [`tower::Service`] that converts [`RpcRequest`]s into [`RpcResponse`]s, +This is your [`tower::Service`] that converts `Request`s into `Response`s, i.e. the "inner handler". -Said concretely, `RpcHandler` is a `tower::Service` where the associated types are from this crate: -- [`RpcRequest`] -- [`RpcResponse`] +Said concretely, `RpcHandler` is 3 `tower::Service`s where the request/response types are +the 3 endpoint enums from [`cuprate_rpc_types`] and the error type is from this crate: +- [`JsonRpcRequest`](cuprate_rpc_types::json::JsonRpcRequest) & [`JsonRpcResponse`](cuprate_rpc_types::json::JsonRpcResponse) +- [`BinRequest`](cuprate_rpc_types::bin::BinRequest) & [`BinResponse`](cuprate_rpc_types::bin::BinRequest) +- [`OtherRequest`](cuprate_rpc_types::other::OtherRequest) & [`OtherResponse`](cuprate_rpc_types::other::OtherRequest) - [`RpcError`] `RpcHandler`'s [`Future`](std::future::Future) is generic, _although_, -it must output `Result`. +it must output `Result<$RESPONSE, RpcError>`. The `RpcHandler` must also hold some state that is required for RPC server operation. @@ -83,7 +85,7 @@ use cuprate_rpc_types::{ json::{JsonRpcRequest, JsonRpcResponse, GetBlockCountResponse}, other::{OtherRequest, OtherResponse}, }; -use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy, RpcRequest}; +use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy}; // Send a `/get_height` request. This endpoint has no inputs. async fn get_height(port: u16) -> OtherResponse { diff --git a/rpc/interface/src/lib.rs b/rpc/interface/src/lib.rs index d4376979..ebea4939 100644 --- a/rpc/interface/src/lib.rs +++ b/rpc/interface/src/lib.rs @@ -7,16 +7,14 @@ mod rpc_error; mod rpc_handler; #[cfg(feature = "dummy")] mod rpc_handler_dummy; -mod rpc_request; -mod rpc_response; +mod rpc_service; pub use router_builder::RouterBuilder; pub use rpc_error::RpcError; pub use rpc_handler::RpcHandler; #[cfg(feature = "dummy")] pub use rpc_handler_dummy::RpcHandlerDummy; -pub use rpc_request::RpcRequest; -pub use rpc_response::RpcResponse; +pub use rpc_service::RpcService; // false-positive: used in `README.md`'s doc-test. #[cfg(test)] diff --git a/rpc/interface/src/route/bin.rs b/rpc/interface/src/route/bin.rs index 942e0917..45447caf 100644 --- a/rpc/interface/src/route/bin.rs +++ b/rpc/interface/src/route/bin.rs @@ -7,7 +7,7 @@ use tower::ServiceExt; use cuprate_epee_encoding::from_bytes; use cuprate_rpc_types::bin::{BinRequest, BinResponse, GetTransactionPoolHashesRequest}; -use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse}; +use crate::rpc_handler::RpcHandler; //---------------------------------------------------------------------------------------------------- Routes /// This macro generates route functions that expect input. @@ -67,13 +67,8 @@ macro_rules! generate_endpoints_inner { paste::paste! { { // Send request. - let request = RpcRequest::Binary($request); - let channel = $handler.oneshot(request).await?; + let response = $handler.oneshot($request).await?; - // Assert the response from the inner handler is correct. - let RpcResponse::Binary(response) = channel else { - panic!("RPC handler did not return a binary response"); - }; let BinResponse::$variant(response) = response else { panic!("RPC handler returned incorrect response"); }; diff --git a/rpc/interface/src/route/json_rpc.rs b/rpc/interface/src/route/json_rpc.rs index bd35e437..bf3d937d 100644 --- a/rpc/interface/src/route/json_rpc.rs +++ b/rpc/interface/src/route/json_rpc.rs @@ -8,21 +8,21 @@ use tower::ServiceExt; use cuprate_json_rpc::{ error::{ErrorCode, ErrorObject}, - Id, + Id, Response, }; use cuprate_rpc_types::{ json::{JsonRpcRequest, JsonRpcResponse}, RpcCallValue, }; -use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse}; +use crate::rpc_handler::RpcHandler; //---------------------------------------------------------------------------------------------------- Routes /// The `/json_rpc` route function used in [`crate::RouterBuilder`]. pub(crate) async fn json_rpc( State(handler): State, Json(request): Json>, -) -> Result>, StatusCode> { +) -> Result>, StatusCode> { // TODO: // // JSON-RPC notifications (requests without `id`) @@ -30,6 +30,11 @@ pub(crate) async fn json_rpc( // must remain. How to do this considering this function will // always return and cause `axum` to respond? + // JSON-RPC 2.0 rule: + // If there was an error in detecting the `Request`'s ID, + // the `Response` must contain an `Id::Null` + let id = request.id.unwrap_or(Id::Null); + // Return early if this RPC server is restricted and // the requested method is only for non-restricted RPC. if request.body.is_restricted() && handler.restricted() { @@ -39,26 +44,15 @@ pub(crate) async fn json_rpc( data: None, }; - // JSON-RPC 2.0 rule: - // If there was an error in detecting the `Request`'s ID, - // the `Response` must contain an `Id::Null` - let id = request.id.unwrap_or(Id::Null); - - let response = cuprate_json_rpc::Response::err(id, error_object); + let response = Response::err(id, error_object); return Ok(Json(response)); } // Send request. - let request = RpcRequest::JsonRpc(request); - let channel = handler.oneshot(request).await?; + let response = handler.oneshot(request.body).await?; - // Assert the response from the inner handler is correct. - let RpcResponse::JsonRpc(response) = channel else { - panic!("RPC handler returned incorrect response"); - }; - - Ok(Json(response)) + Ok(Json(Response::ok(id, response))) } //---------------------------------------------------------------------------------------------------- Tests diff --git a/rpc/interface/src/route/other.rs b/rpc/interface/src/route/other.rs index ce778db9..129ddd59 100644 --- a/rpc/interface/src/route/other.rs +++ b/rpc/interface/src/route/other.rs @@ -25,7 +25,7 @@ use cuprate_rpc_types::{ RpcCall, }; -use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse}; +use crate::rpc_handler::RpcHandler; //---------------------------------------------------------------------------------------------------- Routes /// This macro generates route functions that expect input. @@ -81,13 +81,9 @@ macro_rules! generate_endpoints_inner { } // Send request. - let request = RpcRequest::Other(OtherRequest::$variant($request)); - let channel = $handler.oneshot(request).await?; + let request = OtherRequest::$variant($request); + let response = $handler.oneshot(request).await?; - // Assert the response from the inner handler is correct. - let RpcResponse::Other(response) = channel else { - panic!("RPC handler did not return a binary response"); - }; let OtherResponse::$variant(response) = response else { panic!("RPC handler returned incorrect response") }; diff --git a/rpc/interface/src/rpc_handler.rs b/rpc/interface/src/rpc_handler.rs index bcd08733..1299ec48 100644 --- a/rpc/interface/src/rpc_handler.rs +++ b/rpc/interface/src/rpc_handler.rs @@ -1,43 +1,42 @@ //! RPC handler trait. //---------------------------------------------------------------------------------------------------- Use -use std::future::Future; +use cuprate_rpc_types::{ + bin::{BinRequest, BinResponse}, + json::{JsonRpcRequest, JsonRpcResponse}, + other::{OtherRequest, OtherResponse}, +}; -use tower::Service; - -use crate::{rpc_error::RpcError, rpc_request::RpcRequest, rpc_response::RpcResponse}; +use crate::RpcService; //---------------------------------------------------------------------------------------------------- RpcHandler /// An RPC handler. /// -/// This trait represents a type that can turn [`RpcRequest`]s into [`RpcResponse`]s. +/// This trait represents a type that can turn `Request`s into `Response`s. /// -/// Implementors of this trait must be [`tower::Service`]s that use: -/// - [`RpcRequest`] as the generic `Request` type -/// - [`RpcResponse`] as the associated `Response` type -/// - [`RpcError`] as the associated `Error` type -/// - A generic [`Future`] that outputs `Result` +/// Implementors of this trait must be: +/// - A [`tower::Service`] that uses [`JsonRpcRequest`] & [`JsonRpcResponse`] +/// - A [`tower::Service`] that uses [`BinRequest`] & [`BinResponse`] +/// - A [`tower::Service`] that uses [`OtherRequest`] & [`OtherResponse`] +/// +/// In other words, an [`RpcHandler`] is a type that implements [`tower::Service`] 3 times, +/// one for each request/response enum type found in [`cuprate_rpc_types`]. +/// +/// The error type must always be [`RpcError`](crate::RpcError). /// /// See this crate's `RpcHandlerDummy` for an implementation example of this trait. /// /// # Panics -/// Your [`RpcHandler`] must reply to [`RpcRequest`]s with the correct -/// [`RpcResponse`] or else this crate will panic during routing functions. +/// Your [`RpcHandler`] must reply to `Request`s with the correct +/// `Response` or else this crate will panic during routing functions. /// -/// For example, upon a [`RpcRequest::Binary`] must be replied with -/// [`RpcRequest::Binary`]. If an [`RpcRequest::Other`] were returned instead, -/// this crate would panic. +/// For example, a [`JsonRpcRequest::GetBlockCount`] must be replied with +/// [`JsonRpcResponse::GetBlockCount`]. If anything else is returned, +/// this crate may panic. pub trait RpcHandler: - Clone - + Send - + Sync - + 'static - + Service< - RpcRequest, - Response = RpcResponse, - Error = RpcError, - Future: Future> + Send + Sync + 'static, - > + RpcService + + RpcService + + RpcService { /// Is this [`RpcHandler`] restricted? /// diff --git a/rpc/interface/src/rpc_handler_dummy.rs b/rpc/interface/src/rpc_handler_dummy.rs index 73ffe9c8..06fa4608 100644 --- a/rpc/interface/src/rpc_handler_dummy.rs +++ b/rpc/interface/src/rpc_handler_dummy.rs @@ -3,18 +3,19 @@ //---------------------------------------------------------------------------------------------------- Use use std::task::Poll; +use cuprate_rpc_types::{ + bin::{BinRequest, BinResponse}, + json::{JsonRpcRequest, JsonRpcResponse}, + other::{OtherRequest, OtherResponse}, +}; use futures::channel::oneshot::channel; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use tower::Service; use cuprate_helper::asynch::InfallibleOneshotReceiver; -use cuprate_json_rpc::Id; -use crate::{ - rpc_error::RpcError, rpc_handler::RpcHandler, rpc_request::RpcRequest, - rpc_response::RpcResponse, -}; +use crate::{rpc_error::RpcError, rpc_handler::RpcHandler}; //---------------------------------------------------------------------------------------------------- RpcHandlerDummy /// An [`RpcHandler`] that always returns [`Default::default`]. @@ -42,96 +43,133 @@ impl RpcHandler for RpcHandlerDummy { } } -impl Service for RpcHandlerDummy { - type Response = RpcResponse; +impl Service for RpcHandlerDummy { + type Response = JsonRpcResponse; type Error = RpcError; - type Future = InfallibleOneshotReceiver>; + type Future = InfallibleOneshotReceiver>; fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll> { Poll::Ready(Ok(())) } - fn call(&mut self, req: RpcRequest) -> Self::Future { - use cuprate_rpc_types::bin::BinRequest as BReq; - use cuprate_rpc_types::bin::BinResponse as BResp; - use cuprate_rpc_types::json::JsonRpcRequest as JReq; - use cuprate_rpc_types::json::JsonRpcResponse as JResp; - use cuprate_rpc_types::other::OtherRequest as OReq; - use cuprate_rpc_types::other::OtherResponse as OResp; + fn call(&mut self, req: JsonRpcRequest) -> Self::Future { + use cuprate_rpc_types::json::JsonRpcRequest as Req; + use cuprate_rpc_types::json::JsonRpcResponse as Resp; - #[rustfmt::skip] #[allow(clippy::default_trait_access)] let resp = match req { - RpcRequest::JsonRpc(j) => RpcResponse::JsonRpc(cuprate_json_rpc::Response::ok(Id::Null, match j.body { - JReq::GetBlockCount(_) => JResp::GetBlockCount(Default::default()), - JReq::OnGetBlockHash(_) => JResp::OnGetBlockHash(Default::default()), - JReq::SubmitBlock(_) => JResp::SubmitBlock(Default::default()), - JReq::GenerateBlocks(_) => JResp::GenerateBlocks(Default::default()), - JReq::GetLastBlockHeader(_) => JResp::GetLastBlockHeader(Default::default()), - JReq::GetBlockHeaderByHash(_) => JResp::GetBlockHeaderByHash(Default::default()), - JReq::GetBlockHeaderByHeight(_) => JResp::GetBlockHeaderByHeight(Default::default()), - JReq::GetBlockHeadersRange(_) => JResp::GetBlockHeadersRange(Default::default()), - JReq::GetBlock(_) => JResp::GetBlock(Default::default()), - JReq::GetConnections(_) => JResp::GetConnections(Default::default()), - JReq::GetInfo(_) => JResp::GetInfo(Default::default()), - JReq::HardForkInfo(_) => JResp::HardForkInfo(Default::default()), - JReq::SetBans(_) => JResp::SetBans(Default::default()), - JReq::GetBans(_) => JResp::GetBans(Default::default()), - JReq::Banned(_) => JResp::Banned(Default::default()), - JReq::FlushTransactionPool(_) => JResp::FlushTransactionPool(Default::default()), - JReq::GetOutputHistogram(_) => JResp::GetOutputHistogram(Default::default()), - JReq::GetCoinbaseTxSum(_) => JResp::GetCoinbaseTxSum(Default::default()), - JReq::GetVersion(_) => JResp::GetVersion(Default::default()), - JReq::GetFeeEstimate(_) => JResp::GetFeeEstimate(Default::default()), - JReq::GetAlternateChains(_) => JResp::GetAlternateChains(Default::default()), - JReq::RelayTx(_) => JResp::RelayTx(Default::default()), - JReq::SyncInfo(_) => JResp::SyncInfo(Default::default()), - JReq::GetTransactionPoolBacklog(_) => JResp::GetTransactionPoolBacklog(Default::default()), - JReq::GetMinerData(_) => JResp::GetMinerData(Default::default()), - JReq::PruneBlockchain(_) => JResp::PruneBlockchain(Default::default()), - JReq::CalcPow(_) => JResp::CalcPow(Default::default()), - JReq::FlushCache(_) => JResp::FlushCache(Default::default()), - JReq::AddAuxPow(_) => JResp::AddAuxPow(Default::default()), - JReq::GetTxIdsLoose(_) => JResp::GetTxIdsLoose(Default::default()), - })), - RpcRequest::Binary(b) => RpcResponse::Binary(match b { - BReq::GetBlocks(_) => BResp::GetBlocks(Default::default()), - BReq::GetBlocksByHeight(_) => BResp::GetBlocksByHeight(Default::default()), - BReq::GetHashes(_) => BResp::GetHashes(Default::default()), - BReq::GetOutputIndexes(_) => BResp::GetOutputIndexes(Default::default()), - BReq::GetOuts(_) => BResp::GetOuts(Default::default()), - BReq::GetTransactionPoolHashes(_) => BResp::GetTransactionPoolHashes(Default::default()), - BReq::GetOutputDistribution(_) => BResp::GetOutputDistribution(Default::default()), - }), - RpcRequest::Other(o) => RpcResponse::Other(match o { - OReq::GetHeight(_) => OResp::GetHeight(Default::default()), - OReq::GetTransactions(_) => OResp::GetTransactions(Default::default()), - OReq::GetAltBlocksHashes(_) => OResp::GetAltBlocksHashes(Default::default()), - OReq::IsKeyImageSpent(_) => OResp::IsKeyImageSpent(Default::default()), - OReq::SendRawTransaction(_) => OResp::SendRawTransaction(Default::default()), - OReq::StartMining(_) => OResp::StartMining(Default::default()), - OReq::StopMining(_) => OResp::StopMining(Default::default()), - OReq::MiningStatus(_) => OResp::MiningStatus(Default::default()), - OReq::SaveBc(_) => OResp::SaveBc(Default::default()), - OReq::GetPeerList(_) => OResp::GetPeerList(Default::default()), - OReq::SetLogHashRate(_) => OResp::SetLogHashRate(Default::default()), - OReq::SetLogLevel(_) => OResp::SetLogLevel(Default::default()), - OReq::SetLogCategories(_) => OResp::SetLogCategories(Default::default()), - OReq::SetBootstrapDaemon(_) => OResp::SetBootstrapDaemon(Default::default()), - OReq::GetTransactionPool(_) => OResp::GetTransactionPool(Default::default()), - OReq::GetTransactionPoolStats(_) => OResp::GetTransactionPoolStats(Default::default()), - OReq::StopDaemon(_) => OResp::StopDaemon(Default::default()), - OReq::GetLimit(_) => OResp::GetLimit(Default::default()), - OReq::SetLimit(_) => OResp::SetLimit(Default::default()), - OReq::OutPeers(_) => OResp::OutPeers(Default::default()), - OReq::InPeers(_) => OResp::InPeers(Default::default()), - OReq::GetNetStats(_) => OResp::GetNetStats(Default::default()), - OReq::GetOuts(_) => OResp::GetOuts(Default::default()), - OReq::Update(_) => OResp::Update(Default::default()), - OReq::PopBlocks(_) => OResp::PopBlocks(Default::default()), - OReq::GetTransactionPoolHashes(_) => OResp::GetTransactionPoolHashes(Default::default()), - OReq::GetPublicNodes(_) => OResp::GetPublicNodes(Default::default()), - }) + Req::GetBlockCount(_) => Resp::GetBlockCount(Default::default()), + Req::OnGetBlockHash(_) => Resp::OnGetBlockHash(Default::default()), + Req::SubmitBlock(_) => Resp::SubmitBlock(Default::default()), + Req::GenerateBlocks(_) => Resp::GenerateBlocks(Default::default()), + Req::GetLastBlockHeader(_) => Resp::GetLastBlockHeader(Default::default()), + Req::GetBlockHeaderByHash(_) => Resp::GetBlockHeaderByHash(Default::default()), + Req::GetBlockHeaderByHeight(_) => Resp::GetBlockHeaderByHeight(Default::default()), + Req::GetBlockHeadersRange(_) => Resp::GetBlockHeadersRange(Default::default()), + Req::GetBlock(_) => Resp::GetBlock(Default::default()), + Req::GetConnections(_) => Resp::GetConnections(Default::default()), + Req::GetInfo(_) => Resp::GetInfo(Default::default()), + Req::HardForkInfo(_) => Resp::HardForkInfo(Default::default()), + Req::SetBans(_) => Resp::SetBans(Default::default()), + Req::GetBans(_) => Resp::GetBans(Default::default()), + Req::Banned(_) => Resp::Banned(Default::default()), + Req::FlushTransactionPool(_) => Resp::FlushTransactionPool(Default::default()), + Req::GetOutputHistogram(_) => Resp::GetOutputHistogram(Default::default()), + Req::GetCoinbaseTxSum(_) => Resp::GetCoinbaseTxSum(Default::default()), + Req::GetVersion(_) => Resp::GetVersion(Default::default()), + Req::GetFeeEstimate(_) => Resp::GetFeeEstimate(Default::default()), + Req::GetAlternateChains(_) => Resp::GetAlternateChains(Default::default()), + Req::RelayTx(_) => Resp::RelayTx(Default::default()), + Req::SyncInfo(_) => Resp::SyncInfo(Default::default()), + Req::GetTransactionPoolBacklog(_) => { + Resp::GetTransactionPoolBacklog(Default::default()) + } + Req::GetMinerData(_) => Resp::GetMinerData(Default::default()), + Req::PruneBlockchain(_) => Resp::PruneBlockchain(Default::default()), + Req::CalcPow(_) => Resp::CalcPow(Default::default()), + Req::FlushCache(_) => Resp::FlushCache(Default::default()), + Req::AddAuxPow(_) => Resp::AddAuxPow(Default::default()), + Req::GetTxIdsLoose(_) => Resp::GetTxIdsLoose(Default::default()), + }; + + let (tx, rx) = channel(); + drop(tx.send(Ok(resp))); + InfallibleOneshotReceiver::from(rx) + } +} + +impl Service for RpcHandlerDummy { + type Response = BinResponse; + type Error = RpcError; + type Future = InfallibleOneshotReceiver>; + + fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: BinRequest) -> Self::Future { + use cuprate_rpc_types::bin::BinRequest as Req; + use cuprate_rpc_types::bin::BinResponse as Resp; + + #[allow(clippy::default_trait_access)] + let resp = match req { + Req::GetBlocks(_) => Resp::GetBlocks(Default::default()), + Req::GetBlocksByHeight(_) => Resp::GetBlocksByHeight(Default::default()), + Req::GetHashes(_) => Resp::GetHashes(Default::default()), + Req::GetOutputIndexes(_) => Resp::GetOutputIndexes(Default::default()), + Req::GetOuts(_) => Resp::GetOuts(Default::default()), + Req::GetTransactionPoolHashes(_) => Resp::GetTransactionPoolHashes(Default::default()), + Req::GetOutputDistribution(_) => Resp::GetOutputDistribution(Default::default()), + }; + + let (tx, rx) = channel(); + drop(tx.send(Ok(resp))); + InfallibleOneshotReceiver::from(rx) + } +} + +impl Service for RpcHandlerDummy { + type Response = OtherResponse; + type Error = RpcError; + type Future = InfallibleOneshotReceiver>; + + fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: OtherRequest) -> Self::Future { + use cuprate_rpc_types::other::OtherRequest as Req; + use cuprate_rpc_types::other::OtherResponse as Resp; + + #[allow(clippy::default_trait_access)] + let resp = match req { + Req::GetHeight(_) => Resp::GetHeight(Default::default()), + Req::GetTransactions(_) => Resp::GetTransactions(Default::default()), + Req::GetAltBlocksHashes(_) => Resp::GetAltBlocksHashes(Default::default()), + Req::IsKeyImageSpent(_) => Resp::IsKeyImageSpent(Default::default()), + Req::SendRawTransaction(_) => Resp::SendRawTransaction(Default::default()), + Req::StartMining(_) => Resp::StartMining(Default::default()), + Req::StopMining(_) => Resp::StopMining(Default::default()), + Req::MiningStatus(_) => Resp::MiningStatus(Default::default()), + Req::SaveBc(_) => Resp::SaveBc(Default::default()), + Req::GetPeerList(_) => Resp::GetPeerList(Default::default()), + Req::SetLogHashRate(_) => Resp::SetLogHashRate(Default::default()), + Req::SetLogLevel(_) => Resp::SetLogLevel(Default::default()), + Req::SetLogCategories(_) => Resp::SetLogCategories(Default::default()), + Req::SetBootstrapDaemon(_) => Resp::SetBootstrapDaemon(Default::default()), + Req::GetTransactionPool(_) => Resp::GetTransactionPool(Default::default()), + Req::GetTransactionPoolStats(_) => Resp::GetTransactionPoolStats(Default::default()), + Req::StopDaemon(_) => Resp::StopDaemon(Default::default()), + Req::GetLimit(_) => Resp::GetLimit(Default::default()), + Req::SetLimit(_) => Resp::SetLimit(Default::default()), + Req::OutPeers(_) => Resp::OutPeers(Default::default()), + Req::InPeers(_) => Resp::InPeers(Default::default()), + Req::GetNetStats(_) => Resp::GetNetStats(Default::default()), + Req::GetOuts(_) => Resp::GetOuts(Default::default()), + Req::Update(_) => Resp::Update(Default::default()), + Req::PopBlocks(_) => Resp::PopBlocks(Default::default()), + Req::GetTransactionPoolHashes(_) => Resp::GetTransactionPoolHashes(Default::default()), + Req::GetPublicNodes(_) => Resp::GetPublicNodes(Default::default()), }; let (tx, rx) = channel(); diff --git a/rpc/interface/src/rpc_request.rs b/rpc/interface/src/rpc_request.rs deleted file mode 100644 index 3b66a780..00000000 --- a/rpc/interface/src/rpc_request.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! RPC requests. - -//---------------------------------------------------------------------------------------------------- Import -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - -use cuprate_rpc_types::{bin::BinRequest, json::JsonRpcRequest, other::OtherRequest}; - -//---------------------------------------------------------------------------------------------------- RpcRequest -/// All possible RPC requests. -/// -/// This enum encapsulates all possible RPC requests: -/// - JSON RPC 2.0 requests -/// - Binary requests -/// - Other JSON requests -/// -/// It is the `Request` type required to be used in an [`RpcHandler`](crate::RpcHandler). -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -pub enum RpcRequest { - /// JSON-RPC 2.0 requests. - JsonRpc(cuprate_json_rpc::Request), - /// Binary requests. - Binary(BinRequest), - /// Other JSON requests. - Other(OtherRequest), -} - -//---------------------------------------------------------------------------------------------------- Tests -#[cfg(test)] -mod test { - // use super::*; -} diff --git a/rpc/interface/src/rpc_response.rs b/rpc/interface/src/rpc_response.rs deleted file mode 100644 index 7e8ecdbe..00000000 --- a/rpc/interface/src/rpc_response.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! RPC responses. - -//---------------------------------------------------------------------------------------------------- Import -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - -use cuprate_rpc_types::{bin::BinResponse, json::JsonRpcResponse, other::OtherResponse}; - -//---------------------------------------------------------------------------------------------------- RpcResponse -/// All possible RPC responses. -/// -/// This enum encapsulates all possible RPC responses: -/// - JSON RPC 2.0 responses -/// - Binary responses -/// - Other JSON responses -/// -/// It is the `Response` type required to be used in an [`RpcHandler`](crate::RpcHandler). -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -pub enum RpcResponse { - /// JSON RPC 2.0 responses. - JsonRpc(cuprate_json_rpc::Response), - /// Binary responses. - Binary(BinResponse), - /// Other JSON responses. - Other(OtherResponse), -} - -//---------------------------------------------------------------------------------------------------- Tests -#[cfg(test)] -mod test { - // use super::*; -} diff --git a/rpc/interface/src/rpc_service.rs b/rpc/interface/src/rpc_service.rs new file mode 100644 index 00000000..db848307 --- /dev/null +++ b/rpc/interface/src/rpc_service.rs @@ -0,0 +1,52 @@ +//! RPC [`tower::Service`] trait. + +//---------------------------------------------------------------------------------------------------- Use +use std::future::Future; + +use tower::Service; + +use crate::rpc_error::RpcError; + +//---------------------------------------------------------------------------------------------------- RpcService +/// An RPC [`tower::Service`]. +/// +/// This trait solely exists to encapsulate the traits needed +/// to handle RPC requests and respond with responses - **it is +/// not meant to be used directly.** +/// +/// The `Request` and `Response` are generic and +/// are used in the [`tower::Service`] bounds. +/// +/// The error type is always [`RpcError`]. +/// +/// There is a blanket implementation that implements this +/// trait on types that implement `tower::Service` correctly. +/// +/// See [`RpcHandler`](crate::RpcHandler) for more information. +pub trait RpcService: + Clone + + Send + + Sync + + 'static + + Service< + Request, + Response = Response, + Error = RpcError, + Future: Future> + Send + Sync + 'static, + > +{ +} + +impl RpcService for T where + Self: Clone + + Send + + Sync + + 'static + + Service< + Request, + Response = Response, + Error = RpcError, + Future: Future> + Send + Sync + 'static, + > +{ +}