entropa-core 0.1.1

Entropa core — post-quantum (ML-DSA / NIST FIPS-204) blockchain primitives: probes, transactions, blocks, and a verifiable chain seeded by a public randomness beacon.
Documentation
use entropa_core::{block_digest, probe_id, verify_hex, Block};

fn main() {
    let path = std::env::args().nth(1).expect("path to blocks JSON");
    let data = std::fs::read_to_string(&path).expect("read file");
    let blocks: Vec<Block> = serde_json::from_str(&data).expect("parse blocks");
    println!("loaded {} blocks, index {} to {}", blocks.len(), blocks[0].index, blocks.last().unwrap().index);

    let mut ok = true;
    for (n, b) in blocks.iter().enumerate() {
        if n > 0 {
            let prev = &blocks[n - 1];
            if b.index != prev.index + 1 {
                println!("BAD INDEX SEQUENCE at {}: {} -> {}", n, prev.index, b.index);
                ok = false;
            }
            if b.prev_hash != prev.hash {
                println!("BROKEN LINK at index {}: prev_hash doesn't match block {}'s hash", b.index, prev.index);
                ok = false;
            }
        }
        if probe_id(&b.proposer_pubkey) != b.proposer_id {
            println!("FORGED PROPOSER at index {}", b.index);
            ok = false;
        }
        let digest = block_digest(b.index, b.timestamp, &b.prev_hash, &b.beacon, &b.transactions, &b.proposer_id);
        if hex::encode(digest) != b.hash {
            println!("BAD HASH at index {}", b.index);
            ok = false;
        }
        if !verify_hex(&b.proposer_pubkey, &digest, &b.signature) {
            println!("BAD SIGNATURE at index {}", b.index);
            ok = false;
        }
    }
    if ok {
        println!("SLICE VERIFY OK — all {} blocks: hash-linked, hashes correct, ML-DSA signatures valid", blocks.len());
    } else {
        println!("SLICE VERIFY FAILED — see errors above");
        std::process::exit(1);
    }
}