Skip to content

Commit

Permalink
rpc: start cuprate-rpc-types (#147)
Browse files Browse the repository at this point in the history
* rpc: add `monero-rpc-types`

* lib.rs: add lints

* add base files, deps

* fix macro generation, doc test

* add `strum`, add `misc` module

* document struct generation macro

* add `GetHeight`

* lib.rs: create re-export macro

* macro changes, add few more types

* docs

* `monero-rpc-types` -> `cuprate-rpc-types`

* fix modules

* specify commit in macro, add () type aliases

* macro docs, fixes

* add `Status::Other(String)`

* add TODO for `strum`

* Update rpc/types/Cargo.toml

Co-authored-by: Boog900 <[email protected]>

* add `BinaryString`

* add `ResponseBase`

* add `CORE_RPC_*` constants

* fix status; use `CORE_RPC_*` constants

* cargo.toml: add `epee_encoding`

* rpc: add epee_encoding impl for `Status`

* macro: add epee_encoding for every type

* remove `strum`

* add response bases

* add `CORE_RPC_STATUS_UNKNOWN`

* add response/request bases for epee

* create `base` module

* use different type for macro example

* move base / root types around

* docs, status serde test

* status: use `Status::Unknown` for `epee_default_value`

* json: add missing fields to `GetBlockTemplateRequest`

not sure I missed these

https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L947-L950

---------

Co-authored-by: Boog900 <[email protected]>
  • Loading branch information
hinto-janai and Boog900 authored Jun 26, 2024
1 parent 5c08d1a commit e405786
Show file tree
Hide file tree
Showing 16 changed files with 1,035 additions and 5 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ members = [
"test-utils",
"types",
"rpc/json-rpc",
"rpc/rpc-types",
"rpc/rpc-interface",
"rpc/types",
"rpc/interface",
]

[profile.release]
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion rpc/rpc-types/src/lib.rs

This file was deleted.

11 changes: 9 additions & 2 deletions rpc/rpc-types/Cargo.toml → rpc/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ edition = "2021"
description = "Monero RPC types"
license = "MIT"
authors = ["hinto-janai"]
repository = "https://github.com/Cuprate/cuprate/tree/main/rpc/monero-rpc-types"
keywords = ["monero", "rpc", "types"]
repository = "https://github.com/Cuprate/cuprate/tree/main/rpc/types"
keywords = ["cuprate", "rpc", "types", "monero"]

[features]
default = []

[dependencies]
cuprate-epee-encoding = { path = "../../net/epee-encoding" }

monero-serai = { workspace = true }
paste = { workspace = true }
serde = { workspace = true }

[dev-dependencies]
serde_json = { workspace = true }
62 changes: 62 additions & 0 deletions rpc/types/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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:

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`].

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:
- Convert the endpoint or method name into `UpperCamelCase`
- Remove any suffix extension

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.

# 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:

```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::BinaryString`] instead of [`String`].

TODO: list the specific types.
125 changes: 125 additions & 0 deletions rpc/types/src/base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//! The base data that appear in many RPC request/responses.
//!
//! These are the common "headers" or "base" types that are
//! [`flattened`](https://serde.rs/field-attrs.html#flatten)
//! into many of Monero's RPC types.
//!
//! The `Access*` structs (e.g. [`AccessResponseBase`]
//! are pseudo-deprecated structs for the RPC payment system, see:
//!
//! - <https://github.com/monero-project/monero/commit/2899379791b7542e4eb920b5d9d58cf232806937>
//! - <https://github.com/monero-project/monero/issues/8722>
//! - <https://github.com/monero-project/monero/pull/8843>

//---------------------------------------------------------------------------------------------------- Import
use serde::{Deserialize, Serialize};

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),
")."
)
};
}

//---------------------------------------------------------------------------------------------------- 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)]
pub struct AccessRequestBase {
/// The RPC payment client.
pub client: String,
}

cuprate_epee_encoding::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,
}

/// 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,
)]
pub struct ResponseBase {
/// General RPC error code. [`Status::Ok`] means everything looks good.
pub status: Status,
/// States if the result is obtained using the bootstrap mode,
/// and is therefore not trusted (`true`), or when the daemon
/// is fully synced and thus handles the RPC locally (`false`).
pub untrusted: bool,
}

epee_object! {
ResponseBase,
status: Status,
untrusted: bool,
}

/// 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)]
pub struct AccessResponseBase {
/// A flattened [`ResponseBase`].
#[serde(flatten)]
pub response_base: ResponseBase,
/// If payment for RPC is enabled, the number of credits
/// available to the requesting client. Otherwise, `0`.
pub credits: u64,
/// If payment for RPC is enabled, the hash of the
/// highest block in the chain. Otherwise, empty.
pub top_hash: String,
}

epee_object! {
AccessResponseBase,
credits: u64,
top_hash: String,
!flatten: response_base: ResponseBase,
}

//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
// use super::*;
}
11 changes: 11 additions & 0 deletions rpc/types/src/bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Binary types from [binary](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blocksbin) endpoints.

//---------------------------------------------------------------------------------------------------- Import

//---------------------------------------------------------------------------------------------------- TODO

//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
// use super::*;
}
29 changes: 29 additions & 0 deletions rpc/types/src/binary_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! TODO

//---------------------------------------------------------------------------------------------------- Import

//---------------------------------------------------------------------------------------------------- BinaryString
/// TODO
///
/// ```rust
/// use serde::Deserialize;
/// use serde_json::from_str;
/// use cuprate_rpc_types::BinaryString;
///
/// #[derive(Deserialize)]
/// struct Key {
/// key: BinaryString,
/// }
///
/// let binary = r"�\b����������";
/// let json = format!("{{\"key\":\"{binary}\"}}");
/// let key = from_str::<Key>(&json).unwrap();
/// let binary: BinaryString = key.key;
/// ```
pub type BinaryString = String;

//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
// use super::*;
}
65 changes: 65 additions & 0 deletions rpc/types/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! TODO

// From: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L83-L89>
//
// ```
// When making *any* change here, bump minor
// If the change is incompatible, then bump major and set minor to 0
// This ensures CORE_RPC_VERSION always increases, that every change
// has its own version, and that clients can just test major to see
// whether they can talk to a given daemon without having to know in
// advance which version they will stop working with
// Don't go over 32767 for any of these
// ```
//
// What this means for Cuprate: just follow `monerod`.

//---------------------------------------------------------------------------------------------------- Import

//---------------------------------------------------------------------------------------------------- Status
// Common RPC status strings:
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L78-L81>.
//
// 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>
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>
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>
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>
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
/// 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;

/// 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;

/// 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
#[cfg(test)]
mod test {
// use super::*;
}
Loading

0 comments on commit e405786

Please sign in to comment.