The Attack That Would Have Quietly Drained You
You're holding a hardware wallet. The screen shows the outputs, you confirm, and the device signs. Somewhere between your approval and the broadcast, a rogue coordinator shaves 0.05 BTC off your change output and lets it vanish into the miner fee. The transaction confirms. Nothing looks wrong. You are simply short, and you will spend a long time wondering why.
That is not paranoia. It is the documented threat that motivated one of the most consequential engineering decisions in Bitcoin's signing protocol, and the fix lives inside something called the sighash preimage. Once you understand the mechanism precisely, you will see it for what it is: one of the cleaner pieces of security engineering in the entire stack.
What a Sighash Preimage Actually Is
When you sign a Bitcoin transaction, you are not signing the raw transaction bytes. You are signing a hash of a carefully structured blob of data, assembled by your wallet, hashed with SHA-256d (double SHA-256), and then signed with your private key using ECDSA or Schnorr.
The sighash type controls which parts of the transaction enter that blob. SIGHASH_ALL is the common case: it commits to all inputs and all outputs. Alter any committed field after signing, and the signature is invalid. Rejected.
So the question is not whether the preimage commits to outputs. It does. The sharper question is whether it commits to the values of those outputs. For legacy transactions predating SegWit, the honest answer is: not directly.
The Legacy Blind Spot
In pre-SegWit Bitcoin, the sighash preimage under SIGHASH_ALL includes each input's scriptPubKey, all output scripts and amounts, and sequence numbers. That sounds complete. The input values, however, the actual satoshi counts being spent, are absent from the preimage.
For a software wallet connected to a full node, that omission is harmless. The wallet knows the full UTXO set and can verify input values independently.
For a hardware wallet, it is a different problem entirely. Hardware devices are intentionally isolated: they receive transaction data from a host, sign, and return the signature. If the host misrepresents input values, the device has no independent means of verification.
This creates a specific and practical attack. A malicious host tells the hardware wallet that an input is worth 1.0 BTC when the actual UTXO holds 1.05 BTC. The wallet constructs a transaction with outputs summing to 1.0 BTC, concludes the fee is a reasonable 0.0001 BTC, and signs. The real fee is 0.05 BTC plus that 0.0001, because the actual input is larger. The miner collects the difference. If the attacker is the miner, or is colluding with one, the theft is clean and leaves no obvious trace.
This was not a theoretical edge case. It affected real hardware wallet designs and was a documented concern in multisig deployments handling serious value.
How SegWit's BIP143 Sealed It Shut
SegWit redesigned the sighash preimage format for v0 witness inputs, with the new design specified in BIP143. The structural change is direct: the value of the input being signed is now a mandatory field in the preimage.
The BIP143 preimage is a serialized structure with these fields, in order:
- nVersion (4 bytes)
- hashPrevouts: a hash of all input outpoints
- hashSequence: a hash of all input sequence numbers
- The specific outpoint being signed (txid + vout index)
- The scriptCode for the input being signed
- value: the amount in satoshis of the UTXO being spent (8 bytes, little-endian)
- nSequence for this input
- hashOutputs: a hash of all outputs (scriptPubKey + value pairs)
- nLocktime
- Sighash type
Field 6 is where the attack dies. The input value is baked into the thing you sign. If a malicious host tells your hardware wallet the input is 1.0 BTC but the actual UTXO holds 1.05 BTC, your device constructs a preimage encoding "1.0 BTC" and signs it. Validators reconstructing that preimage from the actual UTXO will encode "1.05 BTC." The hashes diverge. The signature is invalid. Transaction rejected, not at the display layer, but at the cryptographic layer, where exhaustion and inattention cannot be exploited.
Field 8, hashOutputs, closes the other half of the problem. It commits to every output's scriptPubKey and its value as a pair. A coordinator who shaves 0.05 BTC off your change output alters hashOutputs, which breaks the signature. There is no silent diversion. There is only an invalid transaction.
A Worked Scenario, With Numbers
Consider Maria. She wants to send 0.3 BTC to a merchant using a hardware wallet. Her UTXO is worth 0.35 BTC. The intended transaction has two outputs: 0.3 BTC to the merchant and 0.049 BTC back to herself as change, leaving 0.001 BTC as the fee.
A rogue coordinator controls the host software. It presents the hardware wallet with an input value of 0.30 BTC instead of 0.35 BTC, then strips the change output entirely, showing only the 0.3 BTC merchant output. The wallet sees outputs equaling the reported input, concludes the fee is zero, and signs.
On-chain, the actual input is 0.35 BTC. The single output is 0.3 BTC. The miner collects 0.05 BTC. Maria's change is gone.
With BIP143 in place: the hardware wallet signs a preimage encoding the input value as 0.30 BTC. Validators reconstruct the preimage from the actual UTXO, encoding 0.35 BTC. The hashes do not match. The signature is invalid. The attack fails at the validation layer, not because Maria checked the screen carefully, but because the cryptographic commitment makes the lie structurally impossible to sustain.
That is the architectural guarantee: security migrates from "trust what the host reports" to "the math enforces the value regardless of what the host reports."
What People Get Wrong About This Protection
The common misconception is that BIP143's value commitment protects against fee manipulation in general. It does not, quite, and the distinction matters.
It protects against input value misrepresentation on SegWit inputs. Legacy inputs mixed into the same transaction still do not commit to their values in the preimage. That gap motivated the PSBT format defined in BIP174, which requires the full previous transaction to accompany legacy inputs so hardware wallets can independently verify input values by re-hashing the prior transaction and checking its outputs.
BIP143 also does not protect against a correctly behaving host that lies about the recipient address rather than the value. That is a distinct attack surface, addressed by display verification and secure element attestation, not sighash construction. The two problems look similar on the surface and are solved by entirely different mechanisms.
Taproot, specified in BIP341, extended the commitment further still: the preimage now hashes all input amounts and all input scriptPubKeys together, not only the one being signed. That closes a residual surface in multi-input transactions where a signer controls only some inputs and could be deceived about the rest. The progression is worth stating plainly: legacy (no input value commitment), SegWit v0 via BIP143 (commits to this input's value), Taproot via BIP341 (commits to all inputs' values). Each revision tightened the screw by one precise turn.
The Principle Underneath the Engineering
What makes this design worth understanding is not only that it prevents fee theft. It encodes a philosophy about what a signature should be: a precise, bounded, cryptographic statement about exactly what was authorized, not a general endorsement of a transaction's approximate shape. Think of it as the difference between signing a blank check and signing a contract with every line filled in and notarized.
Every field in the preimage is a constraint. Violate it, and the math breaks. That is a more honest security model than relying on wallets to display accurate information and users to verify it under pressure. Humans are unreliable auditors. Cryptographic commitments do not get tired, and they do not get deceived by a convincing interface.
If you are evaluating a signing protocol, a multisig coordinator, or a PSBT workflow for any serious value, the question to put to the documentation is this: what exactly does the signature commit to? If the answer covers input values, output values, and output scripts for every input in the transaction, the security rests on math. If it does not, the security rests on software being honest. Those are not equivalent foundations, and conflating them is how real money disappears.