The Sealed Envelope, Cryptographically Considered
On the strange persistence of hash commitments, the things a UTXO can hold, and why your blockchain auction is a filing cabinet pretending to be a vault
There is a particular kind of architectural sadness that attends the phrase “sealed-bid auction on the blockchain.” It is the sadness of watching someone build a filing cabinet out of granite.
The sealed-bid auction is one of the oldest tricks in mechanism design. Bidders submit their bids in sealed envelopes; the auctioneer opens them all at once; the highest wins (or, for a Vickrey auction, the highest wins but pays the second-highest, and we all feel terribly clever about it). The mechanism has been analysed to death since Vickrey’s 1961 paper, and a graduate student in a reasonable economics department can recite the revenue-equivalence theorem in their sleep. Everything about it is understood.
Except, apparently, for how to put one on a blockchain without producing something structurally embarrassing.
The standard move is a hash commitment. Each bidder takes their bid amount bi, picks a random nonce ri, computes ci = H(bi ∥ ri) — by the blessed powers of SHA-256 — and posts ci to the chain. At the reveal phase, each bidder posts (bi, ri), anyone can verify ci = H(bi ∥ ri), and the auctioneer picks a winner. This is how Kaleidoscope does it, it is how every Ethereum auction contract I have ever read does it, and it is how the tutorial you read last Tuesday tells you to do it. It is, by any reasonable measure, fine. Bids are hidden before the close. Bids are bound at submission. The mechanism works.
It is also, structurally, a filing cabinet.
Three weaknesses that nobody talks about
Let me be precise about my objection, because “hash commitments are bad” is a stupid thing to say and I am not saying it. Hash commitments are an excellent cryptographic primitive, and for many applications they are the correct answer. My complaint is narrower: when you implement a sealed-bid auction on a blockchain using hash commitments, you produce a system with three structural properties that deserve attention and essentially never receive it.
First, the commitment-to-reveal path is protocol-specific. Your smart contract must implement hash verification, timestamp-based deadline enforcement, and winner-determination logic as application code. Every auction run re-implements this logic, which means every auction run re-introduces the opportunity for this logic to be wrong. We know from the smart-contract-bug literature — which is now large enough to fund careers — that on-chain logic bugs are not theoretical. They are, empirically, what happens when people write smart contracts. The commitment-reveal pattern compounds this because the reveal logic typically lives in a different function than the commitment logic, and their temporal coupling (reveal only after commit window closes, but not after reveal window closes, and only by the address that committed, unless transferred, and so on) is exactly the kind of state-machine logic that smart-contract auditors charge per-hour to reason about.
Second, hash commitments are not transferable. The commitment ci is computed with respect to a specific bidder; the commitment binds that bidder to that bid. If the bidder is unable to complete the reveal — their device dies, they lose connectivity, they are arrested, they are hit by a bus — the commitment cannot be opened by anyone else. The bid is forfeit. In a real-world auction setting this is a non-trivial operational constraint. Institutional bidders want their bids to survive individual-device failure. Regulated bidders (government procurement, securities auctions, regulated gaming) sometimes need third-party escrow of the reveal right. Hash commitments handle none of this natively. You bolt on a multisig, or a reveal agent, or a time-lock escrow, and what you have constructed is a small ziggurat of composition in service of a property you could have had by construction.
Third, the reveal phase is a liveness hazard. A bidder who has committed must remain online, reachable, and in possession of ri through the reveal window. If any link in this chain breaks, the bid is forfeit. Most auction designs handle this by penalising non-revealers (forfeit the deposit, extend the reveal window, permit the auctioneer to open an unrevealed bid if the bidder’s key is compromised to a designated trustee). Each of these patches is fine in isolation. Each of them introduces an off-chain party or a policy decision or a new protocol mode. After enough patches you no longer have a sealed-bid auction; you have a sealed-bid auction with a staff of people who handle the edge cases.
A different primitive altogether
Here is what I want to suggest. Instead of thinking of a sealed bid as a commitment to be opened, think of it as an object to be owned.
Consider: what if the bid were a token?
Not a token in the ERC-20 sense — an actual cryptographic artifact that contains the bid value, encrypted, and whose opening is gated by the native consensus rules of the chain rather than by application logic. Call this an encrypted non-fungible token, though the branding is less important than the construction. The bid amount is locked behind a public key that no single party holds the private key for. The bid token is a UTXO on the chain. Opening the bid — revealing the face value — requires spending the UTXO, which requires a threshold-ECDSA signature, which requires cooperation across a pre-designated set of parties. The reveal is not application logic. The reveal is the native primitive “spend this UTXO,” mediated by a threshold signing protocol that nobody needs to implement because it was specified fifteen years ago in standard cryptographic literature.
This is not particularly clever. The components have all existed for a long time. Combined public keys go back to Pedersen’s work in the 1990s; threshold ECDSA has a deep literature and several production-grade implementations; the Bitcoin UTXO model is a public museum exhibit at this point. What is interesting is what you get when you compose them specifically for the sealed-bid-auction use case.
You get three things that hash commitments cannot give you by construction. You get them for free, in the sense that they fall out of the primitives rather than being added on.
Property one: bearer transferability
Because the bid is a UTXO, and UTXOs are transferable by the most basic operation the chain supports, bids are bearer-transferable by construction. If I commit to an auction and then realize on the morning of the reveal that I will be in a hospital with a broken arm and cannot participate, I can transfer the bid UTXO to my spouse. The new owner of the UTXO acquires the right to participate in the reveal for that bid. The transfer is a standard UTXO spend; the chain’s consensus rules enforce it; no smart-contract logic mediates it.
There is a subtlety here, which I am going to flag honestly because this post is not a marketing brochure. “Bearer transferability” requires that the transferor also transmit to the transferee whatever private-key share is needed for the transferee to participate in the reveal. That transmission happens off-chain. If the transferor sends the private scalar vp,i, the transferee can participate in the reveal as if they were the original bidder. If the transferor sends only an encrypted form, the transferee must cooperate with the transferor during the reveal. This is a weaker form of bearer-transferability than an unconditional bearer asset would have — but it is exactly the structure you want for threshold-secured reveals, because it matches the cooperation model of the reveal itself.
Hash commitments, for the record, are zero-percent transferable. The commitment is cryptographically bound to the bidder’s private nonce, which nobody would ever be foolish enough to transmit off-chain. You can attempt to build a transferable hash commitment by layering a second primitive on top (the classic move is “commitment plus designated-verifier signature on the opening”), but at that point you have left sealed-bid-auction land and entered some much stranger territory where you should probably be writing a different paper.
Property two: threshold-gated reveal
This is the one that matters for security, and it is the one that is impossible to retrofit into a hash-commitment construction.
In a hash-commitment auction, the bid can be opened by exactly one party: the bidder. The bidder holds ri; the bidder produces the opening; nobody else has any input. If the bidder is coerced, if the bidder is compromised, if the bidder privately decides to reveal their bid early to a favoured counterparty, nothing in the cryptography stops them. The cryptography protects the bid from everyone except the one person who is allowed to break it, and that person can break it at will.
In the encrypted-NFT construction, the bid is locked behind a combined public key Qbidi constructed as the sum of per-party contributions: one from each bidder and one from the auctioneer. The combined private key is the sum of per-party private scalars, and nobody holds it. Nobody has ever held it. Spending the UTXO to reveal the bid requires producing a valid ECDSA signature under Qbidi, and under the Savanah-Wright threshold protocol this requires cooperation from a pre-designated threshold k of the N+1 participants. Set k = N+1 and you have full-cooperation reveal: no bid opens unless every participant agrees. Set k < N+1 and you have threshold reveal: cooperation of any k participants opens the bid.
The practical implication is that a bidder cannot, even in principle, unilaterally reveal another bidder’s bid. Even if the auctioneer is colluding with them. Even if the auctioneer has been bribed. Even if the auctioneer has been compromised by a state actor with unlimited resources. To open bid i you need k cooperating parties out of N+1; nothing else works.
This is not a property that hash commitments can have. It is not that hash commitments lack the property; it is that the property is cryptographically incompatible with the hash-commitment pattern. A hash commitment that requires threshold cooperation to open is no longer a hash commitment. It is a threshold-encrypted ciphertext with a hash wrapper, which is a different construction entirely, and at that point you might as well skip the hash and go straight to the threshold-encrypted ciphertext.
Property three: protocol uniformity
This one is aesthetic, and I am going to argue that aesthetics matter in protocol design, which will annoy some of you.
The commitment-reveal path of a hash-commitment auction is a bespoke protocol. It lives in application code. It has its own state machine, its own deadline enforcement, its own edge-case handling. If you have a general-purpose BSV infrastructure — and this construction is specifically BSV-native, for reasons I will get to — the hash-commitment auction is an island. Its logic does not reuse anything else in the system.
The encrypted-NFT sealed-bid auction, by contrast, is a composition of existing BSV primitives with no new protocol layer. The bid is a UTXO (standard BSV primitive). The combined public key is a sum of per-party public keys (standard elliptic-curve arithmetic). The reveal is a UTXO spend (standard BSV primitive). The threshold signing is the Savanah-Wright protocol (specified, published, and implemented). The commitment-to-reveal path is not a new state machine; it is the spend of a UTXO, which is the same primitive that spends every other UTXO on the chain.
If you already have tooling for BSV UTXOs — mempool monitoring, fee estimation, transaction-construction libraries, accounting — all of it works for bid UTXOs without modification. If you already have tooling for threshold-ECDSA signing — because you use it for multi-signature wallets or for institutional custody — it works for bid reveal without modification. Everything composes.
Hash commitments are application code. Encrypted NFTs are infrastructure.
The cost question
Now for the part where I try to defuse the obvious objection: isn’t this more expensive? The hash commitment, after all, is a single SHA-256 output per bid, and a SHA-256 output is 32 bytes. The encrypted-NFT bid is a full UTXO with a combined public key, an encrypted face value, a commitment, and a state-data payload. It must be larger.
It is larger, yes, but by less than you might think, and the per-auction total is still astonishingly small.
A sealed-bid auction with 10 bidders on a BSV-native encrypted-NFT implementation requires, on the wire:
- 1 auction-setup transaction: 2,140 bytes - 10 bid-submission transactions: 318 bytes each, so 3,180 bytes total - 10 reveal transactions: 292 bytes each, so 2,920 bytes total - 1 threshold-close-out transaction: 783 bytes - 1 winner-determination transaction: 412 bytes
Total: 9,435 bytes. At the BSV reference fee rate of 0.5 satoshis per byte, that is 4,717.5 satoshis. At BSV priced at USD 30 per coin, that is USD 0.00142 per auction, or about a seventh of a cent.
A 100-bidder auction, just to close the scaling argument, is about 65,000 bytes, which is about 32,500 satoshis, which is about a cent.
For comparison: an equivalent 10-bidder hash-commitment auction on Ethereum L1, implemented as a reference smart contract with two SSTOREs per bid (commitment and reveal) plus the base transaction overhead, runs roughly 530,000 gas in total. At the typical post-merge gas price of 30 gwei with ETH at $3,200, that is about 5 cents per auction. At peak congestion (100 gwei), 17 cents. The BSV construction is therefore somewhere between 36 and 120 times cheaper than the Ethereum hash-commitment equivalent — for a workload that delivers strictly stronger properties (bearer transferability, threshold-gated reveal, protocol uniformity).
The Ethereum L2s (Arbitrum, Optimism, Base) close the gap somewhat, coming in at maybe 2 to 6 times more expensive than the BSV encrypted-NFT. At that point the cost question becomes less important than the property question, and I would argue that the cost question was never the main issue anyway.
Why BSV specifically
A fair question at this point is: why BSV? Why not Ethereum, or Solana, or Cardano, or any of the other chains with smart-contract capabilities? The answer is that the encrypted-NFT construction is specifically a UTXO-plus-Bitcoin-Script construction, and BSV is the chain where those primitives are cheap and where Bitcoin Script is expressive enough to enforce the covenant-chained state machine that the construction requires.
Ethereum cannot host this construction directly because Ethereum does not have UTXOs. You would have to emulate UTXOs in account-model smart contracts, which introduces exactly the application-layer-code problem that the construction was designed to avoid. Ethereum’s EVM also does not have native secp256k1 scalar multiplication outside of the ECRECOVER precompile, which rules out the combined-public-key construction without either on-chain curve emulation (prohibitively expensive — about 107 gas per scalar multiplication) or a pairing-based alternative on BN254 or BLS12-381 (a different curve, a different cryptographic-assumption basis, not the same construction).
Bitcoin Core (BTC) could host a cut-down version of this construction, but the small-block limits and the SegWit witness-data constraints make it operationally awkward. The OP_RETURN size restrictions on post-2017 BTC make it hard to carry the encrypted-face-value payload on-chain, and the fee market’s volatility makes per-auction cost unpredictable.
BSV has none of these restrictions. Transaction size is unbounded (up to the mining-policy limit, which is much larger than any auction will ever need). Script is full Bitcoin Script without the SegWit restrictions. The fee market is stable at approximately 0.5 sat/byte because the block size is not a binding constraint. The combined-public-key construction works natively because secp256k1 is the curve used throughout. And — this matters more than people acknowledge — BSV’s “no gas, no state-rent, no per-operation pricing” model means that the per-auction cost is linear in transaction bytes and nothing else. Predictable pricing.
I am not here to do cheerleading for BSV. I am here to observe that if you want to implement encrypted-NFT sealed-bid auctions, BSV is where the primitives live at a cost that makes the construction viable for auctions worth less than the cost of the construction.
Some things this construction does not solve
In the interest of not being a marketing brochure: here are things the construction does not solve, despite what an uncritical reading might suggest.
It does not eliminate trust. The threshold-ECDSA protocol is trustless in the sense that no participant reconstructs the combined private key, but the reveal requires cooperation of k participants, and that cooperation is itself a trust assumption. If k = N+1 and one participant refuses to cooperate, the reveal does not happen. That is a liveness failure, not a confidentiality failure, but it is still a failure.
It does not solve the coercion problem. If a regulator with a gun wants to know what I bid, I can be coerced into revealing my bid regardless of what the cryptography does. The cryptography protects the bid from cryptographic adversaries; it does not protect the bid from non-cryptographic adversaries. This is true of every cryptographic construction in history and is not a defect, but it is worth stating because marketing materials tend to blur the distinction.
It does not eliminate the TEE trust assumption. The construction requires that each party’s private scalar vp,i be held in a hardware Trusted Execution Environment. This is because if the private scalar leaks, the bid is revealed. TEEs are not perfect. Spectre-class attacks against Intel SGX are well-documented; ARM TrustZone has had its share of vendor-specific exploits; Apple Secure Enclave is less studied but not provably secure. The TEE dependency is the weakest link in the construction, and honest deployments should treat it as such. Mixed-vendor deployments (some bidders on Android, some on iOS, some on Intel machines) significantly reduce the correlated-compromise risk; same-vendor deployments concentrate it.
It does not work for very small auctions. At roughly USD 0.00142 per 10-bidder auction, the cryptographic overhead is negligible for any auction worth more than about USD 1. For an auction of five-cent transactions — say, a toy micro-auction market for vending-machine soda — the cryptographic overhead is a significant fraction of the auction value. This is a weird corner of the design space and I am not sure why anyone would want to build it, but it is a case where hash commitments remain the correct answer.
It does not replace mechanism design. The construction gives you sealed-bid primitives. It does not tell you whether first-price, second-price, or all-pay is the right mechanism for your setting; it does not tell you whether reserve prices are appropriate; it does not tell you how to handle budget-constrained bidders or asymmetric-information-structured bidders or any of the subtler mechanism-design choices that auction theorists have been arguing about for fifty years. It just gives you the sealed bids; you have to decide what to do with them.
The implementation-considerations footnote nobody reads
If someone actually deploys this construction, here are the things that will ruin their day and that deserve to be said explicitly.
iOS key custody is weird. Apple’s Secure Enclave supports NIST P-256 natively but does not support secp256k1 in any first-class way. Secp256k1 bidding on iOS currently requires software-only key custody with some form of Secure Enclave-backed device attestation rather than key-storage — a weakened-custody configuration. This is Apple’s decision, not a cryptographic limitation. For high-assurance deployments, Android StrongBox-backed Keystore (from Android 9 onwards on supported devices) provides proper hardware-rooted secp256k1 custody; iOS deployments should either accept the weakened-custody configuration or restrict participation to Android devices.
Threshold signing is more complicated than threshold signing libraries make it look. The Savanah-Wright protocol requires three message rounds per signature. In a deployment where all N+1 parties are online and cooperative, this adds perhaps 150 milliseconds of latency. In a deployment where one party is flaky, it can add much more. Honest deployments should over-provision deadlines and assume the tail of the distribution will bite.
The reveal-token binding is doing work. Each reveal token is bound to the draw-transaction block height, among other things. This matters because it prevents pre-computation of reveal tokens before the bidding window closes. If you forget this binding, a clever bidder can compute reveal tokens for a wide range of possible bids before committing, which lets them conditionally reveal based on what other bids come in, which breaks the sealed-bid property. Do not forget this binding.
Regulatory observability is a feature, not a bug. For deployments in regulated domains (government procurement, regulated securities markets, regulated gambling), the single-use reveal tokens allow a third-party observer — a regulator who holds no private scalars — to verify that the revealed bid matches the commitment, without participating in the bidding or key construction. This is a useful property. Deployments that need regulatory compliance should design for this from the start rather than retrofitting it later.
Long-term key hygiene matters. The construction uses HKDF to derive per-auction-per-bid scalars from a long-term bidder key skp. If skp leaks after the auction, all historical bids by that bidder become retroactively recoverable. For auctions with long-term confidentiality requirements (for instance, sealed bids in ongoing negotiations with known adversaries), the construction should use per-auction ephemeral long-term keys rather than a single persistent long-term key. This is a standard forward-secrecy argument and should surprise nobody.
Closing thoughts
The larger point, which is maybe the only reason for any of this, is that cryptographic primitives compose differently depending on the substrate. Hash commitments are the natural primitive in an account-model blockchain with smart-contract logic, because that is where application-code mediation makes sense. Encrypted-NFT constructions are the natural primitive in a UTXO-model blockchain with flexible scripting, because that is where native-spend primitives are expressive enough to carry the whole pattern.
Most of the blockchain industry has converged on the account model — Ethereum and its descendants dominate the conversation — and as a consequence the blockchain industry’s default sealed-bid auction is a hash-commitment auction. That is fine for Ethereum. It is not fine everywhere, and the specific thing I want to say in this post is that the encrypted-NFT alternative exists, is cheap enough to deploy at real volume, and delivers properties that hash commitments cannot match.
I recognise that this will sound like Bitcoin-SV advocacy, because the construction is BSV-native and the cost numbers are BSV cost numbers. Fine. It is BSV advocacy, in the narrow sense that I am arguing BSV is the right chain for this specific construction. The broader claim — that UTXO-native cryptographic primitives compose better than account-native cryptographic primitives for a wide class of problems — is a bigger argument than one blog post can carry, and I will not try to make it here.
What I will say is that every time I read a paper about a blockchain auction, I end up wondering why we are still pretending that the only way to put a sealed bid on a chain is to hash it. The hash is fine. The hash is excellent, even. But the hash is what you use when you do not have a better primitive available. On a UTXO chain with threshold-ECDSA support, you have a better primitive available. It is called spending the UTXO. The bid opens when the UTXO is spent. The spend requires threshold cooperation. The bid is a bearer asset because the UTXO is a bearer asset. Everything composes because everything was always going to compose, if you let it.
Sealed envelopes, cryptographically considered, are not a thing you need to simulate. They are a thing you can build. If the tools are there, use the tools.
And if you still want a hash commitment, you are welcome to have one. I just want you to know you had other options.
A note on framing: I am aware that “encrypted NFT” is a branding that encompasses a great deal of nonsense in the current market. I am not interested in that branding, and I would have preferred to use a more neutral term like “threshold-encrypted UTXO” if the literature allowed it. The construction is what matters; the name is a convenience.