Verifiable event log on top of a Merkle Mountain Range (MMR).
Why
The Commonware journal that backs the polychrome event log gives durability and ordering but doesn't make the log tamper-evident: a reader has no way to verify the operator hasn't quietly rewritten an event between when it was appended and when they replayed it. A Merkle Mountain Range (append-only Merkle structure) closes that gap cheaply:
- Every appended event becomes one MMR leaf, with the leaf digest
bound to the event's
(kind, payload)bytes. - After each turn (or any operator-chosen cadence), the journal writer
computes the current MMR root and signs it with the polychrome
JournalAttestationSigner(ed25519). The signed root persists as its own event in the journal — same partition, same atomic batch. - A future reader can ask for any past event's inclusion proof (O(log n) digests), verify it against the most recent signed root, and detect tampering.
Layering vs the journal
This crate is independent of the journal: it consumes
(position, kind, payload) triples and emits leaves + roots + proofs.
Integration with polyc-eventlog lives in the call sites that
append events — they extend the MMR alongside the journal write and
persist the signed root.
Stability of the leaf hash
The leaf digest is SHA-256(position_be || kind_len_be || kind || payload_len_be || payload) (lengths as 8-byte big-endian for
unambiguous framing). This is intentionally not the wire encoding of
the event so a future change to the on-disk format doesn't
invalidate historic proofs.
Durability of the in-memory Mmr
This crate wraps commonware_storage::merkle::mmr::mem::Mmr directly.
Its internal representation never touches disk — only this module's
own hex-encoded [SignedRoot] and [InclusionProof] wire types
persist (inside journal events). A future upstream change to Mmr's
shape can only force a rebuild of this crate; it can never corrupt
anything already written.