Skip to main content

cuprated/config/
rpc.rs

1use std::{
2    net::{IpAddr, Ipv4Addr},
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        #[comment_out = true]
62        /// Maximum amount of RPC connections allowed by a single public IP address.
63        ///
64        /// Setting this to `0` will disable the limit.
65        ///
66        /// Type         | Number
67        /// Valid values | >= 0
68        /// Examples     | 0 (no limit), 2, 4
69        pub public_ip_connection_limit: usize,
70
71        #[comment_out = true]
72        /// Maximum amount of RPC connections allowed by a single private IP address.
73        ///
74        /// Setting this to `0` will disable the limit.
75        ///
76        /// Type         | Number
77        /// Valid values | >= 0
78        /// Examples     | 0 (no limit), 16, 100
79        pub private_ip_connection_limit: usize,
80
81        #[comment_out = true]
82        /// Maximum amount of RPC connections allowed by a loopback address.
83        ///
84        /// Setting this to `0` will disable the limit.
85        ///
86        /// Type         | Number
87        /// Valid values | >= 0
88        /// Examples     | 0 (no limit), 67
89        pub loopback_connection_limit: usize,
90
91        #[comment_out = true]
92        /// Maximum amount of RPC connections allowed globally.
93        ///
94        /// Setting this to `0` will disable the limit.
95        ///
96        /// Type         | Number
97        /// Valid values | >= 0
98        /// Examples     | 0 (no limit), 16, 300
99        pub total_connection_limit: usize,
100
101        #[comment_out = true]
102        /// The list of IP addresses that are excluded from
103        /// all RPC connection limits.
104        ///
105        /// This can be useful if you are using a reverse proxy
106        /// in front of this node.
107        ///
108        /// Type     | IPv4/IPv6 address
109        /// Examples | "", "127.0.0.1", "192.168.1.50"
110        pub excluded_ips_connection_limit: Vec<IpAddr>,
111
112        /// The time period during which the node can try sending data.
113        /// If a send operation do not complete within this Duration,
114        /// the connection is dropped.
115        ///
116        /// Type     | Duration
117        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
118        pub send_timeout: Duration,
119
120        /// The maximum time allowed to receive an HTTP/1 request header.
121        /// Receiving progress does not restart this deadline.
122        ///
123        /// Type     | Duration
124        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
125        pub header_read_timeout: Duration,
126
127        /// The maximum wall-clock time allowed to consume an HTTP request body.
128        /// Receiving progress does not restart this deadline.
129        ///
130        /// Type     | Duration
131        /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
132        pub body_read_timeout: Duration,
133
134        // TODO: <https://github.com/Cuprate/cuprate/issues/445>
135    }
136
137    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
138    #[serde(deny_unknown_fields, default)]
139    pub struct UnrestrictedRpcConfig {
140        /// Allow the unrestricted RPC server to be public.
141        ///
142        /// ⚠️ WARNING ⚠️
143        /// -------------
144        /// Unrestricted RPC should almost never be made available
145        /// to the wider internet. If the unrestricted address
146        /// is a non-local address, `cuprated` will crash,
147        /// unless this setting is set to `true`.
148        ///
149        /// Type         | boolean
150        /// Valid values | true, false
151        pub i_know_what_im_doing_allow_public_unrestricted_rpc: bool,
152    }
153
154    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
155    #[serde(deny_unknown_fields, default)]
156    pub struct RestrictedRpcConfig {
157        /// Advertise the restricted RPC port.
158        ///
159        /// Setting this to `true` will make `cuprated`
160        /// share the restricted RPC server's port
161        /// publicly to the P2P network.
162        ///
163        /// Type         | boolean
164        /// Valid values | true, false
165        pub advertise: bool,
166    }
167}
168
169impl Default for UnrestrictedRpcConfig {
170    fn default() -> Self {
171        Self {
172            i_know_what_im_doing_allow_public_unrestricted_rpc: false,
173            address: IpAddr::V4(Ipv4Addr::LOCALHOST),
174            port: DefaultOrCustom::Default,
175            enable: true,
176            request_byte_limit: 0,
177            public_ip_connection_limit: 0,
178            private_ip_connection_limit: 0,
179            loopback_connection_limit: 0,
180            total_connection_limit: 0,
181            excluded_ips_connection_limit: Vec::new(),
182            send_timeout: Duration::from_secs(5),
183            header_read_timeout: Duration::from_secs(30),
184            body_read_timeout: Duration::from_secs(5),
185        }
186    }
187}
188
189impl Default for RestrictedRpcConfig {
190    fn default() -> Self {
191        Self {
192            advertise: false,
193            address: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
194            port: DefaultOrCustom::Default,
195            enable: false,
196            // 1 megabyte.
197            // <https://github.com/monero-project/monero/blob/3b01c490953fe92f3c6628fa31d280a4f0490d28/src/cryptonote_config.h#L134>
198            request_byte_limit: 1024 * 1024,
199            public_ip_connection_limit: 3,
200            private_ip_connection_limit: 25,
201            loopback_connection_limit: 50,
202            total_connection_limit: 100,
203            excluded_ips_connection_limit: Vec::new(),
204            send_timeout: Duration::from_secs(5),
205            header_read_timeout: Duration::from_secs(30),
206            body_read_timeout: Duration::from_secs(5),
207        }
208    }
209}
210
211/// Gets the port to listen on for restricted RPC connections.
212pub const fn restricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
213    match config {
214        DefaultOrCustom::Default => match network {
215            Network::Mainnet | Network::FakeChain => 18089,
216            Network::Stagenet => 38089,
217            Network::Testnet => 28089,
218        },
219        DefaultOrCustom::Custom(port) => port,
220    }
221}
222
223/// Gets the port to listen on for unrestricted RPC connections.
224pub const fn unrestricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
225    match config {
226        DefaultOrCustom::Default => match network {
227            Network::Mainnet | Network::FakeChain => 18081,
228            Network::Stagenet => 38081,
229            Network::Testnet => 28081,
230        },
231        DefaultOrCustom::Custom(port) => port,
232    }
233}
234
235impl RestrictedRpcConfig {
236    /// Return the restricted RPC port for P2P if available and public.
237    pub const fn port_for_p2p(&self, network: Network) -> u16 {
238        if self.advertise && self.enable {
239            restricted_rpc_port(self.port, network)
240        } else {
241            0
242        }
243    }
244}