mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 11:39:26 +00:00
rpc: feature flags, macro changes, misc setup (#218)
* `serde/epee` feature flags * modify type generator macros * add `defaults.rs` * add `free.rs` * add `misc` module * modify `base.rs`, `contants.rs` * remove `binary_string.rs`, `status.rs` * fix macro usage * base: re-add `AccessRequestBase` * fix default functions * tx_entry: fix link
This commit is contained in:
parent
a82c08cc80
commit
136abf7edd
18 changed files with 1259 additions and 364 deletions
|
@ -9,14 +9,16 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/rpc/types"
|
|||
keywords = ["cuprate", "rpc", "types", "monero"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["serde", "epee"]
|
||||
serde = ["dep:serde"]
|
||||
epee = ["dep:cuprate-epee-encoding"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { path = "../../net/epee-encoding" }
|
||||
cuprate-epee-encoding = { path = "../../net/epee-encoding", optional = true }
|
||||
|
||||
monero-serai = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
@ -10,13 +10,14 @@ This crate ports the types used in Monero's RPC interface, including:
|
|||
# Modules
|
||||
This crate's types are split in the following manner:
|
||||
|
||||
This crate has 4 modules:
|
||||
- The root module; `cuprate_rpc_types`
|
||||
- [`json`] module; JSON types from the `/json_rpc` endpoint
|
||||
- [`bin`] module; Binary types from the binary endpoints
|
||||
- [`other`] module; Misc JSON types from other endpoints
|
||||
|
||||
Miscellaneous types are found in the root module, e.g. [`crate::Status`].
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| The root module | Miscellaneous items, e.g. constants.
|
||||
| [`json`] | Contains JSON request/response (some mixed with binary) that all share the common `/json_rpc` endpoint. |
|
||||
| [`bin`] | Contains request/response types that are expected to be fully in binary (`cuprate_epee_encoding`) in `monerod` and `cuprated`'s RPC interface. These are called at a custom endpoint instead of `/json_rpc`, e.g. `/get_blocks.bin`. |
|
||||
| [`other`] | Contains request/response types that are JSON, but aren't called at `/json_rpc` (e.g. [`crate::other::GetHeightRequest`]). |
|
||||
| [`misc`] | Contains miscellaneous types, e.g. [`crate::misc::Status`]. Many of types here are found and used in request/response types, for example, [`crate::misc::BlockHeader`] is used in [`crate::json::GetLastBlockHeaderResponse`]. |
|
||||
| [`base`] | Contains base types flattened into many request/response types.
|
||||
|
||||
Each type in `{json,bin,other}` come in pairs and have identical names, but are suffixed with either `Request` or `Response`. e.g. [`GetBlockCountRequest`](crate::json::GetBlockCountRequest) & [`GetBlockCountResponse`](crate::json::GetBlockCountResponse).
|
||||
|
||||
|
@ -30,23 +31,21 @@ However, each type will document:
|
|||
|
||||
# Naming
|
||||
The naming for types within `{json,bin,other}` follow the following scheme:
|
||||
- Convert the endpoint or method name into `UpperCamelCase`
|
||||
- Remove any suffix extension
|
||||
1. Convert the endpoint or method name into `UpperCamelCase`
|
||||
1. Remove any suffix extension
|
||||
1. Add `Request/Response` suffix
|
||||
|
||||
For example:
|
||||
|
||||
| Endpoint/method | Crate location and name |
|
||||
|-----------------|-------------------------|
|
||||
| [`get_block_count`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_block_count) | [`json::GetBlockCountRequest`] & [`json::GetBlockCountResponse`]
|
||||
| [`/get_blocks.bin`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blockbin) | `bin::GetBlocksRequest` & `bin::GetBlocksResponse`
|
||||
| [`/get_height`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_height) | `other::GetHeightRequest` & `other::GetHeightResponse`
|
||||
|
||||
TODO: fix doc links when types are ready.
|
||||
| [`/get_blocks.bin`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blockbin) | [`bin::GetBlocksRequest`] & [`bin::GetBlocksResponse`]
|
||||
| [`/get_height`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_height) | [`other::GetHeightRequest`] & [`other::GetHeightResponse`]
|
||||
|
||||
# Mixed types
|
||||
Note that some types within [`other`] mix JSON & binary together, i.e.,
|
||||
the message overall is JSON, however some fields contain binary
|
||||
values inside JSON strings, for example:
|
||||
Note that some types mix JSON & binary together, i.e., the message overall is JSON,
|
||||
however some fields contain binary values inside JSON strings, for example:
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -57,6 +56,20 @@ values inside JSON strings, for example:
|
|||
}
|
||||
```
|
||||
|
||||
`binary` here is (de)serialized as a normal [`String`]. In order to be clear on which fields contain binary data, the struct fields that have them will use [`crate::BinaryString`] instead of [`String`].
|
||||
`binary` here is (de)serialized as a normal [`String`]. In order to be clear on which fields contain binary data, the struct fields that have them will use [`crate::misc::BinaryString`] instead of [`String`].
|
||||
|
||||
TODO: list the specific types.
|
||||
These mixed types are:
|
||||
- [`crate::json::GetTransactionPoolBacklogResponse`]
|
||||
- [`crate::json::GetOutputDistributionResponse`]
|
||||
|
||||
TODO: we need to figure out a type that (de)serializes correctly, `String` errors with `serde_json`
|
||||
|
||||
# Feature flags
|
||||
List of feature flags for `cuprate-rpc-types`.
|
||||
|
||||
All are enabled by default.
|
||||
|
||||
| Feature flag | Does what |
|
||||
|--------------|-----------|
|
||||
| `serde` | Implements `serde` on all types
|
||||
| `epee` | Implements `cuprate_epee_encoding` on all types
|
|
@ -10,76 +10,44 @@
|
|||
//! - <https://github.com/monero-project/monero/commit/2899379791b7542e4eb920b5d9d58cf232806937>
|
||||
//! - <https://github.com/monero-project/monero/issues/8722>
|
||||
//! - <https://github.com/monero-project/monero/pull/8843>
|
||||
//!
|
||||
//! Note that this library doesn't use [`AccessRequestBase`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L114-L122) found in `monerod`
|
||||
//! as the type is practically deprecated.
|
||||
//!
|
||||
//! Although, [`AccessResponseBase`] still exists as to allow
|
||||
//! outputting the same JSON fields as `monerod` (even if deprecated).
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::epee_object;
|
||||
|
||||
use crate::Status;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Macro
|
||||
/// Link the original `monerod` definition for RPC base types.
|
||||
macro_rules! monero_rpc_base_link {
|
||||
($start:literal..=$end:literal) => {
|
||||
concat!(
|
||||
"[Definition](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L",
|
||||
stringify!($start),
|
||||
"-L",
|
||||
stringify!($end),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
use crate::{macros::monero_definition_link, misc::Status};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Requests
|
||||
/// The most common base for responses (nothing).
|
||||
///
|
||||
#[doc = monero_rpc_base_link!(95..=99)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct EmptyRequestBase;
|
||||
|
||||
cuprate_epee_encoding::epee_object! {
|
||||
EmptyRequestBase,
|
||||
}
|
||||
|
||||
/// A base for RPC request types that support RPC payment.
|
||||
///
|
||||
#[doc = monero_rpc_base_link!(114..=122)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "rpc/core_rpc_server_commands_defs.h", 114..=122)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct AccessRequestBase {
|
||||
/// The RPC payment client.
|
||||
pub client: String,
|
||||
}
|
||||
|
||||
cuprate_epee_encoding::epee_object! {
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
AccessRequestBase,
|
||||
client: String,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Responses
|
||||
/// An empty response base.
|
||||
///
|
||||
/// This is for response types that do not contain
|
||||
/// any extra fields, e.g. TODO.
|
||||
// [`CalcPowResponse`](crate::json::CalcPowResponse).
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct EmptyResponseBase;
|
||||
|
||||
cuprate_epee_encoding::epee_object! {
|
||||
EmptyResponseBase,
|
||||
}
|
||||
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "rpc/core_rpc_server_commands_defs.h", 101..=112)]
|
||||
/// The most common base for responses.
|
||||
///
|
||||
#[doc = monero_rpc_base_link!(101..=112)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct ResponseBase {
|
||||
/// General RPC error code. [`Status::Ok`] means everything looks good.
|
||||
pub status: Status,
|
||||
|
@ -89,19 +57,20 @@ pub struct ResponseBase {
|
|||
pub untrusted: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
ResponseBase,
|
||||
status: Status,
|
||||
untrusted: bool,
|
||||
}
|
||||
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "rpc/core_rpc_server_commands_defs.h", 124..=136)]
|
||||
/// A base for RPC response types that support RPC payment.
|
||||
///
|
||||
#[doc = monero_rpc_base_link!(124..=136)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct AccessResponseBase {
|
||||
/// A flattened [`ResponseBase`].
|
||||
#[serde(flatten)]
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub response_base: ResponseBase,
|
||||
/// If payment for RPC is enabled, the number of credits
|
||||
/// available to the requesting client. Otherwise, `0`.
|
||||
|
@ -111,6 +80,7 @@ pub struct AccessResponseBase {
|
|||
pub top_hash: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
AccessResponseBase,
|
||||
credits: u64,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// What this means for Cuprate: just follow `monerod`.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use crate::macros::monero_definition_link;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
// Common RPC status strings:
|
||||
|
@ -23,39 +24,32 @@
|
|||
// Note that these are _distinct_ from the ones in ZMQ:
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/message.cpp#L40-L44>.
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L78>
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 78)]
|
||||
pub const CORE_RPC_STATUS_OK: &str = "OK";
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L79>
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 79)]
|
||||
pub const CORE_RPC_STATUS_BUSY: &str = "BUSY";
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L80>
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 80)]
|
||||
pub const CORE_RPC_STATUS_NOT_MINING: &str = "NOT MINING";
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L81>
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 81)]
|
||||
pub const CORE_RPC_STATUS_PAYMENT_REQUIRED: &str = "PAYMENT REQUIRED";
|
||||
|
||||
/// Custom `CORE_RPC_STATUS` for usage in Cuprate.
|
||||
pub const CORE_RPC_STATUS_UNKNOWN: &str = "UNKNOWN";
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Versions
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 90)]
|
||||
/// RPC major version.
|
||||
///
|
||||
/// See: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L90>.
|
||||
pub const CORE_RPC_VERSION_MAJOR: u32 = 3;
|
||||
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 91)]
|
||||
/// RPC miror version.
|
||||
///
|
||||
/// See: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L91>.
|
||||
pub const CORE_RPC_VERSION_MINOR: u32 = 14;
|
||||
|
||||
#[doc = monero_definition_link!(cc73fe71162d564ffda8e549b79a350bca53c454, "/rpc/core_rpc_server_commands_defs.h", 92..=93)]
|
||||
/// RPC version.
|
||||
///
|
||||
/// See: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L92-L93>.
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(cuprate_rpc_types::CORE_RPC_VERSION, 196_622);
|
||||
/// ```
|
||||
pub const CORE_RPC_VERSION: u32 = (CORE_RPC_VERSION_MAJOR << 16) | CORE_RPC_VERSION_MINOR;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
|
|
70
rpc/types/src/defaults.rs
Normal file
70
rpc/types/src/defaults.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
//! These functions define the default values
|
||||
//! of optional fields in request/response types.
|
||||
//!
|
||||
//! For example, [`crate::json::GetBlockRequest`]
|
||||
//! has a [`crate::json::GetBlockRequest::height`]
|
||||
//! field and a [`crate::json::GetBlockRequest::hash`]
|
||||
//! field, when the RPC interface reads JSON without
|
||||
//! `height`, it will use [`default_height`] to fill that in.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::borrow::Cow;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// Default [`bool`] type used in request/response types, `false`.
|
||||
#[inline]
|
||||
pub(crate) const fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Default [`bool`] type used in _some_ request/response types, `true`.
|
||||
#[inline]
|
||||
pub(crate) const fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Default `Cow<'static, str` type used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) const fn default_cow_str() -> Cow<'static, str> {
|
||||
Cow::Borrowed("")
|
||||
}
|
||||
|
||||
/// Default [`String`] type used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) const fn default_string() -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
/// Default block height used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) const fn default_height() -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
/// Default [`Vec`] used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) const fn default_vec<T>() -> Vec<T> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
/// Default `0` value used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) fn default_zero<T: From<u8>>() -> T {
|
||||
T::from(0)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
/// Tests that [`default_zero`] returns `0` on all unsigned numbers.
|
||||
#[test]
|
||||
fn zero() {
|
||||
assert_eq!(default_zero::<usize>(), 0);
|
||||
assert_eq!(default_zero::<u64>(), 0);
|
||||
assert_eq!(default_zero::<u32>(), 0);
|
||||
assert_eq!(default_zero::<u16>(), 0);
|
||||
assert_eq!(default_zero::<u8>(), 0);
|
||||
}
|
||||
}
|
18
rpc/types/src/free.rs
Normal file
18
rpc/types/src/free.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
//! Free functions.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Serde
|
||||
// These are functions used for conditionally (de)serialization.
|
||||
|
||||
/// Returns `true` if the input `u` is equal to `0`.
|
||||
#[inline]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
|
||||
pub(crate) const fn is_zero(u: &u64) -> bool {
|
||||
*u == 0
|
||||
}
|
||||
|
||||
/// Returns `true` the input `u` is equal to `1`.
|
||||
#[inline]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
|
||||
pub(crate) const fn is_one(u: &u64) -> bool {
|
||||
*u == 1
|
||||
}
|
|
@ -3,10 +3,7 @@
|
|||
//! <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/daemon_messages.h>.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use crate::{
|
||||
base::{EmptyRequestBase, EmptyResponseBase, ResponseBase},
|
||||
macros::define_request_and_response,
|
||||
};
|
||||
use crate::{base::ResponseBase, macros::define_request_and_response};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Struct definitions
|
||||
// This generates 2 structs:
|
||||
|
@ -26,38 +23,43 @@ define_request_and_response! {
|
|||
// The base type name.
|
||||
GetBlockTemplate,
|
||||
|
||||
// The base request type.
|
||||
// The request type.
|
||||
//
|
||||
// This must be a type found in [`crate::base`].
|
||||
// It acts as a "base" that gets flattened into
|
||||
// the actually request type.
|
||||
// If `Request {/* fields */}` is provided, a struct is generate as-is.
|
||||
//
|
||||
// "Flatten" means the field(s) of a struct gets inlined
|
||||
// directly into the struct during (de)serialization, see:
|
||||
// <https://serde.rs/field-attrs.html#flatten>.
|
||||
//
|
||||
// For example here, we're using [`crate::base::EmptyRequestBase`],
|
||||
// which means that there is no extra fields flattened.
|
||||
//
|
||||
// If a request is not specified here, it will create a `type alias YOUR_REQUEST_TYPE = ()`
|
||||
// If `Request {}` is specified here, it will create a `pub type YOUR_REQUEST_TYPE = ()`
|
||||
// instead of a `struct`, see below in other macro definitions for an example.
|
||||
EmptyRequestBase {
|
||||
reserve_size: u64,
|
||||
wallet_address: String,
|
||||
prev_block: String,
|
||||
extra_nonce: String,
|
||||
},
|
||||
|
||||
// The base response type.
|
||||
//
|
||||
// This is the same as the request base type,
|
||||
// it must be a type found in [`crate::base`].
|
||||
//
|
||||
// If there are any additional attributes (`/// docs` or `#[derive]`s)
|
||||
// for the struct, they go here, e.g.:
|
||||
// #[derive(Copy)]
|
||||
Request {
|
||||
// Within the `{}` is an infinite matching pattern of:
|
||||
// ```
|
||||
// $ATTRIBUTES
|
||||
// $FIELD_NAME: $FIELD_TYPE,
|
||||
// ```
|
||||
// The struct generated and all fields are `pub`.
|
||||
extra_nonce: String,
|
||||
prev_block: String,
|
||||
reserve_size: u64,
|
||||
wallet_address: String,
|
||||
},
|
||||
|
||||
// The response type.
|
||||
//
|
||||
// If `Response {/* fields */}` is used,
|
||||
// this will generate a struct as-is.
|
||||
//
|
||||
// If a type found in [`crate::base`] is used,
|
||||
// It acts as a "base" that gets flattened into
|
||||
// the actual request type.
|
||||
//
|
||||
// "Flatten" means the field(s) of a struct gets inlined
|
||||
// directly into the struct during (de)serialization, see:
|
||||
// <https://serde.rs/field-attrs.html#flatten>.
|
||||
ResponseBase {
|
||||
// This is using `crate::base::ResponseBase`,
|
||||
// This is using [`crate::base::ResponseBase`],
|
||||
// so the type we generate will contain this field:
|
||||
// ```
|
||||
// base: crate::base::ResponseBase,
|
||||
|
@ -69,56 +71,18 @@ define_request_and_response! {
|
|||
// status: crate::Status,
|
||||
// untrusted: bool,
|
||||
// ```
|
||||
|
||||
// Within the `{}` is an infinite matching pattern of:
|
||||
// ```
|
||||
// $ATTRIBUTES
|
||||
// $FIELD_NAME: $FIELD_TYPE,
|
||||
// ```
|
||||
// The struct generated and all fields are `pub`.
|
||||
difficulty: u64,
|
||||
wide_difficulty: String,
|
||||
difficulty_top64: u64,
|
||||
height: u64,
|
||||
reserved_offset: u64,
|
||||
expected_reward: u64,
|
||||
prev_hash: String,
|
||||
seed_height: u64,
|
||||
seed_hash: String,
|
||||
next_seed_hash: String,
|
||||
blocktemplate_blob: String,
|
||||
blockhashing_blob: String,
|
||||
}
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_block_count,
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
core_rpc_server_commands_defs.h => 919..=933,
|
||||
GetBlockCount,
|
||||
|
||||
// There is no request type specified,
|
||||
// this will cause the macro to generate a
|
||||
// type alias to `()` instead of a `struct`.
|
||||
|
||||
ResponseBase {
|
||||
count: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
on_get_block_hash,
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
core_rpc_server_commands_defs.h => 935..=939,
|
||||
OnGetBlockHash,
|
||||
#[derive(Copy)]
|
||||
EmptyRequestBase {
|
||||
#[serde(flatten)]
|
||||
block_height: u64,
|
||||
},
|
||||
EmptyResponseBase {
|
||||
#[serde(flatten)]
|
||||
block_hash: String,
|
||||
blocktemplate_blob: String,
|
||||
difficulty_top64: u64,
|
||||
difficulty: u64,
|
||||
expected_reward: u64,
|
||||
height: u64,
|
||||
next_seed_hash: String,
|
||||
prev_hash: String,
|
||||
reserved_offset: u64,
|
||||
seed_hash: String,
|
||||
seed_height: u64,
|
||||
wide_difficulty: String,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
//---------------------------------------------------------------------------------------------------- Lints
|
||||
// Forbid lints.
|
||||
// Our code, and code generated (e.g macros) cannot overrule these.
|
||||
|
@ -13,7 +14,6 @@
|
|||
unused_allocation,
|
||||
coherence_leak_check,
|
||||
while_true,
|
||||
clippy::missing_docs_in_private_items,
|
||||
|
||||
// Maybe can be put into `#[deny]`.
|
||||
unconditional_recursion,
|
||||
|
@ -82,7 +82,15 @@
|
|||
clippy::option_if_let_else,
|
||||
)]
|
||||
// Allow some lints when running in debug mode.
|
||||
#![cfg_attr(debug_assertions, allow(clippy::todo, clippy::multiple_crate_versions))]
|
||||
#![cfg_attr(
|
||||
debug_assertions,
|
||||
allow(
|
||||
clippy::todo,
|
||||
clippy::multiple_crate_versions,
|
||||
unused_imports,
|
||||
unused_variables
|
||||
)
|
||||
)]
|
||||
// Allow some lints in tests.
|
||||
#![cfg_attr(
|
||||
test,
|
||||
|
@ -94,23 +102,25 @@
|
|||
)
|
||||
)]
|
||||
// TODO: remove me after finishing impl
|
||||
#![allow(dead_code)]
|
||||
#![allow(
|
||||
dead_code,
|
||||
rustdoc::broken_intra_doc_links // TODO: remove after `{bin,json,other}.rs` gets merged
|
||||
)]
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
mod binary_string;
|
||||
//---------------------------------------------------------------------------------------------------- Mod
|
||||
mod constants;
|
||||
mod defaults;
|
||||
mod free;
|
||||
mod macros;
|
||||
mod status;
|
||||
|
||||
pub use binary_string::BinaryString;
|
||||
pub mod base;
|
||||
pub mod bin;
|
||||
pub mod json;
|
||||
pub mod misc;
|
||||
pub mod other;
|
||||
|
||||
pub use constants::{
|
||||
CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
|
||||
CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN, CORE_RPC_VERSION,
|
||||
CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR,
|
||||
};
|
||||
pub use status::Status;
|
||||
|
||||
pub mod base;
|
||||
pub mod bin;
|
||||
pub mod json;
|
||||
pub mod other;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Struct definition
|
||||
/// A template for generating 2 `struct`s with a bunch of information filled out.
|
||||
///
|
||||
/// These are the RPC request and response `struct`s.
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response
|
||||
/// A template for generating the RPC request and response `struct`s.
|
||||
///
|
||||
/// These `struct`s automatically implement:
|
||||
/// - `Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash`
|
||||
/// - `serde::{Serialize, Deserialize}`
|
||||
/// - `epee_encoding::EpeeObject`
|
||||
/// - `cuprate_epee_encoding::EpeeObject`
|
||||
///
|
||||
/// It's best to see the output of this macro via the documentation
|
||||
/// of the generated structs via `cargo doc`s to see which parts
|
||||
|
@ -17,110 +15,35 @@
|
|||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro has 2 branches with almost the same output:
|
||||
/// 1. An empty `Request` type
|
||||
/// 2. An `Request` type with fields
|
||||
/// This macro uses:
|
||||
/// - [`__define_request`]
|
||||
/// - [`__define_response`]
|
||||
/// - [`__define_request_and_response_doc`]
|
||||
///
|
||||
/// The first branch is the same as the second with the exception
|
||||
/// that if the caller of this macro provides no fields, it will
|
||||
/// generate:
|
||||
/// # `__define_request`
|
||||
/// This macro has 2 branches. If the caller provides
|
||||
/// `Request {}`, i.e. no fields, it will generate:
|
||||
/// ```
|
||||
/// pub type Request = ();
|
||||
/// ```
|
||||
/// instead of:
|
||||
/// If they _did_ specify fields, it will generate:
|
||||
/// ```
|
||||
/// pub struct Request {/* fields */}
|
||||
/// ```
|
||||
///
|
||||
/// This is because having a bunch of types that are all empty structs
|
||||
/// means they are not compatible and it makes it cumbersome for end-users.
|
||||
/// Really, they semantically are empty types, so `()` is used.
|
||||
///
|
||||
/// Again, other than this, the 2 branches do (should) not differ.
|
||||
/// # `__define_response`
|
||||
/// This macro has 2 branches. If the caller provides `Response`
|
||||
/// it will generate a normal struct with no additional fields.
|
||||
///
|
||||
/// FIXME: there's probably a less painful way to branch here on input
|
||||
/// without having to duplicate 80% of the macro. Sub-macros were attempted
|
||||
/// but they ended up unreadable. So for now, make sure to fix the other
|
||||
/// branch as well when making changes. The only de-duplicated part is
|
||||
/// the doc generation with [`define_request_and_response_doc`].
|
||||
/// If the caller provides a base type from [`crate::base`], it will
|
||||
/// flatten that into the request type automatically.
|
||||
///
|
||||
/// E.g. `Response {/*...*/}` and `ResponseBase {/*...*/}`
|
||||
/// would trigger the different branches.
|
||||
macro_rules! define_request_and_response {
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects a `Request` type with no fields, i.e. `Request {}`.
|
||||
(
|
||||
// The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
|
||||
// The commit hash and `$file.$extension` in which this type is defined in
|
||||
// the Monero codebase in the `rpc/` directory, followed by the specific lines.
|
||||
$monero_code_commit:ident =>
|
||||
$monero_code_filename:ident.
|
||||
$monero_code_filename_extension:ident =>
|
||||
$monero_code_line_start:literal..=
|
||||
$monero_code_line_end:literal,
|
||||
|
||||
// The base `struct` name.
|
||||
$type_name:ident,
|
||||
|
||||
// The response type (and any doc comments, derives, etc).
|
||||
$( #[$response_type_attr:meta] )*
|
||||
$response_base_type:ty {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$response_field_attr:meta] )*
|
||||
$response_field:ident: $response_field_type:ty,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
#[doc = $crate::macros::define_request_and_response_doc!(
|
||||
"response",
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
[<$type_name Request>],
|
||||
)]
|
||||
///
|
||||
/// This request has no inputs.
|
||||
pub type [<$type_name Request>] = ();
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$response_type_attr] )*
|
||||
#[doc = $crate::macros::define_request_and_response_doc!(
|
||||
"request",
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
[<$type_name Response>],
|
||||
)]
|
||||
pub struct [<$type_name Response>] {
|
||||
#[serde(flatten)]
|
||||
pub base: $response_base_type,
|
||||
|
||||
$(
|
||||
$( #[$response_field_attr] )*
|
||||
pub $response_field: $response_field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
[<$type_name Response>],
|
||||
$(
|
||||
$response_field: $response_field_type,
|
||||
)*
|
||||
!flatten: base: $response_base_type,
|
||||
}
|
||||
}};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects a `Request` type with fields.
|
||||
(
|
||||
// The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
|
@ -134,15 +57,18 @@ macro_rules! define_request_and_response {
|
|||
$monero_code_line_end:literal,
|
||||
|
||||
// The base `struct` name.
|
||||
// Attributes added here will apply to _both_
|
||||
// request and response types.
|
||||
$( #[$type_attr:meta] )*
|
||||
$type_name:ident,
|
||||
|
||||
// The request type (and any doc comments, derives, etc).
|
||||
$( #[$request_type_attr:meta] )*
|
||||
$request_base_type:ty {
|
||||
Request {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$request_field_attr:meta] )*
|
||||
$request_field:ident: $request_field_type:ty,
|
||||
$request_field:ident: $request_field_type:ty $(= $request_field_type_default:expr)?,
|
||||
)*
|
||||
},
|
||||
|
||||
|
@ -152,84 +78,213 @@ macro_rules! define_request_and_response {
|
|||
// And any fields.
|
||||
$(
|
||||
$( #[$response_field_attr:meta] )*
|
||||
$response_field:ident: $response_field_type:ty,
|
||||
$response_field:ident: $response_field_type:ty $(= $response_field_type_default:expr)?,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
#[allow(dead_code)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$request_type_attr] )*
|
||||
#[doc = $crate::macros::define_request_and_response_doc!(
|
||||
"response",
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
[<$type_name Request>],
|
||||
)]
|
||||
pub struct [<$type_name Request>] {
|
||||
#[serde(flatten)]
|
||||
pub base: $request_base_type,
|
||||
|
||||
$(
|
||||
$( #[$request_field_attr] )*
|
||||
pub $request_field: $request_field_type,
|
||||
)*
|
||||
$crate::macros::__define_request! {
|
||||
#[doc = $crate::macros::__define_request_and_response_doc!(
|
||||
"response" => [<$type_name Response>],
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$request_type_attr] )*
|
||||
[<$type_name Request>] {
|
||||
$(
|
||||
$( #[$request_field_attr] )*
|
||||
$request_field: $request_field_type $(= $request_field_type_default)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
[<$type_name Request>],
|
||||
$(
|
||||
$request_field: $request_field_type,
|
||||
)*
|
||||
!flatten: base: $request_base_type,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$response_type_attr] )*
|
||||
#[doc = $crate::macros::define_request_and_response_doc!(
|
||||
"request",
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
[<$type_name Response>],
|
||||
)]
|
||||
pub struct [<$type_name Response>] {
|
||||
#[serde(flatten)]
|
||||
pub base: $response_base_type,
|
||||
|
||||
$(
|
||||
$( #[$response_field_attr] )*
|
||||
pub $response_field: $response_field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
[<$type_name Response>],
|
||||
$(
|
||||
$response_field: $response_field_type,
|
||||
)*
|
||||
!flatten: base: $response_base_type,
|
||||
$crate::macros::__define_response! {
|
||||
#[allow(dead_code)]
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[doc = $crate::macros::__define_request_and_response_doc!(
|
||||
"request" => [<$type_name Request>],
|
||||
$monero_daemon_rpc_doc_link,
|
||||
$monero_code_commit,
|
||||
$monero_code_filename,
|
||||
$monero_code_filename_extension,
|
||||
$monero_code_line_start,
|
||||
$monero_code_line_end,
|
||||
)]
|
||||
///
|
||||
$( #[$type_attr] )*
|
||||
///
|
||||
$( #[$response_type_attr] )*
|
||||
$response_base_type => [<$type_name Response>] {
|
||||
$(
|
||||
$( #[$response_field_attr] )*
|
||||
$response_field: $response_field_type $(= $response_field_type_default)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use define_request_and_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request
|
||||
/// Define a request type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request {
|
||||
//------------------------------------------------------------------------------
|
||||
// This branch will generate a type alias to `()` if only given `{}` as input.
|
||||
(
|
||||
// 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 {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$field_attr:meta] )* // field attributes
|
||||
// field_name: FieldType
|
||||
$field:ident: $field_type:ty $(= $field_default:expr)?,
|
||||
// The $field_default is an optional extra token that represents
|
||||
// a default value to pass to [`cuprate_epee_encoding::epee_object`],
|
||||
// see it for usage.
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
#[allow(dead_code, missing_docs)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type $(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_request;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_response
|
||||
/// Define a response type.
|
||||
///
|
||||
/// This is only used in [`define_request_and_response`], see it for docs.
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_response {
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects the literal ident
|
||||
// `Response` => $response_type_name.
|
||||
//
|
||||
// It will create a `struct` that _doesn't_ use a base from [`crate::base`],
|
||||
// for example, [`crate::json::BannedResponse`] doesn't use a base, so it
|
||||
// uses this branch.
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response type.
|
||||
Response => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty $(= $field_default:expr)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type $($field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// This version of the macro expects a `Request` base type from [`crate::bases`].
|
||||
(
|
||||
// Any doc comments, derives, etc.
|
||||
$( #[$attr:meta] )*
|
||||
// The response base type => actual name of the struct
|
||||
$base:ty => $t:ident {
|
||||
// And any fields.
|
||||
// See [`__define_request`] for docs, this does the same thing.
|
||||
$(
|
||||
$( #[$field_attr:meta] )*
|
||||
$field:ident: $field_type:ty $(= $field_default:expr)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub base: $base,
|
||||
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type $(= $field_default)?,
|
||||
)*
|
||||
!flatten: base: $base,
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use __define_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response_doc
|
||||
/// Generate documentation for the types generated
|
||||
/// by the [`define_request_and_response`] macro.
|
||||
/// by the [`__define_request_and_response`] macro.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
macro_rules! define_request_and_response_doc {
|
||||
///
|
||||
/// `__` is used to notate that this shouldn't be called directly.
|
||||
macro_rules! __define_request_and_response_doc {
|
||||
(
|
||||
// This labels the last `[request]` or `[response]`
|
||||
// hyperlink in documentation. Input is either:
|
||||
|
@ -239,7 +294,7 @@ macro_rules! define_request_and_response_doc {
|
|||
// Remember this is linking to the _other_ type,
|
||||
// so if defining a `Request` type, input should
|
||||
// be "response".
|
||||
$request_or_response:literal,
|
||||
$request_or_response:literal => $request_or_response_type:ident,
|
||||
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
$monero_code_commit:ident,
|
||||
|
@ -247,7 +302,6 @@ macro_rules! define_request_and_response_doc {
|
|||
$monero_code_filename_extension:ident,
|
||||
$monero_code_line_start:literal,
|
||||
$monero_code_line_end:literal,
|
||||
$type_name:ident,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
|
@ -269,9 +323,34 @@ macro_rules! define_request_and_response_doc {
|
|||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($type_name),
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use define_request_and_response_doc;
|
||||
pub(crate) use __define_request_and_response_doc;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Macro
|
||||
/// Output a string link to `monerod` source code.
|
||||
macro_rules! monero_definition_link {
|
||||
(
|
||||
$commit:ident, // Git commit hash
|
||||
$file_path:literal, // File path within `monerod`'s `src/`, e.g. `rpc/core_rpc_server_commands_defs.h`
|
||||
$start:literal$(..=$end:literal)? // File lines, e.g. `0..=123` or `0`
|
||||
) => {
|
||||
concat!(
|
||||
"[Definition](https://github.com/monero-project/monero/blob/",
|
||||
stringify!($commit),
|
||||
"/src/",
|
||||
$file_path,
|
||||
"#L",
|
||||
stringify!($start),
|
||||
$(
|
||||
"-L",
|
||||
stringify!($end),
|
||||
)?
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(crate) use monero_definition_link;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
//! TODO
|
||||
//! JSON string containing binary data.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- BinaryString
|
||||
/// TODO
|
||||
/// TODO: we need to figure out a type that (de)serializes correctly, `String` errors with `serde_json`
|
||||
///
|
||||
/// ```rust
|
||||
/// use serde::Deserialize;
|
||||
/// use serde_json::from_str;
|
||||
/// use cuprate_rpc_types::BinaryString;
|
||||
/// use cuprate_rpc_types::misc::BinaryString;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Key {
|
37
rpc/types/src/misc/block_complete_entry.rs
Normal file
37
rpc/types/src/misc/block_complete_entry.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::epee_object;
|
||||
|
||||
use crate::misc::TxBlobEntry;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- BlockCompleteEntry
|
||||
#[doc = crate::macros::monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
210..=221
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct BlockCompleteEntry {
|
||||
pub pruned: bool,
|
||||
pub block: String,
|
||||
pub block_weight: u64,
|
||||
pub txs: Vec<TxBlobEntry>,
|
||||
}
|
||||
|
||||
// TODO: custom epee
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
BlockCompleteEntry,
|
||||
pruned: bool,
|
||||
block: String,
|
||||
block_weight: u64,
|
||||
txs: Vec<TxBlobEntry>,
|
||||
}
|
48
rpc/types/src/misc/key_image_spent_status.rs
Normal file
48
rpc/types/src/misc/key_image_spent_status.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- KeyImageSpentStatus
|
||||
#[doc = crate::macros::monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
456..=460
|
||||
)]
|
||||
/// Used in [`crate::other::IsKeyImageSpentResponse`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(u8)]
|
||||
pub enum KeyImageSpentStatus {
|
||||
Unspent = 0,
|
||||
SpentInBlockchain = 1,
|
||||
SpentInPool = 2,
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
impl EpeeValue for KeyImageSpentStatus {
|
||||
const MARKER: Marker = <String as EpeeValue>::MARKER;
|
||||
|
||||
fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn should_write(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn epee_default_value() -> Option<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
539
rpc/types/src/misc/misc.rs
Normal file
539
rpc/types/src/misc/misc.rs
Normal file
|
@ -0,0 +1,539 @@
|
|||
//! Miscellaneous types.
|
||||
//!
|
||||
//! These are `struct`s that appear in request/response types.
|
||||
//! For example, [`crate::json::GetConnectionsResponse`] contains
|
||||
//! the [`crate::misc::ConnectionInfo`] struct defined here.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
epee_object,
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
constants::{
|
||||
CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
|
||||
CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN,
|
||||
},
|
||||
defaults::default_zero,
|
||||
macros::monero_definition_link,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Macros
|
||||
/// This macro (local to this file) defines all the misc types.
|
||||
///
|
||||
/// This macro:
|
||||
/// 1. Defines a `pub struct` with all `pub` fields
|
||||
/// 2. Implements `serde` on the struct
|
||||
/// 3. Implements `epee` on the struct
|
||||
///
|
||||
/// When using, consider documenting:
|
||||
/// - The original Monero definition site with [`monero_definition_link`]
|
||||
/// - The request/responses where the `struct` is used
|
||||
macro_rules! define_struct_and_impl_epee {
|
||||
(
|
||||
// Optional `struct` attributes.
|
||||
$( #[$struct_attr:meta] )*
|
||||
// The `struct`'s name.
|
||||
$struct_name:ident {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$field_attr:meta] )* // Field attributes
|
||||
// Field name => the type => optional `epee_object` default value.
|
||||
$field_name:ident: $field_type:ty $(= $field_default:expr)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$struct_attr] )*
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct $struct_name {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
pub $field_name: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
$struct_name,
|
||||
$(
|
||||
$field_name: $field_type $(= $field_default)?,
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Type Definitions
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1163..=1212
|
||||
)]
|
||||
///
|
||||
/// Used in:
|
||||
/// - [`crate::json::GetLastBlockHeaderResponse`]
|
||||
/// - [`crate::json::GetBlockHeaderByHashResponse`]
|
||||
/// - [`crate::json::GetBlockHeaderByHeightResponse`]
|
||||
/// - [`crate::json::GetBlockHeadersRangeResponse`]
|
||||
/// - [`crate::json::GetBlockResponse`]
|
||||
BlockHeader {
|
||||
block_size: u64,
|
||||
block_weight: u64,
|
||||
cumulative_difficulty_top64: u64,
|
||||
cumulative_difficulty: u64,
|
||||
depth: u64,
|
||||
difficulty_top64: u64,
|
||||
difficulty: u64,
|
||||
hash: String,
|
||||
height: u64,
|
||||
long_term_weight: u64,
|
||||
major_version: u8,
|
||||
miner_tx_hash: String,
|
||||
minor_version: u8,
|
||||
nonce: u32,
|
||||
num_txes: u64,
|
||||
orphan_status: bool,
|
||||
pow_hash: String,
|
||||
prev_hash: String,
|
||||
reward: u64,
|
||||
timestamp: u64,
|
||||
wide_cumulative_difficulty: String,
|
||||
wide_difficulty: String,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"cryptonote_protocol/cryptonote_protocol_defs.h",
|
||||
47..=116
|
||||
)]
|
||||
/// Used in [`crate::json::GetConnectionsResponse`].
|
||||
ConnectionInfo {
|
||||
address: String,
|
||||
address_type: u8,
|
||||
avg_download: u64,
|
||||
avg_upload: u64,
|
||||
connection_id: String,
|
||||
current_download: u64,
|
||||
current_upload: u64,
|
||||
height: u64,
|
||||
host: String,
|
||||
incoming: bool,
|
||||
ip: String,
|
||||
live_time: u64,
|
||||
localhost: bool,
|
||||
local_ip: bool,
|
||||
peer_id: String,
|
||||
port: String,
|
||||
pruning_seed: u32,
|
||||
recv_count: u64,
|
||||
recv_idle_time: u64,
|
||||
rpc_credits_per_hash: u32,
|
||||
rpc_port: u16,
|
||||
send_count: u64,
|
||||
send_idle_time: u64,
|
||||
ssl: bool,
|
||||
state: String,
|
||||
support_flags: u32,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2034..=2047
|
||||
)]
|
||||
/// Used in [`crate::json::SetBansRequest`].
|
||||
SetBan {
|
||||
host: String,
|
||||
ip: u32,
|
||||
ban: bool,
|
||||
seconds: u32,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1999..=2010
|
||||
)]
|
||||
/// Used in [`crate::json::GetBansResponse`].
|
||||
GetBan {
|
||||
host: String,
|
||||
ip: u32,
|
||||
seconds: u32,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2139..=2156
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
/// Used in [`crate::json::GetOutputHistogramResponse`].
|
||||
HistogramEntry {
|
||||
amount: u64,
|
||||
total_instances: u64,
|
||||
unlocked_instances: u64,
|
||||
recent_instances: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2180..=2191
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
/// Used in [`crate::json::GetVersionResponse`].
|
||||
HardforkEntry {
|
||||
height: u64,
|
||||
hf_version: u8,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2289..=2310
|
||||
)]
|
||||
/// Used in [`crate::json::GetAlternateChainsResponse`].
|
||||
ChainInfo {
|
||||
block_hash: String,
|
||||
block_hashes: Vec<String>,
|
||||
difficulty: u64,
|
||||
difficulty_top64: u64,
|
||||
height: u64,
|
||||
length: u64,
|
||||
main_chain_parent_block: String,
|
||||
wide_difficulty: String,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2393..=2400
|
||||
)]
|
||||
/// Used in [`crate::json::SyncInfoResponse`].
|
||||
SyncInfoPeer {
|
||||
info: ConnectionInfo,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
2402..=2421
|
||||
)]
|
||||
/// Used in [`crate::json::SyncInfoResponse`].
|
||||
Span {
|
||||
connection_id: String,
|
||||
nblocks: u64,
|
||||
rate: u32,
|
||||
remote_address: String,
|
||||
size: u64,
|
||||
speed: u32,
|
||||
start_block_height: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1637..=1642
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
/// Used in [`crate::json::GetTransactionPoolBacklogResponse`].
|
||||
TxBacklogEntry {
|
||||
weight: u64,
|
||||
fee: u64,
|
||||
time_in_pool: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/rpc_handler.h",
|
||||
45..=50
|
||||
)]
|
||||
/// Used in [`crate::json::GetOutputDistributionResponse`].
|
||||
OutputDistributionData {
|
||||
distribution: Vec<u64>,
|
||||
start_height: u64,
|
||||
base: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1016..=1027
|
||||
)]
|
||||
/// Used in [`crate::json::GetMinerDataResponse`].
|
||||
///
|
||||
/// Note that this is different than [`crate::misc::TxBacklogEntry`].
|
||||
GetMinerDataTxBacklogEntry {
|
||||
id: String,
|
||||
weight: u64,
|
||||
fee: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1070..=1079
|
||||
)]
|
||||
/// Used in [`crate::json::AddAuxPowRequest`].
|
||||
AuxPow {
|
||||
id: String,
|
||||
hash: String,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
192..=199
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
TxOutputIndices {
|
||||
indices: Vec<u64>,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
201..=208
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
BlockOutputIndices {
|
||||
indices: Vec<TxOutputIndices>,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
210..=221
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
PoolTxInfo {
|
||||
tx_hash: [u8; 32],
|
||||
tx_blob: String,
|
||||
double_spend_seen: bool,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"cryptonote_protocol/cryptonote_protocol_defs.h",
|
||||
121..=131
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
TxBlobEntry {
|
||||
blob: String,
|
||||
prunable_hash: [u8; 32],
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
512..=521
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
///
|
||||
/// Used in:
|
||||
/// - [`crate::bin::GetOutsRequest`]
|
||||
/// - [`crate::other::GetOutsRequest`]
|
||||
GetOutputsOut {
|
||||
amount: u64,
|
||||
index: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
538..=553
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
/// Used in [`crate::bin::GetOutsRequest`].
|
||||
OutKeyBin {
|
||||
key: [u8; 32],
|
||||
mask: [u8; 32],
|
||||
unlocked: bool,
|
||||
height: u64,
|
||||
txid: [u8; 32],
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1335..=1367
|
||||
)]
|
||||
/// Used in [`crate::other::GetPeerListResponse`].
|
||||
Peer {
|
||||
id: u64,
|
||||
host: String,
|
||||
ip: u32,
|
||||
port: u16,
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_zero"))]
|
||||
rpc_port: u16 = default_zero::<u16>(),
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_zero"))]
|
||||
rpc_credits_per_hash: u32 = default_zero::<u32>(),
|
||||
last_seen: u64,
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_zero"))]
|
||||
pruning_seed: u32 = default_zero::<u32>(),
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1398..=1417
|
||||
)]
|
||||
///
|
||||
/// Used in:
|
||||
/// - [`crate::other::GetPeerListResponse`]
|
||||
/// - [`crate::other::GetPublicNodesResponse`]
|
||||
PublicNode {
|
||||
host: String,
|
||||
last_seen: u64,
|
||||
rpc_port: u16,
|
||||
rpc_credits_per_hash: u32,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1519..=1556
|
||||
)]
|
||||
/// Used in [`crate::other::GetTransactionPoolResponse`].
|
||||
TxInfo {
|
||||
blob_size: u64,
|
||||
do_not_relay: bool,
|
||||
double_spend_seen: bool,
|
||||
fee: u64,
|
||||
id_hash: String,
|
||||
kept_by_block: bool,
|
||||
last_failed_height: u64,
|
||||
last_failed_id_hash: String,
|
||||
last_relayed_time: u64,
|
||||
max_used_block_height: u64,
|
||||
max_used_block_id_hash: String,
|
||||
receive_time: u64,
|
||||
relayed: bool,
|
||||
tx_blob: String,
|
||||
tx_json: String, // TODO: this should be another struct
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_zero"))]
|
||||
weight: u64 = default_zero::<u64>(),
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1558..=1567
|
||||
)]
|
||||
/// Used in [`crate::other::GetTransactionPoolResponse`].
|
||||
SpentKeyImageInfo {
|
||||
id_hash: String,
|
||||
txs_hashes: Vec<String>,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1666..=1675
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
/// Used in [`crate::other::GetTransactionPoolStatsResponse`].
|
||||
TxpoolHisto {
|
||||
txs: u32,
|
||||
bytes: u64,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1677..=1710
|
||||
)]
|
||||
/// Used in [`crate::other::GetTransactionPoolStatsResponse`].
|
||||
TxpoolStats {
|
||||
bytes_max: u32,
|
||||
bytes_med: u32,
|
||||
bytes_min: u32,
|
||||
bytes_total: u64,
|
||||
fee_total: u64,
|
||||
histo_98pc: u64,
|
||||
histo: Vec<TxpoolHisto>,
|
||||
num_10m: u32,
|
||||
num_double_spends: u32,
|
||||
num_failing: u32,
|
||||
num_not_relayed: u32,
|
||||
oldest: u64,
|
||||
txs_total: u32,
|
||||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
582..=597
|
||||
)]
|
||||
/// Used in [`crate::other::GetOutsResponse`].
|
||||
OutKey {
|
||||
key: String,
|
||||
mask: String,
|
||||
unlocked: bool,
|
||||
height: u64,
|
||||
txid: String,
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {}
|
34
rpc/types/src/misc/mod.rs
Normal file
34
rpc/types/src/misc/mod.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
//! Miscellaneous types.
|
||||
//!
|
||||
//! These are data types that appear in request/response types.
|
||||
//!
|
||||
//! For example, [`crate::json::GetConnectionsResponse`] contains
|
||||
//! the [`crate::misc::ConnectionInfo`] struct defined here.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Lints
|
||||
#![allow(
|
||||
missing_docs, // Docs are at: <https://www.getmonero.org/resources/developer-guides/daemon-rpc.html>
|
||||
clippy::struct_excessive_bools, // hey man, tell that to the people who wrote `monerod`
|
||||
)]
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Mod
|
||||
mod binary_string;
|
||||
mod block_complete_entry;
|
||||
mod key_image_spent_status;
|
||||
mod misc;
|
||||
mod pool_info_extent;
|
||||
mod status;
|
||||
mod tx_entry;
|
||||
|
||||
pub use binary_string::BinaryString;
|
||||
pub use block_complete_entry::BlockCompleteEntry;
|
||||
pub use key_image_spent_status::KeyImageSpentStatus;
|
||||
pub use misc::{
|
||||
AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, ConnectionInfo, GetBan,
|
||||
GetMinerDataTxBacklogEntry, GetOutputsOut, HardforkEntry, HistogramEntry, OutKey, OutKeyBin,
|
||||
OutputDistributionData, Peer, PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo,
|
||||
SyncInfoPeer, TxBacklogEntry, TxBlobEntry, TxInfo, TxOutputIndices, TxpoolHisto, TxpoolStats,
|
||||
};
|
||||
pub use pool_info_extent::PoolInfoExtent;
|
||||
pub use status::Status;
|
||||
pub use tx_entry::TxEntry;
|
49
rpc/types/src/misc/pool_info_extent.rs
Normal file
49
rpc/types/src/misc/pool_info_extent.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- PoolInfoExtent
|
||||
#[doc = crate::macros::monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
223..=228
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(u8)]
|
||||
pub enum PoolInfoExtent {
|
||||
None = 0,
|
||||
Incremental = 1,
|
||||
Full = 2,
|
||||
}
|
||||
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
|
||||
#[cfg(feature = "epee")]
|
||||
impl EpeeValue for PoolInfoExtent {
|
||||
const MARKER: Marker = <String as EpeeValue>::MARKER;
|
||||
|
||||
fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn should_write(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn epee_default_value() -> Option<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@
|
|||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
|
@ -16,18 +18,20 @@ use crate::constants::{
|
|||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
// TODO: this type needs to expand more.
|
||||
// There are a lot of RPC calls that will return a random
|
||||
// string inside, which isn't compatible with [`Status`].
|
||||
|
||||
/// RPC response status.
|
||||
///
|
||||
/// This type represents `monerod`'s frequently appearing string field, `status`.
|
||||
///
|
||||
/// This field appears within RPC [JSON response](crate::json) types.
|
||||
///
|
||||
/// Reference: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L78-L81>.
|
||||
///
|
||||
/// ## Serialization and string formatting
|
||||
/// ```rust
|
||||
/// use cuprate_rpc_types::{
|
||||
/// Status,
|
||||
/// misc::Status,
|
||||
/// CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
|
||||
/// CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN
|
||||
/// };
|
||||
|
@ -59,28 +63,27 @@ use crate::constants::{
|
|||
/// assert_eq!(format!("{:?}", Status::PaymentRequired), "PaymentRequired");
|
||||
/// assert_eq!(format!("{:?}", unknown), "Unknown");
|
||||
/// ```
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum Status {
|
||||
// FIXME:
|
||||
// `#[serde(rename = "")]` only takes raw string literals?
|
||||
// We have to re-type the constants here...
|
||||
/// Successful RPC response, everything is OK; [`CORE_RPC_STATUS_OK`].
|
||||
#[serde(rename = "OK")]
|
||||
#[cfg_attr(feature = "serde", serde(rename = "OK"))]
|
||||
#[default]
|
||||
Ok,
|
||||
|
||||
/// The daemon is busy, try later; [`CORE_RPC_STATUS_BUSY`].
|
||||
#[serde(rename = "BUSY")]
|
||||
#[cfg_attr(feature = "serde", serde(rename = "BUSY"))]
|
||||
Busy,
|
||||
|
||||
/// The daemon is not mining; [`CORE_RPC_STATUS_NOT_MINING`].
|
||||
#[serde(rename = "NOT MINING")]
|
||||
#[cfg_attr(feature = "serde", serde(rename = "NOT MINING"))]
|
||||
NotMining,
|
||||
|
||||
/// Payment is required for RPC; [`CORE_RPC_STATUS_PAYMENT_REQUIRED`].
|
||||
#[serde(rename = "PAYMENT REQUIRED")]
|
||||
#[cfg_attr(feature = "serde", serde(rename = "PAYMENT REQUIRED"))]
|
||||
PaymentRequired,
|
||||
|
||||
/// Some unknown other string; [`CORE_RPC_STATUS_UNKNOWN`].
|
||||
|
@ -91,8 +94,8 @@ pub enum Status {
|
|||
/// The reason this isn't `Unknown(String)` is because that
|
||||
/// disallows [`Status`] to be [`Copy`], and thus other types
|
||||
/// that contain it.
|
||||
#[serde(other)]
|
||||
#[serde(rename = "UNKNOWN")]
|
||||
#[cfg_attr(feature = "serde", serde(other))]
|
||||
#[cfg_attr(feature = "serde", serde(rename = "UNKNOWN"))]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
|
@ -132,6 +135,7 @@ impl Display for Status {
|
|||
//
|
||||
// See below for more impl info:
|
||||
// <https://github.com/Cuprate/cuprate/blob/bef2a2cbd4e1194991751d1fbc96603cba8c7a51/net/epee-encoding/src/value.rs#L366-L392>.
|
||||
#[cfg(feature = "epee")]
|
||||
impl EpeeValue for Status {
|
||||
const MARKER: Marker = <String as EpeeValue>::MARKER;
|
||||
|
||||
|
@ -161,6 +165,7 @@ mod test {
|
|||
|
||||
// Test epee (de)serialization works.
|
||||
#[test]
|
||||
#[cfg(feature = "epee")]
|
||||
fn epee() {
|
||||
for status in [
|
||||
Status::Ok,
|
59
rpc/types/src/misc/tx_entry.rs
Normal file
59
rpc/types/src/misc/tx_entry.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
epee_object,
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TxEntry
|
||||
#[doc = crate::macros::monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
389..=428
|
||||
)]
|
||||
/// Used in [`crate::other::GetTransactionsResponse`].
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct TxEntry {
|
||||
pub as_hex: String,
|
||||
pub as_json: String,
|
||||
pub block_height: u64,
|
||||
pub block_timestamp: u64,
|
||||
pub confirmations: u64,
|
||||
pub double_spend_seen: bool,
|
||||
pub in_pool: bool,
|
||||
pub output_indices: Vec<u64>,
|
||||
pub prunable_as_hex: String,
|
||||
pub prunable_hash: String,
|
||||
pub pruned_as_hex: String,
|
||||
pub received_timestamp: u64,
|
||||
pub relayed: bool,
|
||||
pub tx_hash: String,
|
||||
}
|
||||
|
||||
// TODO: custom epee
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L406-L427>
|
||||
#[cfg(feature = "epee")]
|
||||
epee_object! {
|
||||
TxEntry,
|
||||
as_hex: String,
|
||||
as_json: String, // TODO: should be its own struct
|
||||
block_height: u64,
|
||||
block_timestamp: u64,
|
||||
confirmations: u64,
|
||||
double_spend_seen: bool,
|
||||
in_pool: bool,
|
||||
output_indices: Vec<u64>,
|
||||
prunable_as_hex: String,
|
||||
prunable_hash: String,
|
||||
pruned_as_hex: String,
|
||||
received_timestamp: u64,
|
||||
relayed: bool,
|
||||
tx_hash: String,
|
||||
}
|
|
@ -7,11 +7,15 @@ use crate::{base::ResponseBase, macros::define_request_and_response};
|
|||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
define_request_and_response! {
|
||||
save_bc,
|
||||
get_height,
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
core_rpc_server_commands_defs.h => 898..=916,
|
||||
SaveBc,
|
||||
ResponseBase {}
|
||||
core_rpc_server_commands_defs.h => 138..=160,
|
||||
GetHeight,
|
||||
Request {},
|
||||
ResponseBase {
|
||||
hash: String,
|
||||
height: u64,
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
|
|
Loading…
Reference in a new issue