Daily merkle anchoring of attestations
How jurat rolls every attestation into a daily signed merkle root and anchors it to Base calldata, and how to verify a merkle proof by hand.
Why anchoring exists
A signature proves jurat vouches for a record. An anchor proves the record existed before a point in time, independently of jurat. Every day, every new attestation is rolled into a merkle tree; the root is signed and published at /v1/anchors (free), and written to Base calldata when the anchor wallet is funded.
The algorithm, exactly
- Leaf: sha256 of the canonical
signedobject (same canonicalization as the signature: sorted keys, no whitespace). - Order: leaves sorted ascending as hex strings.
- Parent: sha256 of the concatenated raw bytes of the two child hashes. An odd leaf is paired with itself.
- Root signature: ed25519 over canonical
{"date":"YYYY-MM-DD","jurat_anchor":1,"root":"..."}. - Onchain: a zero-value self-send on Base whose calldata is
0x6a757261743a3101("jurat:1" tag) followed by the 32-byte root.
Verifying a proof
Every anchored attestation carries an anchored block: its leaf, a merkle proof (a list of steps, each a sibling hash and a position), the root, the root signature, and the Base transaction hash when written. Recompute the leaf from the record, walk the proof, and compare the final hash to the root:
h = leaf
for step in proof:
pair = (step.hash + h) if step.position == 'left' else (h + step.hash)
h = sha256(bytes.fromhex(pair_left) + bytes.fromhex(pair_right))
assert h == root
If the root also appears in Base calldata, the attestation provably existed before that block. jurat cannot backdate evidence without breaking the tree.