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}