Merkle trees, anchoring, and what a receipt proves
01 · Concepts
No prior blockchain knowledge assumed. This page defines the three ideas everything else in these docs builds on, then draws the line — precisely — around what a Backrun receipt actually proves.
Start with a hash function
Everything here rests on one property of a cryptographic hash function (Backrun uses Keccak-256, the hash Ethereum-family chains use): given some bytes, it produces a fixed-length 32-byte fingerprint, and it is computationally infeasible to find two different inputs that produce the same fingerprint (collision resistance), or to construct an input that produces a chosen output (preimage resistance).
Practically: if you have a document and its hash, and someone hands you a slightly different document claiming it's the same one, hashing their version produces a completely different fingerprint — not a similar one, a completely unrelated one. There is no such thing as "close" for a cryptographic hash. That's the entire mechanism this product is built on.
What a Merkle tree is
A Merkle tree lets you commit to a whole batch of records with a single hash, while keeping the ability to prove any one record was in the batch without revealing the rest.
Build one bottom-up:
- Hash each record individually — these hashes are the leaves.
- Pair adjacent leaves and hash each pair together to get the next level up.
- Repeat until one hash remains: the root.
4 events → 2 internal nodes → 1 root. Doubling the batch adds one level, not double the work per proof.
The root changes if any leaf changes, because that change propagates up through every parent it touches, all the way to the top — this is exactly the property the live demo on the homepage shows: click a record, the leaf's fingerprint changes, and the root computed from it stops matching the one that was anchored.
The useful trick is the second half: an inclusion proof. To prove leaf₁
was in the batch, you don't need the whole tree — just the sibling at each level
(leaf₀, then node₂₃) and which side it sits on. Anyone can fold
those two hashes together with leaf₁ and check they land on the published root. For a
batch of n records, a proof is only log₂(n) hashes — about 20 for a
million-record batch — regardless of how large the batch is. The exact hashing rules
(domain separation, ordering, odd-node handling) are specified precisely on the verification algorithm page; this page is just the
shape of the idea.
What "anchoring" means
Backrun batches your events, builds the Merkle tree above, and submits only the 32-byte root — never your event data — to a smart contract on Base, a public Ethereum L2. That transaction is what "anchoring" refers to throughout these docs.
The contract (AuditAnchor,
0x2560…3f91)
does exactly one thing: it emits an Anchored event recording who published,
what root, and when, and increments a per-publisher counter. It has no owner, no admin
role, no upgrade mechanism, and no function that can revise or remove a past anchor — see
reading the anchor on-chain for the ABI and how to check
this yourself. Once a root is anchored, nobody — including Backrun — has a way to change
what's recorded, because there is no code path that does it.
This is also why only the root goes on-chain, not the raw events: a 32-byte hash reveals nothing about the underlying data (hashes are one-way), batching thousands of events into one root keeps the gas cost roughly constant regardless of volume, and it means your audit data never sits on a public, permanent, globally-replicated ledger — which would be a strange place to put a customer's audit log even if it were technically possible.
What a receipt is
When you submit an event, you get back a receipt: your event's leaf hash, the inclusion proof for it, the root that proof resolves to, and where that root was anchored (chain, contract, transaction hash). The full field-by-field format is on the receipt format page. The important property is that a receipt is self-contained — everything a third party needs to check it travels inside the receipt plus the original event. No call to Backrun's API is required to verify one.
What a receipt proves
Proven
Given an event and its receipt, anyone can independently recompute the leaf, fold it through the proof, and check the result against the root read directly from the chain. If that check passes, three things are true:
- This exact event, byte-for-byte, was included in the batch that produced that root. Change one character anywhere in the canonicalised event and the leaf hash — and therefore the check — changes completely.
- That root was published on-chain, at a specific block, by a specific publisher address, in a transaction nobody (not the customer, not Backrun) can alter or remove after the fact.
- The event existed, in this exact form, no later than the anchor's block timestamp. Anchoring establishes an upper bound on when the record last could have changed — "not after this moment" — which is the property an audit trail needs.
Not proven
Be precise about the boundary — this is the part a technical buyer checks first:
- Truthfulness of the content. A receipt proves the record wasn't altered after submission. It does not prove the record was accurate when submitted — if your system logged the wrong actor, the receipt faithfully proves that wrong record was never tampered with.
- Who the actor really was. This is not an authentication or identity
system. The
actorfield is just data, verified for integrity like every other field — not verified against any real-world identity. - Completeness. A receipt proves a positive claim — this record exists, unaltered — never a negative one. It cannot prove that nothing was omitted, i.e. that every event which should have been logged, was.
- Exact creation time. Only an upper bound is anchored. A record could have been created any time between its own timestamp field and the batch's anchor time; the anchor does not independently attest to the earlier moment, only that it existed by the later one.
- Regulatory compliance as a whole. A receipt is one building block toward demonstrating properties like GoBD's Unveränderbarkeit — see erasure & retention — not a certificate of compliance by itself.
Why this, and not just S3 Object Lock
Write-once storage (S3 Object Lock, and equivalents) already prevents your own staff from editing a record after the fact, and it's cheaper than an anchored product — if it solves your problem, use it. The gap is who has to be trusted to check the claim. With Object Lock, verifying "this wasn't altered" means trusting whoever controls the AWS account — which is you, or Backrun, or whichever vendor runs the bucket. With an anchored root, verification is arithmetic against a public chain that nobody involved in the transaction controls. That's the one property this product adds, and the only one it claims.