Docs

Verify a Proof Record yourself

A Pudding Proof Record is verifiable end-to-end without trusting Pudding. Every record's fingerprint is placed as a leaf in a Merkle tree; only the tree's root is timestamped by OpenTimestamps and, ultimately, the Bitcoin blockchain. This page tells you exactly how to walk that chain of hashes for any record.

What you need from the record page

The three steps

  1. Hash the file. ComputeSHA-256 of the file bytes and confirm it equals the record's fingerprint.
  2. Walk the inclusion path. Start with the 32-byte fingerprint. For each sibling in the path, concatenate the raw bytes in the recorded order — sibling on the left means sha256(sibling ‖ running), sibling on the right means sha256(running ‖ sibling). The final result must equal the batch Merkle root.
  3. Verify the batch .ots proof. Download the batch's .ots file from the record page and run ots verify <file>.ots against a Bitcoin node (or a trusted block explorer). A successful verification proves the Merkle root existed at the anchored Bitcoin block height — and, combined with step 2, that your file existed then too.

Single-record batches

When a batch contains only one record, that record's fingerprint is the batch's Merkle root — there are no siblings to walk. The record page will say so explicitly and won't show an inclusion path. In that case, skip step 2: after hashing the file (step 1), confirm the fingerprint equals the Merkle root shown on the record page, then go straight to step 3 and ots verify the batch .ots against Bitcoin. The proof timestamps the fingerprint directly.

Reference walker (Python)

import hashlib, json

# 1. paste the record's inclusion path JSON
proof = json.loads("""{
  "leaf": "<record fingerprint hex>",
  "path": [
    { "hash": "<sibling hex>", "position": "left"  },
    { "hash": "<sibling hex>", "position": "right" }
  ]
}""")

merkle_root_hex = "<batch merkle root hex>"

h = bytes.fromhex(proof["leaf"])
for step in proof["path"]:
    s = bytes.fromhex(step["hash"])
    pair = s + h if step["position"] == "left" else h + s
    h = hashlib.sha256(pair).digest()

assert h.hex() == merkle_root_hex, "inclusion path does not reach the root"
print("root matches — now run: ots verify <batch>.ots")

What each step proves

Questions? Get in touch.