(
context: tokio::Context,
flags: RunFlags,
key_store: KeyStore<PrivateKey>,
checkpoint: Option<ConsensusState>,
checkpoint_parent_block: Option<Block>,
)
| 448 | /// explicitly waives verification. |
| 449 | pub(crate) fn classify_checkpoint_startup( |
| 450 | has_checkpoint: bool, |
| 451 | has_headers_chain: bool, |
| 452 | unsafe_skip_verification: bool, |
| 453 | ) -> CheckpointStartupDecision { |
| 454 | match (has_checkpoint, has_headers_chain) { |
| 455 | (false, _) => CheckpointStartupDecision::NoCheckpoint, |
| 456 | (true, true) => CheckpointStartupDecision::Verify, |
| 457 | (true, false) if unsafe_skip_verification => CheckpointStartupDecision::SkipUnsafe, |
| 458 | (true, false) => CheckpointStartupDecision::RefuseUnverified, |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | /// Bind a supplied `last_block` to the verified chain terminal's finalized block |
| 463 | /// digest. `last_block` and the finalized-headers chain are loaded from |
| 464 | /// independent files, so a checkpoint directory could otherwise pair a verified |
| 465 | /// checkpoint with an unrelated block. Returns `Err` with a descriptive message |
| 466 | /// on mismatch; `Ok` when the block matches or none was supplied. |
| 467 | pub(crate) fn check_last_block_binding( |
| 468 | last_block_digest: Option<Digest>, |
| 469 | committed_digest: Digest, |
| 470 | ) -> Result<(), String> { |
| 471 | match last_block_digest { |
| 472 | Some(d) if d != committed_digest => Err(format!( |
| 473 | "checkpoint last_block does not match the verified terminal header's \ |
| 474 | finalized block (last_block {d:?}, verified terminal {committed_digest:?})" |
| 475 | )), |
| 476 | _ => Ok(()), |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | async fn run_node_inner( |
| 481 | context: tokio::Context, |
| 482 | flags: RunFlags, |
| 483 | key_store: KeyStore<PrivateKey>, |
| 484 | mut loaded: LoadedCheckpoint<MultisigScheme>, |
| 485 | ) { |
| 486 | let context = context.with_label("summit_cw"); |
| 487 | |
| 488 | // Initialize telemetry first, before genesis acquisition. First-boot |
| 489 | // provisioning can block in acquire_genesis waiting for the genesis RPC, so the |
| 490 | // subscriber must already be installed or those logs (and the RPC's own |
| 491 | // "listening" line) are silently dropped. |
| 492 | let log_level = Level::from_str(&flags.log_level).expect("Invalid log level"); |
| 493 | let critical_log_dir = flags |
| 494 | .critical_log_dir |
| 495 | .as_ref() |
| 496 | .map(|p| get_expanded_path(p).expect("Invalid critical log directory path")); |
| 497 | let _critical_log_guard = crate::telemetry::init(log_level, critical_log_dir.as_deref()); |
| 498 | |
| 499 | let genesis = acquire_genesis(&context, &flags).await; |
| 500 | |
| 501 | let mut committee: Vec<Validator> = genesis.get_validators().expect("Failed to get validators"); |
| 502 | committee.sort_by(|lhs, rhs| lhs.node_public_key.cmp(&rhs.node_public_key)); |
| 503 | |
| 504 | info!( |
| 505 | namespace = genesis.namespace, |
| 506 | genesis_validators = committee.len(), |
| 507 | min_stake = genesis.validator_minimum_stake, |
no test coverage detected