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    /// Configuration for RPC index initialization and bulk loading
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub index_initialization: Option<RpcIndexInitConfig>,
45
46    /// Enable indexing of authenticated events
47    ///
48    /// This controls whether authenticated events are indexed and whether the authenticated
49    /// events API endpoints are available. When disabled, authenticated events are not indexed
50    /// and API calls will return an unsupported error.
51    ///
52    /// Defaults to `false`, with authenticated events indexing and API disabled
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub authenticated_events_indexing: Option<bool>,
55
56    /// Configuration for rendering Objects based on the Display standard
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub display: Option<DisplayConfig>,
59}
60
61impl RpcConfig {
62    pub fn enable_indexing(&self) -> bool {
63        self.enable_indexing.unwrap_or(false)
64    }
65
66    pub fn https_address(&self) -> SocketAddr {
67        self.https_address
68            .unwrap_or_else(|| SocketAddr::from(([0, 0, 0, 0], 9443)))
69    }
70
71    pub fn tls_config(&self) -> Option<&RpcTlsConfig> {
72        self.tls.as_ref()
73    }
74
75    pub fn max_json_move_value_size(&self) -> usize {
76        self.max_json_move_value_size.unwrap_or(1024 * 1024)
77    }
78
79    pub fn index_initialization_config(&self) -> Option<&RpcIndexInitConfig> {
80        self.index_initialization.as_ref()
81    }
82
83    pub fn authenticated_events_indexing(&self) -> bool {
84        self.authenticated_events_indexing.unwrap_or(false)
85    }
86
87    pub fn display(&self) -> &DisplayConfig {
88        const DEFAULT_DISPLAY_CONFIG: DisplayConfig = DisplayConfig {
89            max_field_depth: None,
90            max_format_nodes: None,
91            max_object_loads: None,
92            max_move_value_depth: None,
93            max_output_size: None,
94        };
95
96        self.display.as_ref().unwrap_or(&DEFAULT_DISPLAY_CONFIG)
97    }
98}
99
100#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
101#[serde(rename_all = "kebab-case")]
102pub struct RpcTlsConfig {
103    /// File path to a PEM formatted TLS certificate chain
104    cert: String,
105    /// File path to a PEM formatted TLS private key
106    key: String,
107}
108
109impl RpcTlsConfig {
110    pub fn cert(&self) -> &str {
111        &self.cert
112    }
113
114    pub fn key(&self) -> &str {
115        &self.key
116    }
117}
118
119/// Configuration for RPC index initialization and bulk loading
120#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
121#[serde(rename_all = "kebab-case")]
122pub struct RpcIndexInitConfig {
123    /// Override for RocksDB's set_db_write_buffer_size during bulk indexing.
124    /// This is the total memory budget for all column families' memtables.
125    ///
126    /// Defaults to 90% of system RAM if not specified.
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub db_write_buffer_size: Option<usize>,
129
130    /// Override for each column family's write buffer size during bulk indexing.
131    ///
132    /// Defaults to 25% of system RAM divided by max_write_buffer_number if not specified.
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub cf_write_buffer_size: Option<usize>,
135
136    /// Override for the maximum number of write buffers per column family during bulk indexing.
137    /// This value is capped at 32 as an upper bound.
138    ///
139    /// Defaults to a dynamic value based on system RAM if not specified.
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub cf_max_write_buffer_number: Option<i32>,
142
143    /// Override for the number of background jobs during bulk indexing.
144    ///
145    /// Defaults to the number of CPU cores if not specified.
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub max_background_jobs: Option<i32>,
148
149    /// Override for the batch size limit during bulk indexing.
150    /// This controls how much data is accumulated in memory before flushing to disk.
151    ///
152    /// Defaults to half the write buffer size or 128MB, whichever is smaller.
153    #[serde(skip_serializing_if = "Option::is_none")]
154    pub batch_size_limit: Option<usize>,
155}
156
157#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
158#[serde(rename_all = "kebab-case")]
159pub struct DisplayConfig {
160    /// Maximum number of times the parser can recurse into nested structures. Depth does not
161    /// account for all nodes, only nodes that can be contained within themselves.
162    ///
163    /// Defaults to `32` if not specified.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    max_field_depth: Option<usize>,
166
167    /// Maximum number of AST nodes that can be allocated during parsing. This counts all values
168    /// that are instances of AST types (but not, for example, `Vec<T>`).
169    ///
170    /// Defaults to `32768` if not specified.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    max_format_nodes: Option<usize>,
173
174    /// Maximum number of objects that can be loaded during formatting.
175    ///
176    /// Defaults to `8` if not specified.
177    #[serde(skip_serializing_if = "Option::is_none")]
178    max_object_loads: Option<usize>,
179
180    /// Maximum depth to use when converting a rendered Display value to JSON.
181    ///
182    /// Defaults to `32` if not specified.
183    #[serde(skip_serializing_if = "Option::is_none")]
184    max_move_value_depth: Option<usize>,
185
186    /// Maxumum budget for rendering an object based on its Display template.
187    ///
188    /// This sets the numbers of bytes that we are willing to spend on rendering field names and
189    /// values when rendering an object based on its Display template.
190    ///
191    /// Defaults to `1MiB` if not specified.
192    #[serde(skip_serializing_if = "Option::is_none")]
193    max_output_size: Option<usize>,
194}
195
196impl DisplayConfig {
197    pub fn max_field_depth(&self) -> usize {
198        self.max_field_depth.unwrap_or(32)
199    }
200
201    pub fn max_format_nodes(&self) -> usize {
202        self.max_format_nodes.unwrap_or(32768)
203    }
204
205    pub fn max_object_loads(&self) -> usize {
206        self.max_object_loads.unwrap_or(8)
207    }
208
209    pub fn max_move_value_depth(&self) -> usize {
210        self.max_move_value_depth.unwrap_or(32)
211    }
212
213    pub fn max_output_size(&self) -> usize {
214        self.max_output_size.unwrap_or(1024 * 1024)
215    }
216}