Part III · The SegWit Revolution Chapter 9

P2WPKH: Native SegWit

"The witness must consist of exactly 2 items… The HASH160 of the public key must match the 20-byte witness program."—BIP 141, Segregated Witness

Chapter 8 introduced Segregated Witness through a transaction that wrapped its SegWit spend inside a P2SH shell—a backward-compatible bridge for wallets that had not yet upgraded. In this chapter, we meet SegWit in its native form: Pay to Witness Public Key Hash, or P2WPKH.

A native P2WPKH transaction is the SegWit equivalent of P2PKH. It performs the same cryptographic operation—verify that a signature matches a public key whose Hash160 equals a committed value—but it does so with an empty scriptSig, a two-item witness, and a new address format that starts with bc1q. The result is a transaction that is smaller in virtual size, cheaper in fees, and immune to third-party malleability.

9.1The Specimen

Our specimen comes from block 600,000—a milestone block mined on October 19, 2019, by the Bitfury mining pool. It is a pure P2WPKH transaction: one native SegWit input, two native SegWit outputs, 222 bytes.

Txid:

cafee3cf4697040c35ec0f3bd3778e47c569bd4afbdc81f179be9333a1c67afb

Compare this to the P2PKH specimen from Chapter 5 (block 100,000). The most striking difference: the scriptSig is empty—a single zero byte (0x00) for its length. The signature and public key have moved entirely into the witness field. This is the defining characteristic of native SegWit.

9.2The Empty ScriptSig

In P2PKH, the scriptSig carries the signature and public key—typically 107 bytes. In P2WPKH, the scriptSig is zero bytes. The input structure shrinks from 148 bytes (P2PKH) to 41 bytes:

FieldP2PKHP2WPKH
Previous txid3232
Previous vout44
ScriptSig length11
ScriptSig1070
Sequence44
Total input148 bytes41 bytes

The 107 bytes of signature and public key do not disappear—they move to the witness, where they cost only 1 weight unit per byte instead of 4. The input itself, which is non-witness data, shrinks by 107 bytes \(\times\) 4 WU \(=\) 428 weight units.

Why Not Just a Smaller ScriptSig?

Moving the signature out of the scriptSig—rather than keeping it there at a discounted weight—is essential for the malleability fix. The txid is computed from the stripped transaction, which includes the scriptSig. If the signature remained in the scriptSig, a third party could still modify it and change the txid. An empty scriptSig means there is nothing to malleate.

9.3The Witness Program

The output being spent contains a 22-byte scriptPubKey that encodes the witness program:

P2WPKH ScriptPubKey (22 bytes)
HexOpcodeMeaning
00OP_0Witness version 0
14OP_PUSHBYTES_20Push next 20 bytes
6a35…4520(data)HASH160 of the public key

When a node encounters a scriptPubKey of the form OP_0 <20 bytes>, it recognizes this as a version 0 witness program with a 20-byte program. The 20-byte program is the Hash160 of the public key that can spend this output—exactly the same hash that appears inside a P2PKH scriptPubKey, but with 3 fewer bytes of script opcodes.

TypeScriptPubKeySize
P2PKHOP_DUP OP_HASH160 <20> OP_EQUALVERIFY OP_CHECKSIG25 bytes
P2WPKHOP_0 <20>22 bytes

Both encode the same 20-byte Hash160. P2PKH wraps it in five opcodes that define the spending logic inline. P2WPKH encodes only the witness version and the hash—the spending logic is implicit, defined by BIP 141's consensus rules.

9.4Validation: The Implicit Script

When a node validates a P2WPKH spend, it does not execute the scriptPubKey as Script. Instead, it follows BIP 141's rule: for a version 0 witness program of exactly 20 bytes, the witness must contain exactly two items—a signature and a public key—and the node validates them as if the following P2PKH script were being executed:

OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG

P2WPKH Validation — Implicit Stack Execution
Step 0 / 7
Click Step to begin

The result is cryptographically identical to P2PKH: the public key's Hash160 must match the committed value, and the signature must be valid for that key under BIP 143's digest algorithm.

BIP 143 Digest, Not Legacy

P2WPKH always uses BIP 143's transaction digest for signature verification—the new algorithm that precomputes shared components and eliminates quadratic hashing (Chapter 8's BIP 143 digest algorithm). A P2WPKH signature cannot be verified using the legacy sighash algorithm. This is true even when P2WPKH is wrapped inside P2SH (Chapter 11).

9.5Parsing the Witness

Our specimen's witness contains two items:

Witness Data — Input 0 (107 bytes)
HexElementDetails
02Item count2 items
47Item 0 length71 bytes
3044… dc01DER signature + SIGHASH_ALL\(r\): 32 bytes, \(s\): 32 bytes
21Item 1 length33 bytes
033f…0331Compressed public keyStarts with 03 (odd \(y\))

Total witness: \(1 + 1 + 71 + 1 + 33 = 107\) bytes. The signature is 71 bytes rather than the maximum 72 because both the \(r\) and \(s\) values are 32 bytes—neither requires the 0x00 padding byte that DER demands when the most significant bit is set (Chapter 3).

DER Signature Length Varies

A DER-encoded ECDSA signature ranges from 70 to 72 bytes (plus the 1-byte SIGHASH flag, giving 71–73 total). The \(r\) and \(s\) integers are each 32 bytes, but if the high bit is set (0x80–0xFF), DER requires a leading 0x00 to indicate a positive integer, adding 1 byte per padded value. Our specimen's \(r\) starts with 0x5a and \(s\) with 0x5f—both below 0x80, so neither needs padding.

Chapter 8's specimen had a 72-byte signature because its \(r\) value started with 0xaa (\(\geq\) 0x80), requiring one padding byte.

We can verify the witness by confirming that the public key's Hash160 matches the witness program in the output being spent:

HASH160(033fed…0331) = 6a3511333f288787cad59d7b21339b2c95094520

This is exactly the 20-byte witness program embedded in the scriptPubKey.

9.6Bech32 Addresses

Native SegWit outputs use bech32 addresses (BIP 173), a new encoding designed specifically for witness programs. Our specimen's input address is:

bc1qdg63zvel9zrc0jk4n4ajzvum9j2sj3fqzpj8um

9.6.1Anatomy of a Bech32 Address

A bech32 address has three components:

ComponentValuePurpose
Human-readable part (HRP)bcIdentifies the network (mainnet). Testnet uses tb.
Separator1Always the character "1"
Data partqdg63z… j8umWitness version + program + 6-char checksum

The data part encodes:

  1. Witness version: the first character. For version 0, this is q (the bech32 character for the value 0).
  2. Witness program: the next 32 characters encode the 20-byte Hash160, converted from 8-bit groups to 5-bit groups.
  3. Checksum: the last 6 characters (zpj8um), computed using a BCH error-detecting code.

9.6.2Why Bech32?

Bech32 was designed to address specific limitations of Base58Check (used by P2PKH and P2SH addresses):

PropertyBase58CheckBech32
Case sensitivityMixed caseLowercase only
Error detectionDetects up to 1 errorDetects up to 4 errors
Ambiguous charactersExcludes 0OIlNot applicable (no mixed case)
QR code efficiencyByte mode (mixed case)Alphanumeric mode (smaller QR)
Address length (20-byte hash)34 chars42 chars
BIP 173 and the Bech32 Name

Bech32 was proposed by Pieter Wuille and Greg Maxwell in BIP 173 (March 2017) and named after the BCH error-correcting code family (Bose–Chaudhuri–Hocquenghem) combined with "32" for the 32-character alphabet. The address format was finalized before SegWit activated in August 2017, but wallet adoption was slow—many services did not support sending to bc1 addresses until 2018 or later. This is why the earliest SegWit transactions (including Chapter 8's specimen from block 481,824) used P2SH-wrapped SegWit with 3-addresses rather than native bech32.

9.7Weight and Fee Savings

9.7.1Our Specimen's Weight

ComponentValue
Total size222 bytes
Marker + flag2 bytes
Witness data107 bytes
Stripped size\(222 - 2 - 107 = 113\) bytes
Weight\(113 \times 3 + 222 = 339 + 222 = 561\) WU
Virtual size\(\lceil 561/4 \rceil = 141\) vbytes
Fee10,500 sats
Fee rate\(10{,}500 \div 141 \approx 74.5\) sat/vbyte

9.7.2P2PKH vs P2WPKH: The Full Comparison

ComponentP2PKHP2WPKHDifference
ScriptSig107 bytes0 bytes\(-107\)
Witness0 bytes107 bytes\(+107\)
ScriptPubKey25 bytes22 bytes\(-3\)
Total input148 bytes41 bytes\(-107\)
Total tx (1-in-2-out)226 bytes222 bytes\(-4\)
Weight904 WU561 WU\(-343\)
Virtual size226 vbytes141 vbytes\(-85\)
Fee savings37.6%

The raw byte savings are modest (\(-4\) bytes) because the same signature and public key data exists in both transactions. The weight savings are dramatic (\(-343\) WU, or \(-38\)%) because those bytes move from the expensive non-witness region (4 WU each) to the discounted witness region (1 WU each).

The 3-Byte ScriptPubKey Savings

P2WPKH's scriptPubKey is 22 bytes (OP_0 <20>) versus P2PKH's 25 bytes (OP_DUP OP_HASH160 <20> OP_EQUALVERIFY OP_CHECKSIG). This 3-byte difference in non-witness data saves an additional \(3 \times 4 = 12\) WU per output. For a 2-output transaction, that is 24 WU of savings beyond the witness discount.

9.8The Change Output

Our specimen sends 100,000 sats (the full value of the input) to two outputs:

OutputAddressValue
0bc1qdg63zvel9zrc0jk4n4ajzvum9j2sj3fqzpj8um64,680 sats
1bc1q7mvaz0faxk2u9h5hja2stnsgj77ve6p63q33sf24,820 sats
Fee (input \(-\) outputs)10,500 sats

Output 0 goes to the same address as the input (bc1qdg63… j8um)—this is the change output.

Address Reuse and Privacy

Sending change back to the same address is a privacy anti-pattern. As noted in Satoshi's whitepaper (Section 10): "a new key pair should be used for each transaction to keep them from being linked to a common owner." When change returns to the input address, an observer can trivially identify which output is the payment and which is change. Modern wallets generate a new address for each change output to preserve transaction ambiguity.

9.9What We Learned

9.9.1Looking Ahead

P2WPKH handles the single-key case. Chapter 10 introduces P2WSH—Pay to Witness Script Hash—which extends the SegWit model to arbitrary scripts: multisig, timelocks, and any spending condition that exceeds a single key. Where P2WPKH commits to a 20-byte Hash160, P2WSH commits to a 32-byte SHA-256 hash of the witness script, enabling a larger and more expressive script space.

Exercises

Litmus (L)

  1. What is the size of a P2WPKH scriptPubKey in bytes? How does it compare to P2PKH?
  2. How many items must a P2WPKH witness contain?
  3. What is the scriptSig of a native P2WPKH input?
  4. What does the bc1q prefix tell you about an address?
  5. In our specimen, why is the DER signature 71 bytes instead of 72?

Hands-On (H)

  1. From our specimen's hex, identify the marker, flag, and witness bytes. Compute the stripped size, weight, and vsize. Verify they match the stated values (222, 561, 141).
  2. Verify the Hash160 relationship: compute HASH160 of the public key 033fed…0331 and confirm it equals the witness program 6a3511…4520.
  3. Decode both output scriptPubKeys. What are the two witness programs? What are the corresponding bech32 addresses?
  4. A P2WPKH transaction has 3 inputs (each with a 72-byte signature and 33-byte compressed public key) and 2 P2WPKH outputs. Compute its total size, stripped size, weight, and vsize.

Proofs and Reasoning (P)

  1. Explain why P2WPKH validation is defined as an implicit script rather than by executing the scriptPubKey directly on the stack. What would happen if a pre-SegWit node tried to execute OP_0 <20 bytes> as Script?
  2. Why does the witness program use HASH160 (20 bytes) rather than SHA-256 (32 bytes)? What is the security trade-off?
  3. Prove that a P2WPKH input with the same signature and public key always produces a smaller vsize than the equivalent P2PKH input, regardless of DER signature length.

Connections (C)

  1. Our specimen reuses the input address for its change output. Describe the privacy implications and explain what a properly constructed transaction would do differently.
  2. Compare the bech32 checksum (BCH code, detects up to 4 errors) with Base58Check's checksum (double SHA-256, detects up to 1 error). Why is stronger error detection important for Bitcoin addresses?

Bridge (B)

  1. How would our specimen differ if it used P2SH-P2WPKH (Chapter 11) instead of native P2WPKH? What changes in the scriptSig, scriptPubKey, address format, and total weight?
  2. Taproot (Chapter 12) introduces witness version 1 with 32-byte x-only public keys. If our specimen were a P2TR key-path spend, how would the witness differ?

Solutions

L1. 22 bytes: OP_0 (1 byte) + OP_PUSHBYTES_20 (1 byte) + Hash160 (20 bytes). P2PKH's scriptPubKey is 25 bytes (5 opcodes + 20-byte hash), so P2WPKH saves 3 bytes per output.

L2. Exactly 2 items: the signature and the public key. BIP 141 requires this for version 0, 20-byte witness programs. Any other item count causes validation to fail.

L3. Empty—0 bytes. The scriptSig length varint is 0x00. In native SegWit, the signature and public key live entirely in the witness field.

L4. The address is a native SegWit version 0 output on Bitcoin mainnet. bc is the human-readable part (mainnet), 1 is the separator, and q is the bech32 character for witness version 0. The q prefix (version 0) indicates either P2WPKH (20-byte program) or P2WSH (32-byte program).

L5. The DER signature has \(r = 32\) bytes (starting with 0x5a) and \(s = 32\) bytes (starting with 0x5f). Neither value has its most significant bit set (\(\texttt{0x5a} < \texttt{0x80}\) and \(\texttt{0x5f} < \texttt{0x80}\)), so neither requires the 0x00 padding byte. The total is \(6 + 32 + 32 + 1 = 71\) bytes (6 DER overhead + 1 SIGHASH flag).

H1. From the 222-byte hex:

H2.

  1. SHA-256(033fed439a… c06e0331) (33 bytes of compressed public key)
  2. RIPEMD-160 of the SHA-256 result
  3. Result: 6a3511333f288787cad59d7b21339b2c95094520

This matches the 20-byte witness program in the scriptPubKey 0014\-6a3511…4520.

H3. Both scriptPubKeys follow the pattern 0014<20 bytes>:

The bech32 encoding converts each 20-byte program to 5-bit groups, prepends the witness version (q \(=\) 0), and appends a 6-character BCH checksum.

H4. With 3 inputs (72-byte sig each) and 2 P2WPKH outputs:

P1. If a pre-SegWit node executed OP_0 <20 bytes> as Script, OP_0 would push an empty byte array (falsy) and OP_PUSHBYTES_20 would push the 20-byte hash. The stack would contain [, <20 bytes>]. Under the clean stack rule, this would fail (two items remain). But without the clean stack rule (which was only a relay policy, not consensus, before SegWit), the top stack element is the 20-byte hash (truthy), so old nodes accept it as valid—making SegWit a soft fork. BIP 141 makes the clean stack rule a consensus requirement only for witness programs, not for legacy scripts, preserving backward compatibility. The implicit script approach avoids this ambiguity: validation is handled by special-case consensus code, not by Script execution.

P2. P2WPKH uses HASH160 (20 bytes) to match P2PKH's existing security model and to keep witness programs compact. Using SHA-256 (32 bytes) would provide 256-bit collision resistance, but for a single-key scheme, the relevant attack is a preimage attack (finding a different public key with the same hash), not a collision. HASH160 provides 160-bit preimage resistance, which requires \(2^{160}\) operations—far beyond any foreseeable computational capability. P2WSH (Chapter 10) uses SHA-256 because scripts can have multiple valid spending paths, making collision resistance more important.

P3. A P2WPKH input has: non-witness \(= 41\) bytes (costing \(41 \times 4 = 164\) WU), plus witness \(= 3 + L_{sig} + 33\) bytes at 1 WU each (\(L_{\text{sig}} \in \{71, 72, 73\}\) including SIGHASH flag). A P2PKH input has: non-witness \(= 41 + 1 + L_{sig} + 1 + 33 = 76 + L_{sig}\) bytes (the 41-byte input shell plus push_sig, signature, push_pk, and pubkey), all at 4 WU.

P2PKH input weight: \((76 + L_{sig}) \times 4 = 304 + 4L_{sig}\).

P2WPKH input weight: \(41 \times 4 + (3 + L_{sig} + 33) \times 1 = 164 + 36 + L_{sig} = 200 + L_{sig}\).

Difference: \((304 + 4L_{sig}) - (200 + L_{sig}) = 104 + 3L_{sig}\). Since \(L_{sig} \geq 71\), the difference is at least \(104 + 213 = 317\) WU, which is always positive. P2WPKH always has smaller weight (and therefore smaller vsize) than P2PKH.

C1. Address reuse reveals the transaction graph. When Output 0 returns to the same address as the input, an observer knows: (a) Output 0 is change (not a payment to a third party); (b) the remaining balance is 64,680 sats; (c) Output 1 (24,820 sats) is the payment; (d) any future spend of Output 0 can be linked to this same entity. A properly constructed transaction uses a fresh key pair for the change output, making it ambiguous which output is change and which is the payment. This is BIP 32 (HD wallets) in practice: derive a new change address from the wallet's internal chain for each transaction.

C2. Base58Check uses the first 4 bytes of a double-SHA-256 hash as a checksum. This detects any single-character error (and most multi-character errors), but SHA-256 is designed for cryptographic security, not for optimized error detection. Bech32 uses a BCH code specifically optimized for error detection: it is guaranteed to detect any combination of up to 4 errors in addresses up to 89 characters long, with less than a 1 in \(10^9\) chance of failing to detect more. For Bitcoin addresses, where a single mistyped character could send funds to an unrecoverable address, this stronger guarantee is critical. Additionally, bech32's error-locating properties can tell the user which characters are wrong, aiding manual correction.

B1. In P2SH-P2WPKH:

B2. In a P2TR key-path spend (witness version 1):

← Ch. 8 Ch. 10 →