| 429 | NoCheckpoint, |
| 430 | /// A checkpoint and a finalized-headers chain are present; verify the |
| 431 | /// checkpoint against the chain before installing it. |
| 432 | Verify, |
| 433 | /// A checkpoint was supplied without a finalized-headers chain and the |
| 434 | /// operator opted into importing it unverified. |
| 435 | SkipUnsafe, |
| 436 | /// A checkpoint was supplied without a finalized-headers chain and |
| 437 | /// verification was not waived; refuse to start. |
| 438 | RefuseUnverified, |
| 439 | } |
| 440 | |
| 441 | /// Decide how to treat checkpoint artifacts at startup. |
| 442 | /// |
| 443 | /// Requiring a finalized-headers chain by default is what closes the |
| 444 | /// unauthenticated-import hole (#214): once the chain is present, the |
| 445 | /// signature-verified terminal header authenticates every byte of the checkpoint |
| 446 | /// through the checkpoint-hash binding, so the decoded consensus state cannot be |
| 447 | /// tampered with. A bare checkpoint with no chain is refused unless the operator |
| 448 | /// explicitly waives verification. |
| 449 | pub(crate) fn classify_checkpoint_startup( |
| 450 | has_checkpoint: bool, |
| 451 | has_headers_chain: bool, |