1mod log_level;
4pub use log_level::*;
5
6mod fast_sync;
7pub use fast_sync::*;
8
9mod db_backend;
10pub use db_backend::*;
11
12mod p2p;
13pub use p2p::*;
14
15mod mempool;
16pub use mempool::*;
17
18mod state_sync;
19pub use state_sync::*;
20
21mod consensus;
22pub use consensus::*;
23
24mod tx_index;
25pub use tx_index::*;
26
27mod prometheus;
28pub use prometheus::*;
29
30use crate::{defined, model};
31
32#[derive(Debug, Clone)]
34pub struct Config {
35 pub log_level: LogLevel,
37
38 pub moniker: String,
40
41 pub db_backend: DbBackend,
43
44 pub log_format: LogFormat,
46
47 pub priv_validator_laddr: String,
50
51 pub filter_peers: bool,
54
55 pub pprof_laddr: String,
57
58 pub data_dir: String,
60
61 pub p2p: P2PConfig,
63
64 pub mempool: MempoolConfig,
66
67 pub state_sync: Option<StateSyncConfig>,
73
74 pub fast_sync: Option<FastSyncVersion>,
76
77 pub consensus: ConsensusConfig,
79
80 pub tx_index: TxIndexConfig,
91
92 pub prometheus: Option<PrometheusConfig>,
96}
97
98impl Default for Config {
99 fn default() -> Self {
100 let moniker = String::from("aa");
101
102 Self {
103 moniker,
104 log_format: Default::default(),
105 db_backend: Default::default(),
106 log_level: Default::default(),
107 priv_validator_laddr: Default::default(),
108 filter_peers: false,
109 pprof_laddr: Default::default(),
110 p2p: Default::default(),
111 mempool: Default::default(),
112 state_sync: None,
113 fast_sync: Some(FastSyncVersion::default()),
114 consensus: Default::default(),
115 tx_index: Default::default(),
116 prometheus: None,
117 data_dir: String::new(),
118 }
119 }
120}
121
122impl Config {
123 pub fn new(data_dir: &str) -> Self {
124 Self {
125 data_dir: String::from(data_dir),
126 ..Default::default()
127 }
128 }
129}
130
131macro_rules! define_to_str_for_enum {
132 ($e:ident, $( $key:ident => $value:expr ),*) => {
133 impl $e {
134 pub fn to_str(&self) -> &'static str {
135 match self {
136 $( Self::$key => $value, )*
137 }
138 }
139 }
140 };
141}
142
143pub(crate) use define_to_str_for_enum;
144
145macro_rules! define_build_mode_setter {
146 ($name:ident, str) => {
147 pub fn $name(self, $name: &str) -> Self {
148 let mut this = self;
149 this.$name = String::from($name);
150 this
151 }
152 };
153 ($name:ident, $type:ty) => {
154 pub fn $name(self, $name: $type) -> Self {
155 let mut this = self;
156 this.$name = $name;
157 this
158 }
159 };
160 ($name:ident, $type:ty, option, $enable: ident) => {
161 pub fn $enable(self, $name: $type) -> Self {
162 let mut this = self;
163 this.$name = Some($name);
164 this
165 }
166 };
167}
168
169pub(crate) use define_build_mode_setter;
170
171impl Config {
172 define_build_mode_setter!(log_level, LogLevel);
173
174 define_build_mode_setter!(moniker, str);
175
176 define_build_mode_setter!(db_backend, DbBackend);
177
178 define_build_mode_setter!(log_format, LogFormat);
179
180 define_build_mode_setter!(priv_validator_laddr, str);
181
182 define_build_mode_setter!(filter_peers, bool);
183
184 define_build_mode_setter!(p2p, P2PConfig);
185
186 define_build_mode_setter!(mempool, MempoolConfig);
187
188 define_build_mode_setter!(state_sync, StateSyncConfig, option, enable_state_sync);
189
190 define_build_mode_setter!(fast_sync, FastSyncVersion, option, enable_fast_sync);
191
192 define_build_mode_setter!(consensus, ConsensusConfig);
193
194 define_build_mode_setter!(tx_index, TxIndexConfig);
195
196 define_build_mode_setter!(prometheus, PrometheusConfig, option, enabel_prometheus);
197}
198
199impl Config {
200 pub(crate) fn into_model(self, base_dir: &str) -> model::Config {
201 let db_dir = if self.data_dir.is_empty() {
202 format!("{}/{}", base_dir, defined::DATA_DIR)
203 } else {
204 self.data_dir
205 };
206
207 let rpc = {
208 let laddr = format!("unix://{}/{}", base_dir, defined::RPC_UNIX_SOCKET_FILE);
209
210 model::Rpc {
211 laddr,
212 cors_allowed_origins: Default::default(),
213 cors_allowed_headers: Default::default(),
214 cors_allowed_methods: Default::default(),
215 grpc_laddr: Default::default(),
216 unsafe_opt: true,
217 max_open_connections: 900,
218 max_subscription_clients: 100,
219 max_subscriptions_per_client: 5,
220 experimental_subscription_buffer_size: 200,
221 experimental_websocket_write_buffer_size: 200,
222 experimental_close_on_slow_client: false,
223 timeout_broadcast_tx_commit: String::from("10s"),
224 max_body_bytes: 1000000,
225 max_header_bytes: 1048576,
226 tls_key_file: Default::default(),
227 tls_cert_file: Default::default(),
228 pprof_laddr: self.pprof_laddr,
229 grpc_max_open_connections: 900,
230 }
231 };
232
233 let p2p = {
234 let addr_book_file = format!("{}/{}", base_dir, defined::ADDR_BOOK_FILE);
235 let persistent_peers_max_dial_period = format!(
236 "{}s",
237 self.p2p.persistent_peers_max_dial_period.whole_seconds()
238 );
239 let flush_throttle_timeout =
240 format!("{}ms", self.p2p.flush_throttle_timeout.whole_milliseconds());
241 let handshake_timeout = format!("{}s", self.p2p.handshake_timeout.whole_seconds());
242 let dial_timeout = format!("{}s", self.p2p.dial_timeout.whole_seconds());
243
244 model::P2P {
245 laddr: self.p2p.laddr,
246 external_address: self.p2p.external_address,
247 seeds: self.p2p.seeds.join(","),
248 persistent_peers: self.p2p.persistent_peers.join(","),
249 upnp: self.p2p.upnp,
250 addr_book_file,
251 addr_book_strict: !self.p2p.local_net,
252 max_num_inbound_peers: self.p2p.max_num_inbound_peers,
253 max_num_outbound_peers: self.p2p.max_num_outbound_peers,
254 unconditional_peer_ids: self.p2p.unconditional_peer_ids.join(","),
255 persistent_peers_max_dial_period,
256 flush_throttle_timeout,
257 max_packet_msg_payload_size: self.p2p.max_packet_msg_payload_size,
258 send_rate: self.p2p.send_rate,
259 recv_rate: self.p2p.recv_rate,
260 pex: self.p2p.pex,
261 seed_mode: self.p2p.seed_mode,
262 private_peer_ids: self.p2p.private_peer_ids.join(","),
263 allow_duplicate_ip: self.p2p.allow_duplicate_ip,
264 handshake_timeout,
265 dial_timeout,
266 }
267 };
268
269 let mempool = {
270 let ttl_duration = format!("{}s", self.mempool.ttl_duration.whole_seconds());
271
272 model::Mempool {
273 version: String::from(self.mempool.version.to_str()),
274 wal_dir: Default::default(),
275 size: self.mempool.size,
276 max_tx_bytes: self.mempool.max_tx_bytes,
277 cache_size: self.mempool.cache_size,
278 keep_invalid_txs_in_cache: self.mempool.keep_invalid_txs_in_cache,
279 max_txs_bytes: self.mempool.max_txs_bytes,
280 max_batch_bytes: 0,
281 ttl_duration,
282 ttl_num_blocks: self.mempool.ttl_num_blocks,
283 recheck: self.mempool.recheck,
284 broadcast: self.mempool.broadcast,
285 }
286 };
287
288 let statesync = {
289 let (enable, state_sync) = if let Some(state_sync) = self.state_sync {
290 (true, state_sync)
291 } else {
292 (false, Default::default())
293 };
294
295 let trust_period = format!("{}s", state_sync.trust_period.whole_seconds());
296
297 let discovery_time = format!("{}s", state_sync.discovery_time.whole_seconds());
298
299 let chunk_request_timeout =
300 format!("{}s", state_sync.chunk_request_timeout.whole_seconds());
301
302 model::StateSync {
303 enable,
304 rpc_servers: state_sync.rpc_servers.join(","),
305 trust_hash: state_sync.trust_hash,
306 trust_height: state_sync.trust_height,
307 trust_period,
308 discovery_time,
309 temp_dir: Default::default(),
310 chunk_request_timeout,
311 chunk_fetchers: format!("{}", state_sync.chunk_fetchers),
312 }
313 };
314
315 let (fast_sync, fastsync) = {
316 let fast_sync = self.fast_sync.is_some();
317
318 let version = if let Some(v) = self.fast_sync {
319 String::from(v.to_str())
320 } else {
321 String::from("v0")
322 };
323
324 (fast_sync, model::FastSync { version })
325 };
326
327 let consensus = {
328 let wal_file = format!("{}/{}", db_dir, defined::WAL_FILE);
329
330 model::Consensus {
331 wal_file,
332 timeout_propose: utils::build_duration_ms(self.consensus.timeout_propose),
333 timeout_propose_delta: utils::build_duration_ms(
334 self.consensus.timeout_propose_delta,
335 ),
336 timeout_prevote: utils::build_duration_ms(self.consensus.timeout_prevote),
337 timeout_prevote_delta: utils::build_duration_ms(
338 self.consensus.timeout_prevote_delta,
339 ),
340 timeout_precommit: utils::build_duration_ms(self.consensus.timeout_precommit),
341 timeout_precommit_delta: utils::build_duration_ms(
342 self.consensus.timeout_precommit_delta,
343 ),
344 timeout_commit: utils::build_duration_ms(self.consensus.timeout_commit),
345 double_sign_check_height: self.consensus.double_sign_check_height,
346 skip_timeout_commit: self.consensus.skip_timeout_commit,
347 create_empty_blocks: self.consensus.create_empty_blocks,
348 create_empty_blocks_interval: utils::build_duration_ms(
349 self.consensus.create_empty_blocks_interval,
350 ),
351 peer_gossip_sleep_duration: utils::build_duration_ms(
352 self.consensus.peer_gossip_sleep_duration,
353 ),
354 peer_query_maj23_sleep_duration: utils::build_duration_ms(
355 self.consensus.peer_query_maj23_sleep_duration,
356 ),
357 discard_abci_responses: self.consensus.discard_abci_responses,
358 }
359 };
360
361 let tx_index = {
362 let indexer = self.tx_index.to_str();
363
364 let pgsql_conn = if let TxIndexConfig::Psql(c) = self.tx_index {
365 c
366 } else {
367 Default::default()
368 };
369
370 model::TxIndex {
371 indexer: String::from(indexer),
372 pgsql_conn,
373 }
374 };
375
376 let prometheus = {
377 let (enable, prometheus) = if let Some(p) = self.prometheus {
378 (true, p)
379 } else {
380 (false, Default::default())
381 };
382
383 model::Instrumentation {
384 prometheus: enable,
385 prometheus_listen_addr: prometheus.prometheus_listen_addr,
386 max_open_connections: prometheus.max_open_connections,
387 namespace: prometheus.namespace,
388 }
389 };
390
391 let proxy_app = format!("unix://{}/{}", base_dir, defined::APP_UNIX_SOCKET_FILE);
392 log::debug!("proxy_app socket file is : {}", proxy_app);
393
394 let genesis_file = format!("{}/{}", db_dir, defined::GENESIS_FILE);
395
396 let priv_validator_key_file = format!("{}/{}", base_dir, defined::VALIDATOR_KEY_FILE);
397
398 let priv_validator_state_file = format!("{}/{}", db_dir, defined::VALIDATOR_STATE_FILE);
399
400 let node_key_file = format!("{}/{}", base_dir, defined::NODE_KEY_FILE);
401
402 model::Config {
403 proxy_app,
404 moniker: self.moniker,
405 fast_sync,
406 db_backend: String::from(self.db_backend.to_str()),
407 db_dir,
408 log_level: String::from(self.log_level.to_str()),
409 log_format: String::from(self.log_format.to_str()),
410 genesis_file,
411 priv_validator_key_file,
412 priv_validator_state_file,
413 priv_validator_laddr: self.priv_validator_laddr,
414 node_key_file,
415 abci: String::from("socket"),
416 filter_peers: self.filter_peers,
417 rpc,
418 p2p,
419 mempool,
420 statesync,
421 fastsync,
422 consensus,
423 tx_index,
424 instrumentation: prometheus,
425 }
426 }
427}
428
429mod utils {
430 use time::Duration;
431
432 pub fn build_duration_ms(d: Duration) -> String {
437 format!("{}ms", d.whole_milliseconds())
438 }
439}