OP_INTERNALKEY
OP_INTERNALKEY is a proposed Bitcoin tapscript opcode (BIP 349) that pushes the taproot internal key onto the stack for use in script evaluation.
Key Takeaways
- OP_INTERNALKEY (BIP 349) is a proposed tapscript opcode that pushes the 32-byte taproot internal key onto the stack, making it available for use within script evaluation.
- Without this opcode, scripts must embed the internal key as literal data, wasting 8 vBytes per occurrence and preventing dynamic re-keying patterns where updating the internal key automatically propagates through all script paths.
- OP_INTERNALKEY is part of the LNHANCE soft-fork proposal, where it combines with CTV and CSFS to enable vaults, LN-Symmetry channels, and more efficient Lightning protocols.
What Is OP_INTERNALKEY?
OP_INTERNALKEY is a proposed Bitcoin opcode defined in BIP 349, authored by Brandon Black and Jeremy Rubin. It assigns opcode byte 0xcb (replacing the reserved OP_SUCCESS203 slot) to push the taproot internal key onto the script execution stack during a script path spend.
In taproot (BIP 341), every P2TR output commits to an "internal key" and optionally a merkle tree of scripts. When spending via the script path, the consensus code already extracts the internal key from the control block to verify the merkle proof. However, the executing script has no way to access that key. OP_INTERNALKEY closes this gap by copying the key the consensus layer already possesses onto the stack, where other opcodes like OP_CHECKSIG or OP_CHECKSIGFROMSTACK can use it.
Because it replaces an OP_SUCCESS opcode (which unconditionally succeeds under current tapscript rules defined in BIP 342), OP_INTERNALKEY can be deployed as a backward-compatible soft fork.
How It Works
Understanding OP_INTERNALKEY requires context on how taproot script path spending works. When a user spends a P2TR output via the script path:
- The spender reveals the script leaf and provides a control block containing the internal key
- The consensus code extracts the 32-byte x-only internal key from the control block
- It verifies the merkle proof against the internal key and the script tree commitment
- The script executes with access to the stack and witness data
At step 4, the internal key exists in memory but the script has no opcode to reach it. If a script needs the internal key (for example, to verify a signature against it), the only option today is to embed the key as a 32-byte literal push in the script itself.
OP_INTERNALKEY changes this. When encountered during script execution, it takes no inputs and pushes a single 32-byte value onto the stack: the x-only public key p as defined in BIP 341.
Weight Savings
The practical benefit is straightforward. Consider a script that verifies a signature against the internal key:
# Without OP_INTERNALKEY (34 bytes)
<32-byte-internal-key> OP_CHECKSIG
# With OP_INTERNALKEY (2 bytes)
OP_INTERNALKEY OP_CHECKSIGThis saves 32 bytes of script data (8 vBytes under SegWit witness discount). A depth-0 tapscript spend using OP_INTERNALKEY costs approximately 37 weight units more than a key path spend, but the difference is small enough that scripts can cheaply add conditional logic on top of simple signature verification.
Scope and Constraints
OP_INTERNALKEY operates only within taproot script path spends using leaf version 0xc0 (the standard tapscript leaf version). It cannot be used in legacy scripts, P2WPKH, or P2WSH spends. If the script is executed outside tapscript context, the opcode is undefined.
Why Existing Opcodes Cannot Do This
No existing Bitcoin Script opcode provides access to the taproot internal key during execution. The alternatives have significant drawbacks:
- Embedding the key as literal data wastes 8 vBytes per occurrence and creates a static binding: if the internal key changes (as in protocols that update keys between states), every script leaf in the taptree must be reconstructed
- Pushing the key via witness data is possible but adds the same 32 bytes of witness weight, and the script still needs to verify the pushed value actually matches the internal key, which requires even more opcodes
- There is no opcode for introspecting the control block or other witness structure elements during tapscript execution
OP_INTERNALKEY provides a clean, minimal solution: one byte in the script, zero witness overhead, and guaranteed correctness because the value comes directly from the consensus layer.
The LNHANCE Proposal
OP_INTERNALKEY is one component of the LNHANCE soft-fork bundle, which combines several opcodes to unlock new protocol constructions on Bitcoin. The LNHANCE package includes:
- OP_CHECKTEMPLATEVERIFY (CTV, BIP 119): commits to a transaction template, enabling covenant-like constraints on how coins can be spent
- OP_CHECKSIGFROMSTACK (CSFS, BIP 348): verifies a Schnorr signature over arbitrary stack data rather than the transaction hash, enabling delegation and oracle attestation patterns
- OP_INTERNALKEY (BIP 349): provides efficient access to the internal key from within scripts
These opcodes compose naturally. For example, OP_INTERNALKEY OP_CHECKSIGFROMSTACK verifies that the internal key holder signed some arbitrary message, enabling delegation without embedding the key. Combined with CTV, this creates powerful patterns where the internal key holder can authorize specific pre-committed transactions.
As of 2026, the LNHANCE opcodes are testable on Mutinynet (a signet-based testing network), and Bitcoin Inquisition has implemented CSFS and INTERNALKEY for experimentation. A related proposal, BIP 448, bundles OP_INTERNALKEY with OP_TEMPLATEHASH (BIP 446) and CSFS as a "taproot-native covenant bundle" targeting LN-Symmetry channel constructions.
Use Cases
LN-Symmetry Channels
LN-Symmetry (formerly eltoo) transforms Lightning channels from the current penalty-based model into a symmetric model where the latest state always wins. OP_INTERNALKEY allows update scripts to reference the channel's signing key efficiently. When combined with SIGHASH_ANYPREVOUT or CTV/CSFS, this enables simpler channel state machines with lower on-chain costs during unilateral closes.
Vaults
Vault constructions use time-delayed spending to protect against theft. CTV commits to the exact withdrawal transaction template, while OP_INTERNALKEY and CSFS provide flexible authorization. The internal key holder can authorize a withdrawal, but the CTV constraint ensures funds can only move to pre-committed destinations. A watchtower monitoring for unauthorized spending can trigger a clawback before the timelock expires.
Efficient Script-Path Single-Sig
Sometimes a spending policy requires both a key path and a script path that checks the same key with additional conditions (a timelock, a hash preimage, or a second signature). Without OP_INTERNALKEY, the script path must redundantly include the 32-byte key. With it, the script simply references the internal key:
# Require internal key signature AND a timelock
OP_INTERNALKEY OP_CHECKSIGVERIFY
<144> OP_CHECKSEQUENCEVERIFYThis pattern is useful for inheritance schemes, delayed recovery paths, and any construction where the primary signer also appears in fallback scripts.
Dynamic Re-Keying
In multi-party protocols where participants join or leave, the internal key may change (for example, updating a MuSig2 aggregate key). Scripts that use OP_INTERNALKEY automatically reference the new key without reconstruction. Scripts that embed the key as literal data become invalid when the key changes, requiring the entire taptree to be rebuilt.
Timeout Trees and Channel Factories
Channel factories and timeout trees are hierarchical structures where multiple users share UTXOs. OP_INTERNALKEY reduces the per-leaf script weight across potentially hundreds of script leaves in the taptree, making these constructions more practical on-chain. Combined with CTV for pre-committed exit paths, these structures can scale Lightning Network onboarding by orders of magnitude.
Comparison with Related Proposals
OP_INTERNALKEY operates in a landscape of competing and complementary covenant proposals. Understanding where it fits:
| Proposal | Function | Relationship to OP_INTERNALKEY |
|---|---|---|
| CTV (BIP 119) | Constrains spending to a pre-committed transaction template | Complementary: CTV constrains outputs, INTERNALKEY provides key access |
| CSFS (BIP 348) | Verifies signatures over arbitrary stack messages | Complementary: CSFS verifies signatures, INTERNALKEY provides the key to check against |
| OP_CAT | Concatenates two stack elements | Alternative approach: OP_CAT enables covenants through different mechanisms |
| OP_VAULT | Purpose-built vault opcode | Alternative: dedicated vault vs. general-purpose building blocks |
The broader covenant debate in 2026 involves several competing bundles. LNHANCE advocates argue that OP_INTERNALKEY's minimal footprint (a single opcode byte with simple semantics) makes it low-risk to include alongside CTV and CSFS, while its re-keying and weight-saving capabilities are difficult to replicate otherwise.
Risks and Considerations
Activation Uncertainty
BIP 349 remains in Draft status with no activation parameters defined. Whether it activates as part of LNHANCE, BIP 448, or a standalone soft fork is an open question. Developers building protocols that depend on OP_INTERNALKEY should treat it as experimental until a concrete activation path emerges.
Limited Standalone Utility
OP_INTERNALKEY on its own provides a modest optimization: saving 8 vBytes per key reference. Its full value emerges in combination with other proposed opcodes like CTV and CSFS. Critics argue that bundling opcodes creates all-or-nothing activation dynamics where disagreement over one opcode blocks the rest.
Soft Fork Risks
Any consensus change to Bitcoin Script carries inherent risk. Redefining an OP_SUCCESS opcode is among the safest approaches (it strictly narrows validity), but the interactions between OP_INTERNALKEY and other proposed opcodes must be carefully analyzed to avoid unexpected emergent behaviors. The Bitcoin development community emphasizes extensive review and testing before any activation.
Tapscript Only
OP_INTERNALKEY is available only in tapscript spends. Protocols that operate on pre-taproot output types or non-standard leaf versions cannot use it. This limits its applicability to newer taproot-native constructions and does not help optimize legacy script paths.
Why It Matters
OP_INTERNALKEY is a small opcode with outsized implications. By giving scripts access to the internal key, it bridges the gap between taproot's key path efficiency and script path flexibility. Protocols like Spark and other Bitcoin Layer 2 systems benefit from improvements to taproot scripting capabilities: more expressive scripts mean more sophisticated off-chain constructions that can settle trustlessly on-chain. As Bitcoin Script's limitations are gradually addressed through proposals like LNHANCE, the design space for self-custodial protocols, vaults, and scalable payment networks continues to expand.
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.