mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
rpc: add cuprate-rpc-interface
skeleton files
This commit is contained in:
parent
aa718e224f
commit
ea8f2e681c
15 changed files with 2221 additions and 0 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -757,6 +757,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cuprate-rpc-interface"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cuprate-epee-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-rpc-types"
|
||||
|
|
|
@ -9,7 +9,11 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/rpc/cuprate-rpc-inte
|
|||
keywords = ["cuprate", "rpc", "interface"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { path = "../../net/epee-encoding" }
|
||||
|
||||
serde = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
89
rpc/interface/README.md
Normal file
89
rpc/interface/README.md
Normal file
|
@ -0,0 +1,89 @@
|
|||
Monero RPC types.
|
||||
|
||||
# What
|
||||
This crate ports the types used in Monero's RPC interface, including:
|
||||
- JSON types
|
||||
- Binary (epee) types
|
||||
- Mixed types
|
||||
- Other commonly used RPC types
|
||||
|
||||
# Modules
|
||||
This crate's types are split in the following manner:
|
||||
|
||||
| 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).
|
||||
|
||||
# Documentation
|
||||
The documentation for types within `{json,bin,other}` are omitted, as they can be found in [Monero's RPC documentation](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html).
|
||||
|
||||
However, each type will document:
|
||||
- **Definition**: the exact type definition location in `monerod`
|
||||
- **Documentation**: the Monero RPC documentation link
|
||||
- **Request/response**: the other side of this type, either the request or response
|
||||
|
||||
# Naming
|
||||
The naming for types within `{json,bin,other}` follow the following scheme:
|
||||
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`]
|
||||
|
||||
# Mixed types
|
||||
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
|
||||
{
|
||||
"string": "",
|
||||
"float": 30.0,
|
||||
"integer": 30,
|
||||
"binary": "<serialized binary>"
|
||||
}
|
||||
```
|
||||
|
||||
`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`].
|
||||
|
||||
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`
|
||||
|
||||
# Fixed byte containers
|
||||
TODO
|
||||
|
||||
<!--
|
||||
|
||||
Some fields within requests/responses are containers, but fixed in size.
|
||||
|
||||
For example, [`crate::json::GetBlockTemplateResponse::prev_hash`] is always a 32-byte hash.
|
||||
|
||||
In these cases, stack allocated types like `cuprate_fixed_bytes::StrArray`
|
||||
will be used instead of a more typical [`String`] for optimization reasons.
|
||||
|
||||
-->
|
||||
|
||||
# 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
|
11
rpc/interface/src/constants.rs
Normal file
11
rpc/interface/src/constants.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
11
rpc/interface/src/error.rs
Normal file
11
rpc/interface/src/error.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
18
rpc/interface/src/free.rs
Normal file
18
rpc/interface/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
|
||||
}
|
|
@ -1 +1,115 @@
|
|||
#![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.
|
||||
#![forbid(
|
||||
// `unsafe` is allowed but it _must_ be
|
||||
// commented with `SAFETY: reason`.
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
|
||||
// Never.
|
||||
unused_unsafe,
|
||||
redundant_semicolons,
|
||||
unused_allocation,
|
||||
coherence_leak_check,
|
||||
while_true,
|
||||
|
||||
// Maybe can be put into `#[deny]`.
|
||||
unconditional_recursion,
|
||||
for_loops_over_fallibles,
|
||||
unused_braces,
|
||||
unused_labels,
|
||||
keyword_idents,
|
||||
non_ascii_idents,
|
||||
variant_size_differences,
|
||||
single_use_lifetimes,
|
||||
|
||||
// Probably can be put into `#[deny]`.
|
||||
future_incompatible,
|
||||
let_underscore,
|
||||
break_with_label_and_loop,
|
||||
duplicate_macro_attributes,
|
||||
exported_private_dependencies,
|
||||
large_assignments,
|
||||
overlapping_range_endpoints,
|
||||
semicolon_in_expressions_from_macros,
|
||||
noop_method_call,
|
||||
)]
|
||||
// Deny lints.
|
||||
// Some of these are `#[allow]`'ed on a per-case basis.
|
||||
#![deny(
|
||||
clippy::all,
|
||||
clippy::correctness,
|
||||
clippy::suspicious,
|
||||
clippy::style,
|
||||
clippy::complexity,
|
||||
clippy::perf,
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo,
|
||||
unused_doc_comments,
|
||||
unused_mut,
|
||||
missing_docs,
|
||||
deprecated,
|
||||
unused_comparisons,
|
||||
nonstandard_style,
|
||||
unreachable_pub
|
||||
)]
|
||||
#![allow(
|
||||
// FIXME: this lint affects crates outside of
|
||||
// `database/` for some reason, allow for now.
|
||||
clippy::cargo_common_metadata,
|
||||
|
||||
// FIXME: adding `#[must_use]` onto everything
|
||||
// might just be more annoying than useful...
|
||||
// although it is sometimes nice.
|
||||
clippy::must_use_candidate,
|
||||
|
||||
// FIXME: good lint but too many false positives
|
||||
// with our `Env` + `RwLock` setup.
|
||||
clippy::significant_drop_tightening,
|
||||
|
||||
// FIXME: good lint but is less clear in most cases.
|
||||
clippy::items_after_statements,
|
||||
|
||||
// TODO
|
||||
rustdoc::bare_urls,
|
||||
|
||||
clippy::module_name_repetitions,
|
||||
clippy::module_inception,
|
||||
clippy::redundant_pub_crate,
|
||||
clippy::option_if_let_else,
|
||||
)]
|
||||
// Allow some lints when running in debug mode.
|
||||
#![cfg_attr(
|
||||
debug_assertions,
|
||||
allow(
|
||||
clippy::todo,
|
||||
clippy::multiple_crate_versions,
|
||||
unused_imports,
|
||||
unused_variables
|
||||
)
|
||||
)]
|
||||
// Allow some lints in tests.
|
||||
#![cfg_attr(
|
||||
test,
|
||||
allow(
|
||||
clippy::cognitive_complexity,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::too_many_lines
|
||||
)
|
||||
)]
|
||||
// TODO: remove me after finishing impl
|
||||
#![allow(dead_code)]
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Mod
|
||||
mod constants;
|
||||
mod error;
|
||||
mod free;
|
||||
mod macros;
|
||||
mod request;
|
||||
mod response;
|
||||
mod route;
|
||||
mod state;
|
||||
|
|
379
rpc/interface/src/macros.rs
Normal file
379
rpc/interface/src/macros.rs
Normal file
|
@ -0,0 +1,379 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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}`
|
||||
/// - `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
|
||||
/// generate which docs.
|
||||
///
|
||||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro uses:
|
||||
/// - [`__define_request`]
|
||||
/// - [`__define_response`]
|
||||
/// - [`__define_request_and_response_doc`]
|
||||
///
|
||||
/// # `__define_request`
|
||||
/// This macro has 2 branches. If the caller provides
|
||||
/// `Request {}`, i.e. no fields, it will generate:
|
||||
/// ```
|
||||
/// pub type Request = ();
|
||||
/// ```
|
||||
/// 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.
|
||||
///
|
||||
/// # `__define_response`
|
||||
/// This macro has 2 branches. If the caller provides `Response`
|
||||
/// it will generate a normal struct with no additional fields.
|
||||
///
|
||||
/// 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 {
|
||||
(
|
||||
// The markdown tag for Monero daemon 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.
|
||||
// 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 {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$request_field_attr:meta] )* // Field attribute.
|
||||
$request_field:ident: $request_field_type:ty // field_name: field type
|
||||
$(as $request_field_type_as:ty)? // (optional) alternative type (de)serialization
|
||||
$(= $request_field_type_default:expr, $request_field_type_default_string:literal)?, // (optional) default value
|
||||
)*
|
||||
},
|
||||
|
||||
// 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
|
||||
$(as $response_field_type_as:ty)?
|
||||
$(= $response_field_type_default:expr, $response_field_type_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
$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
|
||||
$(as $request_field_type_as)?
|
||||
$(= $request_field_type_default, $request_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
$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
|
||||
$(as $response_field_type_as)?
|
||||
$(= $response_field_type_default, $response_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
// 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] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub base: $base,
|
||||
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
///
|
||||
/// `__` 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:
|
||||
// - "request"
|
||||
// - "response"
|
||||
//
|
||||
// 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_type:ident,
|
||||
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
$monero_code_commit:ident,
|
||||
$monero_code_filename:ident,
|
||||
$monero_code_filename_extension:ident,
|
||||
$monero_code_line_start:literal,
|
||||
$monero_code_line_end:literal,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
"[Definition](",
|
||||
"https://github.com/monero-project/monero/blob/",
|
||||
stringify!($monero_code_commit),
|
||||
"/src/rpc/",
|
||||
stringify!($monero_code_filename),
|
||||
".",
|
||||
stringify!($monero_code_filename_extension),
|
||||
"#L",
|
||||
stringify!($monero_code_line_start),
|
||||
"-L",
|
||||
stringify!($monero_code_line_end),
|
||||
"), [documentation](",
|
||||
"https://www.getmonero.org/resources/developer-guides/daemon-rpc.html",
|
||||
"#",
|
||||
stringify!($monero_daemon_rpc_doc_link),
|
||||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
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;
|
11
rpc/interface/src/request.rs
Normal file
11
rpc/interface/src/request.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
11
rpc/interface/src/response.rs
Normal file
11
rpc/interface/src/response.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Status
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
125
rpc/interface/src/route/bin.rs
Normal file
125
rpc/interface/src/route/bin.rs
Normal file
|
@ -0,0 +1,125 @@
|
|||
//! Binary types from [`.bin` endpoints](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blocksbin).
|
||||
//!
|
||||
//! 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
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
// define_request_and_response! {
|
||||
// get_blocksbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 162..=262,
|
||||
// GetBlocks,
|
||||
// Request {
|
||||
// requested_info: u8 = default_zero(), "default_zero",
|
||||
// // FIXME: This is a `std::list` in `monerod` because...?
|
||||
// block_ids: ByteArrayVec<32>,
|
||||
// start_height: u64,
|
||||
// prune: bool,
|
||||
// no_miner_tx: bool = default_false(), "default_false",
|
||||
// pool_info_since: u64 = default_zero(), "default_zero",
|
||||
// },
|
||||
// // TODO: this has custom epee (de)serialization.
|
||||
// // <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L242-L259>
|
||||
// ResponseBase {
|
||||
// blocks: Vec<BlockCompleteEntry>,
|
||||
// start_height: u64,
|
||||
// current_height: u64,
|
||||
// output_indices: Vec<BlockOutputIndices>,
|
||||
// daemon_time: u64,
|
||||
// pool_info_extent: u8,
|
||||
// added_pool_txs: Vec<PoolTxInfo>,
|
||||
// remaining_added_pool_txids: Vec<[u8; 32]>,
|
||||
// removed_pool_txids: Vec<[u8; 32]>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_blocks_by_heightbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 264..=286,
|
||||
// GetBlocksByHeight,
|
||||
// Request {
|
||||
// heights: Vec<u64>,
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// blocks: Vec<BlockCompleteEntry>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_hashesbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 309..=338,
|
||||
// GetHashes,
|
||||
// Request {
|
||||
// block_ids: ByteArrayVec<32>,
|
||||
// start_height: u64,
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// m_blocks_ids: ByteArrayVec<32>,
|
||||
// start_height: u64,
|
||||
// current_height: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[cfg(not(feature = "epee"))]
|
||||
// define_request_and_response! {
|
||||
// get_o_indexesbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 487..=510,
|
||||
// GetOutputIndexes,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// txid: [u8; 32],
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// o_indexes: Vec<u64>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "epee")]
|
||||
// define_request_and_response! {
|
||||
// get_o_indexesbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 487..=510,
|
||||
// GetOutputIndexes,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// txid: [u8; 32],
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// o_indexes: Vec<u64> as ContainerAsBlob<u64>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_outsbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 512..=565,
|
||||
// GetOuts,
|
||||
// Request {
|
||||
// outputs: Vec<GetOutputsOut>,
|
||||
// get_txid: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// outs: Vec<OutKeyBin>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_transaction_pool_hashesbin,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1593..=1613,
|
||||
// GetTransactionPoolHashes,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// tx_hashes: ByteArrayVec<32>,
|
||||
// }
|
||||
// }
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
660
rpc/interface/src/route/json.rs
Normal file
660
rpc/interface/src/route/json.rs
Normal file
|
@ -0,0 +1,660 @@
|
|||
//! JSON types from the [`/json_rpc`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#json-rpc-methods) endpoint.
|
||||
//!
|
||||
//! 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
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Struct definitions
|
||||
// // This generates 2 structs:
|
||||
// //
|
||||
// // - `GetBlockTemplateRequest`
|
||||
// // - `GetBlockTemplateResponse`
|
||||
// //
|
||||
// // with some interconnected documentation.
|
||||
// define_request_and_response! {
|
||||
// // The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
|
||||
// get_block_template,
|
||||
|
||||
// // 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.
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 943..=994,
|
||||
|
||||
// // The base type name.
|
||||
// GetBlockTemplate,
|
||||
|
||||
// // The request type.
|
||||
// //
|
||||
// // If `Request {/* fields */}` is provided, a struct is generate as-is.
|
||||
// //
|
||||
// // 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.
|
||||
// //
|
||||
// // 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`.
|
||||
|
||||
// // This optional expression can be placed after
|
||||
// // a `field: field_type`. this indicates to the
|
||||
// // macro to (de)serialize this field using this
|
||||
// // default expression if it doesn't exist in epee.
|
||||
// //
|
||||
// // See `cuprate_epee_encoding::epee_object` for info.
|
||||
// //
|
||||
// // The default function must be specified twice:
|
||||
// //
|
||||
// // 1. As an expression
|
||||
// // 2. As a string literal
|
||||
// //
|
||||
// // For example: `extra_nonce: String /* = default_string(), "default_string" */,`
|
||||
// //
|
||||
// // This is a HACK since `serde`'s default attribute only takes in
|
||||
// // string literals and macros (stringify) within attributes do not work.
|
||||
// extra_nonce: String /* = default_expression, "default_literal" */,
|
||||
|
||||
// // Another optional expression:
|
||||
// // This indicates to the macro to (de)serialize
|
||||
// // this field as another type in epee.
|
||||
// //
|
||||
// // See `cuprate_epee_encoding::epee_object` for info.
|
||||
// prev_block: String /* as Type */,
|
||||
|
||||
// // Regular fields.
|
||||
// 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`],
|
||||
// // so the type we generate will contain this field:
|
||||
// // ```
|
||||
// // base: crate::base::ResponseBase,
|
||||
// // ```
|
||||
// //
|
||||
// // This is flattened with serde and epee, so during
|
||||
// // (de)serialization, it will act as if there are 2 extra fields here:
|
||||
// // ```
|
||||
// // status: crate::Status,
|
||||
// // untrusted: bool,
|
||||
// // ```
|
||||
// blockhashing_blob: 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,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_block_count,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 919..=933,
|
||||
// GetBlockCount,
|
||||
|
||||
// // There are no request fields specified,
|
||||
// // this will cause the macro to generate a
|
||||
// // type alias to `()` instead of a `struct`.
|
||||
// Request {},
|
||||
|
||||
// #[derive(Copy)]
|
||||
// ResponseBase {
|
||||
// count: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// on_get_block_hash,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 935..=939,
|
||||
// OnGetBlockHash,
|
||||
// /// ```rust
|
||||
// /// use serde_json::*;
|
||||
// /// use cuprate_rpc_types::json::*;
|
||||
// ///
|
||||
// /// let x = OnGetBlockHashRequest { block_height: [3] };
|
||||
// /// let x = to_string(&x).unwrap();
|
||||
// /// assert_eq!(x, "[3]");
|
||||
// /// ```
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// // This is `std::vector<u64>` in `monerod` but
|
||||
// // it must be a 1 length array or else it will error.
|
||||
// block_height: [u64; 1],
|
||||
// },
|
||||
// /// ```rust
|
||||
// /// use serde_json::*;
|
||||
// /// use cuprate_rpc_types::json::*;
|
||||
// ///
|
||||
// /// let x = OnGetBlockHashResponse { block_hash: String::from("asdf") };
|
||||
// /// let x = to_string(&x).unwrap();
|
||||
// /// assert_eq!(x, "\"asdf\"");
|
||||
// /// ```
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Response {
|
||||
// block_hash: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// submit_block,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1114..=1128,
|
||||
// SubmitBlock,
|
||||
// /// ```rust
|
||||
// /// use serde_json::*;
|
||||
// /// use cuprate_rpc_types::json::*;
|
||||
// ///
|
||||
// /// let x = SubmitBlockRequest { block_blob: ["a".into()] };
|
||||
// /// let x = to_string(&x).unwrap();
|
||||
// /// assert_eq!(x, r#"["a"]"#);
|
||||
// /// ```
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Request {
|
||||
// // This is `std::vector<std::string>` in `monerod` but
|
||||
// // it must be a 1 length array or else it will error.
|
||||
// block_blob: [String; 1],
|
||||
// },
|
||||
// ResponseBase {
|
||||
// block_id: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// generateblocks,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1130..=1161,
|
||||
// GenerateBlocks,
|
||||
// Request {
|
||||
// amount_of_blocks: u64,
|
||||
// prev_block: String,
|
||||
// starting_nonce: u32,
|
||||
// wallet_address: String,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// blocks: Vec<String>,
|
||||
// height: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_last_block_header,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1214..=1238,
|
||||
// GetLastBlockHeader,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// fill_pow_hash: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// block_header: BlockHeader,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_block_header_by_hash,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1240..=1269,
|
||||
// GetBlockHeaderByHash,
|
||||
// Request {
|
||||
// hash: String,
|
||||
// hashes: Vec<String>,
|
||||
// fill_pow_hash: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// block_header: BlockHeader,
|
||||
// block_headers: Vec<BlockHeader>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_block_header_by_height,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1271..=1296,
|
||||
// GetBlockHeaderByHeight,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// height: u64,
|
||||
// fill_pow_hash: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// block_header: BlockHeader,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_block_headers_range,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1756..=1783,
|
||||
// GetBlockHeadersRange,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// start_height: u64,
|
||||
// end_height: u64,
|
||||
// fill_pow_hash: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// headers: Vec<BlockHeader>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_block,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1298..=1313,
|
||||
// GetBlock,
|
||||
// Request {
|
||||
// // `monerod` has both `hash` and `height` fields.
|
||||
// // In the RPC handler, if `hash.is_empty()`, it will use it, else, it uses `height`.
|
||||
// // <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2674>
|
||||
// hash: String = default_string(), "default_string",
|
||||
// height: u64 = default_height(), "default_height",
|
||||
// fill_pow_hash: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// blob: String,
|
||||
// block_header: BlockHeader,
|
||||
// json: String, // TODO: this should be defined in a struct, it has many fields.
|
||||
// miner_tx_hash: String,
|
||||
// tx_hashes: Vec<String>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_connections,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1734..=1754,
|
||||
// GetConnections,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// // FIXME: This is a `std::list` in `monerod` because...?
|
||||
// connections: Vec<ConnectionInfo>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_info,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 693..=789,
|
||||
// GetInfo,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// adjusted_time: u64,
|
||||
// alt_blocks_count: u64,
|
||||
// block_size_limit: u64,
|
||||
// block_size_median: u64,
|
||||
// block_weight_limit: u64,
|
||||
// block_weight_median: u64,
|
||||
// bootstrap_daemon_address: String,
|
||||
// busy_syncing: bool,
|
||||
// cumulative_difficulty_top64: u64,
|
||||
// cumulative_difficulty: u64,
|
||||
// database_size: u64,
|
||||
// difficulty_top64: u64,
|
||||
// difficulty: u64,
|
||||
// free_space: u64,
|
||||
// grey_peerlist_size: u64,
|
||||
// height: u64,
|
||||
// height_without_bootstrap: u64,
|
||||
// incoming_connections_count: u64,
|
||||
// mainnet: bool,
|
||||
// nettype: String,
|
||||
// offline: bool,
|
||||
// outgoing_connections_count: u64,
|
||||
// restricted: bool,
|
||||
// rpc_connections_count: u64,
|
||||
// stagenet: bool,
|
||||
// start_time: u64,
|
||||
// synchronized: bool,
|
||||
// target_height: u64,
|
||||
// target: u64,
|
||||
// testnet: bool,
|
||||
// top_block_hash: String,
|
||||
// tx_count: u64,
|
||||
// tx_pool_size: u64,
|
||||
// update_available: bool,
|
||||
// version: String,
|
||||
// was_bootstrap_ever_used: bool,
|
||||
// white_peerlist_size: u64,
|
||||
// wide_cumulative_difficulty: String,
|
||||
// wide_difficulty: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// hard_fork_info,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1958..=1995,
|
||||
// HardForkInfo,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// earliest_height: u64,
|
||||
// enabled: bool,
|
||||
// state: u32,
|
||||
// threshold: u32,
|
||||
// version: u8,
|
||||
// votes: u32,
|
||||
// voting: u8,
|
||||
// window: u32,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_bans,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2032..=2067,
|
||||
// SetBans,
|
||||
// Request {
|
||||
// bans: Vec<SetBan>,
|
||||
// },
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_bans,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1997..=2030,
|
||||
// GetBans,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// bans: Vec<GetBan>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// banned,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2069..=2094,
|
||||
// Banned,
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Request {
|
||||
// address: String,
|
||||
// },
|
||||
// #[derive(Copy)]
|
||||
// Response {
|
||||
// banned: bool,
|
||||
// seconds: u32,
|
||||
// status: Status,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// flush_txpool,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2096..=2116,
|
||||
// FlushTransactionPool,
|
||||
// Request {
|
||||
// txids: Vec<String> = default_vec::<String>(), "default_vec",
|
||||
// },
|
||||
// #[derive(Copy)]
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Response {
|
||||
// status: Status,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_output_histogram,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2118..=2168,
|
||||
// GetOutputHistogram,
|
||||
// Request {
|
||||
// amounts: Vec<u64>,
|
||||
// min_count: u64,
|
||||
// max_count: u64,
|
||||
// unlocked: bool,
|
||||
// recent_cutoff: u64,
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// histogram: Vec<HistogramEntry>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_coinbase_tx_sum,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2213..=2248,
|
||||
// GetCoinbaseTxSum,
|
||||
// Request {
|
||||
// height: u64,
|
||||
// count: u64,
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// emission_amount: u64,
|
||||
// emission_amount_top64: u64,
|
||||
// fee_amount: u64,
|
||||
// fee_amount_top64: u64,
|
||||
// wide_emission_amount: String,
|
||||
// wide_fee_amount: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_version,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2170..=2211,
|
||||
// GetVersion,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// version: u32,
|
||||
// release: bool,
|
||||
// #[serde(skip_serializing_if = "is_zero")]
|
||||
// current_height: u64 = default_zero(), "default_zero",
|
||||
// #[serde(skip_serializing_if = "is_zero")]
|
||||
// target_height: u64 = default_zero(), "default_zero",
|
||||
// #[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
// hard_forks: Vec<HardforkEntry> = default_vec(), "default_vec",
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_fee_estimate,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2250..=2277,
|
||||
// GetFeeEstimate,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// fee: u64,
|
||||
// fees: Vec<u64>,
|
||||
// #[serde(skip_serializing_if = "is_one")]
|
||||
// quantization_mask: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_alternate_chains,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2279..=2310,
|
||||
// GetAlternateChains,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// chains: Vec<ChainInfo>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// relay_tx,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2361..=2381,
|
||||
// RelayTx,
|
||||
// Request {
|
||||
// txids: Vec<String>,
|
||||
// },
|
||||
// #[derive(Copy)]
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Response {
|
||||
// status: Status,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// sync_info,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2383..=2443,
|
||||
// SyncInfo,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// height: u64,
|
||||
// next_needed_pruning_seed: u32,
|
||||
// overview: String,
|
||||
// // FIXME: This is a `std::list` in `monerod` because...?
|
||||
// peers: Vec<SyncInfoPeer>,
|
||||
// // FIXME: This is a `std::list` in `monerod` because...?
|
||||
// spans: Vec<Span>,
|
||||
// target_height: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_txpool_backlog,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1637..=1664,
|
||||
// GetTransactionPoolBacklog,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// // TODO: this is a [`BinaryString`].
|
||||
// backlog: Vec<TxBacklogEntry>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_output_distribution,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2445..=2520,
|
||||
// /// This type is also used in the (undocumented)
|
||||
// /// [`/get_output_distribution.bin`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L138)
|
||||
// /// binary endpoint.
|
||||
// GetOutputDistribution,
|
||||
// Request {
|
||||
// amounts: Vec<u64>,
|
||||
// binary: bool,
|
||||
// compress: bool,
|
||||
// cumulative: bool,
|
||||
// from_height: u64,
|
||||
// to_height: u64,
|
||||
// },
|
||||
// /// TODO: this request has custom serde:
|
||||
// /// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L2468-L2508>
|
||||
// AccessResponseBase {
|
||||
// distributions: Vec<OutputDistributionData>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_miner_data,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 996..=1044,
|
||||
// GetMinerData,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// major_version: u8,
|
||||
// height: u64,
|
||||
// prev_id: String,
|
||||
// seed_hash: String,
|
||||
// difficulty: String,
|
||||
// median_weight: u64,
|
||||
// already_generated_coins: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// prune_blockchain,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2747..=2772,
|
||||
// PruneBlockchain,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// check: bool = default_false(), "default_false",
|
||||
// },
|
||||
// #[derive(Copy)]
|
||||
// ResponseBase {
|
||||
// pruned: bool,
|
||||
// pruning_seed: u32,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// calc_pow,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1046..=1066,
|
||||
// CalcPow,
|
||||
// Request {
|
||||
// major_version: u8,
|
||||
// height: u64,
|
||||
// block_blob: String,
|
||||
// seed_hash: String,
|
||||
// },
|
||||
// #[cfg_attr(feature = "serde", serde(transparent))]
|
||||
// #[repr(transparent)]
|
||||
// Response {
|
||||
// pow_hash: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// flush_cache,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2774..=2796,
|
||||
// FlushCache,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// bad_txs: bool = default_false(), "default_false",
|
||||
// bad_blocks: bool = default_false(), "default_false",
|
||||
// },
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// add_aux_pow,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1068..=1112,
|
||||
// AddAuxPow,
|
||||
// Request {
|
||||
// blocktemplate_blob: String,
|
||||
// aux_pow: Vec<AuxPow>,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// blocktemplate_blob: String,
|
||||
// blockhashing_blob: String,
|
||||
// merkle_root: String,
|
||||
// merkle_tree_depth: u64,
|
||||
// aux_pow: Vec<AuxPow>,
|
||||
// }
|
||||
// }
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
5
rpc/interface/src/route/mod.rs
Normal file
5
rpc/interface/src/route/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
//! TODO
|
||||
|
||||
mod bin;
|
||||
mod json;
|
||||
mod other;
|
400
rpc/interface/src/route/other.rs
Normal file
400
rpc/interface/src/route/other.rs
Normal file
|
@ -0,0 +1,400 @@
|
|||
//! JSON types from the [`other`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#other-daemon-rpc-calls) endpoints.
|
||||
//!
|
||||
//! 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
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
// define_request_and_response! {
|
||||
// get_height,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 138..=160,
|
||||
// GetHeight,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// hash: String,
|
||||
// height: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_transactions,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 370..=451,
|
||||
// GetTransactions,
|
||||
// Request {
|
||||
// txs_hashes: Vec<String>,
|
||||
// // FIXME: this is documented as optional but it isn't serialized as an optional
|
||||
// // but it is set _somewhere_ to false in `monerod`
|
||||
// // <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L382>
|
||||
// decode_as_json: bool = default_false(), "default_false",
|
||||
// prune: bool = default_false(), "default_false",
|
||||
// split: bool = default_false(), "default_false",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// txs_as_hex: Vec<String>,
|
||||
// txs_as_json: Vec<String>,
|
||||
// missed_tx: Vec<String>,
|
||||
// txs: Vec<TxEntry>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_alt_blocks_hashes,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 288..=308,
|
||||
// GetAltBlocksHashes,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// blks_hashes: Vec<String>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// is_key_image_spent,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 454..=484,
|
||||
// IsKeyImageSpent,
|
||||
// Request {
|
||||
// key_images: Vec<String>,
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// spent_status: Vec<u8>, // TODO: should be `KeyImageSpentStatus`.
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// send_raw_transaction,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 370..=451,
|
||||
// SendRawTransaction,
|
||||
// Request {
|
||||
// tx_as_hex: String,
|
||||
// do_not_relay: bool = default_false(), "default_false",
|
||||
// do_sanity_checks: bool = default_true(), "default_true",
|
||||
// },
|
||||
// AccessResponseBase {
|
||||
// double_spend: bool,
|
||||
// fee_too_low: bool,
|
||||
// invalid_input: bool,
|
||||
// invalid_output: bool,
|
||||
// low_mixin: bool,
|
||||
// nonzero_unlock_time: bool,
|
||||
// not_relayed: bool,
|
||||
// overspend: bool,
|
||||
// reason: String,
|
||||
// sanity_check_failed: bool,
|
||||
// too_big: bool,
|
||||
// too_few_outputs: bool,
|
||||
// tx_extra_too_big: bool,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// start_mining,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 665..=691,
|
||||
// StartMining,
|
||||
// Request {
|
||||
// miner_address: String,
|
||||
// threads_count: u64,
|
||||
// do_background_mining: bool,
|
||||
// ignore_battery: bool,
|
||||
// },
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// stop_mining,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 825..=843,
|
||||
// StopMining,
|
||||
// Request {},
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// mining_status,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 846..=895,
|
||||
// MiningStatus,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// active: bool,
|
||||
// address: String,
|
||||
// bg_idle_threshold: u8,
|
||||
// bg_ignore_battery: bool,
|
||||
// bg_min_idle_seconds: u8,
|
||||
// bg_target: u8,
|
||||
// block_reward: u64,
|
||||
// block_target: u32,
|
||||
// difficulty: u64,
|
||||
// difficulty_top64: u64,
|
||||
// is_background_mining_enabled: bool,
|
||||
// pow_algorithm: String,
|
||||
// speed: u64,
|
||||
// threads_count: u32,
|
||||
// wide_difficulty: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// save_bc,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 898..=916,
|
||||
// SaveBc,
|
||||
// Request {},
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_peer_list,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1369..=1417,
|
||||
// GetPeerList,
|
||||
// Request {
|
||||
// public_only: bool = default_true(), "default_true",
|
||||
// include_blocked: bool = default_false(), "default_false",
|
||||
// },
|
||||
// ResponseBase {
|
||||
// white_list: Vec<Peer>,
|
||||
// gray_list: Vec<Peer>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_log_hash_rate,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1450..=1470,
|
||||
// SetLogHashRate,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// visible: bool,
|
||||
// },
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_log_level,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1450..=1470,
|
||||
// SetLogLevel,
|
||||
// #[derive(Copy)]
|
||||
// Request {
|
||||
// level: u8,
|
||||
// },
|
||||
// ResponseBase {}
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_log_categories,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1494..=1517,
|
||||
// SetLogCategories,
|
||||
// Request {
|
||||
// categories: String = default_string(), "default_string",
|
||||
// },
|
||||
// ResponseBase {
|
||||
// categories: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_bootstrap_daemon,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1785..=1812,
|
||||
// SetBootstrapDaemon,
|
||||
// Request {
|
||||
// address: String,
|
||||
// username: String,
|
||||
// password: String,
|
||||
// proxy: String,
|
||||
// },
|
||||
// #[derive(Copy)]
|
||||
// Response {
|
||||
// status: Status,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_transaction_pool,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1569..=1591,
|
||||
// GetTransactionPool,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// transactions: Vec<TxInfo>,
|
||||
// spent_key_images: Vec<SpentKeyImageInfo>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_transaction_pool_stats,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1712..=1732,
|
||||
// GetTransactionPoolStats,
|
||||
// Request {},
|
||||
// AccessResponseBase {
|
||||
// pool_stats: TxpoolStats,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// stop_daemon,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1814..=1831,
|
||||
// StopDaemon,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// status: Status,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_limit,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1852..=1874,
|
||||
// GetLimit,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// limit_down: u64,
|
||||
// limit_up: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// set_limit,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1876..=1903,
|
||||
// SetLimit,
|
||||
// Request {
|
||||
// limit_down: i64,
|
||||
// limit_up: i64,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// limit_down: i64,
|
||||
// limit_up: i64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// out_peers,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1876..=1903,
|
||||
// OutPeers,
|
||||
// Request {
|
||||
// set: bool = default_true(), "default_true",
|
||||
// out_peers: u32,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// out_peers: u32,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_net_stats,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 793..=822,
|
||||
// GetNetStats,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// start_time: u64,
|
||||
// total_packets_in: u64,
|
||||
// total_bytes_in: u64,
|
||||
// total_packets_out: u64,
|
||||
// total_bytes_out: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// get_outs,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 567..=609,
|
||||
// GetOuts,
|
||||
// Request {
|
||||
// outputs: Vec<GetOutputsOut>,
|
||||
// get_txid: bool,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// outs: Vec<OutKey>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// update,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2324..=2359,
|
||||
// Update,
|
||||
// Request {
|
||||
// command: String,
|
||||
// path: String = default_string(), "default_string",
|
||||
// },
|
||||
// ResponseBase {
|
||||
// auto_uri: String,
|
||||
// hash: String,
|
||||
// path: String,
|
||||
// update: bool,
|
||||
// user_uri: String,
|
||||
// version: String,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// pop_blocks,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2722..=2745,
|
||||
// PopBlocks,
|
||||
// Request {
|
||||
// nblocks: u64,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// height: u64,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// UNDOCUMENTED_ENDPOINT,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 2798..=2823,
|
||||
// GetTxIdsLoose,
|
||||
// Request {
|
||||
// txid_template: String,
|
||||
// num_matching_bits: u32,
|
||||
// },
|
||||
// ResponseBase {
|
||||
// txids: Vec<String>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// UNDOCUMENTED_ENDPOINT,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1615..=1635,
|
||||
// GetTransactionPoolHashes,
|
||||
// Request {},
|
||||
// ResponseBase {
|
||||
// tx_hashes: Vec<String>,
|
||||
// }
|
||||
// }
|
||||
|
||||
// define_request_and_response! {
|
||||
// UNDOCUMENTED_ENDPOINT,
|
||||
// cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||
// core_rpc_server_commands_defs.h => 1419..=1448,
|
||||
// GetPublicNodes,
|
||||
// Request {
|
||||
// gray: bool = default_false(), "default_false",
|
||||
// white: bool = default_true(), "default_true",
|
||||
// include_blocked: bool = default_false(), "default_false",
|
||||
// },
|
||||
// ResponseBase {
|
||||
// gray: Vec<PublicNode>,
|
||||
// white: Vec<PublicNode>,
|
||||
// }
|
||||
// }
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
379
rpc/interface/src/state.rs
Normal file
379
rpc/interface/src/state.rs
Normal file
|
@ -0,0 +1,379 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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}`
|
||||
/// - `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
|
||||
/// generate which docs.
|
||||
///
|
||||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro uses:
|
||||
/// - [`__define_request`]
|
||||
/// - [`__define_response`]
|
||||
/// - [`__define_request_and_response_doc`]
|
||||
///
|
||||
/// # `__define_request`
|
||||
/// This macro has 2 branches. If the caller provides
|
||||
/// `Request {}`, i.e. no fields, it will generate:
|
||||
/// ```
|
||||
/// pub type Request = ();
|
||||
/// ```
|
||||
/// 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.
|
||||
///
|
||||
/// # `__define_response`
|
||||
/// This macro has 2 branches. If the caller provides `Response`
|
||||
/// it will generate a normal struct with no additional fields.
|
||||
///
|
||||
/// 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 {
|
||||
(
|
||||
// The markdown tag for Monero daemon 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.
|
||||
// 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 {
|
||||
// And any fields.
|
||||
$(
|
||||
$( #[$request_field_attr:meta] )* // Field attribute.
|
||||
$request_field:ident: $request_field_type:ty // field_name: field type
|
||||
$(as $request_field_type_as:ty)? // (optional) alternative type (de)serialization
|
||||
$(= $request_field_type_default:expr, $request_field_type_default_string:literal)?, // (optional) default value
|
||||
)*
|
||||
},
|
||||
|
||||
// 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
|
||||
$(as $response_field_type_as:ty)?
|
||||
$(= $response_field_type_default:expr, $response_field_type_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => { paste::paste! {
|
||||
$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
|
||||
$(as $request_field_type_as)?
|
||||
$(= $request_field_type_default, $request_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
$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
|
||||
$(as $response_field_type_as)?
|
||||
$(= $response_field_type_default, $response_field_type_default_string)?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
// 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] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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
|
||||
$(as $field_as:ty)?
|
||||
$(= $field_default:expr, $field_default_string:literal)?,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
pub struct $t {
|
||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||
pub base: $base,
|
||||
|
||||
$(
|
||||
$( #[$field_attr] )*
|
||||
$(#[cfg_attr(feature = "serde", serde(default = $field_default_string))])?
|
||||
pub $field: $field_type,
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
::cuprate_epee_encoding::epee_object! {
|
||||
$t,
|
||||
$(
|
||||
$field: $field_type
|
||||
$(as $field_as)?
|
||||
$(= $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.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
///
|
||||
/// `__` 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:
|
||||
// - "request"
|
||||
// - "response"
|
||||
//
|
||||
// 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_type:ident,
|
||||
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
$monero_code_commit:ident,
|
||||
$monero_code_filename:ident,
|
||||
$monero_code_filename_extension:ident,
|
||||
$monero_code_line_start:literal,
|
||||
$monero_code_line_end:literal,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
"[Definition](",
|
||||
"https://github.com/monero-project/monero/blob/",
|
||||
stringify!($monero_code_commit),
|
||||
"/src/rpc/",
|
||||
stringify!($monero_code_filename),
|
||||
".",
|
||||
stringify!($monero_code_filename_extension),
|
||||
"#L",
|
||||
stringify!($monero_code_line_start),
|
||||
"-L",
|
||||
stringify!($monero_code_line_end),
|
||||
"), [documentation](",
|
||||
"https://www.getmonero.org/resources/developer-guides/daemon-rpc.html",
|
||||
"#",
|
||||
stringify!($monero_daemon_rpc_doc_link),
|
||||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
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;
|
Loading…
Reference in a new issue