P2SH-P2WSH

P2WSH wrapped in a P2SH

BIP 141: Segregated Witness

A diagram showing the structure of the P2SH-P2WSH locking and unlocking code.

P2SH-P2WSH (also known as Nested P2WSH) is a locking script type that wraps a modern P2WSH inside a legacy P2SH.

It allows you to send bitcoins to a legacy 3address (P2SH), but later take advantage of the cheaper transaction fee costs that come from spending a modern P2WSH output.

Therefore, P2SH-P2WSH provides a stepping-stone until wallets and exchanges support sending directly to bc1qaddresses.

There's no reason to use P2SH-P2WSH if you have the option to use P2WSH directly. P2SH-P2WSH is only useful if you cannot send to a bc1qaddress from your wallet or exchange, but can send to a 3address instead.

Purpose

Why does P2SH-P2WSH exist?

A diagram showing P2SH-P2WSH being used to send bitcoins from a wallet/exchange that does not support sending to P2WSH.

A P2SH-P2WSH serves the same purpose as a P2SH-P2WPKH.

You can send bitcoins to a 3address (P2SH), but then unlock them later on as if you used a modern P2WSH.

This allows you to take advantage of the discount offered by unlocking an output via the Witness, even if the wallet or exchange you are using does not allow you to send to a bc1qaddress (P2WSH) directly.

It makes the unlocking of a P2SH-P2WSH more complex from a technical point of view, but it gives you the benefit of cheaper transaction fees if P2WSH is not an option.

Usage

How does P2SH-P2WSH work?

A P2SH-P2WSH (aka Nested P2WSH) uses both the ScriptSig and Witness field to be unlocked.

ScriptPubKey

A diagram showing the structure of the ScriptPubKey for a P2SH-P2WSH.

The ScriptPubKey is a standard P2SH locking script. For example:

OP_HASH160
OP_PUSHBYTES_20
257014cec2f75c19367b2a6a0e08b9f304108e3b
OP_EQUAL
a914257014cec2f75c19367b2a6a0e08b9f304108e3b87

Transaction: c57007980fabfd7c44895d8fc2c28c6ead93483b7c2bfec682ce0a3eaa4008ce (Output 0)

The script hash is the HASH160 of a P2WSH ScriptPubKey. For example:

P2WSH ScriptPubKey: 0020973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f
HASH160:            257014cec2f75c19367b2a6a0e08b9f304108e3b

The original P2WSH ScriptPubKey will be revealed in the upcoming ScriptSig.

The fact that P2SH-P2WSH uses a standard P2SH ScriptPubKey is what makes it backwards-compatible. Most wallets and exchanges should support sending to a P2SH (3address).

ScriptSig

A diagram showing the structure of the ScriptSig for a P2SH-P2WSH.

The ScriptSig contains a 34-byte data push of a P2WSH ScriptPubKey.

OP_PUSHBYTES_34
0020973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f
220020973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f

Transaction: 55c7c71c63b87478cd30d401e7ca5344a2e159dc8d6990df695c7e0cb2f82783 (Input 0)

This data push is a complete P2WSH ScriptPubKey. In other words, it's the ScriptPubKey you would have used if you were using P2WSH directly.

For the execution of this script type to continue successfully, the HASH160 of this data push must match the script hash in the ScriptPubKey.

tool-683b3120929a6
Tool Icon

HASH160

SHA-256 + RIPEMD-160. Used for shortening a public key or script before converting to an address.

A public key or script for example

0 bytes
Hash Function Icon SHA-256
Hash Function Icon RIPEMD-160

RIPEMD-160(SHA-256(data))

0 bytes
0 secs

The fact that the ScriptSig contains a further P2WSH ScriptPubKey inside it is why this is sometimes referred to as a "Nested P2WSH".

Witness

A diagram showing the structure of the Witness field for a P2SH-P2WSH.

The Witness field contains the data required to unlock the P2WSH ScriptPubkey nested inside the ScriptSig.

00
3044022047ebba593cba4048da04316b9fb6c076d95d17175d7560edc93868a7d170767502203d0ce939ae462ca685a15f5fd3a64b7a1793cb10473665d5bedd3322c55a2b1001
3044022022a8a0ae1f80934abb38d4f8c3febf6f5c5c43e7e70460aa71f9a895aaea4d950220023b8f4d2fd90abdbe6f80c9bcb2b38c7326e5e9e0f3b1ea25a5499d240cacb201
522103591da02bf7c80dc5d0edee4bbbfad7e58320785e3e54d4dab117152361f7002c21027ea2bc65ce49dcd748e4e41a0c8881be388b9182ad5e47579a0de0119803827b2103c5fdaf887f76119a73a7f738d5d4a451ff07bbbc83422c529452d8a36ae59e3953ae
{
  "stackitems": "04",
  "0": {
    "size": "00",
    "item": ""
  },
  "1": {
    "size": "47",
    "item": "3044022047ebba593cba4048da04316b9fb6c076d95d17175d7560edc93868a7d170767502203d0ce939ae462ca685a15f5fd3a64b7a1793cb10473665d5bedd3322c55a2b1001"
  },
  "2": {
    "size": "47",
    "item": "3044022022a8a0ae1f80934abb38d4f8c3febf6f5c5c43e7e70460aa71f9a895aaea4d950220023b8f4d2fd90abdbe6f80c9bcb2b38c7326e5e9e0f3b1ea25a5499d240cacb201"
  },
  "3": {
    "size": "69",
    "item": "522103591da02bf7c80dc5d0edee4bbbfad7e58320785e3e54d4dab117152361f7002c21027ea2bc65ce49dcd748e4e41a0c8881be388b9182ad5e47579a0de0119803827b2103c5fdaf887f76119a73a7f738d5d4a451ff07bbbc83422c529452d8a36ae59e3953ae"
  }
}
0400473044022047ebba593cba4048da04316b9fb6c076d95d17175d7560edc93868a7d170767502203d0ce939ae462ca685a15f5fd3a64b7a1793cb10473665d5bedd3322c55a2b1001473044022022a8a0ae1f80934abb38d4f8c3febf6f5c5c43e7e70460aa71f9a895aaea4d950220023b8f4d2fd90abdbe6f80c9bcb2b38c7326e5e9e0f3b1ea25a5499d240cacb20169522103591da02bf7c80dc5d0edee4bbbfad7e58320785e3e54d4dab117152361f7002c21027ea2bc65ce49dcd748e4e41a0c8881be388b9182ad5e47579a0de0119803827b2103c5fdaf887f76119a73a7f738d5d4a451ff07bbbc83422c529452d8a36ae59e3953ae

Transaction: 55c7c71c63b87478cd30d401e7ca5344a2e159dc8d6990df695c7e0cb2f82783 (Input 0)

The structure of the Witness field for a P2SH-P2WSH is exactly the same as it is for a direct P2WSH.

First of all, the SHA-256 hash of the Witness Script needs to match the 32-byte script hash in the P2WSH ScriptPubKey (in the ScriptSig). For example:

Witness Script: 522103591da02bf7c80dc5d0edee4bbbfad7e58320785e3e54d4dab117152361f7002c21027ea2bc65ce49dcd748e4e41a0c8881be388b9182ad5e47579a0de0119803827b2103c5fdaf887f76119a73a7f738d5d4a451ff07bbbc83422c529452d8a36ae59e3953ae
SHA-256:        973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f

From here, the Witness is executed like a normal P2WSH.

In this example, the Witness Script is a 2-of-3 multisig locking script, and the script inputs before it are the signatures required to unlock it. But seeing as you can use any custom locking script you like as the Witness Script, this witness field could look completely different and require a different number (and size) of script inputs.

tool-683b312092ba6
Tool Icon

Script

Decode and encode a script.

 
Decrease Text Box Size Increase Text Box Size
0 bytes
0 characters
0 secs

The Witness Script within a P2WSH is equivalent to the Redeem Script in a P2SH. They both refer to the data that reveals the actual custom locking script that sets the conditions for unlocking the output.

The script hashes used in P2SH and P2WSH are created using different hash functions:

Therefore, within a P2SH-P2WSH:

I can see why this is confusing. But ultimately, you're performing a "Pay to Script Hash" style locking script twice, as you've got a P2WSH wrapped in a legacy P2SH, and the script hashes for each are created using different hash functions.

Costs

How much cheaper is it to use P2SH-P2WSH over legacy P2SH?

The following table shows the number of bytes required to unlock a comparable legacy P2SH, P2SH-P2WSH, and modern P2WSH.

You can use any kind of custom locking script you like when using a "Pay to Script Hash" style lock, so I've chosen examples that use a 2-of-3 multisig as the Redeem Script (also known as the Witness Script in P2SH-P2WSH and P2WSH).

These are the inputs I've used as examples:

Script Type ScriptSig (bytes) Witness (bytes) Total (bytes)
P2SH 252 0 252
P2SH-P2WSH 35 252 287
P2WSH 0 252 252

Note: The size of signatures can vary slightly in size, but all of the signatures in these examples are 71 bytes.

As you can see, P2SH-P2WSH requires more bytes to unlock than a legacy P2SH or modern P2WSH.

However, the size calculation of a transaction was adjusted during the Segregated Witness upgrade to use virtual bytes instead. This new virtual bytes measurement gives a discount to the bytes in the witness field, where each byte in the witness only takes up 0.25 virtual bytes of space.

The following table shows the number of virtual bytes required to unlock the same scripts:

Script Type ScriptSig (virtual bytes) Witness (virtual bytes) Total (virtual bytes)
P2SH 252 0 252
P2SH-P2WSH 35 63 98
P2WSH 0 63 63

Note: The number of bytes in the witness have been multiplied by 0.25.

So even though spending a P2SH-P2WSH requires more bytes overall, the discount given to the bytes in the witness field means that a P2SH-P2WSH uses fewer virtual bytes compared to a legacy P2SH.

And seeing as the amount you pay in transaction fees is calculated in sats per virtual byte, it works out cheaper to spend a P2SH-P2WSH than a legacy P2SH.

You get the benefits of segwit (with a small penalty, the P2SH wrapping has a cost), but you get to receive coins from senders who do not support native segwit addresses.
Pieter Wuille, bitcoin.stackexchange.com

P2WSH is the cheapest. But if that's not an option, P2SH-P2WSH is cheaper than legacy P2SH.

Sending

There is a slight difference in the amount of space used when sending bitcoins to a P2SH, P2SH-P2WSH, or P2WSH.

This is the number of bytes required to lock an output (i.e. "send") to each of these ScriptPubKey patterns:

Script Type ScriptPubKey (bytes)
P2SH 23
P2SH-P2WSH 23
P2WSH 34

And seeing as the ScriptPubKey field does not get a discount, they take up the same amount of space in terms of virtual bytes:

Script Type ScriptPubKey (virtual bytes)
P2SH 23
P2SH-P2WSH 23
P2WSH 34

So as you can see, it's actually a bit more "expensive" to send to a modern P2WSH than it is to send to a legacy P2SH or P2SH-P2WSH. This is due to the fact that the script hash for a P2WSH is created using SHA-256 (32 bytes), whereas the script hash for a P2SH is created using HASH160 (20 bytes).

But this is a negligible difference, and the improved security due to the lower chance of a collision is the reason behind the change in hash function used to create the script hash for a P2WSH.

Multisig payments currently use P2SH which is secured by the 160-bit HASH160 algorithm (RIPEMD of SHA256). However, if one of the signers wishes to steal all the funds, they can find a collision between a valid address as part of a multisig script and a script that simply pays them all the funds with only 80-bits (280) worth of work, which is already within the realm of possibility for an extremely well-resourced attacker.

Segwit resolves this by using HASH160 only for payments direct to a single public key (where this sort of attack is useless), while using 256-bit SHA256 hashes for payments to a script hash.

bitcoincore.org

Address

How do you create an address for a P2SH-P2WSH?

Diagram showing how to encode a P2SH-P2WSH to an address.

P2SH-P2WSH locking scripts have a 3address.

This is because it uses P2SH for the ScriptPubKey, so it has the same address format as any other P2SH.

To create the address, you start by constructing the P2WSH ScriptPubKey you want to use. You then hash this using HASH160 to create the 20-byte script hash. Finally, you Base58Check encode this script hash using the prefix 05 to signify a P2SH address (which is what gives it a 3 at the start of the address).

tool-683b312092f54
Tool Icon

Address (Base58)

Encode the hash160 of a public key or script to a legacy address.

1 byte
Type
0 bytes
0 bytes

Base58 encoding of the above data

0 characters
0 secs

For example, the hex-encoding of the P2WSH ScriptPubKey placed in the ScriptSig in the example above is:

0020973cfd44e60501c38320ab1105fb3ee3916d2952702e3c8cb4cbb7056aa6b47f

tool-683b312092f66
Tool Icon

Script

Decode and encode a script.

 
Decrease Text Box Size Increase Text Box Size
0 bytes
0 characters
0 secs

If we hash this using HASH160 we get:

257014cec2f75c19367b2a6a0e08b9f304108e3b

tool-683b312093115
Tool Icon

HASH160

SHA-256 + RIPEMD-160. Used for shortening a public key or script before converting to an address.

A public key or script for example

0 bytes
Hash Function Icon SHA-256
Hash Function Icon RIPEMD-160

RIPEMD-160(SHA-256(data))

0 bytes
0 secs

And if we convert this to Base58Check using the prefix 05 we get:

356yCBhiW9tqg5iiPDhEZ8f8t3JfqkEihA

tool-683b31209315e
Tool Icon

Base58Check

Create a checksum for data and then encode to base58.

0 bytes
Expected:
0 characterss
0 secs

It's not possible to identify a P2SH-P2WSH from the address alone. The only way you can identify that a 3address uses Nested P2WSH is when it gets spent, as that's when it reveals the P2WSH locking script wrapped inside the ScriptSig.

Summary

P2SH-P2WSH is a sister to the P2SH-P2WPKH locking script.

In short, it allows you to send bitcoins to a 3address, but then unlock them as if you used a native P2WSH.

It's a bit of a funny script, as P2WSH is the modern version of P2SH, and both are used for custom locking scripts. And to be able to use use P2WSH whilst sending to a P2SH, you need to wrap the modern method (P2WSH) within the legacy method (P2SH). So in other words, you've got a custom locking script within a custom locking script.

Yo dawg meme for P2SH-P2WSH - 'Yo Dawg, I herd you like Bitcoin Script. So I put a custom locking script in your custom locking script so you can script while you script'.

To put it another way, it's like the film Inception, but with Bitcoin Script.

If you still find it confusing (I don't blame you), I'd recommend learning how P2SH and P2WSH work separately first. They both use a similar unlocking mechanism, but with P2SH-P2WSH you've got one wrapped inside the other, so you've got 2 layers of a similar type of unlocking mechanism.

Good luck.

Resources