Witness Script
The spending conditions script placed in the segregated witness section of a transaction, separated from the scriptSig.
Key Takeaways
- A witness script is the spending conditions script revealed in the witness field of a P2WSH transaction: it is the SegWit equivalent of a P2SH redeem script, but placed in the segregated witness section instead of the scriptSig.
- Moving the script into the witness field fixes transaction malleability and qualifies for the witness discount, reducing effective transaction fees by up to 75%.
- Witness scripts are limited to 10,000 bytes under consensus rules (3,600 bytes under default standardness policy), while Taproot script-path spending uses tapscript instead, which removes both the size cap and the 201-opcode limit.
What Is a Witness Script?
A witness script is the Bitcoin Script program that defines the spending conditions for a Pay-to-Witness-Script-Hash (P2WSH) output. When someone creates a P2WSH output, the scriptPubKey commits only to the SHA-256 hash of the witness script. To spend that output, the owner must reveal the full witness script (along with the required signatures and public keys) inside the transaction's witness field.
The concept mirrors how P2SH works with redeem scripts: both output types commit to a hash of a script, and the spender reveals the script at spend time. The critical difference is where the script lives. In P2SH, the redeem script sits in the scriptSig. In P2WSH, the witness script sits in the segregated witness section, which was introduced by SegWit in August 2017 via BIP 141.
This separation provides two major benefits: it fixes transaction malleability (because the witness is excluded from the txid calculation), and it qualifies witness data for a fee discount (1 weight unit per byte instead of 4 for non-witness data).
How It Works
A P2WSH transaction involves two phases: creating the output that commits to the witness script hash, and spending that output by revealing the full script.
Creating a P2WSH Output
- The creator writes a Bitcoin Script defining the spending conditions (for example, a 2-of-3 multisig script)
- The script is hashed with SHA-256 to produce a 32-byte digest
- The scriptPubKey is set to:
OP_0 <32-byte SHA-256 hash>
The OP_0 prefix identifies this as a witness version 0 program. The 32-byte push length tells nodes this is a P2WSH output (a 20-byte push would indicate P2WPKH instead).
Spending a P2WSH Output
- The spender constructs the witness field with the input stack items (signatures, public keys) followed by the serialized witness script as the last item
- The node pops the witness script off the stack and computes its SHA-256 hash
- The node verifies that the hash matches the 32-byte witness program in the scriptPubKey
- If the hash matches, the node executes the witness script against the remaining witness stack items
- If execution succeeds (the stack result is truthy), the spend is valid
The scriptSig for a native P2WSH input must be empty. Any non-empty scriptSig causes the transaction to fail validation.
Witness Script Structure Example
A 2-of-3 multisig witness script and its corresponding P2WSH output:
# Witness script (the actual spending conditions)
OP_2 <pubkey_A> <pubkey_B> <pubkey_C> OP_3 OP_CHECKMULTISIG
# P2WSH scriptPubKey (commits to the hash)
OP_0 <SHA256(witness_script)>
# Witness field when spending
<> <sig_A> <sig_B> <witness_script>The empty item at the start of the witness field is the dummy element required by OP_CHECKMULTISIG due to a well-known off-by-one behavior in the original Bitcoin Script implementation.
Witness Script vs. Redeem Script
Both witness scripts and redeem scripts serve the same purpose: they define spending conditions that are revealed only at spend time. The differences come down to where they live and the rules that govern them:
| Property | Redeem Script (P2SH) | Witness Script (P2WSH) |
|---|---|---|
| Location | scriptSig field | Witness field |
| Hash algorithm | HASH160 (SHA-256 then RIPEMD-160) | SHA-256 only |
| Hash size | 20 bytes | 32 bytes |
| Script size limit | 520 bytes | 10,000 bytes (consensus) |
| Fee treatment | Full weight (4 WU/byte) | Discounted (1 WU/byte) |
| Malleability | Vulnerable | Fixed |
The larger 32-byte SHA-256 hash provides 128 bits of collision resistance, compared to 80 bits with HASH160. This matters for advanced scripts where multiple parties contribute to the spending conditions, as a collision attack could allow one party to substitute a different script. For a deeper look at how these address types evolved, see Bitcoin Address Types: P2PKH to Taproot.
Size Limits and Standardness
BIP 141 imposes a consensus limit of 10,000 bytes on witness scripts. Any witness script larger than this causes the transaction to be invalid regardless of whether it would otherwise execute correctly. This limit is separate from the 520-byte restriction on individual witness stack items, which applies to the input data pushed onto the stack (not to the script itself).
In practice, Bitcoin Core's default relay and mempool policy applies an even tighter standardness limit of 3,600 bytes. Transactions with witness scripts exceeding this threshold are valid under consensus but will not be relayed by default nodes, making them harder to get into a block unless submitted directly to a miner.
There is also a 201-opcode limit for non-push operations within witness scripts (inherited from legacy script rules). These combined limits affect what scripts are practical to deploy on-chain.
Witness Scripts and Taproot
Taproot (BIP 341, activated November 2021) introduced a different approach to script-based spending. P2TR outputs support two spending paths: a key-path spend using a single Schnorr signature, and a script-path spend that reveals a leaf from a Taptree of scripts.
Script-path spending uses tapscript (defined in BIP 342) rather than the witness script format. Tapscript makes several improvements over witness scripts:
- Removes the 10,000-byte script size limit
- Removes the 201 non-push opcode limit
- Replaces OP_CHECKMULTISIG with OP_CHECKSIGADD for batch-friendly multisig
- Uses Schnorr signatures instead of ECDSA
For complex spending conditions, tapscript is now preferred over witness scripts. However, P2WSH and its witness scripts remain widely used and fully valid. For a technical comparison, see Bitcoin Tapscript: Advanced Spending Conditions.
Use Cases
Witness scripts support any spending condition expressible in Bitcoin Script. Common applications include:
- Multisig wallets: m-of-n multisig setups where multiple parties must sign. P2WSH multisig benefits from the witness discount and can support more signers than P2SH (which is constrained to 520 bytes for the redeem script).
- Time-locked contracts: HTLCs used in Lightning channels combine hash locks with OP_CHECKLOCKTIMEVERIFY or OP_CHECKSEQUENCEVERIFY timelocks inside witness scripts.
- Escrow arrangements: scripts requiring signatures from two of three parties (buyer, seller, arbitrator) to release funds
- Complex spending policies: Miniscript-compiled policies that combine multiple conditions, timeouts, and fallback paths
Why It Matters
Witness scripts were essential to making the Lightning Network practical. Lightning channels rely on chaining pre-signed transactions by their txid. Before SegWit, any change to a signature would alter the txid, breaking the chain of dependent transactions. By moving the witness script and its signatures into the segregated witness section, SegWit ensured that txids remain stable regardless of signature changes.
The fee discount is also significant. Since witness data counts at one-quarter weight, complex scripts like multisig are substantially cheaper to execute in P2WSH compared to P2SH. This lower cost has driven adoption of SegWit outputs across the Bitcoin network. Layer 2 protocols like Spark and Lightning build on the malleability fix and script capabilities that witness scripts provide.
Risks and Considerations
Script Visibility
The full witness script is revealed on-chain when the output is spent. This means all spending conditions become publicly visible, including any unused branches. For privacy- sensitive applications, this can reveal information about the wallet setup (for example, the exact m-of-n threshold). Taproot's script-path spending improves on this by revealing only the executed leaf, not the entire script tree.
Collision Resistance
While the 32-byte SHA-256 hash provides strong collision resistance (128 bits), older P2SH wrapped P2WSH outputs reduce this back to 80 bits because P2SH uses HASH160. Developers working on multi-party scripts should prefer native P2WSH over nested P2SH-P2WSH to retain the full collision resistance benefit.
Size Constraints
The 10,000-byte consensus limit and 3,600-byte standardness limit restrict the complexity of witness scripts. For applications requiring very large or opcode-heavy scripts, Taproot's tapscript execution is the better choice, as it removes both limits. The 520-byte limit on individual stack items also constrains what data can be passed into a witness script during execution.
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.