linkex.cclinkex.cc
Verifying the Ledger

Proof bundles and sampling

The artifacts handed over when questions arise — single-dispute bundles, period bundles, deterministic sampling with stated miss rates, and full recomputation.

A period holds hundreds of millions of receipts. Carrying every one of them with its inclusion proof was measured at 2.41 TB in the linkex.ai instance, so no such package is offered. Evidence is layered instead, and each layer states its own reach.

Single-dispute bundle

The shape of the answer to "I don't believe this one charge" — served publicly per receipt at /api/receipt/bundle, about 6 KB:

  • the receipt (envelope) in question, with its predecessor and successor so chain continuity is checkable;
  • the disclosed section payloads backing its numbers;
  • the Merkle proof placing it in its period commitment;
  • the commitment itself (signed, chained, time-fixed);
  • the signing-key history.

Everything verifies offline. Either the charge follows from the signed record, or it doesn't — and both parties can see which, using the same tool.

One detail matters when payloads are disclosed: a disclosed payload is a claim until it hashes. The verifier checks each payload against the envelope's committed section hash before reading any value from it — recomputing first and comparing later would confirm the arithmetic of a document nobody committed to. (Payloads also travel as JSON strings rather than embedded JSON, because re-serializing a payload can transform its bytes — an HTML-escaping serializer turns < into \u003c — and different bytes are a different hash.)

Period bundle

For auditing a whole period: the commitment chain, the key history, and the timestamp tokens — and deliberately no receipts. Its size is O(commitments), not O(receipts): a stream produces a fixed number of commitments per day regardless of traffic, so a stream-month is a few megabytes that a person can open, over a run of receipts that is not.

A period bundle establishes commitment signatures, sequence continuity across the whole period, commitment-chain continuity, and time fixing. It cannot establish Merkle inclusion or recompute amounts — those need receipts, and not carrying receipts is the artifact's entire point. The gap is filled by sampling.

Sampling: drawn, not chosen

Between "one receipt" and "every receipt" sits sampling — done so that the operator cannot pick the sample:

  • The seed is the period's last commitment hash — a value that was signed, and once time-fixed is fixed by somebody other than the operator, before the draw could be made.
  • Membership is one HMAC away. A receipt at sequence seq is in the sample when HMAC-SHA256(seed, tagged("linkex.receipt.sample.v1", uint64_be(seq))), read as a 64-bit prefix, falls below a threshold derived from the population and the stated target. The exact construction — byte encodings, threshold arithmetic, boundary cases — is pinned in the specification with conformance vectors, because a sampling rule only the issuer can compute is indistinguishable from a sample the issuer chose.
  • A counterparty re-draws and re-checks membership for any receipt independently. A receipt substituted into the package that wasn't drawn fails; a drawn receipt that was omitted is detectable by recomputing the draw across the period's sequence range — an O(population) walk that is feasible for an auditor and honestly documented as not performed by the default verifier run.

A sample that verifies bounds tampering; it does not exclude it. The report prints the miss probability instead of hiding behind the word PASS — drawing 1,000 receipts from 100,000 misses ten tampered receipts about nine times in ten. The probability changes as the period grows: the same stream can honestly report a different bound today than yesterday, because there are more receipts and the sample cap didn't move. The number, not the green row, is the conclusion. Want a stronger one? Raise the sample size, or negotiate a scoped full disclosure for the range in dispute.

Assembly refuses rather than emits doubtful evidence

Before cutting any proof, the bundle builder rebuilds each commitment's whole run and compares the root against the signed one. Two conditions stop it cold:

  • the run is shorter than the commitment declares — the tree would be a different tree, and its proofs would verify against nothing;
  • the run rebuilds to a different root than the one signed — the proofs would verify inside the package and nowhere else, which is worse than no package, because it still looks like evidence.

The principle: better to refuse to issue a proof than to issue a dubious one. (Assembly is not a tamper detector, and is not read as one — tampering is caught by the verification checks on the receiving side, which recompute every sampled receipt's self-hash from its envelope.)

Full recomputation on disclosure

When section payloads are disclosed, deterministic recomputation runs receipt by receipt — and the recomputation library is the same code the billing path uses, so the bookkeeper and the auditor cannot drift apart algorithmically. Formula evolution is handled by section generations: each receipt is recomputed under the generation it declares, and signed history is never reinterpreted retroactively. Early generations that didn't sign every input needed for recomputation report SKIPPED with the reason, never a fabricated PASS.

On this page