OXYGENHUB
# 36537112fcac spectra / src / cli / admin.rs
2.2 KiB · Rust · last changed The ledger: hash-chained events in the frozen envelope, signed checkpoints, admin verify, check and rebuild (#3) 2 days ago source blame history raw
1
//! `spectra admin`: the ledger's own checks (spec §9.5, §19).
2
3
use super::{ui, Ctx};
4
use anyhow::Result;
5
use spectra_core::ledger::{Ledger, NoKeys};
6
7
/// `spectra admin verify`: recompute the chain, check every checkpoint and
8
/// proof; exit 1 when anything is wrong.
9
pub async fn verify(ctx: &Ctx, json: bool) -> Result<i32> {
10
    let ledger = Ledger::open(&ctx.db()?, None).await?;
11
    let v = ledger.verify(&NoKeys).await?;
12
    if json {
13
        println!("{}", serde_json::to_string(&v)?);
14
    } else if v.clean() {
15
        println!("{} ledger verified", ui::done(ui::glyph("✔", "ok")));
16
        println!("{}", ui::kv("events", v.events));
17
        println!(
18
            "{}",
19
            ui::kv(
20
                "checkpoints",
21
                format!("{} (last at {})", v.checkpoints, v.last_checkpoint.map(|s| s.to_string()).unwrap_or("none".into()))
22
            )
23
        );
24
        println!("{}", ui::kv("uncovered", format!("{} event(s) after the last checkpoint", v.uncovered)));
25
        println!("{}", ui::kv("head", ui::hash(hex::encode(v.head))));
26
    } else {
27
        println!("{} ledger does not verify: {} finding(s)", ui::err(ui::glyph("✘", "x")), v.findings.len());
28
        for f in &v.findings {
29
            println!("  {} {:?}: {}", ui::id(format!("#{}", f.seq)), f.problem, f.detail);
30
        }
31
    }
32
    Ok(if v.clean() { 0 } else { 1 })
33
}
34
35
/// `spectra admin check`: do the projections equal a rebuild?
36
pub async fn check(ctx: &Ctx) -> Result<i32> {
37
    let ledger = Ledger::open(&ctx.db()?, None).await?;
38
    let differ = ledger.check().await?;
39
    if differ.is_empty() {
40
        println!("{} projections match the ledger", ui::done(ui::glyph("✔", "ok")));
41
        Ok(0)
42
    } else {
43
        println!("{} projections differ from the ledger: {}", ui::err(ui::glyph("✘", "x")), differ.join(", "));
44
        println!("  run {} to rebuild them", ui::id("spectra admin rebuild"));
45
        Ok(1)
46
    }
47
}
48
49
/// `spectra admin rebuild`: replay the ledger into every projection.
50
pub async fn rebuild(ctx: &Ctx) -> Result<i32> {
51
    let ledger = Ledger::open(&ctx.db()?, None).await?;
52
    ledger.rebuild().await?;
53
    println!("{} projections rebuilt from {} event(s)", ui::done(ui::glyph("✔", "ok")), ledger.head().await.0);
54
    Ok(0)
55
}