Covenants: Programmability of Bitcoin

HASHKEY CAPITAL Reading Time: 15.64Min


There has been a recent wave of discussion in the Bitcoin community about re-enabling opcodes such as OP_CAT, and Taproot Wizard has attracted a lot of attention by launching Quantum Cats’ NFT, claiming to have gotten assigned BIP-420. Proponents claim that enabling OP_CAT will realize “covenants”, and thus bring smart contracts or programmability in Bitcoin.


If you notice the word “covenants” and do a little searching, you’ll see that this is another big rabbit hole. Developers have been talking for years about technologies that implement covenants, such as OP_CTV, APO, OP_VAULT, and more, in addition to OP_CAT.


More precisely, current Bitcoin scripts also have some kinds of covenants, such as opcode-based time locks, which are implemented by introspecting a transaction’s nLock or nSequence field to limit the amount of time before the transaction can be spent, but are still just limited to time restrictions.


So what exactly are Bitcoin’s “covenants”? Why has it attracted so much attention and discussion from developers for years? What programmability of Bitcoin can be achieved? What are the design principles behind it? This article attempts to provide an overview and discussion.


What are “Covenants”?


Covenant is a mechanism that can set conditions on future Bitcoin transactions.


In fact current Bitcoin scripts contain constraints, such as having to enter a legitimate signature、 sending in compliant scripts when spending. As long as the user can unlock it, he can spend that UTXO anywhere he wishes.


The Covenant is to make more restrictions on top of this limitation on how to unlock, such as limiting the spending of UTXO after it is spent, which is to achieve an effect similar to that of earmarking, or other input conditions fed into a transaction, etc.


So why do developers and researchers design these restriction checks? That is because covenants are not just restrictions for nothing, but more on setting the rules for trade execution. In this way, the user can only execute transactions according to the pre-set rules, thus completing the intended business process.

So rather counter-intuitively, this brings more application scenarios.


Application Scenarios


Ensuring Staking Penalties


One of the most intuitive examples of a covenant is Babylon’s slashing transaction in the Bitcoin staking process.


Babylon’s Bitcoin staking process involves users sending their BTC to a special script on the main chain with two spend conditions:

  • Happy ending: after a certain amount of time, the user can unlock with their own signature, which means the process of unstaking is complete.

  • Bad ending: If the user has a double-spend attack on the PoS chain, the user can unlock the assets with his/her own signature through EOTS (extractable one-time signatures), and a part of the assets can be forced to be sent to the burn address (slash) by an executing actor in the network.



Source: Bitcoin Staking: Unlocking 21M Bitcoins to Secure the Proof-of-Stake Economy


Note the word “forced”, which means that even if the UTXO can be unlocked, the asset can’t be sent anywhere else, it can only be burned. This ensures that an evil user can’t get away with transferring the asset back to him/herself with his/her own known signature.


This feature, after implementing covenants such as OP_CTV, can be implemented by adding opcodes to the “bad ending” of the staking script.


Before OP_CTV is enabled, Babylon will need a workaround to emulate the effect of enforcing the covenants by having the user + committee work together.


Congestion Control/Scale


Generally speaking, congestion is when the fee is high on Bitcoin with a relatively large number of transactions accumulated in the transaction pool waiting to be packed, so if a user wants to confirm a transaction quickly, he or she needs to raise the fee.


At that point, if a user has to send multiple transactions to multiple addresses, they will have to raise their fees and incur higher costs. Accordingly, it will further push up the transaction fee of the whole network.


If there is a covenant, then there is a solution: a single committed transaction with multiple outputs. This commitment can convince all the recipients that the final transaction will take place and everyone can wait until the fee is low before sending the specific transaction.


As shown below, when the demand for block space is high, it becomes very expensive to conduct transactions. By using OP_CHECKTEMPLATEVERIFY, a high-volume payment processor can aggregate all of its payments into a single O(1) transaction for confirmation. Then, after a period of time, when the demand for block space decreases, payments can be expanded out of that UTXO


Source: https://utxos.org/uses/scaling/


This scenario is one of the more typical use cases presented by this OP_CTV restriction. Many more use cases can be found at https://utxos.org/uses. In addition to the congestion control mentioned above, the page lists Soft Fork Bets, Decentralized options, Drivechains, Batch Channels, Non-Interactive Channels, Trustless Coordination-Free Mining Pools, Vaults, Safer Hashed Time Locked Contracts (HTLCS) Limits, and more.


Vaults


Vaults are one of the more widely discussed use cases of Bitcoin applications, especially within the realm of covenants. Because day-to-day operations inevitably involve balancing the need to keep funds safe with the need to use them, one would like to have such a vault that can keep funds safe, or even restrict their use when the account is hacked (eg, compromising the private key).


Based on the techniques used to implement restriction clauses, this kind of custodial vault can be built relatively easily.


Take the design scheme of OP_VAULT as an example: when spending funds in the vault, a transaction needs to be sent to the chain first. This transaction indicates the intention to spend the vault, which is a “trigger”, and conditions are set in it:

  • If all is well, then the second transaction is eventually withdraw the funds. After waiting for N blocks, the funds can be spent further anywhere.

  • If it turns out that the transaction was stolen (or coerced in a “trigger attack”), the assets can be sent immediately to another secure address (safer for the user) immediately before the withdrawal transaction is sent after N blocks.


Process of OP_VAULT ,source:BIP-345


Note that it is also possible to build out a vault without covenants, and a possible way to do that is to use a private key to prepare a signature for later spending, and then destroy this private key. However, there are still more limitations, such as the need to ensure that the private key has been destroyed (similar to the trusted setup process in zero-knowledge proofs), and the lack of flexibility in determining the amount and fee in advance (because of pre-signing).


Precomputed vaults and OP_VAULT ,source:BIP-345


More robust and flexible state channels


It can generally be assumed that state channels, including the Lightning Network, have nearly the same security as the main chain (in terms of ensuring that nodes can observe the latest state and can properly post the latest state to the chain). However, with the covenants, some new state channel design can be made on top of the Lightning Network more robustly or flexibly. Some of the better-known ones include Eltoo, Ark.。


Eltoo (also known as LN-Symmetry) is a typical example. Taking the acronym of “L2”, this technology proposes an execution layer for the Lightning Network that allows any later channel state to replace the previous state without a penalty mechanism, thus avoiding the need for Lightning Network nodes to save multiple previous states to prevent their adversaries from committing malicious acts. To achieve the above effect, Eltoo proposes the SIGHASH_NOINPUT signature, APO (BIP-118).


Ark aims to reduce the difficulty of inbound liquidity and channel management of the lightning network. It is a protocol in the form of joinpool, where multiple users can accept a service provider as a counterparty for a certain period of time, and trade virtual UTXOs (vUTXOs) off-chain, but share a UTXO on-chain to reduce costs. Similar to vaults, Ark can be implemented on the current Bitcoin network; however, with the introduction of covenants, Ark can reduce the amount of interaction required based on transaction templates, enabling a more trustless one-sided exit.


Overview of Covenants


As can be seen from the above applications, covenants are more like an effect than a certain technology, and as such there are many technical ways of implementing them. They can be categorized as:

  • Type: generic, restrictive

  • Implementation: opcode-based, signature-based

  • Recursion: recursive, non-recursive



Here recursive means: there are some implementations of covenants that can also limit the output of the next transaction by limiting the output of this transaction, which means each transaction in the chain of transactions is restricted by the previous one.

Some of the popular covenants designs include:


Designs of Covenants


As can be seen from the previous introduction, current Bitcoin scripts mainly restrict the conditions for unlocking and do not restrict how that UTXO can be further spent. To implement covenants, we need to think the other way around: why can’t the current Bitcoin scripts implement covenants?

The main reason is that current Bitcoin scripts cannot read the transaction itself, which means the introspection of the transaction.


If we could implement introspection — inspecting anything in the transaction (including the output) — then we could implement covenants.


So the design of the covenants is also centered around how to implement introspection.


Opcode-based vs Signature-based


The simplest and crudest idea is to add one or more opcodes (one opcode + multiple parameters, or multiple opcodes with different functions) and read the content of the transaction directly. This is also known as the opcode-based idea.


Another way of thinking is that instead of reading and checking the content of the transaction itself directly in the script, the hash of the transaction content can be used, which means if this hash has been signed, then by transforming opcode like OP_CHECKSIG in the script to check this signature, it is possible to indirectly implement the transaction introspection and covenants. This idea is based on the signature design approach. It mainly includes APO and OP_CSFS.


APO


SIGHASH_ANYPREVOUT (APO) is a proposal for a signature hash. The simplest way to sign is to commit to both the inputs and outputs of a transaction, but there is a more flexible way for Bitcoin to selectively commit to either the inputs or outputs of a transaction, known as SIGHASH.



The current range of SIGHASH and its combinations of signatures for the inputs and outputs of transactions (source: Mastering Bitcoin, 2nd)


As shown above, in addition to ALL, which applies to all data, NONE is signed in such a way that it applies only to all inputs and not to outputs, and SINGLE builds on this by applying it only to outputs with the same input index number. Additionally, SIGHASH can be combined, with the ANYONECANPAY modifier superimposed, to apply only to one input.


APO’s SIGHASH, on the other hand, only signs the output, not the input. This means that a transaction signed with APO can be attached later to any UTXO that meets the conditions.



This flexibility is the rationale behind APO’s implementation of covenants:

  • One or more transactions can be created in advance

  • The information from these transactions is used to construct a public key that can only the spending signature be derived from/checked against

  • so that any assets sent to this public key address can only be spent through pre-created transactions.


It’s worth noting that because this public key has no corresponding private key, it ensures that these assets can only be spent through pre-created transactions. Then, we can implement a covenant by specifying where the assets go in these pre-created transactions.


This can be further understood by comparing it to Ethereum’s smart contracts: what we can achieve with smart contracts is that we can only withdraw money from a contracted address if certain conditions are met, rather than spending it arbitrarily with an EOA signature. From this point of view, Bitcoin can achieve this effect through improvements in the signature mechanism.


The problem with the above process, however, is that there is a circular dependency in the computation, as one needs to know the input to pre-sign and create the transaction.


The significance of the APO and SIGHASH_NOINPUT implementations of this signature method is that it solves this circular dependency problem by only needing to know (specify) the full output of the transaction at the time of computation.


OP_CTV


OP_CHECKTEMPLATEVERIFY (CTV), or BIP-119, uses an improvement to Opcode. It takes the commitment hash as an argument and requires that any transaction that executes an opcode contains a set of outputs that match that commitment. With CTV, it would allow Bitcoin users to limit how they use Bitcoin.


Originally introduced as OP_CHECKOUTPUTSHASHVERIFY (COSHV) and with an early focus on the ability to create congestion control transactions, criticism of the proposal has also centered on the fact that it is not generic enough and is too specific to the congestion control use case.


In the congestion control use case mentioned above, Alice, the sender, could create 10 outputs and hash those 10 outputs, and use the resulting digest to create a tapleaf script that contains COSHV. Alice could also use the public keys of the participants to form a Taproot internal key that would allow them to collaborate on spending the money without revealing the path of the Taproot script.


Alice then gives each recipient a copy of all 10 outputs so that each of them can verify Alice’s setup transaction. When they want to spend the payment later, any of them can create a transaction with the committed outputs.


Throughout the process, as Alice creates and sends the setup transaction, Alice can send these 10 copies of the outputs via existing asynchronous communication methods, such as email or cloud drives. This means that the recipients do not need to be online or interact with each other.


Source: https://bitcoinops.org/en/newsletters/2019/05/29/#proposed-transaction-output-commitments


Similar to APOs, addresses can be constructed based on spending conditions, and “locks” can be made in different ways, including extra keys, relative or fixed timelocks, and other logics to combine them.


Source: https://twitter.com/OwenKemeys/status/1741575353716326835


Based on this, CTV proposes to check whether the spent transaction after hash matches the defined one, which means the transaction data is used as the key to unlocking the “lock”.


We can extend the above example of 10 receivers, where a receiver can further make his address key be a signed but unbroadcast TX sending to the next batch of receivers, and so on, forming a tree structure as shown in the figure below. Alice can construct a change in account balances involving multiple users on the chain using only 1 UTXO of block space.


Source: https://twitter.com/OwenKemeys/status/1741575353716326835


And what if one of the leaves is a lightning channel, or cold storage, or some other payment path? Then the tree will be expanded from a single-dimensional multi-layer payment tree to a multi-dimensional multi-layer payment tree, and the scenarios that can be supported will be richer and more flexible.


Source: https://twitter.com/OwenKemeys/status/1744181234417140076


Since its proposal, CTV has gone through a name change from COSHV in 2019, being assigned BIP-119 in 2020, and the emergence of Sapio, the programming language used to create the contract to support CTV, and has received a lot of community discussion, updates, and debate about its activation options in 2022 and 2023, and is still one of the most discussed soft fork upgrade proposals in the community.


OP_CAT


OP_CAT, as described in the opening paragraph, is also an upgrade proposal that is currently receiving a lot of attention, and implements a function that concatenates two elements or two data sets from the stack. Although it looks simple, OP_CAT is very flexible and can be implemented in scripts in many ways.


The most direct example is the operation of the Merkle Tree, which can be interpreted as two elements being concatenated and then hashed. Currently, there are OP_SHA256 and other hash opcodes in the Bitcoin script, so if you can concatenate two elements using OP_CAT, you can implement the Merkle Tree verification function in the script, which also provides the ability of light client verification to some extent.


Another basis for implementation is the enhancement of Schnorr signatures: you can set a script’s spend signing condition to be a concatenation of the user’s public key and a public nonce; then if the signer wants to sign another transaction to spend the funds elsewhere, he or she has to use the same nonce, which can leak the private key. That is, OP_CAT achieves the commitment to nonce and thus ensures the validity of the signed transaction.


Other applications of OP_CAT include Bistream, tree signaturesquantum-resistant Lamport signatures, vaults, and more.


OP_CAT itself is not a new feature, as it existed in the earliest versions of Bitcoin, but was disabled in 2010 due to its potential to be exploited by attackers. For example, repeated use of OP_DUP and OP_CAT could easily cause a full node stack to explode when processing such scripts, as seen in this demo.


But won’t the aforementioned stack explosion problem occur nowadays once OP_CAT has been re-enabled? Because the current OP_CAT proposal only involves enabling it in tapscript, which has a limit of 520 bytes per stack element, it will not cause the previous stack explosion problem. There are also some developers who think that Satoshi Nakamoto may be too harsh by disabling OP_CAT outright. However, due to the flexibility of OP_CAT, it may be true that some application scenarios that could lead to vulnerabilities will exist.


Therefore, combining the application scenarios and potential risks, OP_CAT has received a lot of attention recently, and has also had a PR review, and is currently one of the hottest upgrade proposals.


Conclusion


“Self-Regulation Brings Freedom”, as can be seen from the introduction above, covenants can be implemented directly into Bitcoin scripts to qualify further spending on transactions, thus enabling transaction rules similar to the effect of smart contracts. This programming approach can be verified more natively on Bitcoin than off-chain approaches such as BitVM, and can also improve applications on the main chain (congestion control), off-chain applications (state channel), and other new application directions (staking slashing, etc.).


The implementation techniques of the covenants, if combined with some other upgrades, could further unlock the potential of programmability. For example, the recent proposal for 64-bit arithmetic


in the review could be further combined with the proposed OP_TLUV or other covenants that could be programmed based on the number of satoshi output by a transaction.


However, covenants can also lead to unplanned abuses or vulnerabilities, so the community is cautious about this as well. Also, an upgrade of the covenants would need to involve a soft fork upgrade of the consensus rules. Given the circumstances surrounding the taproot upgrade, it is likely that the upgrade related to the covenants will also take time to complete.


Special Thanks

Thanks AjianFisher and Ben for reviewing and suggestions!


References



Disclaimer: This material is for general information only, and does not constitute, nor should it be interpreted as, any form of investment advice, solicitation, or offer of any investments, and no liability or responsibility is accepted by HashKey Capital in relation to the use of or reliance on any such information.