OTS Receipt: From Protocol to Production
In May, I published the OTS Receipt protocol on Substack — a specification for self-sovereign payment receipts that don't depend on any company, platform, or database. The core idea: pair every invoice and receipt with an OpenTimestamps proof, anchor both to the Bitcoin blockchain, and give the customer four files they can verify independently forever. No payment processor. No trust. Just math. The protocol was the blueprint. The reference implementation was a Cloudflare Worker. But a reference implementation isn't production. Over the past month, that Worker has grown into a production-grade system powering real donations on this site. Here's what changed.
The Protocol (Recap)
If you read the original post, skip this section. If not, here's the short version. OTS Receipt generates four files per transaction:
invoice.json — what was agreed (amount, address, description)
invoice.json.ots — proof the invoice existed before payment, anchored to Bitcoin
receipt.json — what was paid (txid, block height, amount received)
receipt.json.ots — proof the receipt was generated after payment confirmation
The temporal chain is: agreement → payment → acknowledgement. The Bitcoin blockchain is the witness. The OTS proofs are the evidence. The customer holds both. If the provider disappears, the proofs remain. They're self-verifying — no server needed, no API keys, no trust.
What Changed: Multi-Calendar Stamping
The original implementation stamped with a single calendar — the first one that responded. That worked, but it created a single point of failure. If that calendar was slow to publish to Bitcoin, the proof sat in pending state. If the calendar went down, the proof couldn't be upgraded. The fix: submit to all four public OTS calendars simultaneously and build a tree where each calendar is a sibling branch. This required porting the OpenTimestamps tree model from the Python and Rust reference implementations to TypeScript — full deserialize/serialize with varint encoding, fork markers (0xff), attestation markers (0x00), and 8-byte attestation tags. The upgrade sweep now processes all pending attestations in one pass. As soon as any one of the four calendars confirms, the proof gets its Bitcoin attestation. The others can catch up later. Redundancy without complexity. The proofs you download from this site contain branches for Alice, Bob, Catallaxy, and Finney — four independent calendars, four independent paths to the Bitcoin blockchain.
What Changed: Mainnet Deployment
The protocol was tested on Bitcoin and Litecoin testnets throughout June. Address derivation, payment detection via CryptoAPIs, OTS stamping, calendar upgrades — all verified on testnet first. The same codebase deploys to mainnet with a single environment variable change: NETWORK=mainnet. The xpub secrets switch from testnet to mainnet keys. Address prefixes switch from tb1/tltc1 to bc1/ltc1. Everything else is identical. The proofs are verifiable with istampit info or any OpenTimestamps client. They'll be verifiable for as long as the Bitcoin blockchain exists.
What Changed: Rate Limiting and Quota Protection
The original implementation polled CryptoAPIs every 10 seconds to check for payment confirmation. During development, I burned through 83,689 of the 100,000 free monthly API calls in 15 days. That's unsustainable for a production system. The fix was three layers of protection. First, automatic polling was replaced with a manual "Check Payment" button — the user controls when API calls happen. Second, a 30-second client-side throttle prevents rapid clicking. Third, a server-side rate limit caps CryptoAPIs calls to once per 30 seconds per invoice, returning a cached response for any requests within that window. Daily API consumption dropped from ~1,000 calls to ~10-20.
What Changed: Email Notifications
The Worker now integrates with Cloudflare Email Routing. When a payment is confirmed, it sends a notification with the amount, transaction ID, and a link to retrieve the proofs. No third-party email service. No SendGrid. No Mailchimp. Just Cloudflare's built-in email infrastructure.
The Production Stack
Cloudflare Workers — serverless runtime for the entire backend. One Worker handles invoice creation, payment detection, OTS stamping, upgrade sweeps, and email notifications.
Cloudflare KV — active job storage with 48-hour TTL. Holds invoice state, pending proofs, address mappings, and rate limit keys.
Cloudflare D1 — permanent audit log. Stores confirmed payments and upgraded OTS proofs indefinitely.
CryptoAPIs — blockchain data provider. REST API for UTXO transaction lookup with timestamp filtering.
OpenTimestamps — four public calendars (Alice, Bob, Catallaxy, Finney) provide attestation. Proofs anchored to the Bitcoin blockchain.
Astro — static site generator for the donation page and proof retrieval interface. Pre-rendered at build time, served from Cloudflare Pages.
TypeScript — end-to-end. Worker, frontend, and shared types all in one language.
The Donation Flow in Practice
Visit datamastersconsulting.com/donate. Enter an amount. Choose Bitcoin or Litecoin. Click "Generate Invoice." You get a unique payment address derived deterministically from an HD wallet — no address reuse, no privacy leaks. You get a QR code and the raw address. You get the invoice files immediately — download them before you even send payment. They're timestamped and prove the invoice existed. Send the payment. Wait for confirmation. Click "Check Payment." The system detects the transaction on-chain, generates the receipt, stamps it with OTS, and presents all four files for download. The invoice OTS gets upgraded with a Bitcoin attestation. The receipt OTS gets upgraded. You walk away with cryptographic proof of your donation. Come back anytime with your job ID. The /retrieve page serves the proofs again — upgraded if the calendars have processed them, pending if not. The D1 database stores everything permanently, even after the KV cache expires.
Verifying a Receipt
Anyone can verify a donation independently:
Hash the JSON file: sha256sum invoice.json
Check the hash against the OTS proof: istampit info invoice.json.ots
Run verification: istampit verify invoice.json.ots (read: https://petertodd.org/2016/opentimestamps-announcement)
Confirm the Bitcoin block header attestation — the proof shows exactly which block anchors the file
No server. No API keys. The proof is a self-contained binary file embedding the merkle path to a Bitcoin block header. As long as the Bitcoin blockchain exists, the proof is verifiable.
What's Next
The reference implementation on this site is the first production deployment. The second will be Veribundle's premium upgrade feature — using the same protocol to issue self-sovereign licenses for the desktop evidence tool. Same verification. Different application. The receipt that survives the store now has a production home. If you're building something that needs payment receipts that outlast your company — for software licenses, donations, whistleblower submissions, or anything else — the protocol is open. The reference implementation is deployed. The proofs are self-verifying. Build on it. https://gitlab.com/cmskdev/ots-receipt
Support open-source infrastructure work directly with Bitcoin or Litecoin at datamastersconsulting.com/donate Every donation comes with a cryptographically verifiable receipt anchored to the Bitcoin blockchain. The original OTS Receipt protocol post is on Substack.