cuprated/config/
rpc.rs

1use std::{
2    net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
3    time::Duration,
4};
5
6use serde::{Deserialize, Serialize};
7
8use cuprate_helper::network::Network;
9
10use super::{default::DefaultOrCustom, macros::config_struct};
11
12config_struct! {
13    /// RPC config.
14    #[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
15    #[serde(deny_unknown_fields, default)]
16    pub struct RpcConfig {
17        #[child = true]
18        /// Configuration for the unrestricted RPC server.
19        pub unrestricted: UnrestrictedRpcConfig,
20
21        #[child = true]
22        /// Configuration for the restricted RPC server.
23        pub restricted: RestrictedRpcConfig,
24    }
25}
26
27config_struct! {
28    Shared {
29        /// The address the RPC server will listen on.
30        ///
31        /// Type     | IPv4/IPv6 address
32        /// Examples | "", "127.0.0.1", "192.168.1.50"
33        pub address: IpAddr,
34
35        /// The port the RPC server will listen on.
36        ///
37        /// Type         | Number
38        /// Valid values | 0..65534
39        /// Examples     | 18081, 18089, 5432
40        pub port: DefaultOrCustom<u16>,
41
42        /// Toggle the RPC server.
43        ///
44        /// If `true` the RPC server will be enabled.
45        /// If `false` the RPC server will be disabled.
46        ///
47        /// Type     | boolean
48        /// Examples | true, false
49        pub enable: bool,
50
51        #[comment_out = true]
52        /// If a request is above this byte limit, it will be rejected.
53        ///
54        /// Setting this to `0` will disable the limit.
55        ///
56        /// Type         | Number
57        /// Valid values | >= 0
58        /// Examples     | 0 (no limit), 5242880 (5MB), 10485760 (10MB)
59        pub request_byte_limit: usize,
60
61        // TODO: <https://github.com/Cuprate/cuprate/issues/445>
62    }
63
64    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
65    #[serde(deny_unknown_fields, default)]
66    pub struct UnrestrictedRpcConfig {
67        /// Allow the unrestricted RPC server to be public.
68        ///
69        /// ⚠️ WARNING ⚠️
70        /// -------------
71        /// Unrestricted RPC should almost never be made available
72        /// to the wider internet. If the unrestricted address
73        /// is a non-local address, `cuprated` will crash,
74        /// unless this setting is set to `true`.
75        ///
76        /// Type         | boolean
77        /// Valid values | true, false
78        pub i_know_what_im_doing_allow_public_unrestricted_rpc: bool,
79    }
80
81    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
82    #[serde(deny_unknown_fields, default)]
83    pub struct RestrictedRpcConfig {
84        /// Advertise the restricted RPC port.
85        ///
86        /// Setting this to `true` will make `cuprated`
87        /// share the restricted RPC server's port
88        /// publicly to the P2P network.
89        ///
90        /// Type         | boolean
91        /// Valid values | true, false
92        pub advertise: bool,
93    }
94}
95
96impl Default for UnrestrictedRpcConfig {
97    fn default() -> Self {
98        Self {
99            i_know_what_im_doing_allow_public_unrestricted_rpc: false,
100            address: IpAddr::V4(Ipv4Addr::LOCALHOST),
101            port: DefaultOrCustom::Default,
102            enable: true,
103            request_byte_limit: 0,
104        }
105    }
106}
107
108impl Default for RestrictedRpcConfig {
109    fn default() -> Self {
110        Self {
111            advertise: false,
112            address: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
113            port: DefaultOrCustom::Default,
114            enable: false,
115            // 1 megabyte.
116            // <https://github.com/monero-project/monero/blob/3b01c490953fe92f3c6628fa31d280a4f0490d28/src/cryptonote_config.h#L134>
117            request_byte_limit: 1024 * 1024,
118        }
119    }
120}
121
122/// Gets the port to listen on for restricted RPC connections.
123pub const fn restricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
124    match config {
125        DefaultOrCustom::Default => match network {
126            Network::Mainnet => 18089,
127            Network::Stagenet => 38089,
128            Network::Testnet => 28089,
129        },
130        DefaultOrCustom::Custom(port) => port,
131    }
132}
133
134/// Gets the port to listen on for unrestricted RPC connections.
135pub const fn unrestricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
136    match config {
137        DefaultOrCustom::Default => match network {
138            Network::Mainnet => 18081,
139            Network::Stagenet => 38081,
140            Network::Testnet => 28081,
141        },
142        DefaultOrCustom::Custom(port) => port,
143    }
144}
145
146impl RestrictedRpcConfig {
147    /// Return the restricted RPC port for P2P if available and public.
148    pub const fn port_for_p2p(&self, network: Network) -> u16 {
149        if self.advertise && self.enable {
150            restricted_rpc_port(self.port, network)
151        } else {
152            0
153        }
154    }
155}