TeachMeBitcoin

Pseudocode for validation weight accounting:

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

10. Tapscript Resource Limits

Tapscript defines specific resource limits that govern how complex a script can be and how much computation a node must perform to validate it. These limits differ from legacy Script in important ways.

Transaction Weight as the Primary Constraint

In legacy Script, individual scripts had byte size limits and opcode count limits. In Tapscript, the primary resource constraint is transaction weight, which affects all script data including the witness.

Transaction weight = base_size × 4 + total_witness_size

Witness discount: witness data counts at 1/4 weight compared to base data
This means Tapscript data (in the witness) is "cheap" relative to non-witness data

The maximum transaction weight is 400,000 weight units. This indirectly limits how large a Tapscript can be, but there is no separate byte limit on individual scripts.

Removed Limits in Tapscript

Removed from Tapscript (vs legacy Script):

- MAX_OPS_PER_SCRIPT (201 non-push opcodes): REMOVED

- MAX_SCRIPT_SIZE (10,000 bytes per script): REMOVED
  (replaced by weight-based limits)

The opcode count limit in legacy Script was a rough proxy for execution cost. Tapscript removes it because:

  1. Schnorr signatures allow batch validation — validating many signatures at once is cheaper than validating each individually, so counting signature check opcodes as "expensive" is inaccurate

  2. Transaction weight provides a more accurate overall constraint

  3. The 201-opcode limit was preventing useful smart contract patterns

Remaining Limits in Tapscript

Unchanged from legacy Script:

- Maximum stack item size: 520 bytes

- Maximum stack depth: 1,000 items (main + alt stack combined)

- Maximum script numeric value: 4 bytes (CScriptNum range)

- Maximum witness item count: 2 + stack depth per input

Validation Weight for Signature Opcodes

BIP 342 introduces a concept called validation weight for signature-checking opcodes in Tapscript. Each input starts with a budget of 50 + witness_size validation weight units. Each executed OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD costs 50 weight units.

Initial budget per Tapscript input:
budget = 50 + len(witness_stack_serialized)

Cost per signature check opcode:

- OP_CHECKSIG (successful): 50 weight units

- OP_CHECKSIGADD (any): 50 weight units

- OP_CHECKSIG with empty signature: 0 weight units (no verification needed)

If budget runs out:
→ Script fails with SCRIPT_ERR_TAPSCRIPT_VALIDATION_WEIGHT

This mechanism prevents a Tapscript from requiring an unbounded number of signature verifications while still allowing complex multi-signature constructions.

# Pseudocode for validation weight accounting:
def execute_tapscript_with_weight_limit(script, witness_stack):
    budget = 50 + sum(len(item) for item in witness_stack)

    for opcode in script:
        if opcode in (OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_CHECKSIGADD):
            if stack[-1] != b'':  # Non-empty signature
                budget -= 50
                if budget < 0:
                    raise ScriptError("TAPSCRIPT_VALIDATION_WEIGHT")

Control Block Size Limits

The control block (Merkle path proof) is also constrained:

Control block size:
Minimum: 33 bytes (1 byte version + 32 bytes internal key, depth 0)
Maximum: 33 + 128 × 32 = 4,129 bytes (depth 128, the maximum tree depth)

Maximum Taproot tree depth: 128 levels
Maximum leaves in a tree: 2^128 (effectively unlimited)

Technical Insight

This topic covers essential mechanics for Chapter 11. Understanding these details is key to mastering advanced Bitcoin script constructions like Taproot and specialized covenants.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!