Docs / 10

Anchoring and the registry

Every case file, sealed or public, is anchored on Robinhood Chain so that anyone holding it can prove it existed, unchanged, at a given time. The contract that holds the anchors is CaseRegistry, at 0x8D45fe8f12Bc81f24E0c7184eEBA5d08AD001bB8, with its source verified on Sourcify.

leaf 0watchleaf 1watchleaf 2sealedleaf 3watchleaf 4sealedleaf 5watchpair 0pair 1pair 2pair 0+1batch rootCaseRegistryfileBatch(root, count, sealedCount)BatchFiled(id, root, ...)
One batch: public and sealed leaves side by side, one root on-chain. The odd node is carried up unchanged.

The leaf

fileHash = sha256(canonicalJson(file))
leaf     = keccak256(abi.encode(bytes32 caseId, bytes32 fileHash, bool sealed))

The sealed flag is part of the leaf, so a public leaf can never be passed off as a sealed one or the reverse.

The batch

Leaves are paired in order. Each pair is hashed as keccak256(abi.encode(a, b)) with the smaller of the two first, so a proof needs no left or right flags; an odd node at the end of a level is carried up unchanged. The top of the tree is the batch root. A batch holding a single leaf has that leaf as its root and an empty proof.

The clerk posts batches with fileBatch(root, count, sealedCount), which records the root, the block time and the counts and emits BatchFiled(batchId, root, count, sealedCount). It runs every fifteen minutes: a batch goes out as soon as a sealed leaf has waited ten minutes, and the Night Watch's public leaves go out at least every three hours. The batch number, its transaction and your leaf's proof are stored with the case and shown on its page.

An open ledger with a brass stamp beside it

Opening, on-chain

When a client opens a sealed file, the clerk calls open(caseId, fileHash, batchId, proof). The contract checks the proof for the sealed leaf against the batch root, refuses a second opening, and emits Opened(caseId, batchId, fileHash); openedFrom(caseId) then returns the batch id plus one.

Check a file yourself

With a file, its case id, the batch number and the proof from its page:

# 1. the fingerprint: sha256 of the canonical JSON (keys sorted, no spaces)
# 2. ask the registry whether the leaf is in the batch
cast call 0x8D45fe8f12Bc81f24E0c7184eEBA5d08AD001bB8 \
  "verify(bytes32,bytes32,bool,uint256,bytes32[])(bool)" \
  <caseId> <fileHash> true <batchId> "[<proof0>,<proof1>,...]" \
  --rpc-url https://rpc.mainnet.chain.robinhood.com

# 3. when was the batch filed
cast call 0x8D45fe8f12Bc81f24E0c7184eEBA5d08AD001bB8 "batch(uint256)((bytes32,uint64,uint32,uint32))" <batchId> \
  --rpc-url https://rpc.mainnet.chain.robinhood.com

verify returns true only if that exact file, under that case id and seal flag, was in the batch. The case page runs the same check for you.

Keys

RoleAddressCan
Owner0x42E3d46E08D5D2EEC80E85c6a7798dAE31Bc3C25Change the clerk, hand over ownership in two steps.
Clerk0x75342A0730180d60188F106a2b3e6b5DBdC81212File batches, record openings.

Neither key can edit or delete a batch once filed: the contract has no function for it.