cuprate_rpc_interface/route/
other_json.rs

1//! Other JSON endpoint route functions.
2
3//---------------------------------------------------------------------------------------------------- Import
4use axum::{extract::State, http::StatusCode, Json};
5use tower::ServiceExt;
6
7use cuprate_rpc_types::{
8    other::{
9        GetAltBlocksHashesRequest, GetAltBlocksHashesResponse, GetHeightRequest, GetHeightResponse,
10        GetLimitRequest, GetLimitResponse, GetNetStatsRequest, GetNetStatsResponse, GetOutsRequest,
11        GetOutsResponse, GetPeerListRequest, GetPeerListResponse, GetPublicNodesRequest,
12        GetPublicNodesResponse, GetTransactionPoolHashesRequest, GetTransactionPoolHashesResponse,
13        GetTransactionPoolRequest, GetTransactionPoolResponse, GetTransactionPoolStatsRequest,
14        GetTransactionPoolStatsResponse, GetTransactionsRequest, GetTransactionsResponse,
15        InPeersRequest, InPeersResponse, IsKeyImageSpentRequest, IsKeyImageSpentResponse,
16        MiningStatusRequest, MiningStatusResponse, OtherRequest, OtherResponse, OutPeersRequest,
17        OutPeersResponse, PopBlocksRequest, PopBlocksResponse, SaveBcRequest, SaveBcResponse,
18        SendRawTransactionRequest, SendRawTransactionResponse, SetBootstrapDaemonRequest,
19        SetBootstrapDaemonResponse, SetLimitRequest, SetLimitResponse, SetLogCategoriesRequest,
20        SetLogCategoriesResponse, SetLogHashRateRequest, SetLogHashRateResponse,
21        SetLogLevelRequest, SetLogLevelResponse, StartMiningRequest, StartMiningResponse,
22        StopDaemonRequest, StopDaemonResponse, StopMiningRequest, StopMiningResponse,
23        UpdateRequest, UpdateResponse,
24    },
25    RpcCall,
26};
27
28use crate::rpc_handler::RpcHandler;
29
30//---------------------------------------------------------------------------------------------------- Routes
31/// This macro generates route functions that expect input.
32///
33/// See below for usage.
34macro_rules! generate_endpoints_with_input {
35    ($(
36        // Syntax:
37        // Function name => Expected input type
38        $endpoint:ident => $variant:ident
39    ),*) => { paste::paste! {
40        $(
41            pub(crate) async fn $endpoint<H: RpcHandler>(
42                State(handler): State<H>,
43                Json(request): Json<[<$variant Request>]>,
44            ) -> Result<Json<[<$variant Response>]>, StatusCode> {
45                generate_endpoints_inner!($variant, handler, request)
46            }
47        )*
48    }};
49}
50
51/// This macro generates route functions that expect _no_ input.
52///
53/// See below for usage.
54macro_rules! generate_endpoints_with_no_input {
55    ($(
56        // Syntax:
57        // Function name => Expected input type (that is empty)
58        $endpoint:ident => $variant:ident
59    ),*) => { paste::paste! {
60        $(
61            pub(crate) async fn $endpoint<H: RpcHandler>(
62                State(handler): State<H>,
63            ) -> Result<Json<[<$variant Response>]>, StatusCode> {
64                generate_endpoints_inner!($variant, handler, [<$variant Request>] {})
65            }
66        )*
67    }};
68}
69
70/// De-duplicated inner function body for:
71/// - [`generate_endpoints_with_input`]
72/// - [`generate_endpoints_with_no_input`]
73macro_rules! generate_endpoints_inner {
74    ($variant:ident, $handler:ident, $request:expr_2021) => {
75        paste::paste! {
76            {
77                // Check if restricted.
78                //
79                // INVARIANT:
80                // The RPC handler functions in `cuprated` depend on this line existing,
81                // the functions themselves do not check if they are being called
82                // from an (un)restricted context. This line must be here or all
83                // methods will be allowed to be called freely.
84                if [<$variant Request>]::IS_RESTRICTED && $handler.is_restricted() {
85                    // TODO: mimic `monerod` behavior.
86                    return Err(StatusCode::FORBIDDEN);
87                }
88
89                // Send request.
90                let request = OtherRequest::$variant($request);
91                let Ok(response) = $handler.oneshot(request).await else {
92                    return Err(StatusCode::INTERNAL_SERVER_ERROR);
93                };
94
95                let OtherResponse::$variant(response) = response else {
96                    panic!("RPC handler returned incorrect response")
97                };
98
99                Ok(Json(response))
100            }
101        }
102    };
103}
104
105generate_endpoints_with_input! {
106    get_transactions => GetTransactions,
107    is_key_image_spent => IsKeyImageSpent,
108    send_raw_transaction => SendRawTransaction,
109    start_mining => StartMining,
110    get_peer_list => GetPeerList,
111    set_log_hash_rate => SetLogHashRate,
112    set_log_level => SetLogLevel,
113    set_log_categories => SetLogCategories,
114    set_bootstrap_daemon => SetBootstrapDaemon,
115    set_limit => SetLimit,
116    out_peers => OutPeers,
117    in_peers => InPeers,
118    get_outs => GetOuts,
119    update => Update,
120    pop_blocks => PopBlocks,
121    get_public_nodes => GetPublicNodes
122}
123
124generate_endpoints_with_no_input! {
125    get_height => GetHeight,
126    get_alt_blocks_hashes => GetAltBlocksHashes,
127    stop_mining => StopMining,
128    mining_status => MiningStatus,
129    save_bc => SaveBc,
130    get_transaction_pool => GetTransactionPool,
131    get_transaction_pool_stats => GetTransactionPoolStats,
132    stop_daemon => StopDaemon,
133    get_limit => GetLimit,
134    get_net_stats => GetNetStats,
135    get_transaction_pool_hashes => GetTransactionPoolHashes
136}
137
138//---------------------------------------------------------------------------------------------------- Tests
139#[cfg(test)]
140mod test {
141    // use super::*;
142}