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.
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.

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.comverify 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
| Role | Address | Can |
|---|---|---|
| Owner | 0x42E3d46E08D5D2EEC80E85c6a7798dAE31Bc3C25 | Change the clerk, hand over ownership in two steps. |
| Clerk | 0x75342A0730180d60188F106a2b3e6b5DBdC81212 | File batches, record openings. |
Neither key can edit or delete a batch once filed: the contract has no function for it.