Compared to Turing-complete blockchains like Ethereum, Bitcoin scripting is considered to be highly restrictive, capable only of basic operations, and it even lacks support for multiplication and division. More importantly, the blockchain's own data is almost inaccessible to scripts, resulting in a significant lack of flexibility and programmability. Hence, there has been a long-standing effort to enable Bitcoin scripts to achieve introspection.
Introspection refers to the ability of Bitcoin scripts to inspect and constrain transaction data. This allows scripts to control the usage of funds based on specific transaction details, enabling more complex functionalities. Currently, most Bitcoin opcodes either push user-supplied data onto the stack or manipulate existing data on the stack. Introspection opcodes, however, can push data from the current transaction (such as timestamps, amounts, txid, etc.) onto the stack, allowing for more granular control over UTXO spending.
As of now, only three main opcodes in Bitcoin scripting support introspection: CHECKLOCKTIMEVERIFY, CHECKSEQUENCEVERIFY, and CHECKSIG, along with its variants CHECKSIGVERIFY, CHECKSIGADD, CHECKMULTISIG, and CHECKMULTISIGVERIFY.
Covenant, simply put, refers to restrictions on how coins are transferred, allowing users to specify how UTXOs are distributed. Many covenants are implemented through introspection opcodes, and discussions about introspection have now been categorized under the topic of covenants on Bitcoin Optech.
Bitcoin currently has two covenants, CSV (CheckSequenceVerify) and CLTV (CheckLockTimeVerify), both time-based covenants that are foundational for many scaling solutions like the Lightning Network. This illustrates how Bitcoin's scaling solutions rely heavily on introspection and covenants.
How do we add conditions to the transfer of coins? In the cryptosphere, our most common method is through commitments, often implemented via hashes. To prove that the transfer requirements are met, signature mechanisms are also needed for verification. Thus, many adjustments to hashes and signatures exist within covenants.
Below, we will describe the widely discussed Covenant opcode proposal.
CTV (CheckTemplateVerify) is a Bitcoin upgrade proposal contained in BIP-119 that has garnered significant community attention. CTV enables the output script to specify a template for spending the funds in a transaction, including fields like nVersion, nLockTime, scriptSig hash, input count, sequences hash, output count, outputs hash, input index. These template restrictions are implemented via a hash commitment, and when the funds are spent, the script checks if the hash values of the specified fields in the spending transaction match the hash values in the input script. This effectively confines the time, method, and amount of future transactions of that UTXO.
Notably, the input TXID is excluded from this hash. This exclusion is necessary, as in both Legacy and Segwit transactions, the TXID depends on the values in the scriptPubKey when using the default SIGHASH_ALL signing type. Including the TXID would lead to a circular dependency in the hash commitment, making it impossible to construct.
CTV implements introspection by directly pulling specified transaction information for hashing and comparing it with the commitment on the stack. This method of introspection is less demanding on chain space but lacks some flexibility.
The foundation of Bitcoin's layer-two solutions like the Lightning Network is pre-signed transactions. Pre-signing typically refers to generating and signing transactions in advance but not broadcasting them until certain conditions are met. Essentially, CTV implements a more rigorous form of pre-signing, posting the commitment of pre-signing on chain, restricted to the predefined template.
CTV was initially proposed to alleviate congestion in Bitcoin, which can also be referred to as congestion control. During times of high congestion, CTV can commit to multiple future transactions within a single transaction, avoiding the need to broadcast multiple transactions during peak times and completing the actual transactions once the congestion eases. This could be particularly helpful during exchange bank runs. Additionally, the template can also be used for implementing Vaults to protect against hacking attacks. Since the direction of funds is predetermined, hackers cannot direct UTXOs using CTV scripts to their own addresses.
CTV can significantly enhance layer-two networks. For instance, in the Lightning Network, CTV can enable the creation of Timeout Trees and Channel Factories by expanding a single UTXO into a CTV tree, opening multiple state channels with just one transaction and one confirmation. Moreover, CTV also supports atomic trades in the Ark protocol through ATLC.
BIP-118 introduces a new type of signature hash flag for tapscript, aimed at facilitating more flexible spending logic known as SIGHASH_ANYPREVOUT. APO and CTV share many similarities. When addressing the cyclic issue between scriptPubKeys and TXIDs, APO's approach is to exclude relevant input information and only sign the outputs, allowing transactions to dynamically bind to different UTXOs.
Logically, the signature verification operation OP_CHECKSIG (and its variants) performs three functions:
Assembling the parts of the spending transaction.
Hashing them.
Verifying that the hash has been signed by a given key.
The specifics of the signature have a lot of flexibility, with the decision on which transaction fields to sign determined by the SIGHASH flag. According to the definition of signature opcodes in BIP 342, SIGHASH flags are divided into SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY. SIGHASH_ANYONECANPAY controls the inputs, while the others control the outputs.
SIGHASH_ALL is the default SIGHASH flag, signing all outputs; SIGHASH_NONE signs no outputs; SIGHASH_SINGLE signs a specific output. SIGHASH_ANYONECANPAY can be set with the first three SIGHASH flags. If SIGHASH_ANYONECANPAY is set, only the specified input is signed; otherwise, all inputs must be signed.
Clearly, these SIGHASH flags do not eliminate the influence of inputs, even SIGHASH_ANYONECANPAY, which requires committing to one input.
Thus, BIP 118 proposes SIGHASH_ANYPREVOUT. The APO signature does not need to commit to the spent input UTXO (known as PREVOUT) but only needs to sign the outputs, providing greater flexibility in Bitcoin control. By pre-building transactions and creating corresponding one-time-use signatures and public keys, assets sent to that public key address must be spent through the pre-built transaction, thus implementing a Covenant. The flexibility of APO can also be used for transaction repair; if a transaction is stuck on the chain due to low fees, another transaction can be easily created to increase the fee without needing a new signature. Moreover, for multi-signature wallets, not depending on the spent inputs makes operations more convenient.
Since it eliminates the cycle between scriptPubKeys and input TXIDs, APO can perform introspection by adding output data in the Witness, although this still requires additional Witness space consumption.
For off-chain protocols like the Lightning Network and Vaults, APO reduces the need to save intermediate states, greatly reducing storage requirements and complexity. APO's most direct use case is Eltoo, which simplifies channel factories, builds lightweight and inexpensive watchtowers, and allows unilateral exits without leaving erroneous states, enhancing the performance of the Lightning Network in many ways. APO can also be used to simulate CTV functions, though it requires individuals to store signatures and pre-signed transactions, which is more costly and less efficient than CTV.
APO's main criticism centers on its need for a new key version, which cannot be implemented by simply being backwards compatible. Additionally, the new signature hash type may introduce potential risks of double spending. After extensive community discussions, APO has added regular signatures on top of the original signing mechanism to alleviate security concerns, thus gaining the BIP-118 code.
BIP-345 proposes the addition of two new opcodes, OP_VAULT and OP_VAULT_RECOVER, which when combined with CTV, implement a specialized Covenant that allows users to enforce a delay on spending specific coins. During this delay, a previously made transaction can be "reversed" via a recovery path.
Users can create a Vault by creating a specific Taproot address that must contain at least two scripts in its MAST: one with the OP_VAULT opcode to facilitate the expected withdrawal process, and another with the OP_VAULT_RECOVER opcode to ensure coins can be recovered at any time before the completion of the withdrawal.
How does OP_VAULT implement interruptible time-locked withdrawals? OP_VAULT accomplishes this by replacing the spent OP_VAULT script with a specified script, effectively updating a single leaf of the MAST while leaving the rest of the Taproot leaf nodes unchanged. This design is similar to TLUV, except that OP_VAULT does not support updates to the internal key.
By introducing a template during the script update process, it is possible to limit payments. The time-lock parameter is specified by OP_VAULT, and the CTV opcode's Template restricts the set of outputs that can be spent through this script path.
BIP-345 is designed specifically for Vaults, leveraging OP_VAULT and OP_VAULT_RECOVER to provide users with a secure custodial method that uses a highly secure key (such as a paper wallet or a distributed multisig) as a recovery path, while configuring a certain delay for regular payments. Users' devices continuously monitor the spending from the Vault, and if an unexpected transfer occurs, users can initiate a recovery.
The implementation of Vault via BIP-345 requires consideration of cost issues, especially for recovery transactions. Possible solutions include CPFP (Child Pays for Parent), temporary anchors, and new SIGHASH_GROUP signature hash flags.
The TLUV scheme is built around Taproot and aims to efficiently address the issue of exiting from shared UTXOs. The guiding principle is that when a Taproot output is spent, partial updates can be made to the internal key and MAST (tapscript trie) through cryptographic transformations and the internal structure of the Taproot address, as described by the TLUV script. This enables the implementation of Covenant functions.
The concept of the TLUV scheme is to create a new Taproot address based on the current spending input by introducing a new opcode, TAPLEAF_UPDATE_VERIFY. This can be achieved by performing one or more of the following actions:
Update the internal public key
Trim the Merkle path
Remove the script currently being executed
Add a new step at the end of the Merkle path
Specifically, TLUV accepts three inputs:
One that specifies how to update the internal public key.
One that specifies a new step for the Merkle path.
One that specifies whether to remove the current script and/or how many steps of the Merkle path to trim.
The TLUV opcode calculates the updated scriptPubKey and verifies that the output corresponding to the current input is spent to this scriptPubKey.
TLUV is inspired by the concept of CoinPool. Today, joint pools can be created using only pre-signed transactions, but if unpermissioned exits are to be realized, it would require creating an exponentially growing number of signatures. TLUV, however, allows for unpermissioned exits without any pre-signatures. For instance, a group of partners could use Taproot to build a shared UTXO, pooling their funds together. They can internally move funds using the Taproot key or jointly sign to initiate payments externally. Individuals can exit the shared fund pool at any time, removing their payment paths, while others can still complete payments through the original paths, and the individual's exit does not expose additional information about others inside. This mode is more efficient and private compared to non-pooled transactions.
The TLUV opcode achieves partial spending restrictions by updating the original Taproot Trie, yet it does not implement introspection of the output amount. Therefore, a new opcode, IN_OUT_AMOUNT, is also needed. This opcode pushes two items onto the stack: the amount of the UTXO for this input and the amount for the corresponding output, then those using TLUV are expected to use mathematical operators to verify that funds are appropriately retained in the updated scriptPubKey.
Introspection of output amounts adds complexity because amounts in satoshis need up to 51 bits to represent, but scripts only allow for 32-bit mathematical operations. This requires redefining opcode behavior to upgrade operators in scripts or using SIGHASH_GROUP to replace IN_OUT_AMOUNT.
TLUV holds potential as a solution for decentralized Layer 2 funding pools, though reliability in tweaking the Taproot Trie still needs confirmation.
MATT (Merkleize All The Things) aims to achieve three objectives: Merkleizing the state, Merkleizing the script, and Merkleizing execution, thereby enabling universal smart contracts.
Merkleizing the state: This involves constructing a Merkle Trie, where each leaf node represents the hash of a state, with the Merkle Root embodying the overall state of the contract.
Merkleizing the script: This refers to the formation of a MAST using Tapscript, where each leaf node represents a possible state transition path.
Merkleizing execution: Execution is Merkleized through cryptographic commitments and a fraud challenge mechanism. For any computational function, participants can compute off-chain and then publish a commitment, f(x)=y. If other participants find an erroneous result, f(x)=z, they can initiate a challenge. Arbitration is conducted through binary searching, similar to the principle of Optimistic Rollup.
To implement MATT, Bitcoin scripting language needs to have the following functionalities:
Force an output to have a certain Script (and their amounts)
Attach a piece of data to an output
Read the data from the current input (or another one)
The second point is crucial: dynamic data means that the state can be computed through input data provided by the spender, as this allows for the simulation of a state machine, capable of determining the next state and additional data. The MATT scheme implements this through the OP_CHECKCONTRACTVERIFY (OP_CCV) opcode, a merger of the previously proposed OP_CHECKOUTPUTCONTRACTVERIFY and OP_CHECKINPUTCONTRACTVERIFY opcodes, using an additional flags parameter to specify the target of the operation.
Control over output amounts: The most straightforward method is direct introspection; however, output amounts are 64-bit numbers, requiring 64-bit arithmetic, which presents significant complexity in Bitcoin scripting. OP_CCV adopts a deferred checking approach, like OP_VAULT, where all inputs to the same output with CCV have their input amounts summed up, serving as a lower limit for that output's amount. The deferment is because this check occurs during the transaction process rather than during the script evaluation of the inputs.
Given the universality of fraud proofs, certain variants of the MATT contract should be capable of implementing all types of smart contracts or Layer 2 constructions, although additional requirements (such as capital lock-up and challenge period delays) need to be accurately assessed; further research is required to evaluate which applications are acceptable for transactions. For example, using cryptographic commitments and fraud challenge mechanisms to simulate the OP_ZK_VERIFY function, achieving trustless Rollups on Bitcoin.
In practice, things are already happening. Johan Torås Halseth has utilized the OP_CHECKCONTRACTVERIFY opcode from the MATT soft fork proposal to implement elftrace, which allows any program that supports RISC-V compilation to be verified on the Bitcoin blockchain, enabling a party within a contract protocol to access funds through contract verification, thus bridging Bitcoin native verification.
From the introduction of the APO opcode, we have learned that OP_CHECKSIG (and its related operations) are responsible for assembling transactions, hashing, and verifying signatures. However, the message verified by these operations is derived from the serialization of the transaction using the opcode, and it does not allow specifying any other message. In simple terms, OP_CHECKSIG (and its related operations) serve to verify via the signature mechanism whether the UTXO being spent as a transaction input has been authorized to be expended by the holder of the signature, thereby protecting the security of Bitcoin.
CSFS, as the name suggests, Checks the Signature From Stack. The CSFS opcode receives three parameters from the stack: a signature, a message, and a public key, and verifies the validity of the signature. This means that people can pass any message to the stack through the Witness and verify it through CSFS, enabling some innovations on Bitcoin.
The flexibility of CSFS allows it to implement mechanisms such as payment signatures, authorization delegation, oracle contracts, double-spend protection bonds, and more importantly, transaction introspection. The principle of using CSFS for transaction introspection is quite simple: if the transaction content used by OP_CHECKSIG is pushed to the stack through the Witness, and the same public key and signature are used to verify both with OP_CSFS and OP_CHECKSIG, and if both verifications pass successfully, then the arbitrary message content passed to OP_CSFS is the same as the serialized spend transaction (and other data) implicitly used by OP_CHECKSIG. We then obtain verified transaction data on the stack, which can be used to apply restrictions to spending transactions with other opcodes.
CSFS often appears together with OP_CAT because OP_CAT can connect different fields of the transaction to complete serialization, allowing for more precise selection of the transaction fields needed for introspection. Without OP_CAT, the script cannot recompute the hash from data that can be checked separately, so what it can really do is to check if the hash corresponds to a specific value, meaning that the coins can only be spent through a single specific transaction.
CSFS can implement opcodes like CLTV, CSV, CTV, APO, etc., making it a versatile introspection opcode. Thus, it also aids in the scalability solutions for Bitcoin Layer2. The downside is that it requires adding a complete copy of the signed transaction on the stack, which may significantly increase the size of transactions intended for introspection using CSFS. In contrast, single-purpose introspection opcodes like CLTV and CSV have minimal overhead, but adding each new special introspection opcode requires consensus changes.
OP_TXHASH is a straightforward introspection-enabled opcode that allows the operator to select and push the hash of a specific field onto the stack. Specifically, OP_TXHASH pops a txhash flag from the stack and computes a (tagged) txhash based on that flag, then pushes the resulting hash back onto the stack.
Due to the similarities between TXHASH and CTV, a considerable amount of discussion has arisen within the community regarding the two.
TXHASH can be considered a universal upgrade of CTV, offering a more advanced transaction template that allows users to specify parts of a spending transaction explicitly, addressing many issues related to transaction fees. Unlike other Covenant opcodes, TXHASH does not require a copy of the necessary data in the witness, further reducing storage requirements; unlike CTV, TXHASH is not NOP-compatible and can only be implemented in tapscript; the combination of TXHASH and CSFS can serve as an alternative to CTV and APO.
From the perspective of constructing covenants, TXHASH is more conducive to creating "additive covenants," where all parts of the transaction data you wish to fix are pushed onto the stack, hashed together, and the resulting hash is verified to match a fixed value; CTV is more suited to creating "subtractive covenants," where all parts of the transaction data you wish to keep free are pushed onto the stack. Then, using a rolling SHA256 opcode, hashing begins from a fixed intermediate state that commits to a prefix of the transaction hash data. The free parts are hashed into this intermediate state.
The TxFieldSelector field defined in the TXHASH specification is expected to be expanded to other opcodes, such as OP_TX.
The BIP related to TXHASH is currently in the Draft status on GitHub and has not been assigned a number.
OP_CAT is an opcode shrouded in mystery, originally abandoned by Satoshi Nakamoto due to security concerns, it has recently sparked intense discussion among core Bitcoin developers and even spurred Meme culture on the internet. Ultimately, OP_CAT was approved under BIP-347 and has been called the most likely BIP proposal to pass in recent times.
In fact, the behavior of OP_CAT is quite simple: it concatenates two elements from the stack. How does it enable the Covenant functionality?
Indeed, the ability to concatenate two elements corresponds to a powerful cryptographic data structure: the Merkle Trie. To build a Merkle Trie, only concatenation and hashing operations are needed, and hashing functions are available in Bitcoin scripts. Thus, with OP_CAT, we theoretically can verify Merkle Proofs within Bitcoin scripts, which is one of the most common lightweight verification methods in blockchain technology.
As previously mentioned, CSFS, with the help of OP_CAT, can implement a universal Covenant scheme. In fact, without CSFS, leveraging the structure of Schnorr signatures, OP_CAT itself can achieve transaction introspection.
In Schnorr signatures, the message that needs to be signed is composed of the following fields:
These fields contain the major elements of a transaction. By placing them in the scriptPubKey or Witness and using OP_CAT combined with OP_SHA256, we can construct a Schnorr signature and verify it using OP_CHECKSIG. If the verification passes, the stack retains the verified transaction data, achieving transaction introspection. This allows us to extract and "check" various parts of the transaction, such as its inputs, outputs, target addresses, or the involved Bitcoin amounts.
For specific cryptographic principles, one could refer to Andrew Poelstra’s article, “CAT and Schnorr Tricks”.
In summary, the versatility of OP_CAT allows it to emulate nearly any Covenant opcode. A multitude of Covenant opcodes rely on OP_CAT's functionality, which significantly advances its position on the merge list. Theoretically, relying solely on OP_CAT and existing Bitcoin opcodes, we are hopeful to build a trust-minimized BTC ZK Rollup. Starknet, Chakra, and other ecosystem partners are actively pushing for this to happen.
As we explore the diverse strategies for scaling Bitcoin and enhancing its programmability, it becomes clear that the path forward involves a blend of native improvements, off-chain computations, and sophisticated scripting capabilities.
Without a flexible base layer, it is impossible to build a more flexible second layer.
Off-chain computation scaling is the future, but Bitcoin's programmability needs to break through to better support this scalability and become a true global currency.
However, the nature of computation on Bitcoin is fundamentally different from that on Ethereum. Bitcoin only supports "verification" as a form of computation and cannot perform general computations, whereas Ethereum is inherently computational, with verification being a byproduct of computation. This difference is evident from one point: Ethereum charges a Gas Fee for transactions that fail to execute, whereas Bitcoin does not.
Covenants represent a form of smart contract based on verification rather than computation. Except for a few Satoshi fundamentalism, it seems that everyone considers Covenants a good choice for improving Bitcoin. However, the community continues to debate fiercely over which approach should be used to implement Covenants.
APO, OP_VAULT, and TLUV lean towards direct applications, and choosing them can achieve specific applications in a cheaper and more efficient way. Lightning Network enthusiasts would prefer APO for achieving LN-Symmetry; those looking to implement a Vault would be best served by OP_VAULT; for building CoinPool, TLUV offers more privacy and efficiency. OP_CAT and TXHASH are more versatile, with a smaller probability of security vulnerabilities, and can implement more use cases when combined with other opcodes, perhaps at the cost of script complexity. CTV and CSFS have adjusted the blockchain processing, with CTV implementing delayed outputs and CSFS implementing delayed signatures. MATT stands out with its strategy of optimistic execution and fraud proofs, utilizing the structure of the Merkle Trie to implement universal smart contracts, though it still requires new opcodes for introspective capabilities.
We see that the Bitcoin community is actively discussing the possibility of obtaining Covenants through a soft fork. Starknet has officially announced its entry into the Bitcoin ecosystem, planning to implement settlements on the Bitcoin network within six months after the merger of OP_CAT. Chakra will continue to monitor the latest developments in the Bitcoin ecosystem, push for the merger of the OP_CAT soft fork, and leverage the programmability brought by Covenants to build a more secure and efficient Bitcoin settlement layer.