rpc-types: add traits and enum requests/responses (#241)
Some checks failed
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (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
This commit is contained in:
hinto-janai 2024-08-01 17:04:22 -04:00 committed by GitHub
parent dced4ed7ec
commit bd375eae40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 700 additions and 61 deletions

View file

@ -7,6 +7,8 @@ This crate ports the types used in Monero's RPC interface, including:
- Mixed types
- Other commonly used RPC types
It also includes some traits for these types.
# Modules
This crate's types are split in the following manner:
@ -94,6 +96,12 @@ The invariants that can be relied upon:
- Types in [`bin`] will implement `epee` correctly
- Misc types will implement `serde/epee` correctly as needed
# Requests and responses
For `enum`s that encapsulate all request/response types, see:
- [`crate::json::JsonRpcRequest`] & [`crate::json::JsonRpcResponse`]
- [`crate::bin::BinRequest`] & [`crate::bin::BinResponse`]
- [`crate::other::OtherRequest`] & [`crate::other::OtherResponse`]
# Feature flags
List of feature flags for `cuprate-rpc-types`.

View file

@ -28,6 +28,7 @@ use crate::{
HardforkEntry, HistogramEntry, OutKeyBin, OutputDistributionData, Peer, PoolInfoExtent,
PoolTxInfo, SetBan, Span, Status, TxBacklogEntry,
},
rpc_call::{RpcCall, RpcCallValue},
};
//---------------------------------------------------------------------------------------------------- Definitions
@ -393,6 +394,72 @@ impl EpeeObject for GetBlocksResponse {
}
}
//---------------------------------------------------------------------------------------------------- Request
/// Binary requests.
///
/// This enum contains all [`crate::bin`] requests.
///
/// See also: [`BinResponse`].
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum BinRequest {
GetBlocks(GetBlocksRequest),
GetBlocksByHeight(GetBlocksByHeightRequest),
GetHashes(GetHashesRequest),
GetOutputIndexes(GetOutputIndexesRequest),
GetOuts(GetOutsRequest),
GetTransactionPoolHashes(GetTransactionPoolHashesRequest),
GetOutputDistribution(crate::json::GetOutputDistributionRequest),
}
impl RpcCallValue for BinRequest {
fn is_restricted(&self) -> bool {
match self {
Self::GetBlocks(x) => x.is_restricted(),
Self::GetBlocksByHeight(x) => x.is_restricted(),
Self::GetHashes(x) => x.is_restricted(),
Self::GetOutputIndexes(x) => x.is_restricted(),
Self::GetOuts(x) => x.is_restricted(),
Self::GetTransactionPoolHashes(x) => x.is_restricted(),
Self::GetOutputDistribution(x) => x.is_restricted(),
}
}
fn is_empty(&self) -> bool {
match self {
Self::GetBlocks(x) => x.is_empty(),
Self::GetBlocksByHeight(x) => x.is_empty(),
Self::GetHashes(x) => x.is_empty(),
Self::GetOutputIndexes(x) => x.is_empty(),
Self::GetOuts(x) => x.is_empty(),
Self::GetTransactionPoolHashes(x) => x.is_empty(),
Self::GetOutputDistribution(x) => x.is_empty(),
}
}
}
//---------------------------------------------------------------------------------------------------- Response
/// Binary responses.
///
/// This enum contains all [`crate::bin`] responses.
///
/// See also: [`BinRequest`].
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[allow(missing_docs)]
pub enum BinResponse {
GetBlocks(GetBlocksResponse),
GetBlocksByHeight(GetBlocksByHeightResponse),
GetHashes(GetHashesResponse),
GetOutputIndexes(GetOutputIndexesResponse),
GetOuts(GetOutsResponse),
GetTransactionPoolHashes(GetTransactionPoolHashesResponse),
GetOutputDistribution(crate::json::GetOutputDistributionResponse),
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {

View file

@ -3,6 +3,9 @@
//! All types are originally defined in [`rpc/core_rpc_server_commands_defs.h`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h).
//---------------------------------------------------------------------------------------------------- Import
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
base::{AccessResponseBase, ResponseBase},
defaults::{
@ -16,6 +19,7 @@ use crate::{
GetMinerDataTxBacklogEntry, HardforkEntry, HistogramEntry, OutputDistributionData, SetBan,
Span, Status, SyncInfoPeer, TxBacklogEntry,
},
rpc_call::RpcCallValue,
};
//---------------------------------------------------------------------------------------------------- Macro
@ -93,7 +97,17 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 943..=994,
// The base type name.
GetBlockTemplate,
//
// After the type name, 2 optional idents are allowed:
// - `restricted`
// - `empty`
//
// These have to be within `()` and will affect the
// [`crate::RpcCall`] implementation on the request type.
//
// This type is not either restricted or empty so nothing is
// here, but the correct syntax is shown in a comment below:
GetBlockTemplate /* (restricted, empty) */,
// The request type.
//
@ -218,7 +232,7 @@ define_request_and_response! {
get_block_count,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 919..=933,
GetBlockCount,
GetBlockCount (empty),
// There are no request fields specified,
// this will cause the macro to generate a
@ -300,7 +314,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1130..=1161,
GenerateBlocks,
GenerateBlocks (restricted),
#[doc = serde_doc_test!(
GENERATE_BLOCKS_REQUEST => GenerateBlocksRequest {
@ -633,7 +647,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1734..=1754,
GetConnections,
GetConnections (restricted, empty),
Request {},
@ -708,7 +722,7 @@ define_request_and_response! {
get_info,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 693..=789,
GetInfo,
GetInfo (empty),
Request {},
#[doc = serde_doc_test!(
@ -802,7 +816,7 @@ define_request_and_response! {
hard_fork_info,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1958..=1995,
HardForkInfo,
HardForkInfo (empty),
Request {},
#[doc = serde_doc_test!(
@ -834,7 +848,8 @@ define_request_and_response! {
set_bans,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2032..=2067,
SetBans,
SetBans (restricted),
#[doc = serde_doc_test!(
SET_BANS_REQUEST => SetBansRequest {
@ -862,7 +877,7 @@ define_request_and_response! {
get_bans,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1997..=2030,
GetBans,
GetBans (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -891,7 +906,8 @@ define_request_and_response! {
banned,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2069..=2094,
Banned,
Banned (restricted),
#[doc = serde_doc_test!(
BANNED_REQUEST => BannedRequest {
@ -920,7 +936,8 @@ define_request_and_response! {
flush_txpool,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2096..=2116,
FlushTransactionPool,
FlushTransactionPool (restricted),
#[doc = serde_doc_test!(
FLUSH_TRANSACTION_POOL_REQUEST => FlushTransactionPoolRequest {
@ -986,7 +1003,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2213..=2248,
GetCoinbaseTxSum,
GetCoinbaseTxSum (restricted),
#[doc = serde_doc_test!(
GET_COINBASE_TX_SUM_REQUEST => GetCoinbaseTxSumRequest {
@ -1025,7 +1042,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2170..=2211,
GetVersion,
GetVersion (empty),
Request {},
#[doc = serde_doc_test!(
@ -1116,7 +1133,7 @@ define_request_and_response! {
get_fee_estimate,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2250..=2277,
GetFeeEstimate,
GetFeeEstimate (empty),
Request {},
#[doc = serde_doc_test!(
@ -1138,7 +1155,7 @@ define_request_and_response! {
get_alternate_chains,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2279..=2310,
GetAlternateChains,
GetAlternateChains (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -1178,7 +1195,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2361..=2381,
RelayTx,
RelayTx (restricted),
#[doc = serde_doc_test!(
RELAY_TX_REQUEST => RelayTxRequest {
@ -1205,7 +1222,8 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2383..=2443,
SyncInfo,
SyncInfo (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -1294,7 +1312,7 @@ define_request_and_response! {
get_txpool_backlog,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1637..=1664,
GetTransactionPoolBacklog,
GetTransactionPoolBacklog (empty),
Request {},
// TODO: enable test after binary string impl.
@ -1361,7 +1379,7 @@ define_request_and_response! {
get_miner_data,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 996..=1044,
GetMinerData,
GetMinerData (empty),
Request {},
#[doc = serde_doc_test!(
@ -1405,7 +1423,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2747..=2772,
PruneBlockchain,
PruneBlockchain (restricted),
#[derive(Copy)]
#[doc = serde_doc_test!(
@ -1435,7 +1453,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1046..=1066,
CalcPow,
CalcPow (restricted),
#[doc = serde_doc_test!(
CALC_POW_REQUEST => CalcPowRequest {
@ -1469,7 +1487,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2774..=2796,
FlushCache,
FlushCache (restricted),
#[derive(Copy)]
#[doc = serde_doc_test!(
@ -1534,6 +1552,203 @@ define_request_and_response! {
}
}
define_request_and_response! {
UNDOCUMENTED_METHOD,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2798..=2823,
GetTxIdsLoose,
Request {
txid_template: String,
num_matching_bits: u32,
},
ResponseBase {
txids: Vec<String>,
}
}
//---------------------------------------------------------------------------------------------------- Request
/// JSON-RPC requests.
///
/// This enum contains all [`crate::json`] requests.
///
/// See also: [`JsonRpcResponse`].
///
/// TODO: document and test (de)serialization behavior after figuring out `method/params`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(
feature = "serde",
serde(rename_all = "snake_case", tag = "method", content = "params")
)]
#[allow(missing_docs)]
pub enum JsonRpcRequest {
GetBlockCount(GetBlockCountRequest),
OnGetBlockHash(OnGetBlockHashRequest),
SubmitBlock(SubmitBlockRequest),
GenerateBlocks(GenerateBlocksRequest),
GetLastBlockHeader(GetLastBlockHeaderRequest),
GetBlockHeaderByHash(GetBlockHeaderByHashRequest),
GetBlockHeaderByHeight(GetBlockHeaderByHeightRequest),
GetBlockHeadersRange(GetBlockHeadersRangeRequest),
GetBlock(GetBlockRequest),
GetConnections(GetConnectionsRequest),
GetInfo(GetInfoRequest),
HardForkInfo(HardForkInfoRequest),
SetBans(SetBansRequest),
GetBans(GetBansRequest),
Banned(BannedRequest),
FlushTransactionPool(FlushTransactionPoolRequest),
GetOutputHistogram(GetOutputHistogramRequest),
GetCoinbaseTxSum(GetCoinbaseTxSumRequest),
GetVersion(GetVersionRequest),
GetFeeEstimate(GetFeeEstimateRequest),
GetAlternateChains(GetAlternateChainsRequest),
RelayTx(RelayTxRequest),
SyncInfo(SyncInfoRequest),
GetTransactionPoolBacklog(GetTransactionPoolBacklogRequest),
GetMinerData(GetMinerDataRequest),
PruneBlockchain(PruneBlockchainRequest),
CalcPow(CalcPowRequest),
FlushCache(FlushCacheRequest),
AddAuxPow(AddAuxPowRequest),
GetTxIdsLoose(GetTxIdsLooseRequest),
}
impl RpcCallValue for JsonRpcRequest {
fn is_restricted(&self) -> bool {
match self {
Self::GetBlockCount(x) => x.is_restricted(),
Self::OnGetBlockHash(x) => x.is_restricted(),
Self::SubmitBlock(x) => x.is_restricted(),
Self::GetLastBlockHeader(x) => x.is_restricted(),
Self::GetBlockHeaderByHash(x) => x.is_restricted(),
Self::GetBlockHeaderByHeight(x) => x.is_restricted(),
Self::GetBlockHeadersRange(x) => x.is_restricted(),
Self::GetBlock(x) => x.is_restricted(),
Self::GetInfo(x) => x.is_restricted(),
Self::HardForkInfo(x) => x.is_restricted(),
Self::GetOutputHistogram(x) => x.is_restricted(),
Self::GetVersion(x) => x.is_restricted(),
Self::GetFeeEstimate(x) => x.is_restricted(),
Self::GetTransactionPoolBacklog(x) => x.is_restricted(),
Self::GetMinerData(x) => x.is_restricted(),
Self::AddAuxPow(x) => x.is_restricted(),
Self::GetTxIdsLoose(x) => x.is_restricted(),
Self::GenerateBlocks(x) => x.is_restricted(),
Self::GetConnections(x) => x.is_restricted(),
Self::SetBans(x) => x.is_restricted(),
Self::GetBans(x) => x.is_restricted(),
Self::Banned(x) => x.is_restricted(),
Self::FlushTransactionPool(x) => x.is_restricted(),
Self::GetCoinbaseTxSum(x) => x.is_restricted(),
Self::GetAlternateChains(x) => x.is_restricted(),
Self::RelayTx(x) => x.is_restricted(),
Self::SyncInfo(x) => x.is_restricted(),
Self::PruneBlockchain(x) => x.is_restricted(),
Self::CalcPow(x) => x.is_restricted(),
Self::FlushCache(x) => x.is_restricted(),
}
}
fn is_empty(&self) -> bool {
match self {
Self::GetBlockCount(x) => x.is_empty(),
Self::OnGetBlockHash(x) => x.is_empty(),
Self::SubmitBlock(x) => x.is_empty(),
Self::GetLastBlockHeader(x) => x.is_empty(),
Self::GetBlockHeaderByHash(x) => x.is_empty(),
Self::GetBlockHeaderByHeight(x) => x.is_empty(),
Self::GetBlockHeadersRange(x) => x.is_empty(),
Self::GetBlock(x) => x.is_empty(),
Self::GetInfo(x) => x.is_empty(),
Self::HardForkInfo(x) => x.is_empty(),
Self::GetOutputHistogram(x) => x.is_empty(),
Self::GetVersion(x) => x.is_empty(),
Self::GetFeeEstimate(x) => x.is_empty(),
Self::GetTransactionPoolBacklog(x) => x.is_empty(),
Self::GetMinerData(x) => x.is_empty(),
Self::AddAuxPow(x) => x.is_empty(),
Self::GetTxIdsLoose(x) => x.is_empty(),
Self::GenerateBlocks(x) => x.is_empty(),
Self::GetConnections(x) => x.is_empty(),
Self::SetBans(x) => x.is_empty(),
Self::GetBans(x) => x.is_empty(),
Self::Banned(x) => x.is_empty(),
Self::FlushTransactionPool(x) => x.is_empty(),
Self::GetCoinbaseTxSum(x) => x.is_empty(),
Self::GetAlternateChains(x) => x.is_empty(),
Self::RelayTx(x) => x.is_empty(),
Self::SyncInfo(x) => x.is_empty(),
Self::PruneBlockchain(x) => x.is_empty(),
Self::CalcPow(x) => x.is_empty(),
Self::FlushCache(x) => x.is_empty(),
}
}
}
//---------------------------------------------------------------------------------------------------- Response
/// JSON-RPC responses.
///
/// This enum contains all [`crate::json`] responses.
///
/// See also: [`JsonRpcRequest`].
///
/// # (De)serialization
/// The `serde` implementation will (de)serialize from
/// the inner variant itself, e.g. [`JsonRpcRequest::Banned`]
/// has the same (de)serialization as [`BannedResponse`].
///
/// ```rust
/// use cuprate_rpc_types::{misc::*, json::*};
///
/// let response = JsonRpcResponse::Banned(BannedResponse {
/// banned: true,
/// seconds: 123,
/// status: Status::Ok,
/// });
/// let json = serde_json::to_string(&response).unwrap();
/// assert_eq!(json, r#"{"banned":true,"seconds":123,"status":"OK"}"#);
/// let response: JsonRpcResponse = serde_json::from_str(&json).unwrap();
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged, rename_all = "snake_case"))]
#[allow(missing_docs)]
pub enum JsonRpcResponse {
GetBlockCount(GetBlockCountResponse),
OnGetBlockHash(OnGetBlockHashResponse),
SubmitBlock(SubmitBlockResponse),
GenerateBlocks(GenerateBlocksResponse),
GetLastBlockHeader(GetLastBlockHeaderResponse),
GetBlockHeaderByHash(GetBlockHeaderByHashResponse),
GetBlockHeaderByHeight(GetBlockHeaderByHeightResponse),
GetBlockHeadersRange(GetBlockHeadersRangeResponse),
GetBlock(GetBlockResponse),
GetConnections(GetConnectionsResponse),
GetInfo(GetInfoResponse),
HardForkInfo(HardForkInfoResponse),
SetBans(SetBansResponse),
GetBans(GetBansResponse),
Banned(BannedResponse),
FlushTransactionPool(FlushTransactionPoolResponse),
GetOutputHistogram(GetOutputHistogramResponse),
GetCoinbaseTxSum(GetCoinbaseTxSumResponse),
GetVersion(GetVersionResponse),
GetFeeEstimate(GetFeeEstimateResponse),
GetAlternateChains(GetAlternateChainsResponse),
RelayTx(RelayTxResponse),
SyncInfo(SyncInfoResponse),
GetTransactionPoolBacklog(GetTransactionPoolBacklogResponse),
GetMinerData(GetMinerDataResponse),
PruneBlockchain(PruneBlockchainResponse),
CalcPow(CalcPowResponse),
FlushCache(FlushCacheResponse),
AddAuxPow(AddAuxPowResponse),
GetTxIdsLoose(GetTxIdsLooseResponse),
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {

View file

@ -112,6 +112,7 @@ mod constants;
mod defaults;
mod free;
mod macros;
mod rpc_call;
#[cfg(feature = "serde")]
mod serde;
@ -127,3 +128,4 @@ pub use constants::{
CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_VERSION, CORE_RPC_VERSION_MAJOR,
CORE_RPC_VERSION_MINOR,
};
pub use rpc_call::{RpcCall, RpcCallValue};

View file

@ -60,7 +60,14 @@ macro_rules! define_request_and_response {
// Attributes added here will apply to _both_
// request and response types.
$( #[$type_attr:meta] )*
$type_name:ident,
// After the type name, 2 optional idents are allowed:
//
// - `restricted`
// - `empty`
//
// These have to be within `()` and will affect the
// [`crate::RpcCall`] implementation on the request type.
$type_name:ident $(($restricted:ident $(, $empty:ident)?))?,
// The request type (and any doc comments, derives, etc).
$( #[$request_type_attr:meta] )*
@ -100,7 +107,7 @@ macro_rules! define_request_and_response {
$( #[$type_attr] )*
///
$( #[$request_type_attr] )*
[<$type_name Request>] {
[<$type_name Request>] $(($restricted $(, $empty)?))? {
$(
$( #[$request_field_attr] )*
$request_field: $request_field_type
@ -141,6 +148,69 @@ macro_rules! define_request_and_response {
}
pub(crate) use define_request_and_response;
//---------------------------------------------------------------------------------------------------- impl_rpc_call
/// Implement [`crate::RpcCall`] and [`crate::RpcCallValue`] on request types.
///
/// Input for this is:
/// `$REQUEST_TYPE restricted empty`
/// where `restricted` and `empty` are the idents themselves.
/// The implementation for [`crate::RpcCall`] will change
/// depending if they exist or not.
macro_rules! impl_rpc_call {
// Restricted and empty RPC calls.
($t:ident, restricted, empty) => {
impl $crate::RpcCall for $t {
const IS_RESTRICTED: bool = true;
const IS_EMPTY: bool = true;
}
impl From<()> for $t {
fn from(_: ()) -> Self {
Self {}
}
}
impl From<$t> for () {
fn from(_: $t) -> Self {}
}
};
// Empty RPC calls.
($t:ident, empty) => {
impl $crate::RpcCall for $t {
const IS_RESTRICTED: bool = false;
const IS_EMPTY: bool = true;
}
impl From<()> for $t {
fn from(_: ()) -> Self {
Self {}
}
}
impl From<$t> for () {
fn from(_: $t) -> Self {}
}
};
// Restricted RPC calls.
($t:ident, restricted) => {
impl $crate::RpcCall for $t {
const IS_RESTRICTED: bool = true;
const IS_EMPTY: bool = false;
}
};
// Not restrict or empty RPC calls.
($t:ident) => {
impl $crate::RpcCall for $t {
const IS_RESTRICTED: bool = false;
const IS_EMPTY: bool = false;
}
};
}
pub(crate) use impl_rpc_call;
//---------------------------------------------------------------------------------------------------- define_request
/// Define a request type.
///
@ -152,22 +222,7 @@ macro_rules! define_request {
// Any doc comments, derives, etc.
$( #[$attr:meta] )*
// The response type.
$t:ident {}
) => {
$( #[$attr] )*
///
/// This request has no inputs.
pub type $t = ();
};
//------------------------------------------------------------------------------
// This branch of the macro expects fields within the `{}`,
// and will generate a `struct`
(
// Any doc comments, derives, etc.
$( #[$attr:meta] )*
// The response type.
$t:ident {
$t:ident $(($restricted:ident $(, $empty:ident)?))? {
// And any fields.
$(
$( #[$field_attr:meta] )* // field attributes
@ -193,6 +248,8 @@ macro_rules! define_request {
)*
}
$crate::macros::impl_rpc_call!($t $(, $restricted $(, $empty)?)?);
#[cfg(feature = "epee")]
::cuprate_epee_encoding::epee_object! {
$t,

View file

@ -3,6 +3,9 @@
//! All types are originally defined in [`rpc/core_rpc_server_commands_defs.h`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h).
//---------------------------------------------------------------------------------------------------- Import
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
base::{AccessResponseBase, ResponseBase},
defaults::{default_false, default_string, default_true, default_vec, default_zero},
@ -11,6 +14,8 @@ use crate::{
GetOutputsOut, KeyImageSpentStatus, OutKey, Peer, PublicNode, SpentKeyImageInfo, Status,
TxEntry, TxInfo, TxpoolStats,
},
rpc_call::RpcCall,
RpcCallValue,
};
//---------------------------------------------------------------------------------------------------- Macro
@ -93,7 +98,7 @@ define_request_and_response! {
get_height,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 138..=160,
GetHeight,
GetHeight (empty),
Request {},
#[doc = serde_doc_test!(
@ -146,7 +151,7 @@ define_request_and_response! {
get_alt_blocks_hashes,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 288..=308,
GetAltBlocksHashes,
GetAltBlocksHashes (empty),
Request {},
#[doc = serde_doc_test!(
@ -258,7 +263,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 665..=691,
StartMining,
StartMining (restricted),
#[doc = serde_doc_test!(
START_MINING_REQUEST => StartMiningRequest {
@ -287,7 +292,7 @@ define_request_and_response! {
stop_mining,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 825..=843,
StopMining,
StopMining (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -302,7 +307,7 @@ define_request_and_response! {
mining_status,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 846..=895,
MiningStatus,
MiningStatus (restricted),
Request {},
#[doc = serde_doc_test!(
@ -348,7 +353,7 @@ define_request_and_response! {
save_bc,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 898..=916,
SaveBc,
SaveBc (restricted),
Request {},
#[doc = serde_doc_test!(
@ -364,7 +369,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1369..=1417,
GetPeerList,
GetPeerList (restricted),
#[doc = serde_doc_test!(
GET_PEER_LIST_REQUEST => GetPeerListRequest {
@ -446,7 +451,8 @@ define_request_and_response! {
set_log_hash_rate,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1450..=1470,
SetLogHashRate,
SetLogHashRate (restricted),
#[derive(Copy)]
#[doc = serde_doc_test!(
@ -471,7 +477,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1450..=1470,
SetLogLevel,
SetLogLevel (restricted),
#[derive(Copy)]
#[doc = serde_doc_test!(
@ -496,7 +502,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1494..=1517,
SetLogCategories,
SetLogCategories (restricted),
#[doc = serde_doc_test!(
SET_LOG_CATEGORIES_REQUEST => SetLogCategoriesRequest {
@ -523,7 +529,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1785..=1812,
SetBootstrapDaemon,
SetBootstrapDaemon (restricted),
#[doc = serde_doc_test!(
SET_BOOTSTRAP_DAEMON_REQUEST => SetBootstrapDaemonRequest {
@ -555,7 +561,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1569..=1591,
GetTransactionPool,
GetTransactionPool (empty),
Request {},
#[doc = serde_doc_test!(GET_TRANSACTION_POOL_RESPONSE)]
@ -570,7 +576,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1712..=1732,
GetTransactionPoolStats,
GetTransactionPoolStats (empty),
Request {},
#[doc = serde_doc_test!(
@ -614,7 +620,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1814..=1831,
StopDaemon,
StopDaemon (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -632,7 +638,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1852..=1874,
GetLimit,
GetLimit (empty),
Request {},
#[doc = serde_doc_test!(
@ -653,7 +659,8 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1876..=1903,
SetLimit,
SetLimit (restricted),
#[doc = serde_doc_test!(
SET_LIMIT_REQUEST => SetLimitRequest {
limit_down: 1024,
@ -684,7 +691,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1876..=1903,
OutPeers,
OutPeers (restricted),
#[doc = serde_doc_test!(
OUT_PEERS_REQUEST => OutPeersRequest {
@ -708,12 +715,26 @@ define_request_and_response! {
}
}
define_request_and_response! {
in_peers,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1932..=1956,
InPeers (restricted),
Request {
set: bool = default_true(), "default_true",
in_peers: u32,
},
ResponseBase {
in_peers: u32,
}
}
define_request_and_response! {
get_net_stats,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 793..=822,
GetNetStats,
GetNetStats (restricted, empty),
Request {},
#[doc = serde_doc_test!(
@ -786,7 +807,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2324..=2359,
Update,
Update (restricted),
#[doc = serde_doc_test!(
UPDATE_REQUEST => UpdateRequest {
@ -825,7 +846,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2722..=2745,
PopBlocks,
PopBlocks (restricted),
#[doc = serde_doc_test!(
POP_BLOCKS_REQUEST => PopBlocksRequest {
@ -852,7 +873,7 @@ define_request_and_response! {
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1615..=1635,
GetTransactionPoolHashes,
GetTransactionPoolHashes (empty),
Request {},
#[doc = serde_doc_test!(
@ -889,7 +910,8 @@ define_request_and_response! {
UNDOCUMENTED_ENDPOINT,
cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 1419..=1448,
GetPublicNodes,
GetPublicNodes (restricted),
#[doc = serde_doc_test!(
GET_PUBLIC_NODES_REQUEST => GetPublicNodesRequest {
@ -930,6 +952,178 @@ define_request_and_response! {
}
}
//---------------------------------------------------------------------------------------------------- Request
/// Other JSON requests.
///
/// This enum contains all [`crate::other`] requests.
///
/// See also: [`OtherResponse`].
///
/// # (De)serialization
/// The `serde` implementation will (de)serialize from
/// the inner variant itself, e.g. [`OtherRequest::SetLogLevel`]
/// has the same (de)serialization as [`SetLogLevelRequest`].
///
/// ```rust
/// use cuprate_rpc_types::other::*;
///
/// let request = OtherRequest::SetLogLevel(Default::default());
/// let json = serde_json::to_string(&request).unwrap();
/// assert_eq!(json, r#"{"level":0}"#);
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[allow(missing_docs)]
pub enum OtherRequest {
GetHeight(GetHeightRequest),
GetTransactions(GetTransactionsRequest),
GetAltBlocksHashes(GetAltBlocksHashesRequest),
IsKeyImageSpent(IsKeyImageSpentRequest),
SendRawTransaction(SendRawTransactionRequest),
StartMining(StartMiningRequest),
StopMining(StopMiningRequest),
MiningStatus(MiningStatusRequest),
SaveBc(SaveBcRequest),
GetPeerList(GetPeerListRequest),
SetLogHashRate(SetLogHashRateRequest),
SetLogLevel(SetLogLevelRequest),
SetLogCategories(SetLogCategoriesRequest),
SetBootstrapDaemon(SetBootstrapDaemonRequest),
GetTransactionPool(GetTransactionPoolRequest),
GetTransactionPoolStats(GetTransactionPoolStatsRequest),
StopDaemon(StopDaemonRequest),
GetLimit(GetLimitRequest),
SetLimit(SetLimitRequest),
OutPeers(OutPeersRequest),
InPeers(InPeersRequest),
GetNetStats(GetNetStatsRequest),
GetOuts(GetOutsRequest),
Update(UpdateRequest),
PopBlocks(PopBlocksRequest),
GetTransactionPoolHashes(GetTransactionPoolHashesRequest),
GetPublicNodes(GetPublicNodesRequest),
}
impl RpcCallValue for OtherRequest {
fn is_restricted(&self) -> bool {
match self {
Self::GetHeight(x) => x.is_restricted(),
Self::GetTransactions(x) => x.is_restricted(),
Self::GetAltBlocksHashes(x) => x.is_restricted(),
Self::IsKeyImageSpent(x) => x.is_restricted(),
Self::SendRawTransaction(x) => x.is_restricted(),
Self::StartMining(x) => x.is_restricted(),
Self::StopMining(x) => x.is_restricted(),
Self::MiningStatus(x) => x.is_restricted(),
Self::SaveBc(x) => x.is_restricted(),
Self::GetPeerList(x) => x.is_restricted(),
Self::SetLogHashRate(x) => x.is_restricted(),
Self::SetLogLevel(x) => x.is_restricted(),
Self::SetLogCategories(x) => x.is_restricted(),
Self::SetBootstrapDaemon(x) => x.is_restricted(),
Self::GetTransactionPool(x) => x.is_restricted(),
Self::GetTransactionPoolStats(x) => x.is_restricted(),
Self::StopDaemon(x) => x.is_restricted(),
Self::GetLimit(x) => x.is_restricted(),
Self::SetLimit(x) => x.is_restricted(),
Self::OutPeers(x) => x.is_restricted(),
Self::InPeers(x) => x.is_restricted(),
Self::GetNetStats(x) => x.is_restricted(),
Self::GetOuts(x) => x.is_restricted(),
Self::Update(x) => x.is_restricted(),
Self::PopBlocks(x) => x.is_restricted(),
Self::GetTransactionPoolHashes(x) => x.is_restricted(),
Self::GetPublicNodes(x) => x.is_restricted(),
}
}
fn is_empty(&self) -> bool {
match self {
Self::GetHeight(x) => x.is_empty(),
Self::GetTransactions(x) => x.is_empty(),
Self::GetAltBlocksHashes(x) => x.is_empty(),
Self::IsKeyImageSpent(x) => x.is_empty(),
Self::SendRawTransaction(x) => x.is_empty(),
Self::StartMining(x) => x.is_empty(),
Self::StopMining(x) => x.is_empty(),
Self::MiningStatus(x) => x.is_empty(),
Self::SaveBc(x) => x.is_empty(),
Self::GetPeerList(x) => x.is_empty(),
Self::SetLogHashRate(x) => x.is_empty(),
Self::SetLogLevel(x) => x.is_empty(),
Self::SetLogCategories(x) => x.is_empty(),
Self::SetBootstrapDaemon(x) => x.is_empty(),
Self::GetTransactionPool(x) => x.is_empty(),
Self::GetTransactionPoolStats(x) => x.is_empty(),
Self::StopDaemon(x) => x.is_empty(),
Self::GetLimit(x) => x.is_empty(),
Self::SetLimit(x) => x.is_empty(),
Self::OutPeers(x) => x.is_empty(),
Self::InPeers(x) => x.is_empty(),
Self::GetNetStats(x) => x.is_empty(),
Self::GetOuts(x) => x.is_empty(),
Self::Update(x) => x.is_empty(),
Self::PopBlocks(x) => x.is_empty(),
Self::GetTransactionPoolHashes(x) => x.is_empty(),
Self::GetPublicNodes(x) => x.is_empty(),
}
}
}
//---------------------------------------------------------------------------------------------------- Response
/// Other JSON responses.
///
/// This enum contains all [`crate::other`] responses.
///
/// See also: [`OtherRequest`].
///
/// # (De)serialization
/// The `serde` implementation will (de)serialize from
/// the inner variant itself, e.g. [`OtherRequest::SetBootstrapDaemon`]
/// has the same (de)serialization as [`SetBootstrapDaemonResponse`].
///
/// ```rust
/// use cuprate_rpc_types::other::*;
///
/// let response = OtherResponse::SetBootstrapDaemon(Default::default());
/// let json = serde_json::to_string(&response).unwrap();
/// assert_eq!(json, r#"{"status":"OK"}"#);
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[allow(missing_docs)]
pub enum OtherResponse {
GetHeight(GetHeightResponse),
GetTransactions(GetTransactionsResponse),
GetAltBlocksHashes(GetAltBlocksHashesResponse),
IsKeyImageSpent(IsKeyImageSpentResponse),
SendRawTransaction(SendRawTransactionResponse),
StartMining(StartMiningResponse),
StopMining(StopMiningResponse),
MiningStatus(MiningStatusResponse),
SaveBc(SaveBcResponse),
GetPeerList(GetPeerListResponse),
SetLogHashRate(SetLogHashRateResponse),
SetLogLevel(SetLogLevelResponse),
SetLogCategories(SetLogCategoriesResponse),
SetBootstrapDaemon(SetBootstrapDaemonResponse),
GetTransactionPool(GetTransactionPoolResponse),
GetTransactionPoolStats(GetTransactionPoolStatsResponse),
StopDaemon(StopDaemonResponse),
GetLimit(GetLimitResponse),
SetLimit(SetLimitResponse),
OutPeers(OutPeersResponse),
InPeers(InPeersResponse),
GetNetStats(GetNetStatsResponse),
GetOuts(GetOutsResponse),
Update(UpdateResponse),
PopBlocks(PopBlocksResponse),
GetTransactionPoolHashes(GetTransactionPoolHashesResponse),
GetPublicNodes(GetPublicNodesResponse),
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {

96
rpc/types/src/rpc_call.rs Normal file
View file

@ -0,0 +1,96 @@
//! RPC call metadata.
//---------------------------------------------------------------------------------------------------- Import
//---------------------------------------------------------------------------------------------------- RpcCall
/// Metadata about an RPC call.
///
/// This trait describes some metadata about RPC requests.
///
/// It is implemented on all request types within:
/// - [`crate::json`]
/// - [`crate::other`]
/// - [`crate::bin`]
///
/// See also [`RpcCallValue`] for a dynamic by-value version of this trait.
pub trait RpcCall {
/// Is `true` if this RPC method should
/// only be allowed on local servers.
///
/// If this is `false`, it should be
/// okay to execute the method even on restricted
/// RPC servers.
///
/// ```rust
/// use cuprate_rpc_types::{RpcCall, json::*};
///
/// // Allowed method, even on restricted RPC servers (18089).
/// assert!(!GetBlockCountRequest::IS_RESTRICTED);
///
/// // Restricted methods, only allowed
/// // for unrestricted RPC servers (18081).
/// assert!(GetConnectionsRequest::IS_RESTRICTED);
/// ```
const IS_RESTRICTED: bool;
/// Is `true` if this RPC method has no inputs, i.e. it is a `struct` with no fields.
///
/// ```rust
/// use cuprate_rpc_types::{RpcCall, json::*};
///
/// assert!(GetBlockCountRequest::IS_EMPTY);
/// assert!(!OnGetBlockHashRequest::IS_EMPTY);
/// ```
const IS_EMPTY: bool;
}
//---------------------------------------------------------------------------------------------------- RpcCallValue
/// By-value version of [`RpcCall`].
///
/// This trait is a mirror of [`RpcCall`],
/// except it takes `self` by value instead
/// of being a `const` property.
///
/// This exists for `enum`s where requests must be dynamically
/// `match`ed like [`JsonRpcRequest`](crate::json::JsonRpcRequest).
///
/// All types that implement [`RpcCall`] automatically implement [`RpcCallValue`].
pub trait RpcCallValue {
/// Same as [`RpcCall::IS_RESTRICTED`].
///
/// ```rust
/// use cuprate_rpc_types::{RpcCallValue, json::*};
///
/// assert!(!GetBlockCountRequest::default().is_restricted());
/// assert!(GetConnectionsRequest::default().is_restricted());
/// ```
fn is_restricted(&self) -> bool;
/// Same as [`RpcCall::IS_EMPTY`].
///
/// ```rust
/// use cuprate_rpc_types::{RpcCallValue, json::*};
///
/// assert!(GetBlockCountRequest::default().is_empty());
/// assert!(!OnGetBlockHashRequest::default().is_empty());
/// ```
fn is_empty(&self) -> bool;
}
impl<T: RpcCall> RpcCallValue for T {
#[inline]
fn is_restricted(&self) -> bool {
Self::IS_RESTRICTED
}
#[inline]
fn is_empty(&self) -> bool {
Self::IS_EMPTY
}
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
// use super::*;
}