Skip to main content

tycho_rpc/
config.rs

1use std::net::{Ipv4Addr, SocketAddr};
2use std::path::{Path, PathBuf};
3use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6use tycho_types::models::StdAddr;
7use tycho_util::config::PartialConfig;
8use tycho_util::serde_helpers;
9
10#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, PartialConfig)]
11#[serde(default)]
12pub struct RpcConfig {
13    /// TCP socket address to listen for incoming RPC connections.
14    ///
15    /// Default: `0.0.0.0:8000`
16    #[important]
17    pub listen_addr: SocketAddr,
18
19    /// Whether to generate a stub keyblock from zerostate.
20    ///
21    /// Default: `false`.
22    pub generate_stub_keyblock: bool,
23
24    /// Number of virtual shards.
25    ///
26    /// Default: `4` (= 16 virtual shards).
27    pub shard_split_depth: u8,
28
29    // NOTE: TEMP
30    /// Whether `getKeyBlockProof`, `getBlockProof` and `getBlockData` queries are enabled.
31    ///
32    /// Default: `false`.
33    pub allow_huge_requests: bool,
34
35    /// Max number of parallel block downloads.
36    ///
37    /// Default: `10`.
38    pub max_parallel_block_downloads: usize,
39
40    /// Configuration of getter requests.
41    pub run_get_method: RunGetMethodConfig,
42
43    /// Subscriptions limits and buffering.
44    pub subscriptions: SubscriptionsConfig,
45
46    #[important]
47    pub storage: RpcStorageConfig,
48}
49
50#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
51#[serde(default)]
52pub struct RunGetMethodConfig {
53    /// The maximum number of methods running in parallel.
54    /// Zero means disabled.
55    ///
56    /// Default: `20`.
57    pub max_vms: usize,
58
59    /// Max time to wait for a VM slot.
60    ///
61    /// Default: `50ms`.
62    #[serde(with = "serde_helpers::humantime")]
63    pub max_wait_for_vm: Duration,
64
65    /// Max stack items in response.
66    ///
67    /// Default: 32.
68    pub max_response_stack_items: usize,
69
70    /// Default VM gas.
71    ///
72    /// Default: `1000000`.
73    pub vm_getter_gas: u64,
74}
75
76impl Default for RunGetMethodConfig {
77    fn default() -> Self {
78        Self {
79            max_vms: 20,
80            max_wait_for_vm: Duration::from_millis(50),
81            max_response_stack_items: 32,
82            vm_getter_gas: 1000000,
83        }
84    }
85}
86
87#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
88#[serde(tag = "type")]
89pub enum RpcStorageConfig {
90    Full {
91        /// Transactions garbage collector configuration.
92        ///
93        /// Default: clear all transactions older than `1 week` every `1 hour`.
94        ///
95        /// `None` to disable garbage collection.
96        gc: Option<TransactionsGcConfig>,
97
98        /// Reset all accounts.
99        ///
100        /// Default: `false`.
101        force_reindex: bool,
102
103        /// Path to account blacklist file. RPC skips storing transactions for this list.
104        ///
105        /// Default: `None`.
106        blacklist_path: Option<PathBuf>,
107    },
108    /// Only store the state, no transactions and code hashes.
109    StateOnly,
110}
111
112impl RpcStorageConfig {
113    pub fn is_full(&self) -> bool {
114        matches!(self, Self::Full { .. })
115    }
116
117    pub fn gc_is_enabled(&self) -> bool {
118        match self {
119            Self::Full { gc, .. } => gc.is_some(),
120            Self::StateOnly => false,
121        }
122    }
123
124    pub fn is_force_reindex(&self) -> bool {
125        match self {
126            Self::Full { force_reindex, .. } => *force_reindex,
127            Self::StateOnly => false,
128        }
129    }
130
131    pub fn blacklist_path(&self) -> Option<PathBuf> {
132        match self {
133            Self::Full { blacklist_path, .. } => blacklist_path.clone(),
134            Self::StateOnly => None,
135        }
136    }
137}
138
139impl Default for RpcConfig {
140    fn default() -> Self {
141        Self {
142            listen_addr: (Ipv4Addr::UNSPECIFIED, 8000).into(),
143            generate_stub_keyblock: false,
144            shard_split_depth: 4,
145            allow_huge_requests: false,
146            max_parallel_block_downloads: 10,
147            run_get_method: RunGetMethodConfig::default(),
148            subscriptions: SubscriptionsConfig::default(),
149            storage: RpcStorageConfig::Full {
150                gc: Some(Default::default()),
151                force_reindex: false,
152                blacklist_path: None,
153            },
154        }
155    }
156}
157
158#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, PartialConfig)]
159#[serde(default)]
160pub struct SubscriptionsConfig {
161    pub max_clients: u32,
162    pub max_addrs: u32,
163    /// Pending updates buffered per client; clamped to at least 1.
164    pub queue_depth: usize,
165}
166
167impl Default for SubscriptionsConfig {
168    fn default() -> Self {
169        Self {
170            max_clients: 1_000_000,
171            max_addrs: 1_000_000,
172            queue_depth: 5,
173        }
174    }
175}
176
177#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
178pub struct TransactionsGcConfig {
179    /// Minimum transaction TTL.
180    ///
181    /// Default: `1 week`.
182    #[serde(with = "serde_helpers::humantime")]
183    pub tx_ttl: Duration,
184
185    /// Keep at least this amount of transactions per account.
186    ///
187    /// Default: `10`.
188    #[serde(default)]
189    pub keep_tx_per_account: usize,
190}
191
192impl Default for TransactionsGcConfig {
193    fn default() -> Self {
194        Self {
195            tx_ttl: Duration::from_secs(60 * 60 * 24 * 7),
196            keep_tx_per_account: 10,
197        }
198    }
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize, Default)]
202pub struct BlackListConfig {
203    pub accounts: Vec<StdAddr>,
204}
205
206impl BlackListConfig {
207    pub fn load_from<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
208        serde_helpers::load_json_from_file(path)
209    }
210}