Written by Chakra Research

Overview

Compared with Turing-complete blockchains such as Ethereum, scripts on Bitcoin are considered to be very limited and can only perform basic operations, and do not even support multiplication and division. More importantly, the data on the blockchain itself is almost impossible to be read by the script, resulting in a serious lack of flexibility and low programmability. Therefore, people have long been trying to find ways to introspect Bitcoin scripts.

Introspection refers to the ability to allow Bitcoin scripts to inspect and constrain transaction data. This allows scripts to control the use of funds based on the specific details of the transaction, thereby achieving more complex functions. Currently, most Bitcoin opcodes only have two functions, pushing user-provided data onto the stack or manipulating data already on the stack. Introspection opcodes can push the data of the current transaction (such as timestamp, amount, transaction ID, etc.) onto the stack, providing more fine-grained control over how UTXOs are spent.

Currently, there are only three main opcodes in Bitcoin Script that support introspection: CHECKLOCKTIMEVERIFY, CHECKSEQUENCEVERIFY, and CHECKSIG; CHECKSIG also has variants such as CHECKSIGVERIFY, CHECKSIGADD, CHECKMULTISIG, and CHECKMULTISIGVERIFY.

Covenants are simply restrictions on how tokens are transferred. Users can specify how UTXOs are distributed through covenants. Many covenants are implemented through introspection opcodes, and introspection has now been categorized under the covenant entry in Bitcoin Optech.

Bitcoin currently has two contracts, CSV (CheckSequenceVerify) and CLTV (CheckLockTimeVerify), both of which are time contracts, which are the basis for many expansion plans, such as the Lightning Network. From this we can also see that Bitcoin's expansion plan relies heavily on introspection and contracts.

How to add restrictions to the transfer of tokens? In the crypto world, the most common method is commitment, which is often implemented through hashing. In order to prove that we meet the transfer requirements, we need to verify it through a signature mechanism. Therefore, there are many adjustments to hashing and signatures in the contract.

Below we describe the widely discussed contract opcode proposal.

CTV (CheckTemplateVerify) BIP-119

CTV (CheckTemplateVerify) is a Bitcoin upgrade that is hotly debated by the community and is included in BIP-119. CTV enables the output script to specify the template for using the funds in the spending transaction, including the transaction's nVersion, nLockTime, scriptSig hash, input count, sequences hash, output count, outputs hash, input index and other fields. These template restrictions are implemented through a hash commitment. When spending in the future, the script will check that the hash value of the specified field in the spending transaction matches the hash value in the input script. These templates actually limit the time, method, amount and other details of the UTXO's future spending transactions.

It is worth noting that the input TXID is excluded from the hash commitment. This exclusion is necessary because in both Legacy and Segwit transactions, the TXID is generated based on the value of the scriptPubKey in the default SIGHASH_ALL signature type. Therefore, including the TXID will result in a loop in the hash commitment and cannot be successfully constructed.

CTV implements introspection by directly obtaining the specified information of the transaction through a new opcode, hashing it, and comparing it with the commitment in the stack. This introspection method consumes less space on the chain, but lacks certain flexibility.

The foundation of Bitcoin's second-layer solutions such as the Lightning Network is pre-signed transactions. Pre-signatures usually refer to generating and signing transactions in advance, but not broadcasting them to the network until certain conditions are met. In essence, CTV implements a more stringent pre-signature function, publishing the pre-signed commitment directly on the chain, and transactions can only be carried out according to the pre-template.

CTV was originally proposed to ease Bitcoin congestion, which can also be called congestion control. When Bitcoin is congested, CTV can be used to commit to multiple future transactions through a single transaction, without broadcasting multiple transactions during congestion, and the actual transaction can be completed after the block congestion is relieved. Congestion control can be of great help when an exchange is run. In addition, the template can also be used for the implementation of a vault to prevent hacker attacks. Since the destination of the funds is determined, hackers cannot send UTXOs using CTV scripts to their own addresses.

CTV can bring great improvements to the second-layer network. For example, for the implementation of Timeout Trees and Channel Factory in Lightning Network, through CTV, a single UTXO can be expanded into a CTV tree, and multiple state channels can be opened at the same time, while there is only one transaction and one confirmation on the chain. In addition, CTV also provides support for atomic transactions ATLC in Ark protocol.

APO (SIGHASH_ANYPREVOUT) BIP-118

BIP-118 proposes a new signature hash flag for tapscript to facilitate writing more flexible spending logic, called SIGHASH_ANYPREVOUT. APO is similar to CTV in many ways. Facing the loop problem between scriptPubKeys and TXID, APO's solution is to exclude relevant information about the input and only sign the output, so that transactions can be dynamically bound to different UTXOs.

Logically speaking, the signature verification operation OP_CHECKSIG (and similar opcodes) has three functions:

  1. Assembling the parts of a spend transaction

  2. Hash it.

  3. Verifies that the hash was signed by the given key.

The specific content of the signature has a lot of room for adjustment. Which transaction fields are assembled for signing is determined by the SIGHASH flag. According to the definition of the BIP 342 signature opcode, the SIGHASH flag is divided into SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, SIGHASH_ANYONECANPAY, etc. Among them, SIGHASH_ANYONECANPAY controls input, and the others control output.

SIGHASH_ALL is the default SIGHASH flag, which signs all outputs; SIGHASH_NONE does not sign any output; SIGHASH_SINGLE signs a specified output. SIGHASH_ANYONECANPAY can be set together with the first three SIGHASH flags. If SIGHASH_ANYONECANPAY is set, only the specified input is signed, otherwise all inputs need to be signed.

Obviously, none of these SIGHASH flags can eliminate the impact of the input. Even SIGHASH_ANYONECANPAY requires a commitment to an input.

Therefore, BIP 118 proposes SIGHASH_ANYPREVOUT. APO signatures do not need to commit to the input UTXO being spent (called PREVOUT), but only need to sign the output, providing greater flexibility for the control of Bitcoin. By pre-building transactions and constructing corresponding single-use signatures and public keys, assets sent to the public key address must be spent through pre-built transactions to implement the contract. 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 fees without the need for new signatures. In addition, for multi-signature wallets, the fact that signatures do not rely on spent inputs makes operations easier.

Since the cycle between scriptPubKeys and input TXIDs is eliminated, APO can implement introspection by adding output data to the witness, of course this still requires additional witness data space consumption.

For off-chain protocols such as the Lightning Network and the Vault, APO reduces the intermediate states that need to be saved, greatly reducing storage requirements and complexity. The most direct use case of APO is Eltoo, which simplifies the channel factory, builds a lightweight and cheap watchtower, and allows unilateral exit without leaving error states, improving the performance of the Lightning Network in all aspects. APO can also be used to simulate the functions of CTV, but it requires personal storage signatures and pre-signed transactions, which is more expensive and less efficient than CTV.

The criticism of APO mainly focuses on the fact that it requires a completely new key version, which cannot be achieved through simple backward compatibility. In addition, the new signature hash type may bring potential double-spending risks. After extensive discussion in the community, APO requires the addition of ordinary signatures on the basis of the original signatures, and the security issues are alleviated, so it is also awarded the BIP-118 number.

OP_VAULT BIP-345

BIP-345 proposes to add two new opcodes, OP_VAULT and OP_VAULT_RECOVER, which, combined with CTV, implement a dedicated contract that allows users to force a delay period for the spending of specified tokens, during which previous spending can be "undone" through a recovery path.

A user can construct a vault by creating a specific Taproot address, which needs to contain at least two scripts in the MAST, an OP_VAULT script to facilitate the expected withdrawal process, and another OP_VAULT_RECOVER script to ensure that coins can be recovered at any time before the withdrawal is completed.

How does OP_VAULT achieve interruptible time-locked withdrawals? In simple terms, the OP_VAULT opcode accomplishes one thing: replace the spent OP_VAULT script with the specified script, which actually completes the update of a single leaf node of MAST, and the remaining leaf nodes remain unchanged. It is similar to the design of TLUV, except that OP_VAULT does not support the update of internal keys.

By introducing a template during the script update process, the effect of limiting payments can be achieved. The time lock parameter is specified by OP_VAULT, and the template brought by the CTV opcode limits the output set spent through the script path.

BIP-345 was created for vaults. With OP_VAULT and OP_VAULT_RECOVER, users can have a secure custody method, with a highly secure key (paper wallet, distributed multi-signature) as a recovery path, and a certain spending delay for the rest of their daily payments. The user's device continuously monitors the vault's spending, and if an unexpected transfer occurs, the user can recover.

Fees need to be considered when implementing BIP-345 vaults, especially when recovering transactions. Possible solutions include CPFP, temporary anchors, and new signature hash flags such as SIGHASH_GROUP.

TLUV (TapleafUpdateVerify)

The TLUV solution is built around Taproot and aims to solve the problem of efficient exit of shared UTXO. The guiding idea is that when a Taproot output is spent, we can partially update the internal key and MAST by using the internal structure and cryptographic transformation of the Taproot address according to the update steps described by the TLUV script, thereby realizing the contract function.

The idea of ​​the TLUV scheme is to create a new Taproot address based on the current consumption input through a new opcode TAPLEAF_UPDATE_VERIFY, by performing one or more of the following operations:

  • Update internal public key

  • Clipping the Merkle Path

  • Remove the currently executing leaf node

  • Add a new leaf node at the end of the Merkle path

Specifically, TLUV receives three inputs:

  • A method for updating internal public keys

  • A new leaf node is specified for the Merkle path

  • A parameter that specifies whether to remove the current leaf node and/or how many Merkle path leaf nodes to remove.

The TLUV opcode calculates the updated scriptPubKey and verifies that the output corresponding to the current input consumes that scriptPubKey.

The inspiration scenario of TLUV is the joint fund pool (CoinPool). Today, a joint pool can be created using only pre-signed transactions, but if you want to achieve a permissionless exit, you need to create an exponentially growing number of signatures, and TLUV can achieve a permissionless exit without any pre-signature. For example, a group of partners use Taproot to build a shared UTXO, pooling each other's funds. They can use Taproot keys to move funds internally, or they can sign together to initiate payments to the outside. Individuals can exit the shared fund pool at any time and delete their own payment path. The rest of the people can still complete the payment through the original path, and the individual's exit will not expose additional information about other people inside. Compared with non-pooled transactions, this method is more efficient and private.

The TLUV opcode implements partial spending restrictions by updating the original MAST, however, it does not implement introspection of output amounts. Therefore, a new opcode IN_OUT_AMOUNT needs to be included, which pushes two pieces of data onto the stack: the amount of this input UTXO and the amount of the corresponding output, and then the person who is expected to use TLUV uses mathematical operators to verify that the funds are appropriately reserved in the updated scriptPubKey.

Introspection of output amounts adds another complication, because Bitcoin amounts require up to 51 bits to be expressed in satoshis, but script only allows 32-bit math, requiring operators in scripts to be upgraded by redefining opcode behavior, or using SIGHASH_GROUP instead of IN_OUT_AMOUNT.

TLUV is expected to provide a solution for decentralized Layer 2 funding pools. Of course, its reliability in tweaking the Taproot public key remains to be confirmed.

MATT

MATT (Merkleize All The Things) attempts to achieve three goals: Merkle state, Merkle script and Merkle execution, and then realize general smart contracts.

Merkle state: Build a Merkle Trie where each leaf node is the hash value of the state, and the Merkle Root represents the state of the entire contract.

Merkle script: MAST composed of Tapscript, each leaf node is a possible state transition path.

Merkle execution: Merkle execution is achieved through encrypted commitment and fraud challenge mechanism. For any computational function, participants can publish a commitment after off-chain calculation, f(x)=y. If other participants find that the calculation result is wrong f(x)=z, they can challenge it and arbitrate through binary search, which is the same as the principle of Optimistic Rollup.

Merkle-based Execution Fraud Challenges

To implement MATT, Bitcoin scripts need to have the following functionality:

  1. Enforce an output to have specific scripts (and their amounts)

  2. Append a piece of data to an output

  3. Read data from the current input (or other inputs)

The second point is very important. Dynamic data means that the state can be calculated based on the input data provided by the consumer, because this provides a simulation of the state machine and can determine the next state and additional data. The MATT scheme is implemented by proposing the OP_CHECKCONTRACTVERIFY (OP_CCV) opcode, which is a merger of the previously proposed OP_CHECKOUTPUTCONTRACTVERIFY and OP_CHECKINPUTCONTRACTVERIFY opcodes, and specifies the object of the operation through an additional flags parameter.

Control of output amount: The most direct way is through direct introspection, however the output amount is a 64-bit number, which requires 64-bit operations, which is very complex in the implementation of Bitcoin script. CCV uses a delayed check method, similar to OP_VAULT, all inputs with CCV to the same output, their input amounts are summed as the lower limit of the output amount. The delay is because the check is performed during the transaction process rather than during the input script evaluation.

Given the versatility of fraud proofs, some variant of the MATT contract should enable all types of smart contracts or second-layer constructions, although additional requirements (such as capital locks and challenge period delays) need to be accurately evaluated; further research is needed to evaluate which applications are acceptable transactions. For example, using cryptographic commitments and fraud challenge mechanisms to simulate the OP_ZK_VERIFY function to implement trustless Rollup on Bitcoin.

In fact, it is already happening. Johan Torås Halseth used the OP_CHECKCONTRACTVERIFY opcode in the MATT soft fork proposal to implement elftrace, which can verify all programs that support RISC-V compilation on the Bitcoin chain, allowing one party in the contract agreement to receive funds through the contract, thus achieving a bridge to Bitcoin's native verification.

CSFS (OP_CHECKSIGFROMSTACK)

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 it verifies is obtained by serializing the transaction using this opcode, and other messages are not allowed to be specified. In short, OP_CHECKSIG (and its related operations) plays a role in verifying whether the UTXO used as the transaction input is authorized to be spent by the holder of the signature through the signature mechanism, thereby protecting the security of Bitcoin.

CSFS, as the name implies, checks the signature from the 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, which means that people can pass arbitrary messages to the stack through witness data and verify them through CSFS, which makes some innovations on Bitcoin possible.

The flexible nature of CSFS enables it to implement multiple mechanisms such as payment signatures, authority delegation, oracle contracts, double-spending protection bonds, and more importantly, transaction introspection. The principle of using CSFS for transaction introspection is very simple. If the transaction content used by OP_CHECKSIG is pushed to the stack through a witness, the content is verified once with both CSFS and OP_CHECKSIG using the same public key and signature. If both pass successfully, then the content of any message passed to CSFS is the same as the serialized spend transaction (and other data) implicitly used for OP_CHECKSIG. We have verified transaction data on the stack and can use other opcodes to impose restrictions on spend transactions.

CSFS is often used in conjunction with OP_CAT, because OP_CAT allows the concatenation of different fields of a transaction to be serialized, allowing for more precise selection of transaction fields that require introspection. Without OP_CAT, the script cannot recalculate the hash from individually inspectable data, so all it can really do is check if the hash is equal to a specific value, which means that the coin can only be spent through a single specific transaction.

CSFS can implement CLTV, CSV, CTV, APO and other operation codes. It is a general introspection operation code, so it can also help Bitcoin Layer 2 expansion plan. The disadvantage is that a complete copy of the signed transaction needs to be added to the stack, which may significantly increase the size of the transactions you want to introspect with CSFS. In comparison, single-purpose introspection opcodes like CLTV and CSV use minimal overhead, but adding each new special introspection opcode requires a consensus change.

TXHASH (OP_TXHASH)

OP_TXHASH is a very straightforward introspection opcode that lets the operator choose a hash of a field to push onto the stack. Specifically, OP_TXHASH pops a txhash flag from the stack, computes a (tagged) txhash based on that flag, and then pushes the resulting hash onto the stack.

Due to the similarities between TXHASH and CTV, there has been a lot of discussion about the two within the community.

TXHASH can be seen as a general upgrade of CTV, providing a more advanced transaction template that allows users to explicitly spend part of a transaction, which solves many issues regarding transaction fees. Compared to other contract opcodes, TXHASH does not require a copy of the required data in the witness, further reducing the need for storage; unlike CTV, TXHASH is not NOP-compatible and can only be implemented in tapscript; the combination of TXHASH and CSFS can be used as an alternative to CTV and APO.

From the perspective of how contracts are constructed, TXHASH makes it easier to implement an "additive contract", push all the parts of the transaction data you want fixed onto the stack, hash them all together, and verify that the resulting hash matches the fixed value; CTV makes it easier to implement a "subtractive contract", push all the parts of the transaction data you want to keep free onto the stack. Then use a rolling OP_SHA256 to start from a fixed intermediate state that commits to a prefix of the transaction hash data. The free part is hashed into this intermediate state.

The TxFieldSelector field defined in the TXHASH specification is expected to be extended to other opcodes, such as OP_TX.

The TXHASH-related BIP is currently in Draft status on Github and the number has not been determined.

OP_CAT

OP_CAT is a rather mysterious operation code. It was abandoned by Satoshi Nakamoto due to security issues. Recently, it has aroused a lot of discussion among Bitcoin core developers and even triggered Meme culture on the Internet. Finally, OP_CAT was approved as BIP-347 and was called by many people as the BIP proposal most likely to be passed in the near future.

In fact, the behavior of OP_CAT is very simple, it concatenates two elements on the stack into one. How to implement the contract function?

In fact, the function of splicing two elements corresponds to a powerful cryptographic data structure, Merkle Trie. The construction process of Merkle Trie only requires two operations, splicing and hashing, and hash functions are available in Bitcoin scripts. Therefore, with OP_CAT, we can theoretically verify Merkle Proof in Bitcoin scripts, which is the most commonly used lightweight verification method in blockchain.

As mentioned before, CSFS, with the help of OP_CAT, can implement a general contract scheme. In fact, without CSFS, OP_CAT itself can achieve introspection of transactions by leveraging the structure of Schnorr signatures.

In Schnorr signature, the message to be signed is composed of the following fields:

These fields contain the main elements of the transaction, and by placing them in scriptPubKey or witness, using OP_CAT and OP_SHA256, we can construct a Schnorr signature and use OP_CHECKSIG to verify it. If the verification passes, the verified transaction data is retained in the stack, enabling transaction introspection, being able to extract and "check" various parts of the transaction, such as its inputs, outputs, destination addresses, or the amount of Bitcoin involved.

For specific cryptographic principles, please refer to the article CAT and Schnorr Tricks published by Andrew Poelstra.

In summary, OP_CAT's flexibility allows it to emulate almost any contract opcode, and a large number of contract opcodes rely on OP_CAT's functionality, which puts it significantly ahead on the merge list. In theory, relying solely on OP_CAT and existing Bitcoin opcodes, we can hope to build a trust-minimized BTC ZK Rollup, and Starknet, Chakra, and other ecological partners are actively promoting this.

Conclusion

As we explore multiple strategies for scaling Bitcoin and increasing its programmability, it becomes clear that the path forward involves a combination of native improvements, off-chain computation, and sophisticated scripting capabilities.

Without a flexible base layer, it is impossible to build a more flexible second layer.

Off-chain computing expansion is the future, but there must be breakthroughs in the programmability of Bitcoin to better support expansion and become a true world currency.

However, the computation of Bitcoin and Ethereum is actually fundamentally different. Bitcoin only supports "verification" as a form of computation and cannot perform general computation, while Ethereum is computational in nature, and verification is a byproduct of computation. This difference can be seen from one point: Ethereum charges a handling fee in the form of Gas for failed transactions, while Bitcoin does not.

The contract implements a form of smart contract based on verification rather than calculation. With regard to the contract, except for a very small number of Satoshi fundamentalists, it seems that everyone thinks that the contract is a good choice for improving Bitcoin. However, the community has been arguing about which solution to implement the contract.

APO, OP_VAULT, and TLUV are more inclined to direct applications. Choosing them can realize specific applications in a cheaper and more efficient way. Lightning Network enthusiasts will prefer APO because it can realize LN-Symmetry; if you want to realize a vault, it is best to use OP_VAULT; to build a CoinPool, TLUV is more private and efficient. OP_CAT and TXHASH are more versatile and less likely to have security vulnerabilities. By combining with other opcodes, more use cases can be realized, of course, it may be necessary to pay the price of script complexity. CTV and CSFS have made adjustments to the processing of the blockchain. CTV has achieved delayed output and CSFS has achieved delayed signature. MATT is relatively unique. It uses the ideas of optimistic execution and fraud proofs and the structure of Merkle Trie to realize general smart contracts, but it still needs new opcodes to bring introspection functions.

We have seen that the Bitcoin community has been intensively discussing the possibility of obtaining contracts for Bitcoin through soft forks. Starknet has officially announced its entry into the Bitcoin ecosystem and plans to achieve settlement on the Bitcoin network within six months after the OP_CAT merger. Chakra will continue to pay attention to the latest developments in the Bitcoin ecosystem, promote the merger of the OP_CAT soft fork, and use the programmability brought by introspection and contracts to build a more secure and efficient Bitcoin settlement layer.

Thanks to Jeffrey, Ben, Mutourend, Lynndell for reviewing and providing suggestions on this article