Glossary

Tapscript

Tapscript is the upgraded scripting language used inside Taproot script-path spends, enabling new opcodes and improved flexibility.

Key Takeaways

  • Tapscript is the modified scripting language defined in BIP 342 that governs validation of Taproot script-path spends, replacing ECDSA signature checks with Schnorr signatures and introducing new opcodes for flexible spending conditions.
  • Tapscript removes legacy limitations: the 10,000-byte script size cap and the 201 non-push opcode limit are eliminated, replaced by a per-input signature budget tied to witness data size, enabling more complex scripts without arbitrary constraints.
  • A built-in upgrade mechanism called OP_SUCCESS opcodes allows future soft forks to introduce entirely new opcodes without the limitations of the legacy OP_NOP upgrade path, making Tapscript a foundation for long-term Bitcoin programmability.

What Is Tapscript?

Tapscript is the scripting language used to validate spending conditions inside Taproot (BIP 341) outputs when they are spent via the script-path rather than the key-path. It is not a replacement for Bitcoin Script but an evolution of it: a modified version with targeted changes that take advantage of Schnorr signatures and remove longstanding limitations on script complexity.

Tapscript was activated alongside BIP 340 (Schnorr Signatures) and BIP 341 (Taproot) on November 14, 2021, at block height 709,632. Together, these three BIPs form the complete Taproot upgrade. While BIP 340 defines the cryptographic signature scheme and BIP 341 defines the new output type (P2TR), BIP 342 specifies the rules for executing scripts within Taproot's MAST structure.

Tapscript uses leaf version 0xC0 within Taproot's script tree. This versioning means future leaf versions can define entirely different script validation rules, providing another upgrade path beyond the OP_SUCCESS mechanism.

How It Works

To understand Tapscript, it helps to first understand the two ways a Taproot output can be spent: key-path and script-path.

Key-Path vs. Script-Path Spends

A P2TR output commits to a single public key that encodes both a direct spending key and an optional Merkle tree of scripts. The spender chooses which path to use:

  • Key-path spend: the owner(s) of the internal key produce a single Schnorr signature. On-chain, this looks identical to any other single-signature spend. Observers cannot determine whether alternative script conditions existed. This is the most efficient and private spending method.
  • Script-path spend: the spender reveals a specific script leaf from the committed Merkle tree, provides a Merkle proof (the sibling hashes along the path to the root), and supplies a control block containing the internal public key and leaf version. The spender then satisfies the revealed script using Tapscript rules. Only the utilized leaf is revealed on-chain: all other branches remain hidden.

Tapscript only applies to script-path spends. Key-path spends bypass script execution entirely, relying on a single Schnorr signature verified against the tweaked output key.

Signature Verification Changes

The most fundamental change in Tapscript is how signatures are verified. OP_CHECKSIG and OP_CHECKSIGVERIFY are redefined to validate Schnorr signatures (BIP 340) instead of ECDSA:

  • 64-byte signatures are verified as Schnorr signatures using the default sighash type (SIGHASH_DEFAULT, equivalent to SIGHASH_ALL)
  • 65-byte signatures include an explicit sighash flag as the final byte, with the first 64 bytes verified as a Schnorr signature
  • Empty signatures cause OP_CHECKSIG to push an empty vector onto the stack (allowing the script to continue), while OP_CHECKSIGVERIFY causes immediate failure
  • Any other signature length causes immediate script failure

OP_CHECKSIGADD: Replacing Multisig

Tapscript disables OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY entirely (they behave like OP_RETURN, immediately failing the script). In their place, Tapscript introduces a new opcode called OP_CHECKSIGADD.

The reason for this change is technical: OP_CHECKMULTISIG does not associate specific signatures with specific public keys until runtime, creating a combinatorial search that prevents efficient batch validation of Schnorr signatures. OP_CHECKSIGADD eliminates this problem by requiring each signature to be explicitly paired with its corresponding key.

OP_CHECKSIGADD pops three elements from the stack:

  1. A public key (top of stack)
  2. A CScriptNum counter n (second on stack)
  3. A signature (third on stack)

If the signature is non-empty and valid, the opcode pushes n + 1. If the signature is empty, it pushes n unchanged. A 2-of-3 multisig in Tapscript looks like this:

// Tapscript 2-of-3 multisig
<pubkey1> OP_CHECKSIG
<pubkey2> OP_CHECKSIGADD
<pubkey3> OP_CHECKSIGADD
OP_2 OP_NUMEQUAL

// Each signer provides a signature or empty value
// The counter accumulates valid signatures
// Script succeeds if exactly 2 signatures are valid

This approach is functionally equivalent to OP_CHECKMULTISIG but uses only one byte per key-check instead of requiring the dummy element workaround, and it enables batch verification of all signatures in a block.

Resource Limit Changes

Tapscript removes two major resource limits that constrained legacy Bitcoin Script:

ResourceLegacy ScriptTapscript
Script size10,000 bytes maximumNo limit (bounded by block weight)
Non-push opcodes201 per scriptNo limit
Signature operationsBlock-wide limit of 80,000Per-input budget: 50 + witness size in bytes
Stack + altstack elements1,000 maximum1,000 maximum (unchanged)
Stack element size520 bytes maximum520 bytes maximum (unchanged)

The per-input signature budget deserves explanation: each input starts with a budget of 50 plus the total serialized witness size in bytes. Each executed signature opcode with a non-empty signature costs 50 from this budget. If the budget is exhausted, the script fails. This ties computational cost directly to witness data that the spender must pay for, providing denial-of-service protection without arbitrary limits.

OP_SUCCESS: The Upgrade Mechanism

One of Tapscript's most forward-looking features is the OP_SUCCESS opcode family. Specific opcode numbers (80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254) are designated as OP_SUCCESS opcodes.

If any OP_SUCCESS opcode appears anywhere in a tapscript, even in an unexecuted branch, the entire script unconditionally succeeds. This is fundamentally different from legacy OP_NOP-based upgrades: OP_NOP opcodes can only add new validation conditions because they cannot modify the stack, while OP_SUCCESS opcodes bypass all validation, allowing a future soft fork to redefine them with full stack read and write access.

A soft fork narrows the conditions under which an OP_SUCCESS opcode succeeds, effectively defining new opcode behavior. For example, BIP 347 proposes redefining OP_SUCCESS126 as OP_CAT, which would concatenate two stack values. Before activation, any script containing opcode 126 automatically succeeds. After a soft fork, opcode 126 would perform concatenation and could fail: a valid tightening of the rules.

Sighash Algorithm

Tapscript extends the BIP 341 common signature message with three additional fields:

  • tapleaf_hash (32 bytes): commits to the leaf version and the script being executed, replacing the legacy scriptCode commitment and eliminating the quadratic hashing concern that originally justified the script size limit
  • key_version (1 byte): currently a constant 0x00, allowing future soft forks to introduce new key types with different signature algorithms
  • codesep_pos (4 bytes): the position of the last executed OP_CODESEPARATOR before the current signature opcode, or 0xffffffff if none was executed

Use Cases

Advanced Threshold Signatures

Tapscript's Schnorr-based signature verification directly enables FROST threshold signatures. FROST allows any t participants out of n total signers to produce a single valid Schnorr signature that is indistinguishable from a regular single-key signature on-chain. When used in a Taproot key-path spend, FROST provides maximum privacy: nobody can determine that a threshold scheme was involved or which subset of signers participated.

For fallback conditions, FROST keys can be combined with Tapscript branches. For example, a 3-of-5 FROST key-path with a script-path fallback that allows a time-locked 2-of-5 recovery after six months.

Complex Spending Policies

The removal of the 201-opcode limit and 10,000-byte script size cap allows Miniscript policies that were previously impossible. Wallet developers can express rich spending conditions: multi-tiered access controls, time-locked inheritance schemes, and multi-party covenant structures that would have exceeded legacy resource limits.

Miniscript has been extended to support Tapscript (formalized in BIP 379 and BIP 382), so the same policy language can target both pre-Taproot P2WSH and Taproot script paths. Bitcoin Core has integrated Tapscript Miniscript support, enabling wallet descriptors for script-path spends through output descriptors.

Privacy-Preserving Contracts

Combined with MAST, Tapscript enables contracts where only the executed branch is revealed on-chain. A contract with dozens of conditional spending paths (dispute resolution, timeout recovery, multi-party approval) only exposes the single path that was actually used. All alternatives remain hidden, improving both privacy and efficiency.

This is particularly valuable for Lightning channels and other Layer 2 protocols where complex fallback conditions exist but are rarely exercised.

Future Protocol Upgrades

The OP_SUCCESS mechanism positions Tapscript as a platform for future Bitcoin programmability. Active proposals include:

  • OP_CAT (BIP 347): concatenates stack values, enabling covenants, zero-knowledge proof verification, and other advanced applications. BIP 347 reached version 1.0.0 and was marked complete in March 2026.
  • SIGHASH_ANYPREVOUT (BIP 118): new sighash flags for Tapscript that would enable eltoo/LN-Symmetry payment channels, a significant improvement over current penalty-based channel designs

Why It Matters

Tapscript represents a generational upgrade to Bitcoin's programmability. Before Tapscript, adding new opcodes to Bitcoin required either reusing limited OP_NOP slots (which cannot modify the stack) or entirely new SegWit versions. Tapscript's OP_SUCCESS opcodes and leaf versioning provide two independent upgrade paths, making it significantly easier to introduce new functionality through soft forks.

For Layer 2 protocols like Spark and the Lightning Network, Tapscript's improvements are directly relevant. The combination of Schnorr signatures, batch verification, and relaxed script limits enables more efficient and private channel constructions. FROST threshold signatures, made practical by Tapscript's Schnorr verification, are foundational to protocols that require distributed key management without revealing their multi-party nature on-chain.

For a deeper exploration of the Taproot upgrade and how Schnorr signatures fit into Bitcoin's evolution, see the Taproot and Schnorr Signatures Explained research article.

Risks and Considerations

Adoption Timeline

Although Tapscript has been active since November 2021, adoption of its advanced features has been gradual. Many wallets and services still default to SegWit v0 outputs. Script-path spends, which are the only context where Tapscript applies, represent a fraction of on-chain transactions. Developers building on Tapscript should consider that counterparties and infrastructure may not yet fully support P2TR script-path spending.

Complexity Tradeoffs

The removal of script size and opcode count limits means Tapscript can express much larger programs. However, larger scripts still consume block weight and require witness data to be transmitted across the network. The per-input signature budget provides denial-of-service protection, but developers must still consider the economic cost of complex scripts and the impact on transaction fees.

OP_SUCCESS Security Model

Scripts containing OP_SUCCESS opcodes unconditionally succeed today, which means funds sent to such scripts can be spent by anyone. Until a soft fork redefines a specific OP_SUCCESS opcode, no one should create outputs whose spending conditions rely on the future behavior of that opcode. The security guarantee only exists after activation.

Backward Compatibility

Tapscript is not backward-compatible with legacy Script or SegWit v0. Scripts written for P2WSH outputs cannot be directly reused in Taproot script-path spends without modification. The changes to signature verification (Schnorr vs. ECDSA), multisig construction (OP_CHECKSIGADD vs. OP_CHECKMULTISIG), and resource limits require scripts to be rewritten for the Tapscript environment.

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.