Part III · The SegWit Revolution Chapter 8

Segregated Witness

"This BIP defines a new structure called a 'witness' that is committed to blocks separately from the transaction merkle tree."—BIP 141, Segregated Witness

On August 24, 2017, at 01:57 UTC, Bitcoin miner BTCC Pool mined block 481,824—the block at which Segregated Witness activated. Among its transactions was one that carried, in an OP_RETURN output, a message for posterity:

BIP141 o/ Hello SegWit :-) keep it strong! LLAP Bitcoin

That transaction—our specimen for this chapter—was the first SegWit transaction ever confirmed on the Bitcoin network. It marked the most significant upgrade to Bitcoin's transaction format since the genesis block: the separation of witness data from the transaction structure that the witness authenticates.

8.1The Malleability Problem

To understand why SegWit was necessary, we must understand what it fixed.

In pre-SegWit transactions, the scriptSig (unlocking script) is part of the serialized transaction data that gets hashed to produce the txid. But the scriptSig contains the signature—and ECDSA signatures have a property that makes this dangerous: for any valid signature \((r, s)\), the pair \((r, n - s)\) is also valid (where \(n\) is the curve order). A DER-encoded signature can also be padded or reformatted in ways that change the bytes without changing the mathematical validity.

This means a third party—a miner, a relay node, anyone who sees the transaction before it is confirmed—can modify the scriptSig, producing a valid transaction with a different txid.

Third-Party Transaction Malleability

Pre-SegWit, anyone could take a valid unconfirmed transaction, modify its scriptSig encoding (without invalidating the signature), recompute the txid, and rebroadcast it. Both the original and the mutated version are valid—only one can be confirmed, but the sender cannot predict which one. The sender's expected txid may never appear in the blockchain, even though the payment went through.

This was not merely a theoretical concern. Transaction malleability:

Mt. Gox and Malleability

In February 2014, the Mt. Gox exchange cited transaction malleability as a factor in the loss of approximately 850,000 BTC. The precise role of malleability in the collapse remains debated—internal fraud appears to have been the primary cause—but the incident focused the Bitcoin community's attention on the malleability problem and accelerated the search for a solution.

8.2The Specimen

Our specimen is the first SegWit transaction ever confirmed on Bitcoin, from block 481,824 (August 24, 2017). It is a P2SH-P2WPKH transaction—a SegWit spend wrapped in a P2SH shell for backward compatibility (explored in Chapter 10).

Txid:

8f907925d2ebe48765103e6845c06f1f2bb77c6adc1cc002865865eb5cfd5c1c

This 302-byte transaction introduced a new element to Bitcoin's serialization: the two bytes 00 01 between the version and the input count—the marker and flag—and the violet witness data between the outputs and the locktime. These are the hallmarks of a SegWit transaction.

8.3The New Serialization Format

Pre-SegWit, a transaction was serialized as:

[version][inputs][outputs][locktime]

SegWit transactions add three new elements:

[version] [marker][flag] [inputs][outputs] [witness] [locktime]

8.3.1Marker and Flag

The marker byte (0x00) and flag byte (0x01) appear immediately after the version field. Together they signal that this transaction contains witness data.

In a pre-SegWit transaction, the byte after the version is the input count (a varint). A zero input count (0x00) is invalid in legacy transactions—no transaction can have zero inputs. SegWit exploits this: when a parser encounters 0x00 as the "input count," it recognizes this as the SegWit marker and reads the next byte as the flag. This design ensures that SegWit transactions are unambiguously distinguishable from legacy ones without any protocol negotiation.

8.3.2The Stripped Transaction

Old nodes that do not understand SegWit receive a stripped version of the transaction: the marker, flag, and witness fields are removed. What remains is a valid legacy transaction:

[version][inputs][outputs][locktime]

The stripped transaction has the same txid as the full SegWit transaction—because the txid is computed from the stripped form. This backward compatibility was the key design insight that allowed SegWit to be deployed as a soft fork: old nodes accept SegWit transactions without understanding the witness.

8.4Parsing the Witness

The witness field sits between the last output and the locktime. It contains one witness stack per input, in the same order as the inputs.

For our specimen (one input), the witness structure is:

Witness Data — Input 0 (108 bytes)
HexElementSize
02Item count2 items in this witness stack
48Item 0 length72 bytes
3045… c57401DER signature + SIGHASH_ALL72 bytes
21Item 1 length33 bytes
021e… c74fbCompressed public key33 bytes

Total witness: \(1 + 1 + 72 + 1 + 33 = 108\) bytes. In a pre-SegWit P2PKH transaction, these 105 bytes of signature and public key would sit inside the scriptSig. SegWit moves them to the witness, outside the data that determines the txid.

Per-Input Witness Stacks

Every input in a SegWit transaction has its own witness stack, even if it is empty. A transaction with three inputs has three witness stacks. A legacy (non-SegWit) input has a witness stack with zero items: just the byte 00. This structure ensures that the witness field is always parseable regardless of input types.

8.5txid vs wtxid

SegWit introduced a second transaction identifier:

IdentifierComputed FromPurpose
txidStripped transaction (no marker, flag, witness)Backward-compatible identifier
wtxidFull serialized transaction (including witness)Witness commitment in blocks

The txid is computed by double-SHA-256 hashing the stripped transaction—the same data that old nodes see. Modifying the witness (e.g., re-encoding a signature) does not change the txid. This is the malleability fix: the signature is no longer part of the txid preimage.

The wtxid hashes the full serialized transaction, including witness data. It is used in the witness commitment—a hash tree embedded in the coinbase transaction of each block—ensuring that miners commit to the exact witness data.

Malleability Is Not Eliminated

SegWit eliminates third-party malleability—an observer cannot change the txid by modifying the witness. But the transaction's creator can still produce a different signature (and therefore a different wtxid) before broadcasting. SegWit does not, and cannot, prevent the signer from changing their own signature.

8.6Weight and Virtual Size

SegWit replaced the simple "transaction size in bytes" with a more nuanced metric: weight.

🔧 Interactive: Weight Lab

8.6.1The Weight Formula

weight = stripped_size × 3 + total_size

where:

Equivalently, non-witness bytes count 4 weight units (WU) each, while witness bytes count 1 WU each. The maximum block weight is 4,000,000 WU (replacing the old 1,000,000-byte block size limit).

8.6.2Our Specimen's Weight

ComponentValue
Total size302 bytes
Marker + flag2 bytes
Witness data108 bytes
Stripped size\(302 - 2 - 108 = 192\) bytes
Weight\(192 \times 3 + 302 = 576 + 302 = 878\) WU
Virtual size (vsize)\(\lceil 878/4 \rceil = 220\) vbytes

8.6.3Virtual Size

Virtual size (vsize) converts weight back to a byte-like unit for fee estimation:

\[ \text{vsize} = \left\lceil \frac{\text{weight}}{4} \right\rceil \]

Fee rates are quoted in sat/vbyte. Our specimen paid \(189{,}000 \div 220 \approx 859\) sat/vbyte—an extraordinarily high fee rate, befitting the first SegWit transaction in history.

8.7The Witness Discount

The 4:1 ratio between non-witness and witness weight units is not arbitrary. It reflects a deliberate economic design.

Why Discount the Witness?

The UTXO set—the set of all unspent transaction outputs—must be held in memory by every full node. It is the most expensive data structure in Bitcoin. Non-witness data (outputs, scriptPubKeys) contributes to the UTXO set. Witness data (signatures, public keys) does not—it is validated once and can be pruned.

By making witness data 4\(\times\) cheaper in weight, SegWit incentivizes transaction structures that minimize UTXO-set growth. Signatures, which are large and can be discarded after validation, cost less. Outputs, which persist in every node's memory, cost more.

The practical impact is significant. A P2PKH transaction's scriptSig contains approximately 107 bytes: a push opcode and 72-byte DER signature, plus a push opcode and 33-byte compressed public key. A P2WPKH transaction moves the signature and public key to the witness, where they cost \(14\) the weight. For a standard 1-input, 2-output payment, this produces a fee savings of roughly 38%—the vsize drops from 226 to approximately 141 vbytes.

8.8BIP 141, 143, and 144

SegWit was specified across three BIPs, each addressing a different layer:

BIPLayerPurpose
141ConsensusDefines witness structure, weight formula, witness programs, and validation rules. The core of SegWit.
143ConsensusDefines a new transaction digest algorithm for signature verification. Fixes quadratic hashing and enables efficient signing.
144Peer ServicesDefines how SegWit transactions are serialized on the network, including the marker/flag bytes and witness field.

8.8.1BIP 143: The New Digest

BIP 143 deserves special attention because it solved a second problem beyond malleability: quadratic hashing. In pre-SegWit transactions, computing the signature hash required serializing the entire transaction for each input. For a transaction with \(n\) inputs, this produced \(O(n^2)\) hashing work—a denial-of-service vector for large transactions.

BIP 143 introduced a new digest algorithm where each input's signature hash can be computed in \(O(n)\) time by precomputing shared components (hash of all prevouts, hash of all sequences, hash of all outputs). These precomputed hashes are reused across inputs, eliminating the quadratic blowup.

8.9What We Learned

8.9.1Looking Ahead

This chapter introduced SegWit's format and economics. The next three chapters examine the transaction types it enables. Chapter 9 covers P2WPKH—native SegWit for single-key payments, with empty scriptSigs and bech32 addresses. Chapter 10 presents P2WSH—SegWit's replacement for P2SH, with larger script limits and witness-discounted multisig. Chapter 11 explores the backward-compatible wrappers (P2SH-P2WPKH and P2SH-P2WSH) that our specimen uses—the bridge between the legacy and SegWit worlds.

Exercises

Litmus (L)

  1. What two bytes immediately follow the version in a SegWit transaction?
  2. Why is 0x00 used as the marker byte?
  3. How many weight units (WU) does a non-witness byte cost?
  4. What is the maximum block weight under SegWit?
  5. What data is excluded from the txid but included in the wtxid?

Hands-On (H)

  1. From our specimen's hex, compute the stripped size by identifying and removing the marker, flag, and witness bytes. Verify the weight matches 878 WU.
  2. Decode the OP_RETURN message in Output 1. What does "LLAP" stand for?
  3. A legacy P2PKH transaction (1 input, 2 P2PKH outputs) is 226 bytes. Compute its weight and vsize. Then compute the same for a P2WPKH transaction of the same payment (1 input, 2 P2WPKH outputs): 223 bytes total, 113 bytes stripped. What is the fee savings?
  4. Compute the fee rate of our specimen in sat/vbyte.

Proofs and Reasoning (P)

  1. Explain why SegWit is a soft fork, not a hard fork. What do old nodes see when they encounter a SegWit transaction?
  2. Why does BIP 143's new digest algorithm reduce signature computation from \(O(n^2)\) to \(O(n)\)? What component is precomputed and shared across inputs?
  3. Prove that modifying the witness data of a confirmed transaction cannot change the txid.

Connections (C)

  1. Lightning Network payment channels require stable txids for pre-signed commitment transactions. Explain how SegWit enables trustless payment channels.
  2. Compare the weight of a 2-of-3 P2SH multisig spend (from Chapter 7's table: 254-byte scriptSig) with a hypothetical P2WSH equivalent where the signatures move to the witness.

Bridge (B)

  1. Our specimen uses P2SH-P2WPKH (Chapter 11). How would the transaction differ if it used native P2WPKH (Chapter 9)?
  2. Taproot (Chapter 12) replaces the witness version from 0 to 1. What new capabilities does witness version 1 enable?

Solutions

L1. The marker byte 0x00 and the flag byte 0x01.

L2. Because 0x00 as an input count is invalid in legacy transactions (no transaction can have zero inputs). When a parser encounters 0x00 after the version, it unambiguously identifies the transaction as SegWit, without protocol negotiation.

L3. 4 WU. Witness bytes cost 1 WU.

L4. 4,000,000 WU. This replaced the legacy 1,000,000-byte block size limit.

L5. The witness data (marker, flag, and per-input witness stacks). The txid is computed from the stripped transaction (without these fields).

H1. From the 302-byte hex:

H2. The OP_RETURN payload (424950313431…) decodes to ASCII:

BIP141 o/ Hello SegWit :-) keep it strong! LLAP Bitcoin twitter.com/khs9ne

"LLAP" stands for Live Long and Prosper—the Vulcan salutation from Star Trek, popularized by Leonard Nimoy.

H3. Legacy P2PKH (226 bytes, no witness):

P2WPKH (223 bytes total, 113 bytes stripped):

Savings: \(226 - 141 = 85\) vbytes, a 37.6% reduction. At the same sat/vbyte fee rate, P2WPKH costs roughly 38% less.

H4. Fee: 189,000 sats. vsize: 220 vbytes. Fee rate: \(189{,}000 \div 220 \approx 859\) sat/vbyte.

P1. SegWit is a soft fork because old nodes can validate SegWit transactions without understanding the witness. A SegWit output's scriptPubKey (e.g., OP_0 <20 bytes>) is valid under old rules as an "anyone-can-spend" script—it evaluates to TRUE because the version byte (OP_0) pushes a value and the witness program is a data push, leaving a truthy value on the stack. Old nodes accept these transactions. New nodes apply additional validation rules (checking the witness). Since old nodes accept everything new nodes accept, no chain split occurs. This is a soft fork: a tightening of the rules, not a loosening.

P2. Pre-SegWit, signing input \(i\) required serializing the entire transaction (all inputs and outputs) with modifications for input \(i\). For \(n\) inputs, this required \(n\) full serializations, each \(O(n)\) in size, for a total of \(O(n^2)\) hashing work.

BIP 143 precomputes three hashes that are shared across all inputs:

  1. hashPrevouts: double-SHA-256 of all input outpoints (txid + vout).
  2. hashSequence: double-SHA-256 of all input sequence numbers.
  3. hashOutputs: double-SHA-256 of all outputs (value + scriptPubKey).

These three hashes are computed once (each \(O(n)\)) and reused for every input. Each input's signature hash then requires only \(O(1)\) additional work (combining the precomputed hashes with input-specific data). Total: \(O(n) + n \times O(1) = O(n)\).

P3. The txid is defined as the double-SHA-256 hash of the stripped transaction: version, inputs, outputs, and locktime. The witness data is not part of this serialization. Any modification to the witness (different signature encoding, different public key format) changes the witness bytes but not the stripped transaction. Since SHA-256 is deterministic, the same stripped bytes always produce the same hash. The txid is invariant under witness modifications.

C1. A Lightning payment channel is built on a 2-of-2 multisig funding transaction. Before SegWit, the funding txid could be malleated by a third party, invalidating all pre-signed commitment transactions (which reference the funding txid). With SegWit, the funding transaction's txid is immune to third-party modification (signatures are in the witness, excluded from the txid). Commitment transactions that reference this txid remain valid regardless of witness modifications. This stability is what makes trustless, pre-signed transaction chains possible.

C2. P2SH 2-of-3 multisig (from Chapter 7):

P2WSH 2-of-3 equivalent:

The witness data alone saves \(1,016 - 254 = 762\) WU, a 75% reduction in the signature/script weight.

B1. In native P2WPKH: (a) the scriptSig would be empty (0 bytes) instead of containing the 23-byte witness program push; (b) the prevout scriptPubKey would be OP_0 <20-byte key hash> (22 bytes) instead of a P2SH script (OP_HASH160 <20-byte script hash> OP_EQUAL, 23 bytes); (c) the address would start with bc1q (bech32) instead of 3 (Base58Check). The witness data (signature + pubkey) would be identical.

B2. Witness version 1 (Taproot, BIP 341) enables: (a) Schnorr signatures (64 bytes, no DER encoding, batch-verifiable); (b) x-only public keys (32 bytes, saving 1 byte per key); (c) key-path spending (a single signature validates against the output key, with no script revealed); (d) script-path spending via a Merkle tree of TapScripts, revealing only the executed script leaf. Together, these allow complex spending conditions (multisig, timelocks, hash-locks) to be hidden behind a single public key that, in the common case, looks indistinguishable from a simple single-signature spend.

← Ch. 7 Ch. 9 →