sui_config/rpc_config.rs
1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::net::SocketAddr;
5
6#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
7#[serde(rename_all = "kebab-case")]
8pub struct RpcConfig {
9 /// Enable indexing of transactions and objects
10 ///
11 /// This enables indexing of transactions and objects which allows for a slightly richer rpc
12 /// api. There are some APIs which will be disabled/enabled based on this config while others
13 /// (eg GetTransaction) will still be enabled regardless of this config but may return slight
14 /// less data (eg GetTransaction won't return the checkpoint that includes the requested
15 /// transaction).
16 ///
17 /// Defaults to `false`, with indexing and APIs which require indexes being disabled
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub enable_indexing: Option<bool>,
20
21 /// Configure the address to listen on for https
22 ///
23 /// Defaults to `0.0.0.0:9443` if not specified.
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub https_address: Option<SocketAddr>,
26
27 /// TLS configuration to use for https.
28 ///
29 /// If not provided then the node will not create an https service.
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub tls: Option<RpcTlsConfig>,
32
33 /// Maxumum budget for rendering a Move value into JSON.
34 ///
35 /// This sets the numbers of bytes that we are willing to spend on rendering field names and
36 /// values when rendering a Move value into a JSON value.
37 ///
38 /// Defaults to `1MiB` if not specified.
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub max_json_move_value_size: Option<usize>,
41
42 /// Aggregate budget for Move-value JSON rendering across a single response.
43 ///
44 /// Endpoints that render many Move values in one response (e.g. `GetCheckpoint`
45 /// with a `read_mask` that selects every event's `json` field) share this
46 /// budget across all per-item renders, so the response cannot multiply one
47 /// request into hundreds of MiB of materialized `prost_types::Value`.
48 ///
49 /// Defaults to `16 MiB` if not specified.
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub max_json_move_value_response_size: Option<usize>,
52
53 /// Configuration for RPC index initialization and bulk loading
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub index_initialization: Option<RpcIndexInitConfig>,
56
57 /// Enable indexing of authenticated events
58 ///
59 /// This controls whether authenticated events are indexed and whether the authenticated
60 /// events API endpoints are available. When disabled, authenticated events are not indexed
61 /// and API calls will return an unsupported error.
62 ///
63 /// Defaults to `false`, with authenticated events indexing and API disabled
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub authenticated_events_indexing: Option<bool>,
66
67 /// Configuration for rendering Objects based on the Display standard
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub display: Option<DisplayConfig>,
70}
71
72impl RpcConfig {
73 pub fn enable_indexing(&self) -> bool {
74 self.enable_indexing.unwrap_or(false)
75 }
76
77 pub fn https_address(&self) -> SocketAddr {
78 self.https_address
79 .unwrap_or_else(|| SocketAddr::from(([0, 0, 0, 0], 9443)))
80 }
81
82 pub fn tls_config(&self) -> Option<&RpcTlsConfig> {
83 self.tls.as_ref()
84 }
85
86 pub fn max_json_move_value_size(&self) -> usize {
87 self.max_json_move_value_size.unwrap_or(1024 * 1024)
88 }
89
90 pub fn max_json_move_value_response_size(&self) -> usize {
91 self.max_json_move_value_response_size
92 .unwrap_or(16 * 1024 * 1024)
93 }
94
95 pub fn index_initialization_config(&self) -> Option<&RpcIndexInitConfig> {
96 self.index_initialization.as_ref()
97 }
98
99 pub fn authenticated_events_indexing(&self) -> bool {
100 self.authenticated_events_indexing.unwrap_or(false)
101 }
102
103 pub fn display(&self) -> &DisplayConfig {
104 const DEFAULT_DISPLAY_CONFIG: DisplayConfig = DisplayConfig {
105 max_field_depth: None,
106 max_format_nodes: None,
107 max_object_loads: None,
108 max_move_value_depth: None,
109 max_output_size: None,
110 };
111
112 self.display.as_ref().unwrap_or(&DEFAULT_DISPLAY_CONFIG)
113 }
114}
115
116#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
117#[serde(rename_all = "kebab-case")]
118pub struct RpcTlsConfig {
119 /// File path to a PEM formatted TLS certificate chain
120 cert: String,
121 /// File path to a PEM formatted TLS private key
122 key: String,
123}
124
125impl RpcTlsConfig {
126 pub fn cert(&self) -> &str {
127 &self.cert
128 }
129
130 pub fn key(&self) -> &str {
131 &self.key
132 }
133}
134
135/// Configuration for RPC index initialization and bulk loading
136#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
137#[serde(rename_all = "kebab-case")]
138pub struct RpcIndexInitConfig {
139 /// Override for RocksDB's set_db_write_buffer_size during bulk indexing.
140 /// This is the total memory budget for all column families' memtables.
141 ///
142 /// Defaults to 90% of system RAM if not specified.
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub db_write_buffer_size: Option<usize>,
145
146 /// Override for each column family's write buffer size during bulk indexing.
147 ///
148 /// Defaults to 25% of system RAM divided by max_write_buffer_number if not specified.
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub cf_write_buffer_size: Option<usize>,
151
152 /// Override for the maximum number of write buffers per column family during bulk indexing.
153 /// This value is capped at 32 as an upper bound.
154 ///
155 /// Defaults to a dynamic value based on system RAM if not specified.
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub cf_max_write_buffer_number: Option<i32>,
158
159 /// Override for the number of background jobs during bulk indexing.
160 ///
161 /// Defaults to the number of CPU cores if not specified.
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub max_background_jobs: Option<i32>,
164
165 /// Override for the batch size limit during bulk indexing.
166 /// This controls how much data is accumulated in memory before flushing to disk.
167 ///
168 /// Defaults to half the write buffer size or 128MB, whichever is smaller.
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub batch_size_limit: Option<usize>,
171}
172
173#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
174#[serde(rename_all = "kebab-case")]
175pub struct DisplayConfig {
176 /// Maximum number of times the parser can recurse into nested structures. Depth does not
177 /// account for all nodes, only nodes that can be contained within themselves.
178 ///
179 /// Defaults to `32` if not specified.
180 #[serde(skip_serializing_if = "Option::is_none")]
181 max_field_depth: Option<usize>,
182
183 /// Maximum number of AST nodes that can be allocated during parsing. This counts all values
184 /// that are instances of AST types (but not, for example, `Vec<T>`).
185 ///
186 /// Defaults to `32768` if not specified.
187 #[serde(skip_serializing_if = "Option::is_none")]
188 max_format_nodes: Option<usize>,
189
190 /// Maximum number of objects that can be loaded during formatting.
191 ///
192 /// Defaults to `8` if not specified.
193 #[serde(skip_serializing_if = "Option::is_none")]
194 max_object_loads: Option<usize>,
195
196 /// Maximum depth to use when converting a rendered Display value to JSON.
197 ///
198 /// Defaults to `32` if not specified.
199 #[serde(skip_serializing_if = "Option::is_none")]
200 max_move_value_depth: Option<usize>,
201
202 /// Maxumum budget for rendering an object based on its Display template.
203 ///
204 /// This sets the numbers of bytes that we are willing to spend on rendering field names and
205 /// values when rendering an object based on its Display template.
206 ///
207 /// Defaults to `1MiB` if not specified.
208 #[serde(skip_serializing_if = "Option::is_none")]
209 max_output_size: Option<usize>,
210}
211
212impl DisplayConfig {
213 pub fn max_field_depth(&self) -> usize {
214 self.max_field_depth.unwrap_or(32)
215 }
216
217 pub fn max_format_nodes(&self) -> usize {
218 self.max_format_nodes.unwrap_or(32768)
219 }
220
221 pub fn max_object_loads(&self) -> usize {
222 self.max_object_loads.unwrap_or(8)
223 }
224
225 pub fn max_move_value_depth(&self) -> usize {
226 self.max_move_value_depth.unwrap_or(32)
227 }
228
229 pub fn max_output_size(&self) -> usize {
230 self.max_output_size.unwrap_or(1024 * 1024)
231 }
232}