BIP143 - Transaction Signature Verification for Version 0 Witness Programs¶
BIP143 (Bitcoin Improvement Proposal 143) is one of the Bitcoin improvement proposals, put forward by Johnson Lau and Pieter Wuille in 2016. It defines the signature hash algorithm for Segregated Witness (SegWit) transactions. This proposal addresses several security and performance issues of the traditional signature verification algorithm and is an important complement to BIP141 (Segregated Witness).
Core Concept¶
Before BIP143, the signature hash algorithm used by Bitcoin had several serious problems, particularly the quadratic hashing problem (O(n^2) complexity) and security risks for hardware wallets. BIP143 designed an entirely new signature hash algorithm for SegWit transactions, fundamentally solving these problems.
BIP143 only applies to version 0 witness programs, including P2WPKH (Pay to Witness Public Key Hash) and P2WSH (Pay to Witness Script Hash). This new algorithm not only improves performance but also enhances security, especially for hardware wallet users.
Problems with the Old Algorithm¶
1. Quadratic Hashing Problem (O(n^2) Complexity)¶
The traditional SIGHASH algorithm had performance issues when verifying transactions:
Problem Description: - Each input's signature verification required hashing the entire transaction - For a transaction with N inputs, N complete transaction hashes were needed - Each hash had to process all N inputs - Total complexity was O(N^2)
Practical Impact:
1 input transaction: 1 hash
10 input transaction: 10 hashes x 10 inputs = 100 operations
100 input transaction: 100 hashes x 100 inputs = 10,000 operations
Attack Vector: - Maliciously constructed large transactions (hundreds or thousands of inputs) - Caused exponential growth in node verification time - Could result in denial-of-service attacks - In 2015, attack transactions requiring over 1 minute to verify were observed
2. Hardware Wallet Security Issues¶
The traditional algorithm was unfriendly to hardware wallets:
Unable to Verify Input Amounts During Signing: - The signature hash did not include the input amount - Hardware wallets could not independently verify input amounts - A malicious host could misrepresent input amounts - Users could unknowingly sign transactions that sent most of their funds as fees
Example:
Actual situation:
Input: 10 BTC
Output: 0.1 BTC (recipient) + 9.9 BTC (change)
Fee: 0 BTC
Malicious host tells the hardware wallet:
Input: 0.2 BTC
Output: 0.1 BTC (recipient) + 0.09 BTC (change)
Fee: 0.01 BTC
Hardware wallet displays to user: Fee 0.01 BTC (appears reasonable)
Actual fee: 10 - 0.1 - 9.9 = 0 BTC (or worse, if the change address is replaced)
After the user signs:
The real fee could be as high as 9.9 BTC (if the malicious host removes the change output)
3. Offline Signing Difficulty¶
The traditional algorithm required complete transaction data: - Hardware wallets needed to receive the complete transaction data for all inputs - Large data transfer volumes and complex verification - Increased attack surface and user operation complexity
BIP143 Solution¶
Signature Hash Algorithm Improvements¶
BIP143 introduced a new signature hash calculation method:
New Algorithm Features: 1. Linear complexity (O(n)): Each hash operation is performed only once 2. Commits to input amounts: The signature includes the input amount 3. Cache-friendly: Common hash values can be precomputed 4. Hardware wallet secure: All critical information can be independently verified
Signature Hash Structure¶
Signature hash = SHA256(SHA256(
1. nVersion (4 bytes)
2. hashPrevouts (32 bytes)
3. hashSequence (32 bytes)
4. outpoint (36 bytes)
5. scriptCode (variable length)
6. value (8 bytes) <- New!
7. nSequence (4 bytes)
8. hashOutputs (32 bytes)
9. nLocktime (4 bytes)
10. nHashType (4 bytes)
))
Key Field Details¶
1. nVersion¶
Transaction version number (4 bytes)
2. hashPrevouts¶
Hash of all input outpoints:
Advantage: - Computed only once and can be cached - All inputs share the same hash value - Reduces complexity from O(n^2) to O(n)
3. hashSequence¶
Hash of all input sequence numbers:
Purpose: - Commits to all inputs' nSequence values - Prevents selective signing attacks - Supports BIP68 relative time-locks
4. outpoint¶
The current input's outpoint (36 bytes):
5. scriptCode¶
Script code (variable length):
For P2WPKH:
Equivalent to a P2PKH script:OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG For P2WSH:
6. value¶
Input amount (8 bytes) <- The most important improvement!
Security Significance: - Explicitly commits to the input amount during signing - Hardware wallets can independently verify this - Prevents malicious hosts from misrepresenting amounts - Users can accurately calculate fees
7. nSequence¶
Current input's sequence number (4 bytes)
8. hashOutputs¶
Hash of all outputs:
hashOutputs = SHA256(SHA256(all outputs))
Each output = value (8 bytes) + scriptPubKey (variable length)
Advantage: - Computed only once - Commits to all outputs - Hardware wallets can verify outputs one by one before signing
9. nLocktime¶
Transaction locktime (4 bytes)
10. nHashType¶
Signature hash type (4 bytes)
Technical Advantages¶
1. Performance Optimization¶
Old Algorithm:
For a transaction with N inputs:
- Each input signature requires hashing the entire transaction
- Total hash operations: O(N^2)
- Large transaction verification time: exponential growth
New Algorithm (BIP143):
For a transaction with N inputs:
- hashPrevouts: computed 1 time, shared by all inputs
- hashSequence: computed 1 time, shared by all inputs
- hashOutputs: computed 1 time, shared by all inputs
- Each input only needs to hash about 200 bytes of data
- Total hash operations: O(N)
Practical Comparison:
100 input transaction:
- Old algorithm: ~10,000 hash operations (assuming 1KB per input)
- New algorithm: ~103 hash operations (3 common hashes + 100 inputs)
- Speed improvement: approximately 100x
2. Hardware Wallet Security¶
Input Amount Verification:
Signing flow:
1. Host sends: UTXO amount
2. Hardware wallet computes signature hash (includes amount)
3. Amount is included in the signature
4. If the host misrepresents the amount, the signature will be invalid
Output Verification:
Signing flow:
1. Host sends outputs one by one
2. Hardware wallet displays each output for user confirmation
3. Hardware wallet computes hashOutputs
4. hashOutputs is included in the signature
5. If any output is modified, the signature will be invalid
Fee Calculation:
Hardware wallet can safely compute:
Total inputs = sum(input amounts) <- included in signature
Total outputs = sum(output amounts) <- included in signature
Fee = Total inputs - Total outputs
Displayed to user: accurate fee
3. Offline Signing Optimization¶
Minimal Data Requirements: Hardware wallets only need: - Current input's UTXO information (txid, vout, amount, script) - List of all outputs - hashPrevouts, hashSequence (can be precomputed or provided by host)
No Complete Transaction History Required: - Does not need complete preceding transactions for all inputs - Reduces data transfer volume - Simplifies user operation
SIGHASH Type Support¶
BIP143 supports all traditional SIGHASH types:
SIGHASH_ALL (0x01)¶
Signs all inputs and outputs:
hashPrevouts = SHA256(SHA256(all outpoints))
hashSequence = SHA256(SHA256(all nSequence values))
hashOutputs = SHA256(SHA256(all outputs))
SIGHASH_NONE (0x02)¶
Signs all inputs but no outputs:
hashPrevouts = SHA256(SHA256(all outpoints))
hashSequence = 0x0000...0000 (32 zeros)
hashOutputs = 0x0000...0000 (32 zeros)
SIGHASH_SINGLE (0x03)¶
Signs all inputs and the output at the corresponding index:
hashPrevouts = SHA256(SHA256(all outpoints))
hashSequence = 0x0000...0000 (32 zeros)
hashOutputs = SHA256(SHA256(output at corresponding index))
SIGHASH_ANYONECANPAY (0x80)¶
Can be combined with the above types, signs only the current input:
hashPrevouts = 0x0000...0000 (32 zeros)
hashSequence = 0x0000...0000 (32 zeros)
hashOutputs = depends on the combined SIGHASH type
Practical Applications¶
Hardware Wallets (Ledger, Trezor, etc.)¶
Secure Signing Flow: 1. User initiates a transaction on the hardware wallet 2. Host application builds the transaction and sends it to the hardware wallet 3. Hardware wallet displays each output address and amount, requesting user confirmation 4. Hardware wallet calculates and displays the total fee 5. After user confirmation, the hardware wallet signs (amounts and outputs are included in the signature) 6. Even if the host application is malicious, it cannot modify the transaction after user confirmation
Batch Payments¶
Optimized Signing Performance: - Exchanges or payment service providers need to process transactions with many outputs - For example: 1 input + 1000 outputs (batch payroll) - BIP143 makes signing and verification of such transactions faster - Nodes can quickly verify large batch payment transactions
Lightning Network¶
Commitment Transaction Security: - Lightning Network commitment transactions may have multiple inputs - BIP143 ensures efficient signature verification - Committing to input amounts enhances channel security
Relationship with Other BIPs¶
BIP141 (Segregated Witness)¶
BIP143 is a companion proposal to BIP141: - BIP141 defines the structure of witness data - BIP143 defines the signature algorithm for witness transactions - Together they form the complete SegWit implementation
BIP144 (Peer-to-Peer Services)¶
BIP144 defines the network transmission format: - Transmits witness data between nodes - BIP143 signature verification occurs on the receiving end
BIP341 (Taproot)¶
Taproot uses a different signature algorithm: - Taproot uses BIP340 (Schnorr signatures) - But the signature hash algorithm draws on BIP143's design - Similarly commits to input amounts with linear complexity
Security Considerations¶
1. Input Amount Verification¶
Hardware wallet implementations must: - Independently obtain and verify UTXO amounts - Verify amounts before computing the signature hash - Display accurate fees to the user
2. Output Hash Verification¶
All outputs must be verified: - Display output addresses and amounts to the user one by one - Compute hashOutputs after user confirmation - Ensure hashOutputs is not modified after signing
3. Replay Protection¶
Although BIP143 itself does not provide replay protection: - Committing to input amounts makes cross-chain replay attacks more difficult - Combined with other mechanisms (such as different coin types), replay can be prevented
Implementation Details¶
Pseudocode Example¶
def SignatureHash(scriptCode, txTo, inIdx, hashType, value):
"""
Compute the BIP143 signature hash
Parameters:
- scriptCode: Script code
- txTo: Transaction to sign
- inIdx: Current input index
- hashType: Signature hash type
- value: Input amount (satoshis)
"""
# 1. nVersion
hashPrevouts = b'\x00' * 32
hashSequence = b'\x00' * 32
hashOutputs = b'\x00' * 32
# 2. hashPrevouts
if not (hashType & SIGHASH_ANYONECANPAY):
hashPrevouts = GetHashPrevouts(txTo)
# 3. hashSequence
if (not (hashType & SIGHASH_ANYONECANPAY) and
(hashType & 0x1f) != SIGHASH_SINGLE and
(hashType & 0x1f) != SIGHASH_NONE):
hashSequence = GetHashSequence(txTo)
# 4. hashOutputs
if (hashType & 0x1f) not in [SIGHASH_SINGLE, SIGHASH_NONE]:
hashOutputs = GetHashOutputs(txTo)
elif ((hashType & 0x1f) == SIGHASH_SINGLE and
inIdx < len(txTo.vout)):
hashOutputs = SHA256(SHA256(txTo.vout[inIdx].serialize()))
# Build the signature hash preimage
ss = b''
ss += struct.pack('<I', txTo.nVersion)
ss += hashPrevouts
ss += hashSequence
ss += txTo.vin[inIdx].prevout.serialize()
ss += SerializeScriptCode(scriptCode)
ss += struct.pack('<Q', value) # Input amount
ss += struct.pack('<I', txTo.vin[inIdx].nSequence)
ss += hashOutputs
ss += struct.pack('<I', txTo.nLockTime)
ss += struct.pack('<I', hashType)
return SHA256(SHA256(ss))
def GetHashPrevouts(tx):
"""Compute hash of all input outpoints"""
ss = b''
for inp in tx.vin:
ss += inp.prevout.serialize()
return SHA256(SHA256(ss))
def GetHashSequence(tx):
"""Compute hash of all input sequence numbers"""
ss = b''
for inp in tx.vin:
ss += struct.pack('<I', inp.nSequence)
return SHA256(SHA256(ss))
def GetHashOutputs(tx):
"""Compute hash of all outputs"""
ss = b''
for out in tx.vout:
ss += out.serialize()
return SHA256(SHA256(ss))
Comparison: Before and After BIP143¶
| Feature | Traditional SIGHASH | BIP143 |
|---|---|---|
| Complexity | O(n^2) | O(n) |
| Large Transaction Verification | Slow (could exceed 1 minute) | Fast (seconds) |
| Input Amount Commitment | No | Yes |
| Hardware Wallet Security | Cannot independently verify | Can independently verify |
| Cache Optimization | Not supported | Supported |
| DoS Attack Risk | High | Low |
| Data Transfer Volume (hardware wallet) | Large (needs complete transaction) | Small (only key data needed) |
Practical Impact¶
Impact on Users¶
Hardware Wallet Users: - More secure: Can accurately verify fees - Faster: Improved signing speed - Simpler: Reduced data transfer volume
Regular Users: - Faster transaction confirmations (faster node verification) - Reduced network congestion risk - Support for more complex transaction types
Impact on Developers¶
Wallet Development: - Requires implementing the new signature algorithm - Hardware wallets can provide a better user experience - Simplifies offline signing implementation
Node Software: - Significantly improved verification performance - Enhanced resistance to DoS attacks - Support for larger batch transactions
Impact on the Network¶
Performance Improvements: - Faster block verification - Can safely process larger transactions - Reduced hardware requirements for verification nodes
Security Enhancements: - Eliminated the quadratic hashing attack vector - Improved hardware wallet security - Reduced signature-related security vulnerabilities
Activation and Deployment¶
Soft Fork Activation¶
BIP143 was activated as part of the SegWit upgrade in August 2017: - Activation method: BIP9 version bit 1 - Activation height: 481,824 (August 24, 2017) - Activated simultaneously with BIP141 - Backward compatible: Old nodes treat SegWit transactions as "anyone-can-spend"
Compatibility¶
New and Old Transaction Types: - Legacy transactions (non-SegWit): Continue using the old SIGHASH algorithm - SegWit v0 transactions (P2WPKH, P2WSH): Use the BIP143 algorithm - SegWit v1 transactions (Taproot): Use the new algorithm defined in BIP341
Wallet Support: All major wallets have implemented BIP143: - Hardware wallets: Ledger, Trezor, Coldcard fully support it - Software wallets: Bitcoin Core, Electrum, Wasabi, etc. - Enterprise solutions: BitGo, Coinbase, etc.
Future Development¶
Lessons Applied to Taproot¶
BIP341 (Taproot) signature hash algorithm: - Draws on BIP143's design principles - Similarly commits to input amounts - Similarly uses O(n) complexity - Further optimized and extended
Batch Verification¶
Further optimizations based on BIP143: - Batch verification of Schnorr signatures - Cross-input signature aggregation - More efficient block verification
Summary¶
BIP143 brought significant performance and security improvements to Segregated Witness transactions through an improved signature hash algorithm:
Core Improvements: - Performance: Reduced from O(n^2) to O(n), eliminating the quadratic hashing problem - Security: Commits to input amounts, protecting hardware wallet users - Efficiency: Supports caching, optimizing signing and verification speed - Simplification: Reduces data requirements for offline signing
Practical Value: - Eliminated the DoS attack vector based on large transactions - Enabled hardware wallets to safely display accurate fees - Improved node capability to verify large transactions - Laid the foundation for subsequent upgrades like Taproot
Although BIP143 is a highly technical proposal, its impact is far-reaching. It not only solved long-standing performance and security problems but also provided a solid foundation for the expansion and secure use of the Bitcoin network. For hardware wallet users, BIP143 is a key technology for protecting funds; for the Bitcoin network, it is an important upgrade for resisting attacks and improving performance.