How the scheme works
For each UTC day we collect every recorded outcome, sort them deterministically by (clientSeed, cursor, nonce), hash each one into a leaf, and combine pairs upward with SHA-256 until a single root remains. The root is then written to daily_merkle_roots with a publish timestamp.
- Hash:
SHA-256throughout. - Leaf:
SHA256(0x00 || utf8("outcomeId|serverHash|clientSeed|timestampMs")), whereoutcomeId = clientSeed:cursor:nonce. - Internal node:
SHA256(0x01 || left(32) || right(32)). - Odd level: the last node is duplicated (Bitcoin-style).
- Empty day: root is the empty string
""andleafCount = 0.
A full reference is in the API reference, and the security overview walks through how the daily root fits into the rest of the verification chain. You can fetch any day's root at GET /api/merkle/:date and an inclusion proof at GET /api/merkle/:date/proof/:outcomeId.
Published roots (last 30 days)
| UTC date | Leaves | Height | Root | Published | |
|---|---|---|---|---|---|
| Loading… | |||||
Verify an inclusion proof
Paste the JSON returned by GET /api/merkle/:date/proof/:outcomeId. We recompute the root in your browser from the leaf and siblings and compare it to the published root — no server roundtrip is needed.