HashAnchor Guide

How anchoring works

Writing every machine event to a chain is slow and expensive. HashAnchor collects hashes into a batch and anchors one root for all of them, which is why it is asynchronous by design.

The lifecycle#

  1. Submit — a 32-byte hash you computed, or content for the service to hash. The answer is accepted or duplicate.
  2. Batch — hashes wait for the next batch (pending, then batched).
  3. Anchor — the batch's Merkle root is written to a public chain in one transaction (anchored).
  4. Receipt — each record gets its path to the root and the anchor transaction.

The states are pending → batched → anchored, or failed. A receipt exists only at anchored.

Why Merkle batching#

public chain · 1 tx root proof 3 proof 2 yours proof 1 #1#2 #5#6 #7#8 8 RECORDS · 1 ON-CHAIN ROOT · YOUR PROOF = 3 SIBLING HASHES
Your proof is the sibling hashes on the way up. A verifier needs only those — not the other records in the batch.
  • Lower cost per record — thousands of records share one transaction.
  • Higher throughput — submission never waits on a block.
  • Privacy — a receipt reveals nothing about the other records in its batch.
  • Portable verification — the receipt carries everything needed to check it.

Pairs are hashed with Keccak-256, sorted pair by pair, so a verifier does not need to know which side each sibling sits on.

Inside a receipt#

GET /v1/receipts/:hash
{
  "@context": "https://hashanchor.io/receipt/v1",
  "hash": "0x…",
  "merkleRoot": "0x…",
  "proof": [ { "position": "right", "data": "0x…" },
             { "position": "left",  "data": "0x…" } ],
  "anchor": { "chainId": 137, "contractAddress": "0x…", "txHash": "0x…",
              "blockNumber": 0, "blockTimestamp": 0 }
}
FieldWhat it is for
hashThe record's 32-byte digest — the leaf. Recompute it from the record to know the receipt is about these bytes.
proofThe sibling hashes on the way up the tree.
merkleRootWhere the path must arrive. If it does, the record was in this batch, unchanged.
anchor.chainIdThe chain the root was written to.
anchor.txHashThe public transaction that committed the root.
anchor.blockTimestampAn upper bound: the record existed no later than this block.

The receipt can be stored with the customer, the operator, an insurer, a marketplace or an auditor. Checking it does not depend on the original database staying online — or staying honest.

Linking records into a process#

One anchored record proves that it existed and has not changed. A business process is a sequence — offer, acceptance, delivery, payment, completion — so give each record a session, order or previous-record identifier. The anchored records then form a verifiable chain of the whole process, which is what lets two operators settle a half-finished transaction from the same evidence.