P2WPKH Script - Full Witness Execution
5. P2WPKH Script — Full Witness Execution
Overview
Pay-to-Witness-Public-Key-Hash (P2WPKH) is the SegWit (Segregated Witness) equivalent of P2PKH, introduced in BIP 141 and activated in August 2017. SegWit separates signature data (the witness) from the transaction body, solving transaction malleability, enabling the Lightning Network, and reducing effective transaction weight.
P2WPKH native addresses use Bech32 encoding (prefix bc1q on mainnet).
Script Structure
Locking script (scriptPubKey) — 22 bytes:
OP_0 <20-byte witness program>
The 20-byte witness program is identical to the pubKeyHash in P2PKH: HASH160(pubkey).
scriptSig: Empty (zero bytes) — this is critical for SegWit.
Witness field (replaces scriptSig):
02 <- witness item count
<sig> <- item 1: DER signature + SIGHASH byte
<pubkey> <- item 2: compressed public key
Byte-Level Anatomy
scriptPubKey (22 bytes):
00 <- OP_0 (witness version 0)
14 <- push 20 bytes
<20-byte HASH160(pubkey)>
Witness (serialized):
02 <- 2 witness items
47 <- item 1 length (71 bytes)
<71-byte signature>
21 <- item 2 length (33 bytes)
<33-byte compressed pubkey>
SegWit Execution Rules
For SegWit inputs, the standard script interpreter is bypassed. Instead:
-
The
scriptPubKeyis detected as a witness program (starts withOP_0toOP_16). -
The
scriptSigmust be empty. If not, the transaction is invalid. -
The witness stack is used as input.
-
For version 0 with 20-byte program (P2WPKH), a virtual P2PKH script is constructed:
Implicit script constructed by the interpreter:
OP_DUP OP_HASH160 <20-byte witness program> OP_EQUALVERIFY OP_CHECKSIG
- This implicit script is executed with the witness items as the stack.
Transaction Weight and Discount
SegWit introduces weight units (WU) with a discount for witness data:
Transaction weight formula:
weight = (non-witness bytes × 4) + (witness bytes × 1)
1 weight unit = 0.25 vbytes
Block limit = 4,000,000 WU = 1,000,000 vbytes
A P2WPKH input contributes:
- 41 bytes non-witness (outpoint + sequence + empty scriptSig) × 4 = 164 WU
- ~107 bytes witness × 1 = 107 WU
- Total ≈ 271 WU ≈ 67.75 vbytes
vs P2PKH input:
- 148 bytes × 4 = 592 WU ≈ 148 vbytes
This ~55% size reduction makes P2WPKH transactions significantly cheaper to send.
BIP 143 Signature Hash
SegWit v0 uses a new signature hashing algorithm (BIP 143) to prevent quadratic hashing attacks:
def bip143_sighash(tx, input_index, script_code, value, sighash_type=1):
"""
BIP143 sighash for P2WPKH
script_code = OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG
value = satoshis locked in the UTXO being spent
"""
hash_prevouts = double_sha256(serialize_all_outpoints(tx))
hash_sequence = double_sha256(serialize_all_sequences(tx))
hash_outputs = double_sha256(serialize_all_outputs(tx))
preimage = (
tx.version.to_bytes(4, 'little') +
hash_prevouts +
hash_sequence +
serialize_outpoint(tx.inputs[input_index]) +
script_code +
value.to_bytes(8, 'little') +
tx.inputs[input_index].sequence.to_bytes(4, 'little') +
hash_outputs +
tx.locktime.to_bytes(4, 'little') +
sighash_type.to_bytes(4, 'little')
)
return double_sha256(preimage)
The key difference from legacy sighash is that the value (amount) of the UTXO being spent is now committed to in the signature, closing the "hardware wallet attack" where a malicious host could misrepresent amounts.
TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation: