mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
rpc/interface: separate RpcHandler
into 3 tower::Service
s (#266)
Some checks failed
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
Some checks failed
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
* apply diff * cleanup * fix test
This commit is contained in:
parent
0941f68efc
commit
4653ac5884
10 changed files with 227 additions and 219 deletions
|
@ -17,7 +17,7 @@ CLIENT ─► ROUTE ─► REQUEST ─► HANDLER ─► RESPONSE ─► CLIENT
|
||||||
|
|
||||||
Everything coming _in_ from a client is handled by this crate.
|
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.
|
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
|
3. Do whatever with it
|
||||||
|
|
||||||
# The [`RpcHandler`]
|
# 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".
|
i.e. the "inner handler".
|
||||||
|
|
||||||
Said concretely, `RpcHandler` is a `tower::Service` where the associated types are from this crate:
|
Said concretely, `RpcHandler` is 3 `tower::Service`s where the request/response types are
|
||||||
- [`RpcRequest`]
|
the 3 endpoint enums from [`cuprate_rpc_types`] and the error type is from this crate:
|
||||||
- [`RpcResponse`]
|
- [`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`]
|
- [`RpcError`]
|
||||||
|
|
||||||
`RpcHandler`'s [`Future`](std::future::Future) is generic, _although_,
|
`RpcHandler`'s [`Future`](std::future::Future) is generic, _although_,
|
||||||
it must output `Result<RpcResponse, RpcError>`.
|
it must output `Result<$RESPONSE, RpcError>`.
|
||||||
|
|
||||||
The `RpcHandler` must also hold some state that is required
|
The `RpcHandler` must also hold some state that is required
|
||||||
for RPC server operation.
|
for RPC server operation.
|
||||||
|
@ -83,7 +85,7 @@ use cuprate_rpc_types::{
|
||||||
json::{JsonRpcRequest, JsonRpcResponse, GetBlockCountResponse},
|
json::{JsonRpcRequest, JsonRpcResponse, GetBlockCountResponse},
|
||||||
other::{OtherRequest, OtherResponse},
|
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.
|
// Send a `/get_height` request. This endpoint has no inputs.
|
||||||
async fn get_height(port: u16) -> OtherResponse {
|
async fn get_height(port: u16) -> OtherResponse {
|
||||||
|
|
|
@ -7,16 +7,14 @@ mod rpc_error;
|
||||||
mod rpc_handler;
|
mod rpc_handler;
|
||||||
#[cfg(feature = "dummy")]
|
#[cfg(feature = "dummy")]
|
||||||
mod rpc_handler_dummy;
|
mod rpc_handler_dummy;
|
||||||
mod rpc_request;
|
mod rpc_service;
|
||||||
mod rpc_response;
|
|
||||||
|
|
||||||
pub use router_builder::RouterBuilder;
|
pub use router_builder::RouterBuilder;
|
||||||
pub use rpc_error::RpcError;
|
pub use rpc_error::RpcError;
|
||||||
pub use rpc_handler::RpcHandler;
|
pub use rpc_handler::RpcHandler;
|
||||||
#[cfg(feature = "dummy")]
|
#[cfg(feature = "dummy")]
|
||||||
pub use rpc_handler_dummy::RpcHandlerDummy;
|
pub use rpc_handler_dummy::RpcHandlerDummy;
|
||||||
pub use rpc_request::RpcRequest;
|
pub use rpc_service::RpcService;
|
||||||
pub use rpc_response::RpcResponse;
|
|
||||||
|
|
||||||
// false-positive: used in `README.md`'s doc-test.
|
// false-positive: used in `README.md`'s doc-test.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -7,7 +7,7 @@ use tower::ServiceExt;
|
||||||
use cuprate_epee_encoding::from_bytes;
|
use cuprate_epee_encoding::from_bytes;
|
||||||
use cuprate_rpc_types::bin::{BinRequest, BinResponse, GetTransactionPoolHashesRequest};
|
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
|
//---------------------------------------------------------------------------------------------------- Routes
|
||||||
/// This macro generates route functions that expect input.
|
/// This macro generates route functions that expect input.
|
||||||
|
@ -67,13 +67,8 @@ macro_rules! generate_endpoints_inner {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
{
|
{
|
||||||
// Send request.
|
// Send request.
|
||||||
let request = RpcRequest::Binary($request);
|
let response = $handler.oneshot($request).await?;
|
||||||
let channel = $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 {
|
let BinResponse::$variant(response) = response else {
|
||||||
panic!("RPC handler returned incorrect response");
|
panic!("RPC handler returned incorrect response");
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,21 +8,21 @@ use tower::ServiceExt;
|
||||||
|
|
||||||
use cuprate_json_rpc::{
|
use cuprate_json_rpc::{
|
||||||
error::{ErrorCode, ErrorObject},
|
error::{ErrorCode, ErrorObject},
|
||||||
Id,
|
Id, Response,
|
||||||
};
|
};
|
||||||
use cuprate_rpc_types::{
|
use cuprate_rpc_types::{
|
||||||
json::{JsonRpcRequest, JsonRpcResponse},
|
json::{JsonRpcRequest, JsonRpcResponse},
|
||||||
RpcCallValue,
|
RpcCallValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse};
|
use crate::rpc_handler::RpcHandler;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Routes
|
//---------------------------------------------------------------------------------------------------- Routes
|
||||||
/// The `/json_rpc` route function used in [`crate::RouterBuilder`].
|
/// The `/json_rpc` route function used in [`crate::RouterBuilder`].
|
||||||
pub(crate) async fn json_rpc<H: RpcHandler>(
|
pub(crate) async fn json_rpc<H: RpcHandler>(
|
||||||
State(handler): State<H>,
|
State(handler): State<H>,
|
||||||
Json(request): Json<cuprate_json_rpc::Request<JsonRpcRequest>>,
|
Json(request): Json<cuprate_json_rpc::Request<JsonRpcRequest>>,
|
||||||
) -> Result<Json<cuprate_json_rpc::Response<JsonRpcResponse>>, StatusCode> {
|
) -> Result<Json<Response<JsonRpcResponse>>, StatusCode> {
|
||||||
// TODO: <https://www.jsonrpc.org/specification#notification>
|
// TODO: <https://www.jsonrpc.org/specification#notification>
|
||||||
//
|
//
|
||||||
// JSON-RPC notifications (requests without `id`)
|
// JSON-RPC notifications (requests without `id`)
|
||||||
|
@ -30,6 +30,11 @@ pub(crate) async fn json_rpc<H: RpcHandler>(
|
||||||
// must remain. How to do this considering this function will
|
// must remain. How to do this considering this function will
|
||||||
// always return and cause `axum` to respond?
|
// 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
|
// Return early if this RPC server is restricted and
|
||||||
// the requested method is only for non-restricted RPC.
|
// the requested method is only for non-restricted RPC.
|
||||||
if request.body.is_restricted() && handler.restricted() {
|
if request.body.is_restricted() && handler.restricted() {
|
||||||
|
@ -39,26 +44,15 @@ pub(crate) async fn json_rpc<H: RpcHandler>(
|
||||||
data: None,
|
data: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// JSON-RPC 2.0 rule:
|
let response = Response::err(id, error_object);
|
||||||
// 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);
|
|
||||||
|
|
||||||
return Ok(Json(response));
|
return Ok(Json(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send request.
|
// Send request.
|
||||||
let request = RpcRequest::JsonRpc(request);
|
let response = handler.oneshot(request.body).await?;
|
||||||
let channel = handler.oneshot(request).await?;
|
|
||||||
|
|
||||||
// Assert the response from the inner handler is correct.
|
Ok(Json(Response::ok(id, response)))
|
||||||
let RpcResponse::JsonRpc(response) = channel else {
|
|
||||||
panic!("RPC handler returned incorrect response");
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Json(response))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Tests
|
//---------------------------------------------------------------------------------------------------- Tests
|
||||||
|
|
|
@ -25,7 +25,7 @@ use cuprate_rpc_types::{
|
||||||
RpcCall,
|
RpcCall,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{rpc_handler::RpcHandler, rpc_request::RpcRequest, rpc_response::RpcResponse};
|
use crate::rpc_handler::RpcHandler;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Routes
|
//---------------------------------------------------------------------------------------------------- Routes
|
||||||
/// This macro generates route functions that expect input.
|
/// This macro generates route functions that expect input.
|
||||||
|
@ -81,13 +81,9 @@ macro_rules! generate_endpoints_inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send request.
|
// Send request.
|
||||||
let request = RpcRequest::Other(OtherRequest::$variant($request));
|
let request = OtherRequest::$variant($request);
|
||||||
let channel = $handler.oneshot(request).await?;
|
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 {
|
let OtherResponse::$variant(response) = response else {
|
||||||
panic!("RPC handler returned incorrect response")
|
panic!("RPC handler returned incorrect response")
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,43 +1,42 @@
|
||||||
//! RPC handler trait.
|
//! RPC handler trait.
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Use
|
//---------------------------------------------------------------------------------------------------- Use
|
||||||
use std::future::Future;
|
use cuprate_rpc_types::{
|
||||||
|
bin::{BinRequest, BinResponse},
|
||||||
|
json::{JsonRpcRequest, JsonRpcResponse},
|
||||||
|
other::{OtherRequest, OtherResponse},
|
||||||
|
};
|
||||||
|
|
||||||
use tower::Service;
|
use crate::RpcService;
|
||||||
|
|
||||||
use crate::{rpc_error::RpcError, rpc_request::RpcRequest, rpc_response::RpcResponse};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- RpcHandler
|
//---------------------------------------------------------------------------------------------------- RpcHandler
|
||||||
/// An RPC handler.
|
/// 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:
|
/// Implementors of this trait must be:
|
||||||
/// - [`RpcRequest`] as the generic `Request` type
|
/// - A [`tower::Service`] that uses [`JsonRpcRequest`] & [`JsonRpcResponse`]
|
||||||
/// - [`RpcResponse`] as the associated `Response` type
|
/// - A [`tower::Service`] that uses [`BinRequest`] & [`BinResponse`]
|
||||||
/// - [`RpcError`] as the associated `Error` type
|
/// - A [`tower::Service`] that uses [`OtherRequest`] & [`OtherResponse`]
|
||||||
/// - A generic [`Future`] that outputs `Result<RpcResponse, RpcError>`
|
///
|
||||||
|
/// 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.
|
/// See this crate's `RpcHandlerDummy` for an implementation example of this trait.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// Your [`RpcHandler`] must reply to [`RpcRequest`]s with the correct
|
/// Your [`RpcHandler`] must reply to `Request`s with the correct
|
||||||
/// [`RpcResponse`] or else this crate will panic during routing functions.
|
/// `Response` or else this crate will panic during routing functions.
|
||||||
///
|
///
|
||||||
/// For example, upon a [`RpcRequest::Binary`] must be replied with
|
/// For example, a [`JsonRpcRequest::GetBlockCount`] must be replied with
|
||||||
/// [`RpcRequest::Binary`]. If an [`RpcRequest::Other`] were returned instead,
|
/// [`JsonRpcResponse::GetBlockCount`]. If anything else is returned,
|
||||||
/// this crate would panic.
|
/// this crate may panic.
|
||||||
pub trait RpcHandler:
|
pub trait RpcHandler:
|
||||||
Clone
|
RpcService<JsonRpcRequest, JsonRpcResponse>
|
||||||
+ Send
|
+ RpcService<BinRequest, BinResponse>
|
||||||
+ Sync
|
+ RpcService<OtherRequest, OtherResponse>
|
||||||
+ 'static
|
|
||||||
+ Service<
|
|
||||||
RpcRequest,
|
|
||||||
Response = RpcResponse,
|
|
||||||
Error = RpcError,
|
|
||||||
Future: Future<Output = Result<RpcResponse, RpcError>> + Send + Sync + 'static,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
/// Is this [`RpcHandler`] restricted?
|
/// Is this [`RpcHandler`] restricted?
|
||||||
///
|
///
|
||||||
|
|
|
@ -3,18 +3,19 @@
|
||||||
//---------------------------------------------------------------------------------------------------- Use
|
//---------------------------------------------------------------------------------------------------- Use
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
|
|
||||||
|
use cuprate_rpc_types::{
|
||||||
|
bin::{BinRequest, BinResponse},
|
||||||
|
json::{JsonRpcRequest, JsonRpcResponse},
|
||||||
|
other::{OtherRequest, OtherResponse},
|
||||||
|
};
|
||||||
use futures::channel::oneshot::channel;
|
use futures::channel::oneshot::channel;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
|
|
||||||
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
||||||
use cuprate_json_rpc::Id;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{rpc_error::RpcError, rpc_handler::RpcHandler};
|
||||||
rpc_error::RpcError, rpc_handler::RpcHandler, rpc_request::RpcRequest,
|
|
||||||
rpc_response::RpcResponse,
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- RpcHandlerDummy
|
//---------------------------------------------------------------------------------------------------- RpcHandlerDummy
|
||||||
/// An [`RpcHandler`] that always returns [`Default::default`].
|
/// An [`RpcHandler`] that always returns [`Default::default`].
|
||||||
|
@ -42,96 +43,133 @@ impl RpcHandler for RpcHandlerDummy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service<RpcRequest> for RpcHandlerDummy {
|
impl Service<JsonRpcRequest> for RpcHandlerDummy {
|
||||||
type Response = RpcResponse;
|
type Response = JsonRpcResponse;
|
||||||
type Error = RpcError;
|
type Error = RpcError;
|
||||||
type Future = InfallibleOneshotReceiver<Result<RpcResponse, RpcError>>;
|
type Future = InfallibleOneshotReceiver<Result<JsonRpcResponse, RpcError>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: RpcRequest) -> Self::Future {
|
fn call(&mut self, req: JsonRpcRequest) -> Self::Future {
|
||||||
use cuprate_rpc_types::bin::BinRequest as BReq;
|
use cuprate_rpc_types::json::JsonRpcRequest as Req;
|
||||||
use cuprate_rpc_types::bin::BinResponse as BResp;
|
use cuprate_rpc_types::json::JsonRpcResponse as Resp;
|
||||||
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;
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[allow(clippy::default_trait_access)]
|
#[allow(clippy::default_trait_access)]
|
||||||
let resp = match req {
|
let resp = match req {
|
||||||
RpcRequest::JsonRpc(j) => RpcResponse::JsonRpc(cuprate_json_rpc::Response::ok(Id::Null, match j.body {
|
Req::GetBlockCount(_) => Resp::GetBlockCount(Default::default()),
|
||||||
JReq::GetBlockCount(_) => JResp::GetBlockCount(Default::default()),
|
Req::OnGetBlockHash(_) => Resp::OnGetBlockHash(Default::default()),
|
||||||
JReq::OnGetBlockHash(_) => JResp::OnGetBlockHash(Default::default()),
|
Req::SubmitBlock(_) => Resp::SubmitBlock(Default::default()),
|
||||||
JReq::SubmitBlock(_) => JResp::SubmitBlock(Default::default()),
|
Req::GenerateBlocks(_) => Resp::GenerateBlocks(Default::default()),
|
||||||
JReq::GenerateBlocks(_) => JResp::GenerateBlocks(Default::default()),
|
Req::GetLastBlockHeader(_) => Resp::GetLastBlockHeader(Default::default()),
|
||||||
JReq::GetLastBlockHeader(_) => JResp::GetLastBlockHeader(Default::default()),
|
Req::GetBlockHeaderByHash(_) => Resp::GetBlockHeaderByHash(Default::default()),
|
||||||
JReq::GetBlockHeaderByHash(_) => JResp::GetBlockHeaderByHash(Default::default()),
|
Req::GetBlockHeaderByHeight(_) => Resp::GetBlockHeaderByHeight(Default::default()),
|
||||||
JReq::GetBlockHeaderByHeight(_) => JResp::GetBlockHeaderByHeight(Default::default()),
|
Req::GetBlockHeadersRange(_) => Resp::GetBlockHeadersRange(Default::default()),
|
||||||
JReq::GetBlockHeadersRange(_) => JResp::GetBlockHeadersRange(Default::default()),
|
Req::GetBlock(_) => Resp::GetBlock(Default::default()),
|
||||||
JReq::GetBlock(_) => JResp::GetBlock(Default::default()),
|
Req::GetConnections(_) => Resp::GetConnections(Default::default()),
|
||||||
JReq::GetConnections(_) => JResp::GetConnections(Default::default()),
|
Req::GetInfo(_) => Resp::GetInfo(Default::default()),
|
||||||
JReq::GetInfo(_) => JResp::GetInfo(Default::default()),
|
Req::HardForkInfo(_) => Resp::HardForkInfo(Default::default()),
|
||||||
JReq::HardForkInfo(_) => JResp::HardForkInfo(Default::default()),
|
Req::SetBans(_) => Resp::SetBans(Default::default()),
|
||||||
JReq::SetBans(_) => JResp::SetBans(Default::default()),
|
Req::GetBans(_) => Resp::GetBans(Default::default()),
|
||||||
JReq::GetBans(_) => JResp::GetBans(Default::default()),
|
Req::Banned(_) => Resp::Banned(Default::default()),
|
||||||
JReq::Banned(_) => JResp::Banned(Default::default()),
|
Req::FlushTransactionPool(_) => Resp::FlushTransactionPool(Default::default()),
|
||||||
JReq::FlushTransactionPool(_) => JResp::FlushTransactionPool(Default::default()),
|
Req::GetOutputHistogram(_) => Resp::GetOutputHistogram(Default::default()),
|
||||||
JReq::GetOutputHistogram(_) => JResp::GetOutputHistogram(Default::default()),
|
Req::GetCoinbaseTxSum(_) => Resp::GetCoinbaseTxSum(Default::default()),
|
||||||
JReq::GetCoinbaseTxSum(_) => JResp::GetCoinbaseTxSum(Default::default()),
|
Req::GetVersion(_) => Resp::GetVersion(Default::default()),
|
||||||
JReq::GetVersion(_) => JResp::GetVersion(Default::default()),
|
Req::GetFeeEstimate(_) => Resp::GetFeeEstimate(Default::default()),
|
||||||
JReq::GetFeeEstimate(_) => JResp::GetFeeEstimate(Default::default()),
|
Req::GetAlternateChains(_) => Resp::GetAlternateChains(Default::default()),
|
||||||
JReq::GetAlternateChains(_) => JResp::GetAlternateChains(Default::default()),
|
Req::RelayTx(_) => Resp::RelayTx(Default::default()),
|
||||||
JReq::RelayTx(_) => JResp::RelayTx(Default::default()),
|
Req::SyncInfo(_) => Resp::SyncInfo(Default::default()),
|
||||||
JReq::SyncInfo(_) => JResp::SyncInfo(Default::default()),
|
Req::GetTransactionPoolBacklog(_) => {
|
||||||
JReq::GetTransactionPoolBacklog(_) => JResp::GetTransactionPoolBacklog(Default::default()),
|
Resp::GetTransactionPoolBacklog(Default::default())
|
||||||
JReq::GetMinerData(_) => JResp::GetMinerData(Default::default()),
|
}
|
||||||
JReq::PruneBlockchain(_) => JResp::PruneBlockchain(Default::default()),
|
Req::GetMinerData(_) => Resp::GetMinerData(Default::default()),
|
||||||
JReq::CalcPow(_) => JResp::CalcPow(Default::default()),
|
Req::PruneBlockchain(_) => Resp::PruneBlockchain(Default::default()),
|
||||||
JReq::FlushCache(_) => JResp::FlushCache(Default::default()),
|
Req::CalcPow(_) => Resp::CalcPow(Default::default()),
|
||||||
JReq::AddAuxPow(_) => JResp::AddAuxPow(Default::default()),
|
Req::FlushCache(_) => Resp::FlushCache(Default::default()),
|
||||||
JReq::GetTxIdsLoose(_) => JResp::GetTxIdsLoose(Default::default()),
|
Req::AddAuxPow(_) => Resp::AddAuxPow(Default::default()),
|
||||||
})),
|
Req::GetTxIdsLoose(_) => Resp::GetTxIdsLoose(Default::default()),
|
||||||
RpcRequest::Binary(b) => RpcResponse::Binary(match b {
|
};
|
||||||
BReq::GetBlocks(_) => BResp::GetBlocks(Default::default()),
|
|
||||||
BReq::GetBlocksByHeight(_) => BResp::GetBlocksByHeight(Default::default()),
|
let (tx, rx) = channel();
|
||||||
BReq::GetHashes(_) => BResp::GetHashes(Default::default()),
|
drop(tx.send(Ok(resp)));
|
||||||
BReq::GetOutputIndexes(_) => BResp::GetOutputIndexes(Default::default()),
|
InfallibleOneshotReceiver::from(rx)
|
||||||
BReq::GetOuts(_) => BResp::GetOuts(Default::default()),
|
}
|
||||||
BReq::GetTransactionPoolHashes(_) => BResp::GetTransactionPoolHashes(Default::default()),
|
}
|
||||||
BReq::GetOutputDistribution(_) => BResp::GetOutputDistribution(Default::default()),
|
|
||||||
}),
|
impl Service<BinRequest> for RpcHandlerDummy {
|
||||||
RpcRequest::Other(o) => RpcResponse::Other(match o {
|
type Response = BinResponse;
|
||||||
OReq::GetHeight(_) => OResp::GetHeight(Default::default()),
|
type Error = RpcError;
|
||||||
OReq::GetTransactions(_) => OResp::GetTransactions(Default::default()),
|
type Future = InfallibleOneshotReceiver<Result<BinResponse, RpcError>>;
|
||||||
OReq::GetAltBlocksHashes(_) => OResp::GetAltBlocksHashes(Default::default()),
|
|
||||||
OReq::IsKeyImageSpent(_) => OResp::IsKeyImageSpent(Default::default()),
|
fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
OReq::SendRawTransaction(_) => OResp::SendRawTransaction(Default::default()),
|
Poll::Ready(Ok(()))
|
||||||
OReq::StartMining(_) => OResp::StartMining(Default::default()),
|
}
|
||||||
OReq::StopMining(_) => OResp::StopMining(Default::default()),
|
|
||||||
OReq::MiningStatus(_) => OResp::MiningStatus(Default::default()),
|
fn call(&mut self, req: BinRequest) -> Self::Future {
|
||||||
OReq::SaveBc(_) => OResp::SaveBc(Default::default()),
|
use cuprate_rpc_types::bin::BinRequest as Req;
|
||||||
OReq::GetPeerList(_) => OResp::GetPeerList(Default::default()),
|
use cuprate_rpc_types::bin::BinResponse as Resp;
|
||||||
OReq::SetLogHashRate(_) => OResp::SetLogHashRate(Default::default()),
|
|
||||||
OReq::SetLogLevel(_) => OResp::SetLogLevel(Default::default()),
|
#[allow(clippy::default_trait_access)]
|
||||||
OReq::SetLogCategories(_) => OResp::SetLogCategories(Default::default()),
|
let resp = match req {
|
||||||
OReq::SetBootstrapDaemon(_) => OResp::SetBootstrapDaemon(Default::default()),
|
Req::GetBlocks(_) => Resp::GetBlocks(Default::default()),
|
||||||
OReq::GetTransactionPool(_) => OResp::GetTransactionPool(Default::default()),
|
Req::GetBlocksByHeight(_) => Resp::GetBlocksByHeight(Default::default()),
|
||||||
OReq::GetTransactionPoolStats(_) => OResp::GetTransactionPoolStats(Default::default()),
|
Req::GetHashes(_) => Resp::GetHashes(Default::default()),
|
||||||
OReq::StopDaemon(_) => OResp::StopDaemon(Default::default()),
|
Req::GetOutputIndexes(_) => Resp::GetOutputIndexes(Default::default()),
|
||||||
OReq::GetLimit(_) => OResp::GetLimit(Default::default()),
|
Req::GetOuts(_) => Resp::GetOuts(Default::default()),
|
||||||
OReq::SetLimit(_) => OResp::SetLimit(Default::default()),
|
Req::GetTransactionPoolHashes(_) => Resp::GetTransactionPoolHashes(Default::default()),
|
||||||
OReq::OutPeers(_) => OResp::OutPeers(Default::default()),
|
Req::GetOutputDistribution(_) => Resp::GetOutputDistribution(Default::default()),
|
||||||
OReq::InPeers(_) => OResp::InPeers(Default::default()),
|
};
|
||||||
OReq::GetNetStats(_) => OResp::GetNetStats(Default::default()),
|
|
||||||
OReq::GetOuts(_) => OResp::GetOuts(Default::default()),
|
let (tx, rx) = channel();
|
||||||
OReq::Update(_) => OResp::Update(Default::default()),
|
drop(tx.send(Ok(resp)));
|
||||||
OReq::PopBlocks(_) => OResp::PopBlocks(Default::default()),
|
InfallibleOneshotReceiver::from(rx)
|
||||||
OReq::GetTransactionPoolHashes(_) => OResp::GetTransactionPoolHashes(Default::default()),
|
}
|
||||||
OReq::GetPublicNodes(_) => OResp::GetPublicNodes(Default::default()),
|
}
|
||||||
})
|
|
||||||
|
impl Service<OtherRequest> for RpcHandlerDummy {
|
||||||
|
type Response = OtherResponse;
|
||||||
|
type Error = RpcError;
|
||||||
|
type Future = InfallibleOneshotReceiver<Result<OtherResponse, RpcError>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
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();
|
let (tx, rx) = channel();
|
||||||
|
|
|
@ -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<JsonRpcRequest>),
|
|
||||||
/// Binary requests.
|
|
||||||
Binary(BinRequest),
|
|
||||||
/// Other JSON requests.
|
|
||||||
Other(OtherRequest),
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Tests
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
// use super::*;
|
|
||||||
}
|
|
|
@ -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<JsonRpcResponse>),
|
|
||||||
/// Binary responses.
|
|
||||||
Binary(BinResponse),
|
|
||||||
/// Other JSON responses.
|
|
||||||
Other(OtherResponse),
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Tests
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
// use super::*;
|
|
||||||
}
|
|
52
rpc/interface/src/rpc_service.rs
Normal file
52
rpc/interface/src/rpc_service.rs
Normal file
|
@ -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<Request, Response>:
|
||||||
|
Clone
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static
|
||||||
|
+ Service<
|
||||||
|
Request,
|
||||||
|
Response = Response,
|
||||||
|
Error = RpcError,
|
||||||
|
Future: Future<Output = Result<Response, RpcError>> + Send + Sync + 'static,
|
||||||
|
>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Request, Response, T> RpcService<Request, Response> for T where
|
||||||
|
Self: Clone
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static
|
||||||
|
+ Service<
|
||||||
|
Request,
|
||||||
|
Response = Response,
|
||||||
|
Error = RpcError,
|
||||||
|
Future: Future<Output = Result<Response, RpcError>> + Send + Sync + 'static,
|
||||||
|
>
|
||||||
|
{
|
||||||
|
}
|
Loading…
Reference in a new issue