Skip to main content

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 or "Default"
38        /// Valid values | 0..65534, "Default"
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        /// The time period during which the node can try sending data.
62        /// If a send operation do not complete within this Duration,
63        /// the connection is dropped.
64        ///
65        /// Type     | Duration
66        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
67        pub send_timeout: Duration,
68
69        /// The maximum time allowed to receive an HTTP/1 request header.
70        /// Receiving progress does not restart this deadline.
71        ///
72        /// Type     | Duration
73        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
74        pub header_read_timeout: Duration,
75
76        /// The maximum wall-clock time allowed to consume an HTTP request body.
77        /// Receiving progress does not restart this deadline.
78        ///
79        /// Type     | Duration
80        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
81        pub body_read_timeout: Duration,
82
83        // TODO: <https://github.com/Cuprate/cuprate/issues/445>
84    }
85
86    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
87    #[serde(deny_unknown_fields, default)]
88    pub struct UnrestrictedRpcConfig {
89        /// Allow the unrestricted RPC server to be public.
90        ///
91        /// ⚠️ WARNING ⚠️
92        /// -------------
93        /// Unrestricted RPC should almost never be made available
94        /// to the wider internet. If the unrestricted address
95        /// is a non-local address, `cuprated` will crash,
96        /// unless this setting is set to `true`.
97        ///
98        /// Type         | boolean
99        /// Valid values | true, false
100        pub i_know_what_im_doing_allow_public_unrestricted_rpc: bool,
101    }
102
103    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
104    #[serde(deny_unknown_fields, default)]
105    pub struct RestrictedRpcConfig {
106        /// Advertise the restricted RPC port.
107        ///
108        /// Setting this to `true` will make `cuprated`
109        /// share the restricted RPC server's port
110        /// publicly to the P2P network.
111        ///
112        /// Type         | boolean
113        /// Valid values | true, false
114        pub advertise: bool,
115    }
116}
117
118impl Default for UnrestrictedRpcConfig {
119    fn default() -> Self {
120        Self {
121            i_know_what_im_doing_allow_public_unrestricted_rpc: false,
122            address: IpAddr::V4(Ipv4Addr::LOCALHOST),
123            port: DefaultOrCustom::Default,
124            enable: true,
125            request_byte_limit: 0,
126            send_timeout: Duration::from_secs(5),
127            header_read_timeout: Duration::from_secs(30),
128            body_read_timeout: Duration::from_secs(5),
129        }
130    }
131}
132
133impl Default for RestrictedRpcConfig {
134    fn default() -> Self {
135        Self {
136            advertise: false,
137            address: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
138            port: DefaultOrCustom::Default,
139            enable: false,
140            // 1 megabyte.
141            // <https://github.com/monero-project/monero/blob/3b01c490953fe92f3c6628fa31d280a4f0490d28/src/cryptonote_config.h#L134>
142            request_byte_limit: 1024 * 1024,
143            send_timeout: Duration::from_secs(5),
144            header_read_timeout: Duration::from_secs(30),
145            body_read_timeout: Duration::from_secs(5),
146        }
147    }
148}
149
150/// Gets the port to listen on for restricted RPC connections.
151pub const fn restricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
152    match config {
153        DefaultOrCustom::Default => match network {
154            Network::Mainnet | Network::FakeChain => 18089,
155            Network::Stagenet => 38089,
156            Network::Testnet => 28089,
157        },
158        DefaultOrCustom::Custom(port) => port,
159    }
160}
161
162/// Gets the port to listen on for unrestricted RPC connections.
163pub const fn unrestricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
164    match config {
165        DefaultOrCustom::Default => match network {
166            Network::Mainnet | Network::FakeChain => 18081,
167            Network::Stagenet => 38081,
168            Network::Testnet => 28081,
169        },
170        DefaultOrCustom::Custom(port) => port,
171    }
172}
173
174impl RestrictedRpcConfig {
175    /// Return the restricted RPC port for P2P if available and public.
176    pub const fn port_for_p2p(&self, network: Network) -> u16 {
177        if self.advertise && self.enable {
178            restricted_rpc_port(self.port, network)
179        } else {
180            0
181        }
182    }
183}