In a previous article we documented what some of the standard Bitcoin transactions are. In 2015, the Bitcoin developers came up with a number of improvements commonly referred to as a Segregated Witness – SegWit. The overall process was standardized mostly in BIP141, BIP143 and few others.

SegWit's main intention was to remove transaction's signature out of the scriptSig (for a number of reasons) and move it to another designated field, called witness. This led to the introduction of two new types, which we cover in this second article.

SegWit transactions

A scriptPubKey that consists of a 1-byte push opcode followed by a data push between 2 and 40 bytes gets a special meaning. In another words, if a number between 0 to 16 is pushed onto the stack[1] and then some more data between 2 and 40 bytes are, the upgraded nodes recognize this as a SegWit transaction.

A general native SegWit transaction looks like this:

ScriptPubKey: <1 byte witness version> <2-40 bytes witness program>
ScriptSig: (empty)
Witness: <witness items>

A non-upgraded node sees this as a ANYONE_CAN_SPEND transaction, because the scriptPubKey is just a push of some data and doesn't lay any conditions on the reciever. That's why the scriptSig can be empty and it is a valid tranaction on older nodes.

In SegWit world, the first value in the scriptPubKey is interpreted as a witness version and the second is a witness protected program, or just a witness program for short. The version flag denotes, how the witness program is evaluated. If a node encounters a witness version that it is unfamiliar with, it considers the transaction again as a ANYONE_CAN_SPEND, which allows further soft-fork compatible upgrades. As of today, there is only one witness version – version 0, so we are solely devoted to this version in this article.

When SegWit-aware node recognizes a witness version it supports, it interprets its witness program. In version 0 this starts of by checking the length of the witness program. If it is equal to 20 bytes, it is interpreted as a P2WPKH; if 32 bytes, it is a P2WSH. If it is neither 20 nor 32 bytes, it aborts. This is a version 0 convention hardcoded in the standard and the code itself.

P2WPKH (Pay-to-Witness-Public-Key-Hash)

This is the P2PKH described earlier, only SegWit upgraded.

ScriptPubKey: 0 <20-byte-PublicKeyHash>
ScriptSig: (empty)
Witness: <Signature> <PublicKey>

In P2WPKH the verification goes as follows:

  • Check that the witness contains exactly two items
  • Verify that HASH160 of the witness' public key is equal to the one present in the witness program
  • Verify the signature as <Signature> <PublicKey> OP_CHECKSIG

The length of the witness program (20 bytes) indicates that it is a P2WPKH type. Again, this is an arbitrary definition, hardcoded into the standard. There is no OP_CHECKSIG operand in neither scriptPubKey nor witness, it is implicit by the definition of P2WPKH.

P2WSH (Pay-to-Witness-Script-Hash)

Now, remember P2SH? There is a native version of the very same principle for SegWit.

ScriptPubKey: 0 <32-byte-redeemScriptHash>
ScriptSig: (empty)
Witness: <witness items> <redeemScript>

RedeemScript: (any)

The first 0 indicates a witness version 0. The following 32 bytes indicates that this is a P2WSH type. The last item in the witness is the redeemScript. It is hashed with SHA256, compared against the 32-byte redeemScriptHash in the scriptPubKey, and then executed alongside with the witness items.

If this seems a little bit too abstract, have a look at the BIP141 example, which is a 1-of-2 multi-signature P2WSH.

Both P2WPKH and P2WSH are not using the traditional base58 addresses, but a new bech32 format as defined in BIP173. The format is not covered in the scope of this article, see the standard for more information.

Those two represent so called native SegWit transaction types. To allow non-SegWit wallets to generate a SegWit transaction two additional types were introduced. It uses a P2SH transaction as the cornerstone and includes either P2WPKH or P2WSH inside it. If a SegWit-aware node sees a P2SH which contains P2WPKH or P2WSH it interprets it in the native way.

P2WPKH nested in P2SH

ScriptPubKey: OP_HASH160 <20-byte-redeemScriptHash> OP_EQUAL
ScriptSig: <0 <20-byte-PublicKeyHash>>
Witness: <Signature> <PublicKey>

RedeemScript: 0 <20-byte-PublicKeyHash>

The P2SH redeem script is equal to 0 <20-byte-PublicKeyHash> which is exactly the same as P2WPKH scriptPubKey. The scriptSig is somewhat confusing, it is a canonical push of data, which contain another canonical push of data.

Let's have a look how this evalutes on older nodes. They see the scriptSig as a push of some data – 0014{20-byte-PublicKeyHash}. Older nodes consider it as a simple redeemScript, which contains only a push of some data, weird redeemScript right? Then the scriptPubKey is concatenated and it does a HASH160 of the redeemScript and compares the result against the redeemScriptHash. Hurray, they match! So older nodes see this as a wierd P2SH ANYONE_CAN_SPEND transaction with no signature, where two hashes are compared and that's it.

As far as the upgraded nodes are concerned, they see this as as a P2SH transaction as well, but they recognize the meaning of the pushed data (0014{20-byte-PublicKeyHash}) and they interpret it as a P2WPKH.

P2WSH nested in P2SH

This is quite similar to P2WPKH in P2SH. It just doesn't nest a P2WPKH but a P2WSH.

ScriptPubKey: OP_HASH160 <20-byte-P2SH-RedeemScriptHash> OP_EQUAL
ScriptSig: <0 <32-byte-P2WSH-RedeemScriptHash>>
Witness: <witness items> <P2WSH-RedeemScript>

P2SH RedeemScript: <0 <32-byte-P2WSH-RedeemScriptHash>>
P2WSH RedeemScript: (any)

The redeem script can be any valid Script script, the very same concept as in P2SH.

  1. OP_x where x <= 16 is a Script command that pushes the value of x onto the stack. That is exactly what is used here. OP_0 for a witness version 0, OP_1 for future version 1 etc. In another words, we can specify the witness version in one single opcode. ↩︎