Backend-agnostic anchoring / attestation (Slice 8).
A transparency log's anti-equivocation guarantee is only as strong as a
relying party's ability to detect a split view — an operator showing one
checkpoint to Alice and a different, inconsistent one to Bob. Independent
witnesses (MetamorphicLog.Note) are one defence; anchoring is the other:
periodically committing a checkpoint's signed tree head to an external,
hard-to-equivocate medium (a blockchain transaction, an RFC 3161 notary
receipt, object-lock / WORM storage, or another transparency log) so the
operator cannot later present a tree that disagrees with what was anchored
without that contradiction being publicly visible.
This module surfaces the engine's contribution to anchoring — the format and the verification — and is deliberately backend-agnostic and I/O-free. There is no network client, chain RPC, or notary integration here, and no anchor cadence / fee / confirmation-depth policy: those belong to the operator (the paid mosskeys app). What lives here is:
record_canonical_bytes/6/parse_record/1— the canonical, byte-locked attestation record binding a checkpoint head (origin,size,root_hash) to an opaquelocatorand an agnosticmediumtag.anchor_commitment/1— the fixed-size, medium-independent commitment an operator publishes to (and re-fetches from) the medium.verify_anchored/4— the third-party audit that an attestation binds a checkpoint and that successive anchored heads are append-only consistent, trusting neither the operator nor the medium.verify_commitment/2— the medium-side counterpart: check bytes fetched from the medium equal the recomputed commitment.
I/O stays on the BEAM side
The Rust core's CommitmentSink trait (and its logic-only *_via bridges) is
intentionally not wrapped: a sink with an associated error type and a real
backend (chain/notary/object store) is idiomatically BEAM code. Your operator
publishes/fetches the commitment bytes itself, then uses anchor_commitment/1
verify_commitment/2to check them.
Honest framing (no zero-knowledge)
This is plain anchoring: publish a checkpoint-head commitment and prove consistency between successive anchored heads. It involves zero zero-knowledge machinery; the optional ZK-anchoring enhancement is a separate effort and is not coupled to this format.
Binary values are base64-encoded (standard padded alphabet), byte-identical to the native Rust core and the browser WASM SDK.
Summary
Types
A parsed anchor record
Functions
The fixed-size commitment over the record's checkpoint head — the value an operator publishes to (and re-fetches from) the external medium.
Parse a canonical anchor record into a anchor_record/0 map. Validates the layout,
format version, algorithm tag, medium grammar, and non-empty origin/locator.
Returns {:ok, record} or {:error, reason}.
Build the canonical bytes of an anchor attestation record from an explicit checkpoint head.
The RFC 6962 Merkle leaf hash of the record's canonical bytes, so an operator
may also log its attestations as Layer-0 leaves. Returns {:ok, hash_b64} or
{:error, reason}. Dirty CPU.
Verify an anchored checkpoint.
Medium-side check: the bytes fetched_commitment_b64 retrieved from the
external medium equal the commitment recomputed from record_b64's checkpoint
head.
Types
@type anchor_record() :: %{ origin: String.t(), size: non_neg_integer(), root: String.t(), commitment_alg: String.t(), medium: String.t(), locator: String.t() }
A parsed anchor record:
:origin— the bound checkpoint origin (log identity):size— the bound checkpoint tree size:root— base64 RFC 6962 root hash atsize(32 bytes):commitment_alg— the safe-menu commitment algorithm ("sha3_512"):medium— the medium identifier (e.g."ethereum/mainnet"):locator— base64 opaque external-commitment locator
Functions
The fixed-size commitment over the record's checkpoint head — the value an operator publishes to (and re-fetches from) the external medium.
Medium- and locator-independent: the same head yields the same commitment
regardless of where it is anchored. Returns {:ok, commitment_b64} or
{:error, reason}. Runs on a dirty CPU scheduler.
@spec parse_record(record_b64 :: String.t()) :: {:ok, anchor_record()} | {:error, String.t()}
Parse a canonical anchor record into a anchor_record/0 map. Validates the layout,
format version, algorithm tag, medium grammar, and non-empty origin/locator.
Returns {:ok, record} or {:error, reason}.
@spec record_canonical_bytes( origin :: String.t(), size :: non_neg_integer(), root_b64 :: String.t(), medium :: String.t(), locator_b64 :: String.t(), commitment_alg :: String.t() ) :: {:ok, String.t()} | {:error, String.t()}
Build the canonical bytes of an anchor attestation record from an explicit checkpoint head.
medium is a printable-ASCII identifier (no whitespace/control bytes, /
allowed for hierarchy, e.g. "ethereum/mainnet"); locator_b64 is the opaque
external-commitment handle (tx id, block height, receipt, object key);
commitment_alg is a safe-menu tag ("sha3_512", the v0.1 default and only
entry). Returns {:ok, record_b64} or {:error, reason}.
The RFC 6962 Merkle leaf hash of the record's canonical bytes, so an operator
may also log its attestations as Layer-0 leaves. Returns {:ok, hash_b64} or
{:error, reason}. Dirty CPU.
@spec verify_anchored( note_text :: String.t(), vkeys :: [String.t()], record_b64 :: String.t(), opts :: keyword() ) :: :ok | {:error, String.t()}
Verify an anchored checkpoint.
Checks that record_b64 binds the checkpoint carried by note_text (verified
against the trusted vkeys), and — when a previous anchored checkpoint is
supplied — that the newer checkpoint is an append-only extension of it.
This is the log-side audit of "the operator never equivocated between anchored
heads": it trusts neither the operator nor the medium. Pair it with
verify_commitment/2 (the medium-side check) for the full guarantee. Runs on a
dirty CPU scheduler.
Options
:prev_note— a previously-anchored checkpoint signed note. When given, consistency from it tonote_textis verified.:consistency_proof— a list of base64 RFC 9162 consistency-proof hashes from:prev_notetonote_text(each 32 bytes). Required (and only used) when:prev_noteis set.
With no :prev_note, only the attestation-binds-checkpoint check runs.
Returns :ok on success or {:error, reason} (a failed binding/consistency
check or malformed input).
Examples
# binding-only
:ok = MetamorphicLog.Anchor.verify_anchored(note, [vkey], record)
# binding + consistency from a previous anchored head
:ok =
MetamorphicLog.Anchor.verify_anchored(newer_note, [vkey], record,
prev_note: older_note,
consistency_proof: proof_b64
)
@spec verify_commitment( record_b64 :: String.t(), fetched_commitment_b64 :: String.t() ) :: :ok | {:error, :commitment_mismatch | String.t()}
Medium-side check: the bytes fetched_commitment_b64 retrieved from the
external medium equal the commitment recomputed from record_b64's checkpoint
head.
On :ok the medium genuinely attests to this checkpoint head. This is the
counterpart to verify_anchored/4: together they prove the head was anchored
and the operator never equivocated between anchored heads. The fetch itself
is your operator's job (this library performs no I/O).
Returns :ok, {:error, :commitment_mismatch}, or {:error, reason} if the
record is malformed.