1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![allow(
4 unused_imports,
5 unreachable_pub,
6 unreachable_code,
7 unused_crate_dependencies,
8 dead_code,
9 unused_variables,
10 clippy::needless_pass_by_value,
11 clippy::unused_async,
12 clippy::diverging_sub_expression,
13 unused_mut,
14 clippy::let_unit_value,
15 clippy::needless_pass_by_ref_mut,
16 reason = "TODO: remove after v1.0.0"
17)]
18
19use std::{mem, sync::Arc};
20
21use tokio::sync::mpsc;
22use tower::{Service, ServiceExt};
23use tracing::{info, level_filters::LevelFilter};
24use tracing_subscriber::{layer::SubscriberExt, reload::Handle, util::SubscriberInitExt, Registry};
25
26use cuprate_consensus_context::{
27 BlockChainContextRequest, BlockChainContextResponse, BlockchainContextService,
28};
29use cuprate_helper::time::secs_to_hms;
30use cuprate_types::blockchain::BlockchainWriteRequest;
31
32use crate::{
33 config::Config, constants::PANIC_CRITICAL_SERVICE_ERROR, logging::CupratedTracingFilter,
34};
35
36mod blockchain;
37mod commands;
38mod config;
39mod constants;
40mod killswitch;
41mod logging;
42mod p2p;
43mod rpc;
44mod signals;
45mod statics;
46mod txpool;
47mod version;
48
49fn main() {
50 killswitch::init_killswitch();
52
53 statics::init_lazylock_statics();
55
56 let config = config::read_config_and_args();
57
58 blockchain::set_fast_sync_hashes(!config.no_fast_sync, config.network());
59
60 logging::init_logging(&config);
62
63 init_global_rayon_pool(&config);
66
67 let rt = init_tokio_rt(&config);
68
69 let db_thread_pool = cuprate_database_service::init_thread_pool(
70 cuprate_database_service::ReaderThreads::Number(config.storage.reader_threads),
71 );
72
73 let (mut blockchain_read_handle, mut blockchain_write_handle, _) =
76 cuprate_blockchain::service::init_with_pool(
77 config.blockchain_config(),
78 Arc::clone(&db_thread_pool),
79 )
80 .unwrap();
81 let (txpool_read_handle, txpool_write_handle, _) =
82 cuprate_txpool::service::init_with_pool(config.txpool_config(), db_thread_pool).unwrap();
83
84 rt.block_on(async move {
87 blockchain_write_handle
89 .ready()
90 .await
91 .expect(PANIC_CRITICAL_SERVICE_ERROR)
92 .call(BlockchainWriteRequest::FlushAltBlocks)
93 .await
94 .expect(PANIC_CRITICAL_SERVICE_ERROR);
95
96 blockchain::check_add_genesis(
98 &mut blockchain_read_handle,
99 &mut blockchain_write_handle,
100 config.network(),
101 )
102 .await;
103
104 let context_svc =
106 blockchain::init_consensus(blockchain_read_handle.clone(), config.context_config())
107 .await
108 .unwrap();
109
110 let (clearnet, incoming_tx_handler_tx) = p2p::start_clearnet_p2p(
112 blockchain_read_handle.clone(),
113 context_svc.clone(),
114 txpool_read_handle.clone(),
115 config.clearnet_p2p_config(),
116 )
117 .await
118 .unwrap();
119
120 let tx_handler = txpool::IncomingTxHandler::init(
122 clearnet.clone(),
123 txpool_write_handle.clone(),
124 txpool_read_handle,
125 context_svc.clone(),
126 blockchain_read_handle.clone(),
127 );
128 if incoming_tx_handler_tx.send(tx_handler).is_err() {
129 unreachable!()
130 }
131
132 blockchain::init_blockchain_manager(
134 clearnet,
135 blockchain_write_handle,
136 blockchain_read_handle,
137 txpool_write_handle,
138 context_svc.clone(),
139 config.block_downloader_config(),
140 )
141 .await;
142
143 if std::io::IsTerminal::is_terminal(&std::io::stdin()) {
145 let (command_tx, command_rx) = mpsc::channel(1);
146 std::thread::spawn(|| commands::command_listener(command_tx));
147
148 tokio::spawn(commands::io_loop(command_rx, context_svc))
150 .await
151 .unwrap();
152 } else {
153 info!("Terminal/TTY not detected, disabling STDIN commands");
155 tokio::signal::ctrl_c().await.unwrap();
156 }
157 });
158}
159
160fn init_tokio_rt(config: &Config) -> tokio::runtime::Runtime {
162 tokio::runtime::Builder::new_multi_thread()
163 .worker_threads(config.tokio.threads)
164 .thread_name("cuprated-tokio")
165 .enable_all()
166 .build()
167 .unwrap()
168}
169
170fn init_global_rayon_pool(config: &Config) {
172 rayon::ThreadPoolBuilder::new()
173 .num_threads(config.rayon.threads)
174 .thread_name(|index| format!("cuprated-rayon-{index}"))
175 .build_global()
176 .unwrap();
177}