From 926b2b4a6e69578723faec0bae5dadc313ef3f63 Mon Sep 17 00:00:00 2001 From: ecbsj <61910547+ECBSJ@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:48:50 +0800 Subject: [PATCH] added standard payment scripts --- .vitepress/config.js | 30 +++++++ script/index.md | 2 +- script/standard-payment-scripts/P2PK.md | 62 +++++++++++++ script/standard-payment-scripts/P2PKH.md | 55 ++++++++++++ .../standard-payment-scripts/P2SH-P2WPKH.md | 72 ++++++++++++++++ script/standard-payment-scripts/P2SH.md | 57 ++++++++++++ script/standard-payment-scripts/P2TR.md | 86 +++++++++++++++++++ script/standard-payment-scripts/P2WPKH.md | 65 ++++++++++++++ script/standard-payment-scripts/P2WSH.md | 69 +++++++++++++++ 9 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 script/standard-payment-scripts/P2PK.md create mode 100644 script/standard-payment-scripts/P2PKH.md create mode 100644 script/standard-payment-scripts/P2SH-P2WPKH.md create mode 100644 script/standard-payment-scripts/P2SH.md create mode 100644 script/standard-payment-scripts/P2TR.md create mode 100644 script/standard-payment-scripts/P2WPKH.md create mode 100644 script/standard-payment-scripts/P2WSH.md diff --git a/.vitepress/config.js b/.vitepress/config.js index 1278b83..84234b6 100644 --- a/.vitepress/config.js +++ b/.vitepress/config.js @@ -277,6 +277,36 @@ export default { { text: "ASM Representation", link: "/script/asm.md" }, { text: "Push Operators", link: "/script/push.md" }, { text: "Numbers in Script", link: "/script/numbers.md" }, + { text: "Standard Payment Scripts", collapsed: false, items: [ + { + text: "P2PK", + link: "/script/standard-payment-scripts/P2PK.md" + }, + { + text: "P2PKH", + link: "/script/standard-payment-scripts/P2PKH.md" + }, + { + text: "P2SH", + link: "/script/standard-payment-scripts/P2SH.md" + }, + { + text: "P2SH-P2WPKH", + link: "/script/standard-payment-scripts/P2SH-P2WPKH.md" + }, + { + text: "P2WPKH", + link: "/script/standard-payment-scripts/P2WPKH.md" + }, + { + text: "P2WSH", + link: "/script/standard-payment-scripts/P2WSH.md" + }, + { + text: "P2TR", + link: "/script/standard-payment-scripts/P2TR.md" + } + ] } ] }, diff --git a/script/index.md b/script/index.md index 94c9676..a96da4c 100644 --- a/script/index.md +++ b/script/index.md @@ -1,2 +1,2 @@ # Bitcoin Script -The pages in this section explore the bitcoin scripting system. +The pages in this section explore the bitcoin scripting system. \ No newline at end of file diff --git a/script/standard-payment-scripts/P2PK.md b/script/standard-payment-scripts/P2PK.md new file mode 100644 index 0000000..5672fc4 --- /dev/null +++ b/script/standard-payment-scripts/P2PK.md @@ -0,0 +1,62 @@ +# P2PK + +:::info +**Script Type:** Pay-to-PubKey (P2PK) +**Byte representation:** `0x21` + pubkey + `0xac` (compressed) or `0x41` + pubkey + `0xac` (uncompressed) +**Address format:** None — P2PK has no standard Bitcoin address encoding +**Short description:** A script that locks funds directly to a public key. +::: + +Pay-to-PubKey (P2PK) is one of the simplest and oldest Bitcoin payment scripts. It locks funds directly to a public key, requiring a valid signature from the corresponding private key to spend them. + +### Historical Context + +P2PK is the original Bitcoin payment script used by Satoshi Nakamoto in the genesis block and in early coinbase outputs. In those early days, uncompressed 65-byte public keys were the norm; compressed 33-byte keys became standard later. P2PK has since been superseded by P2PKH, which improves privacy by withholding the public key from the locking script. Notably, P2PK has no standard address format — funds locked in P2PK outputs cannot be represented as a traditional Bitcoin address. + +### Operation + +**Locking (ScriptPubKey):** +1. The recipient's public key is embedded directly in the script. +2. `OP_CHECKSIG` signals that a valid signature will be required to spend. + +**Unlocking (ScriptSig):** +1. The spender pushes a DER-encoded signature (appended with a sighash type byte) onto the stack. +2. `OP_CHECKSIG` pops the signature and the public key, verifies the ECDSA signature against the transaction data, and pushes `1` (true) if valid or `0` (false) if not. +3. If the result is `0`, the script fails. + +### Notes + +- P2PK exposes the public key in the locking script itself, making it visible on-chain before any spending occurs. P2PKH only reveals the public key at spend time. +- There is no P2PK address format. You cannot represent a P2PK output as a standard Base58Check or bech32 address. +- Uncompressed public keys (65 bytes, prefix `04`) were common in early Bitcoin. Compressed keys (33 bytes, prefix `02` or `03`) are standard today. +- A large amount of early Bitcoin — including Satoshi's coinbase rewards — is locked in P2PK outputs. Their public keys are already visible on-chain, making them potentially vulnerable to future quantum computing attacks. + +### Example + +#### ScriptPubKey + +```shell +# ASM (compressed pubkey) +<33-byte-pubkey> OP_CHECKSIG + +# ASM (uncompressed pubkey, early Bitcoin) +<65-byte-pubkey> OP_CHECKSIG + +# Raw bytes (compressed) +21 <33-byte-pubkey> ac + +# Raw bytes (uncompressed) +41 <65-byte-pubkey> ac +``` + +#### ScriptSig + +```shell +# ASM + + +# Raw bytes +# Signature is DER-encoded + 1-byte sighash type (01 = SIGHASH_ALL) + 01 +# Example: 48 <71-byte DER sig> 01 +``` diff --git a/script/standard-payment-scripts/P2PKH.md b/script/standard-payment-scripts/P2PKH.md new file mode 100644 index 0000000..9e77c3d --- /dev/null +++ b/script/standard-payment-scripts/P2PKH.md @@ -0,0 +1,55 @@ +# P2PKH + +:::info +**Script Type:** Pay-to-PubKey-Hash (P2PKH) +**Byte representation:** `0x76 0xa9 0x14` + 20-byte hash + `0x88 0xac` +**Address format:** Base58Check encoded, starts with `1` (mainnet) +**Short description:** A script that locks funds to the HASH160 of a public key. +::: + +Pay-to-PubKey-Hash (P2PKH) is the most widely used legacy Bitcoin payment script. It locks funds to the HASH160 (RIPEMD160 of SHA256) of a public key, requiring the spender to reveal the public key and provide a valid signature to unlock the funds. + +### Historical Context + +P2PKH was introduced early in Bitcoin's history as an improvement over P2PK. By hashing the public key, it keeps the key hidden until spend time — improving both privacy and efficiency. P2PKH addresses are Base58Check encoded and start with `1` on mainnet (e.g. `1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf Na`). This was the dominant address format until native SegWit addresses were introduced in 2017. + +### Operation + +1. The ScriptPubKey contains the HASH160 of the recipient's public key (always 20 bytes). +2. `OP_DUP` duplicates the top stack item (the public key provided in the ScriptSig). +3. `OP_HASH160` hashes the duplicate: first SHA256, then RIPEMD160, producing a 20-byte hash. +4. The 20-byte expected hash from the script is pushed onto the stack. +5. `OP_EQUALVERIFY` checks that the computed hash matches. If not, the script fails immediately. +6. `OP_CHECKSIG` verifies the signature against the original (non-hashed) public key. Pushes `1` if valid. + +### Notes + +- P2PKH improves privacy over P2PK: the public key is only revealed when funds are spent, not when they are received. +- The pubkey hash is always 20 bytes — the result of HASH160 (SHA256 then RIPEMD160). It is pushed in the raw script using opcode `0x14` (push 20 bytes). +- On mainnet, P2PKH addresses start with `1` due to the Base58Check version byte `0x00`. +- Once a P2PKH address has been spent from, the public key becomes visible on-chain. Reusing the same address after spending weakens privacy and exposes the public key to future scrutiny. + +### Example + +#### ScriptPubKey + +```shell +# ASM +OP_DUP OP_HASH160 <20-byte-pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG + +# Raw bytes +76 a9 14 <20-byte-pubkeyhash> 88 ac +# 76 = OP_DUP, a9 = OP_HASH160, 14 = push 20 bytes, 88 = OP_EQUALVERIFY, ac = OP_CHECKSIG +``` + +#### ScriptSig + +```shell +# ASM + + +# Raw bytes (compressed pubkey example) + 01 21 <33-byte-pubkey> +# siglen: typically 0x47 or 0x48 (71 or 72 bytes incl. sighash type) +# 21 = push 33 bytes (compressed pubkey, prefix 02 or 03) +``` diff --git a/script/standard-payment-scripts/P2SH-P2WPKH.md b/script/standard-payment-scripts/P2SH-P2WPKH.md new file mode 100644 index 0000000..45f1961 --- /dev/null +++ b/script/standard-payment-scripts/P2SH-P2WPKH.md @@ -0,0 +1,72 @@ +# P2SH-P2WPKH + +:::info +**Script Type:** Pay-to-Script-Hash of Pay-to-Witness-PubKey-Hash (P2SH-P2WPKH) +**Byte representation:** `0xa9 0x14` + 20-byte hash + `0x87` (ScriptPubKey — identical to P2SH) +**Address format:** Base58Check encoded, starts with `3` (mainnet) — indistinguishable from a plain P2SH address +**Short description:** A wrapped SegWit script: a P2SH address that embeds a native P2WPKH witness program. +::: + +P2SH-P2WPKH is a "wrapped SegWit" format introduced alongside SegWit to allow SegWit adoption on wallets and services that only supported legacy P2SH addresses. It wraps a P2WPKH witness program inside a standard P2SH locking script. The actual signature and public key travel in the **witness** field, not the ScriptSig. + +### Historical Context + +SegWit (BIP 141) was activated on mainnet in August 2017. To ease the transition, BIP 49 defined P2SH-P2WPKH as a compatibility bridge: it uses a `3...` address (familiar to wallets and exchanges) but takes advantage of the SegWit witness structure under the hood. This allowed services to send to SegWit-compatible wallets without needing to support the new bech32 address format. Today, native P2WPKH (bech32 `bc1q...`) is preferred for lower fees and cleaner semantics. + +### Operation + +P2SH-P2WPKH has three layers: + +1. **ScriptPubKey** — a standard P2SH script containing the HASH160 of the redeem script. +2. **ScriptSig** — contains *only* the serialized redeem script, which is the P2WPKH witness program: `OP_0 <20-byte-pubkeyhash>`. +3. **Witness** — contains the signature and public key, exactly as in native P2WPKH. + +**Spending flow:** +1. The script engine sees a standard P2SH ScriptPubKey: `OP_HASH160 OP_EQUAL`. +2. The ScriptSig provides only the redeem script (`OP_0 `). The engine hashes it and verifies the match. +3. The redeem script is recognized as a version-0 witness program (22 bytes: `00 14 <20-byte-hash>`). +4. The witness field is evaluated as P2WPKH: `OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG` is run against the witness `` and ``. +5. If all checks pass, the script succeeds. + +### Notes + +- The ScriptPubKey is structurally identical to a regular P2SH output — you cannot distinguish P2SH-P2WPKH from plain P2SH by the address alone. +- The ScriptSig contains **only** the redeem script. Signatures and public keys go in the witness field. +- Witness data benefits from the SegWit weight discount (1 weight unit per byte instead of 4), making transactions cheaper. +- BIP 49 defines the HD wallet derivation path for P2SH-P2WPKH: `m/49'/0'/0'/account'/change/index`. +- This format is considered a transitional compatibility layer. New wallets should prefer native P2WPKH with bech32 addresses. + +### Example + +#### ScriptPubKey + +```shell +# ASM (standard P2SH — identical structure to any P2SH output) +OP_HASH160 <20-byte-hash-of-redeem-script> OP_EQUAL + +# Raw bytes +a9 14 <20-byte-hash-of-redeem-script> 87 +``` + +#### ScriptSig + +```shell +# ASM (only the redeem script — the P2WPKH witness program) +OP_0 <20-byte-pubkeyhash> + +# Raw bytes (the 22-byte redeem script pushed as a single data item) +16 00 14 <20-byte-pubkeyhash> +# 16 = push 22 bytes, 00 = OP_0, 14 = push 20 bytes +``` + +#### Witness + +```shell +# Two items in the witness stack (not in the ScriptSig) + + + +# Example (compressed pubkey) + 01 # sig + SIGHASH_ALL byte +21 <33-byte-compressed-pubkey> # 21 = push 33 bytes +``` diff --git a/script/standard-payment-scripts/P2SH.md b/script/standard-payment-scripts/P2SH.md new file mode 100644 index 0000000..83fa9cc --- /dev/null +++ b/script/standard-payment-scripts/P2SH.md @@ -0,0 +1,57 @@ +# P2SH + +:::info +**Script Type:** Pay-to-Script-Hash (P2SH) +**Byte representation:** `0xa9 0x14` + 20-byte hash + `0x87` +**Address format:** Base58Check encoded, starts with `3` (mainnet) +**Short description:** A script that locks funds to the HASH160 of a redeem script. +::: + +Pay-to-Script-Hash (P2SH) allows funds to be locked to the HASH160 of an arbitrary redeem script. At spend time, the spender reveals the redeem script and provides all inputs needed to satisfy it. + +### Historical Context + +P2SH was introduced in BIP 16, activated in March 2012. Before P2SH, complex spending conditions (like multisig) required embedding the full script in the ScriptPubKey, which was costly and burdensome for the sender. P2SH shifts that complexity to the spender: the sender only needs to know a 20-byte hash, while the spender provides the full script. P2SH addresses are Base58Check encoded and start with `3` on mainnet (e.g. `3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy`). It is still widely used today for multisig wallets and as a wrapper for SegWit outputs (P2SH-P2WPKH, P2SH-P2WSH). + +### Operation + +1. The ScriptPubKey contains the HASH160 of the redeem script (always 20 bytes). +2. To spend, the ScriptSig must push: + - All arguments required to satisfy the redeem script (e.g. signatures for a multisig). + - The serialized redeem script itself as the **final** pushed item. +3. The script engine hashes the top stack item (the redeem script) and checks it matches the hash in the ScriptPubKey via `OP_EQUAL`. +4. If the hash matches, the redeem script is deserialized and executed with the remaining stack items as inputs. +5. If execution of the redeem script succeeds with a truthy top value, the script passes. + +### Notes + +- The serialized redeem script must always be the **last** item pushed in the ScriptSig. +- The script hash is always 20 bytes (HASH160 output), pushed in the raw ScriptPubKey using `0x14` (push 20 bytes). +- P2SH shifts the transaction size cost and script encoding complexity to the spender rather than the sender. +- On mainnet, P2SH addresses start with `3` due to the Base58Check version byte `0x05`. +- P2SH is also used as a SegWit compatibility wrapper: P2SH-P2WPKH and P2SH-P2WSH wrap native SegWit witness programs inside a P2SH address. + +### Example + +#### ScriptPubKey + +```shell +# ASM +OP_HASH160 <20-byte-scripthash> OP_EQUAL + +# Raw bytes +a9 14 <20-byte-scripthash> 87 +# a9 = OP_HASH160, 14 = push 20 bytes, 87 = OP_EQUAL +``` + +#### ScriptSig + +```shell +# ASM (example: 2-of-3 multisig redeem script) +OP_0 + +# Raw bytes +00 +# OP_0 is required due to a known off-by-one bug in OP_CHECKMULTISIG +# The redeem script is always the last pushed item +``` diff --git a/script/standard-payment-scripts/P2TR.md b/script/standard-payment-scripts/P2TR.md new file mode 100644 index 0000000..8752db7 --- /dev/null +++ b/script/standard-payment-scripts/P2TR.md @@ -0,0 +1,86 @@ +# P2TR + +:::info +**Script Type:** Pay-to-Taproot (P2TR) +**Byte representation:** `0x51 0x20` + 32-byte x-only tweaked pubkey (always 34 bytes total) +**Address format:** bech32m encoded, starts with `bc1p` (mainnet) +**Short description:** A SegWit v1 script that locks funds to a Taproot tweaked x-only public key, supporting both key path and script path spending. +::: + +Pay-to-Taproot (P2TR) is the most expressive Bitcoin payment type available today. It locks funds to a 32-byte x-only public key that commits to both a key path (a single Schnorr signature) and an optional Merkle tree of spending scripts. Unexercised script branches are never revealed on-chain. + +### Historical Context + +P2TR was introduced by the Taproot soft fork, which bundled three BIPs: BIP 340 (Schnorr Signatures), BIP 341 (Taproot), and BIP 342 (Tapscript). It activated on mainnet in November 2021 at block 709632. Taproot replaced ECDSA with Schnorr signatures, enabling key and signature aggregation schemes like MuSig2. P2TR addresses use bech32m encoding (BIP 350) and start with `bc1p` on mainnet. BIP 86 defines the HD wallet derivation path: `m/86'/0'/0'`. + +### Operation + +P2TR supports two spending paths: + +**Key path spend:** +1. The ScriptPubKey contains `OP_1 <32-byte-tweaked-x-only-pubkey>`. +2. The ScriptSig is **empty**. +3. The spender provides a single 64-byte Schnorr signature in the witness field. +4. The signature is verified against the tweaked public key using BIP 340 Schnorr verification. If valid, the script succeeds. + +**Script path spend:** +1. Same ScriptPubKey — only the witness data differs. +2. The spender provides in the witness: all inputs required by the leaf script, the leaf script itself, and a control block. +3. The control block encodes the internal public key and a Merkle proof demonstrating that the leaf script is committed to by the output key. +4. The script engine verifies the Merkle proof, then executes the leaf script with the provided inputs. +5. If the script executes successfully, the spend is valid. + +### Notes + +- The output key is a *tweaked* key: `Q = P + t·G`, where `t = HASH(P || merkle_root)`. This mathematically commits all script paths into the key itself. +- If no script paths are needed, the key is tweaked with just the internal key hash, resulting in a key-path-only output that is indistinguishable on-chain from one with a full script tree. +- All unexercised script branches remain private — only the executed path (or none, for key path) is ever revealed. +- Schnorr signatures (BIP 340) are 64 bytes, more compact than DER-encoded ECDSA, and enable key aggregation. +- The ScriptSig is always **empty** for P2TR. +- All P2TR outputs look identical on-chain regardless of the underlying script tree, improving privacy for all users. +- BIP 86 derivation path: `m/86'/0'/0'/account'/change/index`. + +### Example + +#### ScriptPubKey + +```shell +# ASM +OP_1 <32-byte-x-only-tweaked-pubkey> + +# Raw bytes (always 34 bytes) +51 20 <32-byte-x-only-tweaked-pubkey> +# 51 = OP_1 (witness version 1), 20 = push 32 bytes +``` + +#### ScriptSig + +```shell +# Always empty for P2TR +(empty) +``` + +#### Witness — Key Path Spend + +```shell +# Single Schnorr signature (64 bytes) +<64-byte-schnorr-sig> + +# With non-default sighash type appended (optional) +<64-byte-schnorr-sig> +# SIGHASH_DEFAULT (implicit) = commits to all inputs and outputs +``` + +#### Witness — Script Path Spend + +```shell +# Stack items required by the script, then the script, then the control block + ... + + + +# Control block structure: +# [leaf_version + output_key_parity (1 byte)] +# [internal_x_only_pubkey (32 bytes)] +# [merkle_proof_node_1 (32 bytes)] ... [merkle_proof_node_n (32 bytes)] +``` diff --git a/script/standard-payment-scripts/P2WPKH.md b/script/standard-payment-scripts/P2WPKH.md new file mode 100644 index 0000000..ace949a --- /dev/null +++ b/script/standard-payment-scripts/P2WPKH.md @@ -0,0 +1,65 @@ +# P2WPKH + +:::info +**Script Type:** Pay-to-Witness-PubKey-Hash (P2WPKH) +**Byte representation:** `0x00 0x14` + 20-byte pubkeyhash (always 22 bytes total) +**Address format:** bech32 encoded, starts with `bc1q` (mainnet) +**Short description:** A native SegWit v0 script that locks funds to the HASH160 of a public key. +::: + +Pay-to-Witness-PubKey-Hash (P2WPKH) is the native SegWit version of P2PKH. It moves the signature and public key into the transaction's witness field, leaving the ScriptSig empty and enabling a transaction weight discount. + +### Historical Context + +P2WPKH was introduced with SegWit (BIP 141), activated on mainnet in August 2017 at block 481824. It uses bech32 address encoding (BIP 173), producing addresses that start with `bc1q` on mainnet. BIP 84 defines the HD wallet derivation path for P2WPKH: `m/84'/0'/0'`. A key motivation for SegWit was eliminating transaction malleability — a long-standing issue where a third party could alter witness data and change a transaction's TXID before confirmation. This fix was a prerequisite for the Lightning Network. + +### Operation + +1. The ScriptPubKey contains a witness version byte (`OP_0`) followed by the 20-byte HASH160 of the recipient's public key. +2. The ScriptSig is **empty** — no data is placed there. +3. To spend, the witness field provides: + - A valid DER-encoded signature (+ sighash type byte). + - The compressed public key. +4. The script engine computes HASH160 of the provided public key and verifies it matches the hash in the ScriptPubKey. +5. `OP_CHECKSIG` verifies the signature against the transaction data and the public key. +6. If both checks pass, the script succeeds. + +### Notes + +- The ScriptSig is always **empty** for P2WPKH. All spending data is in the witness field. +- Witness bytes are counted at 1 weight unit instead of 4, making P2WPKH transactions cheaper than P2PKH. +- P2WPKH addresses use bech32 encoding and start with `bc1q` on mainnet. +- BIP 84 defines the derivation path: `m/84'/0'/0'/account'/change/index`. +- The pubkeyhash is always 20 bytes, produced by HASH160 (SHA256 then RIPEMD160 of the compressed public key). + +### Example + +#### ScriptPubKey + +```shell +# ASM +OP_0 <20-byte-pubkeyhash> + +# Raw bytes (always 22 bytes) +00 14 <20-byte-pubkeyhash> +# 00 = OP_0 (witness version 0), 14 = push 20 bytes +``` + +#### ScriptSig + +```shell +# Always empty for P2WPKH +(empty) +``` + +#### Witness + +```shell +# Two items in the witness stack + + + +# Example (compressed pubkey) + 01 # sig + SIGHASH_ALL byte +21 <33-byte-compressed-pubkey> # 21 = push 33 bytes +``` diff --git a/script/standard-payment-scripts/P2WSH.md b/script/standard-payment-scripts/P2WSH.md new file mode 100644 index 0000000..bbcdcf7 --- /dev/null +++ b/script/standard-payment-scripts/P2WSH.md @@ -0,0 +1,69 @@ +# P2WSH + +:::info +**Script Type:** Pay-to-Witness-Script-Hash (P2WSH) +**Byte representation:** `0x00 0x20` + 32-byte SHA256 witness script hash (always 34 bytes total) +**Address format:** bech32 encoded, starts with `bc1q` (mainnet) — longer than P2WPKH +**Short description:** A native SegWit v0 script that locks funds to the SHA256 hash of a witness script, enabling complex multi-party conditions with the SegWit weight discount. +::: + +Pay-to-Witness-Script-Hash (P2WSH) is the native SegWit equivalent of P2SH. It locks funds to the SHA256 hash of an arbitrary witness script. At spend time, the spender reveals the full witness script and all required inputs in the witness field, leaving the ScriptSig entirely empty. + +### Historical Context + +P2WSH was introduced with SegWit (BIP 141), activated on mainnet in August 2017. It serves the same role as P2SH — enabling complex scripts like multisig — but with two key improvements: the script hash is 32 bytes (SHA256 only, not HASH160), providing stronger collision resistance, and all witness data receives the SegWit weight discount. P2WSH addresses use bech32 encoding (BIP 173) and share the `bc1q` prefix with P2WPKH, but are 62 characters long compared to P2WPKH's 42. Like P2SH, P2WSH is also available in a wrapped form (P2SH-P2WSH) for backward compatibility with legacy wallets. + +### Operation + +1. The ScriptPubKey contains a witness version byte (`OP_0`) followed by the 32-byte SHA256 hash of the witness script. +2. The ScriptSig is **empty** — no data is placed there. +3. To spend, the witness field must provide: + - All inputs required by the witness script (e.g. signatures for a multisig). + - The full serialized witness script as the **last** item. +4. The script engine hashes the last witness item (the witness script) with SHA256 and verifies it matches the hash in the ScriptPubKey. +5. If the hash matches, the witness script is deserialized and executed with the remaining witness stack items as inputs. +6. If the witness script executes successfully with a truthy top value, the script passes. + +### Notes + +- The ScriptSig is always **empty** for P2WSH. All spending data goes in the witness field. +- P2WSH uses SHA256 (32 bytes) for its script hash, unlike P2SH which uses HASH160 (20 bytes). This provides stronger preimage resistance. +- The witness script must be the **last** item in the witness stack. +- Witness data benefits from the SegWit weight discount (1 weight unit per byte instead of 4), making complex scripts such as large multisigs significantly cheaper than their P2SH equivalents. +- P2WSH is commonly used for Lightning Network channel funding outputs and multisig wallets. +- P2WSH addresses start with `bc1q` on mainnet and are 62 characters long (vs. 42 for P2WPKH), making them visually distinguishable. + +### Example + +#### ScriptPubKey + +```shell +# ASM (e.g. for a 2-of-3 multisig witness script) +OP_0 <32-byte-sha256-witness-script-hash> + +# Raw bytes (always 34 bytes) +00 20 <32-byte-sha256-witness-script-hash> +# 00 = OP_0 (witness version 0), 20 = push 32 bytes +``` + +#### ScriptSig + +```shell +# Always empty for P2WSH +(empty) +``` + +#### Witness + +```shell +# Witness stack items: inputs required by the script + the witness script last +# Example: 2-of-3 multisig + +OP_0 # required due to off-by-one bug in OP_CHECKMULTISIG + + + + +# Where the witness script is the serialized redeem logic, e.g.: +# OP_2 OP_3 OP_CHECKMULTISIG +```