(
context: tokio::Context,
flags: RunFlags,
key_store: KeyStore<PrivateKey>,
loaded: LoadedCheckpoint<MultisigScheme>,
)
| 227 | Command::Keys(cmd) => cmd.exec(), |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | pub fn run_node(&self, flags: &RunFlags) { |
| 232 | // Initialize tokio-console subscriber if feature is enabled |
| 233 | #[cfg(feature = "tokio-console")] |
| 234 | { |
| 235 | console_subscriber::init(); |
| 236 | } |
| 237 | |
| 238 | let loaded = if let Some(checkpoint_path) = &flags.checkpoint_path { |
| 239 | read_checkpoint::<MultisigScheme>(checkpoint_path, flags.checkpoint_or_default) |
| 240 | } else { |
| 241 | LoadedCheckpoint { |
| 242 | consensus_state: None, |
| 243 | last_block: None, |
| 244 | finalized_header: None, |
| 245 | raw_checkpoint: None, |
| 246 | finalized_headers_chain: None, |
| 247 | } |
| 248 | }; |
| 249 | let store_path = get_expanded_path(&flags.store_path).expect("Invalid store path"); |
| 250 | |
| 251 | // Initialize runtime |
| 252 | let worker_threads = flags |
| 253 | .worker_threads |
| 254 | .unwrap_or_else(|| std::thread::available_parallelism().map_or(4, |n| n.get())); |
| 255 | let cfg = tokio::Config::default() |
| 256 | .with_tcp_nodelay(Some(true)) |
| 257 | .with_worker_threads(worker_threads) |
| 258 | .with_storage_directory(store_path) |
| 259 | .with_catch_panics(false); |
| 260 | let executor = tokio::Runner::new(cfg); |
| 261 | |
| 262 | let flags = flags.clone(); |
| 263 | |
| 264 | executor.start(|context| async move { |
| 265 | let key_store = expect_key_store(&flags.key_store_path); |
| 266 | run_node_inner(context, flags, key_store, loaded).await; |
| 267 | }) |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | /// How the configured genesis path looks at startup. Extracted from |
| 272 | /// [`acquire_genesis`] so the present-but-invalid decision can be exercised |
| 273 | /// directly in tests — the live path calls `std::process::exit` on that case, |
| 274 | /// which can't be asserted against in-process. |
| 275 | enum GenesisPathState { |
| 276 | /// A valid genesis file is already present at the path. |
| 277 | Valid(Box<Genesis>), |
| 278 | /// A file exists at the path but does not parse/validate. |
| 279 | InvalidPresent(String), |
| 280 | /// No file at the path; first-boot provisioning is required. |
| 281 | Absent, |
| 282 | } |
| 283 | |
| 284 | /// Classify the configured genesis path without side effects (no exit, no RPC). |
| 285 | fn classify_genesis_path(genesis_path: &str) -> GenesisPathState { |
| 286 | let present = get_expanded_path(genesis_path) |
no test coverage detected