Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build a log and verify the proofs

This tutorial stores the three records from getting started, checks the proofs a reader assembles from tiles, signs a checkpoint, and then builds a small indexed log. The tree shape is the Merkle tree page. The program is docs/examples/src/bin/tutorial.rs.

cargo run -q -p rfc9162-docs-examples --bin tutorial

From a new crate, the same calls need rfc9162, rfc9162-tiles, rfc9162-log and tempfile at the versions in installation. The snippets below are the program, split at the points where the output changes.

Write three records

PosixStore is a directory. Writer takes the writer lock, appends each record, and writes the tree state last. With three entries the level-0 tile and the entry bundle are partial tiles of width 3. A full tile holds 256 hashes, so nothing is sealed yet and there is no key sidecar.

beta sits under the node of alpha and beta. Its inclusion proof carries alpha’s leaf hash, then gamma’s leaf hash. The figure marks those two siblings.

//! Build a directory log, check proofs, sign a checkpoint, then index a log.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use rfc9162_log::{AuthenticatedLog, Store};
use rfc9162_tiles::index::no_keys;
use rfc9162_tiles::{MemoryStore, PosixStore, Reader, Signer, TileStore, Writer};

fn main() {
    let dir = tempfile::tempdir().expect("temp dir");
    let store = PosixStore::open(dir.path()).expect("store");
    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    for record in ["alpha", "beta", "gamma"] {
        let index = writer.append(record.as_bytes()).expect("append");
        println!("append {index} {record}");
    }
    let early_size = writer.size();
    let early_root = rfc9162::hex(&writer.root());
    println!("stored size {early_size}");
    println!("stored root {early_root}");
    drop(writer);

    let mut files = store.list("").expect("list");
    files.retain(|path| !path.ends_with(".lock"));
    println!("files");
    for path in &files {
        println!("  {path}");
    }

    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let entry = reader.get(1).expect("get").expect("present");
    println!("get 1 = {}", String::from_utf8(entry).expect("utf-8"));
    let proof = reader.inclusion(1).expect("inclusion").expect("in tree");
    let leaves: Vec<[u8; 32]> = ["alpha", "beta", "gamma"]
        .iter()
        .map(|record| rfc9162::leaf_hash(record.as_bytes()))
        .collect();
    let flat = rfc9162::inclusion_proof(&leaves, 1).expect("flat proof");
    println!("tile proof matches flat proof {}", proof == flat);
    println!(
        "verify inclusion {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(reader.size()).unwrap(),
            &proof,
            &rfc9162::hex(&reader.root()),
        )
    );

    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let index = writer.append(b"delta").expect("append");
    println!("append {index} delta");
    drop(writer);
    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let consistency = reader
        .consistency(early_size)
        .expect("consistency")
        .expect("prefix");
    println!(
        "verify consistency {}",
        rfc9162::verify_consistency(
            usize::try_from(early_size).unwrap(),
            &early_root,
            usize::try_from(reader.size()).unwrap(),
            &rfc9162::hex(&reader.root()),
            &consistency,
        )
    );

    let signer =
        Signer::new("example.org/log", SigningKey::from_bytes(&[7u8; 32])).expect("signer");
    let writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let note = writer
        .checkpoint(&signer, "example.org/log")
        .expect("checkpoint");
    println!("checkpoint");
    print!("{}", note.to_text());
    drop(writer);
    let trusted = [signer.verifier()];
    let opened =
        Reader::open_checkpoint(store, "example.org/log", &trusted, no_keys()).expect("open");
    println!("opened at checkpoint size {}", opened.size());
    let again = opened.inclusion(1).expect("inclusion").expect("in tree");
    println!(
        "inclusion at checkpoint {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(opened.size()).unwrap(),
            &again,
            &rfc9162::hex(&opened.root()),
        )
    );

    let mut log = Store::open(
        MemoryStore::new(),
        Arc::new(|entry: &[u8]| {
            entry
                .split(|byte| *byte == b' ')
                .filter(|field| !field.is_empty())
                .map(<[u8]>::to_vec)
                .collect()
        }),
    )
    .expect("log");
    log.append(b"module=petsc pkg=petsc").expect("append");
    log.append(b"module=openmpi pkg=openmpi").expect("append");
    let run = log.seal().expect("seal");
    println!(
        "sealed {}..={} manifest {}",
        run.entries.start(),
        run.entries.end(),
        run.manifest_index.expect("logged"),
    );
    let found = log.find(b"module=petsc").expect("find");
    let hit = &found[0];
    let bytes = log
        .index()
        .expect("index")
        .reader()
        .get(hit.entry.index)
        .expect("get")
        .expect("present");
    println!(
        "find module=petsc index {} run {} inclusion {}",
        hit.entry.index,
        hit.run.is_some(),
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(&bytes),
            usize::try_from(hit.entry.index).unwrap(),
            usize::try_from(hit.entry.tree_size).unwrap(),
            &hit.entry.path,
            &rfc9162::hex(&log.root()),
        )
    );
}

Read the proof back

Reader trusts the tree state the writer stored. inclusion builds the path from the tiles. That path is the same bytes inclusion_proof returns over the flat leaf slice, and verify_inclusion accepts it for beta at index 1.

//! Build a directory log, check proofs, sign a checkpoint, then index a log.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use rfc9162_log::{AuthenticatedLog, Store};
use rfc9162_tiles::index::no_keys;
use rfc9162_tiles::{MemoryStore, PosixStore, Reader, Signer, TileStore, Writer};

fn main() {
    let dir = tempfile::tempdir().expect("temp dir");
    let store = PosixStore::open(dir.path()).expect("store");
    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    for record in ["alpha", "beta", "gamma"] {
        let index = writer.append(record.as_bytes()).expect("append");
        println!("append {index} {record}");
    }
    let early_size = writer.size();
    let early_root = rfc9162::hex(&writer.root());
    println!("stored size {early_size}");
    println!("stored root {early_root}");
    drop(writer);

    let mut files = store.list("").expect("list");
    files.retain(|path| !path.ends_with(".lock"));
    println!("files");
    for path in &files {
        println!("  {path}");
    }

    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let entry = reader.get(1).expect("get").expect("present");
    println!("get 1 = {}", String::from_utf8(entry).expect("utf-8"));
    let proof = reader.inclusion(1).expect("inclusion").expect("in tree");
    let leaves: Vec<[u8; 32]> = ["alpha", "beta", "gamma"]
        .iter()
        .map(|record| rfc9162::leaf_hash(record.as_bytes()))
        .collect();
    let flat = rfc9162::inclusion_proof(&leaves, 1).expect("flat proof");
    println!("tile proof matches flat proof {}", proof == flat);
    println!(
        "verify inclusion {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(reader.size()).unwrap(),
            &proof,
            &rfc9162::hex(&reader.root()),
        )
    );

    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let index = writer.append(b"delta").expect("append");
    println!("append {index} delta");
    drop(writer);
    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let consistency = reader
        .consistency(early_size)
        .expect("consistency")
        .expect("prefix");
    println!(
        "verify consistency {}",
        rfc9162::verify_consistency(
            usize::try_from(early_size).unwrap(),
            &early_root,
            usize::try_from(reader.size()).unwrap(),
            &rfc9162::hex(&reader.root()),
            &consistency,
        )
    );

    let signer =
        Signer::new("example.org/log", SigningKey::from_bytes(&[7u8; 32])).expect("signer");
    let writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let note = writer
        .checkpoint(&signer, "example.org/log")
        .expect("checkpoint");
    println!("checkpoint");
    print!("{}", note.to_text());
    drop(writer);
    let trusted = [signer.verifier()];
    let opened =
        Reader::open_checkpoint(store, "example.org/log", &trusted, no_keys()).expect("open");
    println!("opened at checkpoint size {}", opened.size());
    let again = opened.inclusion(1).expect("inclusion").expect("in tree");
    println!(
        "inclusion at checkpoint {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(opened.size()).unwrap(),
            &again,
            &rfc9162::hex(&opened.root()),
        )
    );

    let mut log = Store::open(
        MemoryStore::new(),
        Arc::new(|entry: &[u8]| {
            entry
                .split(|byte| *byte == b' ')
                .filter(|field| !field.is_empty())
                .map(<[u8]>::to_vec)
                .collect()
        }),
    )
    .expect("log");
    log.append(b"module=petsc pkg=petsc").expect("append");
    log.append(b"module=openmpi pkg=openmpi").expect("append");
    let run = log.seal().expect("seal");
    println!(
        "sealed {}..={} manifest {}",
        run.entries.start(),
        run.entries.end(),
        run.manifest_index.expect("logged"),
    );
    let found = log.find(b"module=petsc").expect("find");
    let hit = &found[0];
    let bytes = log
        .index()
        .expect("index")
        .reader()
        .get(hit.entry.index)
        .expect("get")
        .expect("present");
    println!(
        "find module=petsc index {} run {} inclusion {}",
        hit.entry.index,
        hit.run.is_some(),
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(&bytes),
            usize::try_from(hit.entry.index).unwrap(),
            usize::try_from(hit.entry.tree_size).unwrap(),
            &hit.entry.path,
            &rfc9162::hex(&log.root()),
        )
    );
}

Append and check consistency

A second writer opens the same directory after the first drops the lock. Appending delta moves the size from 3 to 4. consistency returns the proof from the earlier size, and verify_consistency accepts the earlier root together with the new one. Those three nodes are listed on the consistency page.

//! Build a directory log, check proofs, sign a checkpoint, then index a log.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use rfc9162_log::{AuthenticatedLog, Store};
use rfc9162_tiles::index::no_keys;
use rfc9162_tiles::{MemoryStore, PosixStore, Reader, Signer, TileStore, Writer};

fn main() {
    let dir = tempfile::tempdir().expect("temp dir");
    let store = PosixStore::open(dir.path()).expect("store");
    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    for record in ["alpha", "beta", "gamma"] {
        let index = writer.append(record.as_bytes()).expect("append");
        println!("append {index} {record}");
    }
    let early_size = writer.size();
    let early_root = rfc9162::hex(&writer.root());
    println!("stored size {early_size}");
    println!("stored root {early_root}");
    drop(writer);

    let mut files = store.list("").expect("list");
    files.retain(|path| !path.ends_with(".lock"));
    println!("files");
    for path in &files {
        println!("  {path}");
    }

    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let entry = reader.get(1).expect("get").expect("present");
    println!("get 1 = {}", String::from_utf8(entry).expect("utf-8"));
    let proof = reader.inclusion(1).expect("inclusion").expect("in tree");
    let leaves: Vec<[u8; 32]> = ["alpha", "beta", "gamma"]
        .iter()
        .map(|record| rfc9162::leaf_hash(record.as_bytes()))
        .collect();
    let flat = rfc9162::inclusion_proof(&leaves, 1).expect("flat proof");
    println!("tile proof matches flat proof {}", proof == flat);
    println!(
        "verify inclusion {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(reader.size()).unwrap(),
            &proof,
            &rfc9162::hex(&reader.root()),
        )
    );

    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let index = writer.append(b"delta").expect("append");
    println!("append {index} delta");
    drop(writer);
    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let consistency = reader
        .consistency(early_size)
        .expect("consistency")
        .expect("prefix");
    println!(
        "verify consistency {}",
        rfc9162::verify_consistency(
            usize::try_from(early_size).unwrap(),
            &early_root,
            usize::try_from(reader.size()).unwrap(),
            &rfc9162::hex(&reader.root()),
            &consistency,
        )
    );

    let signer =
        Signer::new("example.org/log", SigningKey::from_bytes(&[7u8; 32])).expect("signer");
    let writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let note = writer
        .checkpoint(&signer, "example.org/log")
        .expect("checkpoint");
    println!("checkpoint");
    print!("{}", note.to_text());
    drop(writer);
    let trusted = [signer.verifier()];
    let opened =
        Reader::open_checkpoint(store, "example.org/log", &trusted, no_keys()).expect("open");
    println!("opened at checkpoint size {}", opened.size());
    let again = opened.inclusion(1).expect("inclusion").expect("in tree");
    println!(
        "inclusion at checkpoint {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(opened.size()).unwrap(),
            &again,
            &rfc9162::hex(&opened.root()),
        )
    );

    let mut log = Store::open(
        MemoryStore::new(),
        Arc::new(|entry: &[u8]| {
            entry
                .split(|byte| *byte == b' ')
                .filter(|field| !field.is_empty())
                .map(<[u8]>::to_vec)
                .collect()
        }),
    )
    .expect("log");
    log.append(b"module=petsc pkg=petsc").expect("append");
    log.append(b"module=openmpi pkg=openmpi").expect("append");
    let run = log.seal().expect("seal");
    println!(
        "sealed {}..={} manifest {}",
        run.entries.start(),
        run.entries.end(),
        run.manifest_index.expect("logged"),
    );
    let found = log.find(b"module=petsc").expect("find");
    let hit = &found[0];
    let bytes = log
        .index()
        .expect("index")
        .reader()
        .get(hit.entry.index)
        .expect("get")
        .expect("present");
    println!(
        "find module=petsc index {} run {} inclusion {}",
        hit.entry.index,
        hit.run.is_some(),
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(&bytes),
            usize::try_from(hit.entry.index).unwrap(),
            usize::try_from(hit.entry.tree_size).unwrap(),
            &hit.entry.path,
            &rfc9162::hex(&log.root()),
        )
    );
}

Sign a checkpoint and open at that size

Signer is an Ed25519 key under the origin example.org/log. The seed here is the fixed 32-byte value used by the documentation programs, so the signature line is stable. Writer::checkpoint writes a signed note at checkpoint. Reader::open_checkpoint accepts the log when that note verifies under a trusted key and the origin matches.

The checkpoint body is the origin, the decimal size and the root in standard base64. The base64 line decodes to the size-4 root 42fc54eeb6352f90cc81fdd5791292cca3974a168208b395b06a76240b24884d, which is the later root from getting started. The line that follows the blank line is the signature. It begins with an em dash, then the key name, then the key id and signature.

//! Build a directory log, check proofs, sign a checkpoint, then index a log.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use rfc9162_log::{AuthenticatedLog, Store};
use rfc9162_tiles::index::no_keys;
use rfc9162_tiles::{MemoryStore, PosixStore, Reader, Signer, TileStore, Writer};

fn main() {
    let dir = tempfile::tempdir().expect("temp dir");
    let store = PosixStore::open(dir.path()).expect("store");
    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    for record in ["alpha", "beta", "gamma"] {
        let index = writer.append(record.as_bytes()).expect("append");
        println!("append {index} {record}");
    }
    let early_size = writer.size();
    let early_root = rfc9162::hex(&writer.root());
    println!("stored size {early_size}");
    println!("stored root {early_root}");
    drop(writer);

    let mut files = store.list("").expect("list");
    files.retain(|path| !path.ends_with(".lock"));
    println!("files");
    for path in &files {
        println!("  {path}");
    }

    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let entry = reader.get(1).expect("get").expect("present");
    println!("get 1 = {}", String::from_utf8(entry).expect("utf-8"));
    let proof = reader.inclusion(1).expect("inclusion").expect("in tree");
    let leaves: Vec<[u8; 32]> = ["alpha", "beta", "gamma"]
        .iter()
        .map(|record| rfc9162::leaf_hash(record.as_bytes()))
        .collect();
    let flat = rfc9162::inclusion_proof(&leaves, 1).expect("flat proof");
    println!("tile proof matches flat proof {}", proof == flat);
    println!(
        "verify inclusion {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(reader.size()).unwrap(),
            &proof,
            &rfc9162::hex(&reader.root()),
        )
    );

    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let index = writer.append(b"delta").expect("append");
    println!("append {index} delta");
    drop(writer);
    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let consistency = reader
        .consistency(early_size)
        .expect("consistency")
        .expect("prefix");
    println!(
        "verify consistency {}",
        rfc9162::verify_consistency(
            usize::try_from(early_size).unwrap(),
            &early_root,
            usize::try_from(reader.size()).unwrap(),
            &rfc9162::hex(&reader.root()),
            &consistency,
        )
    );

    let signer =
        Signer::new("example.org/log", SigningKey::from_bytes(&[7u8; 32])).expect("signer");
    let writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let note = writer
        .checkpoint(&signer, "example.org/log")
        .expect("checkpoint");
    println!("checkpoint");
    print!("{}", note.to_text());
    drop(writer);
    let trusted = [signer.verifier()];
    let opened =
        Reader::open_checkpoint(store, "example.org/log", &trusted, no_keys()).expect("open");
    println!("opened at checkpoint size {}", opened.size());
    let again = opened.inclusion(1).expect("inclusion").expect("in tree");
    println!(
        "inclusion at checkpoint {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(opened.size()).unwrap(),
            &again,
            &rfc9162::hex(&opened.root()),
        )
    );

    let mut log = Store::open(
        MemoryStore::new(),
        Arc::new(|entry: &[u8]| {
            entry
                .split(|byte| *byte == b' ')
                .filter(|field| !field.is_empty())
                .map(<[u8]>::to_vec)
                .collect()
        }),
    )
    .expect("log");
    log.append(b"module=petsc pkg=petsc").expect("append");
    log.append(b"module=openmpi pkg=openmpi").expect("append");
    let run = log.seal().expect("seal");
    println!(
        "sealed {}..={} manifest {}",
        run.entries.start(),
        run.entries.end(),
        run.manifest_index.expect("logged"),
    );
    let found = log.find(b"module=petsc").expect("find");
    let hit = &found[0];
    let bytes = log
        .index()
        .expect("index")
        .reader()
        .get(hit.entry.index)
        .expect("get")
        .expect("present");
    println!(
        "find module=petsc index {} run {} inclusion {}",
        hit.entry.index,
        hit.run.is_some(),
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(&bytes),
            usize::try_from(hit.entry.index).unwrap(),
            usize::try_from(hit.entry.tree_size).unwrap(),
            &hit.entry.path,
            &rfc9162::hex(&log.root()),
        )
    );
}

An inclusion proof at the checkpoint size still verifies for beta. The checkpoint covers four entries, so the path is the path in a tree of size 4.

Index a log and prove the lookup

rfc9162-log stores lookup keys in sorted runs and appends each run’s manifest as a log entry. The key function here splits an entry on spaces. The identity hash SHA-256(entry) is always a key as well.

seal writes the run for the unsealed tail and logs the manifest. The two entries occupy indexes 0 and 1. The manifest is logged at index 2. find returns the entry’s inclusion path and the path of the manifest that located it. Both are at the current tree size, and the entry path verifies.

//! Build a directory log, check proofs, sign a checkpoint, then index a log.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use rfc9162_log::{AuthenticatedLog, Store};
use rfc9162_tiles::index::no_keys;
use rfc9162_tiles::{MemoryStore, PosixStore, Reader, Signer, TileStore, Writer};

fn main() {
    let dir = tempfile::tempdir().expect("temp dir");
    let store = PosixStore::open(dir.path()).expect("store");
    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    for record in ["alpha", "beta", "gamma"] {
        let index = writer.append(record.as_bytes()).expect("append");
        println!("append {index} {record}");
    }
    let early_size = writer.size();
    let early_root = rfc9162::hex(&writer.root());
    println!("stored size {early_size}");
    println!("stored root {early_root}");
    drop(writer);

    let mut files = store.list("").expect("list");
    files.retain(|path| !path.ends_with(".lock"));
    println!("files");
    for path in &files {
        println!("  {path}");
    }

    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let entry = reader.get(1).expect("get").expect("present");
    println!("get 1 = {}", String::from_utf8(entry).expect("utf-8"));
    let proof = reader.inclusion(1).expect("inclusion").expect("in tree");
    let leaves: Vec<[u8; 32]> = ["alpha", "beta", "gamma"]
        .iter()
        .map(|record| rfc9162::leaf_hash(record.as_bytes()))
        .collect();
    let flat = rfc9162::inclusion_proof(&leaves, 1).expect("flat proof");
    println!("tile proof matches flat proof {}", proof == flat);
    println!(
        "verify inclusion {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(reader.size()).unwrap(),
            &proof,
            &rfc9162::hex(&reader.root()),
        )
    );

    let mut writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let index = writer.append(b"delta").expect("append");
    println!("append {index} delta");
    drop(writer);
    let reader = Reader::open(store.clone(), no_keys()).expect("reader");
    let consistency = reader
        .consistency(early_size)
        .expect("consistency")
        .expect("prefix");
    println!(
        "verify consistency {}",
        rfc9162::verify_consistency(
            usize::try_from(early_size).unwrap(),
            &early_root,
            usize::try_from(reader.size()).unwrap(),
            &rfc9162::hex(&reader.root()),
            &consistency,
        )
    );

    let signer =
        Signer::new("example.org/log", SigningKey::from_bytes(&[7u8; 32])).expect("signer");
    let writer = Writer::open(store.clone(), no_keys()).expect("writer");
    let note = writer
        .checkpoint(&signer, "example.org/log")
        .expect("checkpoint");
    println!("checkpoint");
    print!("{}", note.to_text());
    drop(writer);
    let trusted = [signer.verifier()];
    let opened =
        Reader::open_checkpoint(store, "example.org/log", &trusted, no_keys()).expect("open");
    println!("opened at checkpoint size {}", opened.size());
    let again = opened.inclusion(1).expect("inclusion").expect("in tree");
    println!(
        "inclusion at checkpoint {}",
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(b"beta"),
            1,
            usize::try_from(opened.size()).unwrap(),
            &again,
            &rfc9162::hex(&opened.root()),
        )
    );

    let mut log = Store::open(
        MemoryStore::new(),
        Arc::new(|entry: &[u8]| {
            entry
                .split(|byte| *byte == b' ')
                .filter(|field| !field.is_empty())
                .map(<[u8]>::to_vec)
                .collect()
        }),
    )
    .expect("log");
    log.append(b"module=petsc pkg=petsc").expect("append");
    log.append(b"module=openmpi pkg=openmpi").expect("append");
    let run = log.seal().expect("seal");
    println!(
        "sealed {}..={} manifest {}",
        run.entries.start(),
        run.entries.end(),
        run.manifest_index.expect("logged"),
    );
    let found = log.find(b"module=petsc").expect("find");
    let hit = &found[0];
    let bytes = log
        .index()
        .expect("index")
        .reader()
        .get(hit.entry.index)
        .expect("get")
        .expect("present");
    println!(
        "find module=petsc index {} run {} inclusion {}",
        hit.entry.index,
        hit.run.is_some(),
        rfc9162::verify_inclusion(
            &rfc9162::leaf_hash(&bytes),
            usize::try_from(hit.entry.index).unwrap(),
            usize::try_from(hit.entry.tree_size).unwrap(),
            &hit.entry.path,
            &rfc9162::hex(&log.root()),
        )
    );
}

The whole transcript

append 0 alpha
append 1 beta
append 2 gamma
stored size 3
stored root 385da30f3917282c8939dff851957e519ab1846b1351a14c0adb3b11632742aa
files
  .state/treeState
  tile/0/000.p/3
  tile/entries/000.p/3
get 1 = beta
tile proof matches flat proof true
verify inclusion true
append 3 delta
verify consistency true
checkpoint
example.org/log
4
QvxU7rY1L5DMgf3VeRKSzKOXShaCCLOVsGp2JAskiE0=

— example.org/log XizvABGVVgSZCUqVA+tuUquqJ/4ZqAkwPrKofuvUMbxYclF9uL33Ylz1U8bIIrNIZ9VDhwLzfA995O3vyFoe51KWGA4=
opened at checkpoint size 4
inclusion at checkpoint true
sealed 0..=1 manifest 2
find module=petsc index 0 run true inclusion true

The tiles how-to covers packs, identity lookup and cosignatures. The log how-to covers ranges, compaction, recovery and the sidecar command.