Have you fallen into the ‘rabbit hole’ of covenants?
Covenants are an old yet fresh topic. As early as 2013, developers began discussing this topic, and in recent years, multiple BIPs aimed at implementing covenants have been proposed, sparking intense debates and making it one of the hottest topics.
Covenants warrant serious discussion due to their powerful capabilities. They are considered to bring new possibilities to the programmability of Bitcoin and are believed to enable smart contracts. For Bitcoin, this is undoubtedly a double-edged sword. In this article, we will explore what covenants are, how they work, their robust functionality, and their significance for Bitcoin. While discussing details, this article often uses CTV as an example, but CTV is not the only method of implementing covenants.
This article delves into the exploration of covenants but also magnifies a slice of Bitcoin under a microscope for observation. Through this observation, we can understand how Bitcoin operates at a granular level, comprehending both its capabilities and limitations. Understanding what it cannot do is as crucial as understanding what it can do because only then can we choose the right path for building on Bitcoin.
Before discussing covenants, clarifying two issues related to Bitcoin may be necessary, which can help us better understand covenants.
We know that Bitcoin uses a scripting language, and it is known that scripting languages support the implementation of smart contracts. However, in reality, smart contracts have not been implemented on the Bitcoin main chain. This inevitably creates a sense that implementing smart contracts on Bitcoin faces some insurmountable obstacles, and it seems impossible on the Bitcoin network.
However, many people may not be aware that although Bitcoin can be programmed using a scripting language, the set of opcodes is extremely limited. This limited set of opcodes restricts the programmability scope of Bitcoin, meaning that, although the scripting language can implement smart contracts, programmers do not have sufficient “tools” to implement smart contracts.
Definitely, Bitcoin Script can be considered limiting as it can only perform the basic operations such as making simple payments. Some of the reasons that people may find it “limiting” is that it doesn’t have a global state, it’s not considered turing complete, it uses a UTXO-based system (which has “value blindness”) instead of an account-based system. The last big reason is that very little data from the blockchain itself can be integrated into contracts causing blockchain-blindness.
This has created a lot of challenges over the years as people have worked around these limitations. We’ve also had a semantic shift with the term “smart contract” to mean one specific thing when you should consider the lightning network a production of many smart contracts formed by many individuals. Those multi-sigs with hashlocks and timelocks are not only smart contracts, but also have time-based covenants.
The problem is, just as you mentioned before, because Bitcoin only has simple opcodes to perform just the basics, if you attempt to scale beyond two people in a smart contract, you can get either a lot of bloat for an on-chain footprint or the things you want to do just might not be possible. This strict limitation comes from a few places, I think the biggest being that when the inflation bug occurred back in 2010, Satoshi had disabled a whole list of higher order opcodes including OP_CAT which would’ve allowed us to create more dynamic smart contracts via transaction introspection.
BCH has since overcome this limitation within their own script, showing that Script isn’t as weak as everyone assumes, just that Bitcoin has always been slower due to its decentralization and coordination is near impossible except over long periods of time. We’ve also barely touched on Taproot and Tapscript which will alleviate a lot of the footprint concerns and allows for new behaviors such as BitVM by rolling up the contract into the signature and you only reveal as necessary.
Let’s talk about another “limitation” of Bitcoin. Bitcoin only supports “verification” as a form of computation and can’t do general-purpose computation.
We also know that, for example, smart contracts on Ethereum contain rules for state transitions. It completes the state transition through computation, enabling the functionality of smart contracts. In comparison, Bitcoin can’t do general-purpose computation, meaning it cannot achieve state transitions through computation on its own.
Yeah, I’d agree that’s a simple summary of the current state of things. Bitcoin could be made to support computational transactions and the line can become quite thin when covenants and state transitions are involved, but those proposals aren’t as well researched and might not be something that’s considered desirable.
I’m actually not that much of a fan of the way Ethereum does things. Due to it being computational in nature with the verification built on-top, if I attempt to perform a trade, my window could shift and I could “fail to trade” but the transaction for the attempt to trade was still valid so i still paid for fees which wasted my money on what i’d want to consider a failed transaction and wasted blockspace for someone else. Another weird aspect are the Oracles in Ethereum. Oracles must pay gas to update their oracle prices whereas in Bitcoin DLC’s, the Oracle are blinded and are just providing a signature and can’t be “pinned” due to a change in fees nor can Oracles target specific contracts.
Earlier I discussed all the downsides to the UTXO model compared to the account model and global state model, but what allows the UTXO model to shine is parallelism. The only concern you have is the child transactions to the same UTXO, nothing else matters, this allows the system to scale much better.
Let’s start discussing covenants now. What are covenants?
Covenants usually refer to restrictions on how coins can be transferred. The word covenant seems to carry some sort of connotation with it so it helps to demystify it and explain it as simple locking mechanisms you can place only on your *own* coin.
We have two covenants already inside Bitcoin and they power the Lightning Network, CSV [CheckSequenceVerify] and CLTV [CheckLockTimeVerify]. Some just call these opcodes “smart contract primitives” as they’re simple time locks, but they can also be classified as time covenants.
CTV [CheckTemplateVerify] is a proposed Bitcoin upgrade and is included in BIP 119. It is different from CSV and CLTV, you can think of CTV as a “TXID [Transaction ID] lock” or “UTXO lock”, only these TXID’s can be made from this lock. For CTV, we refer to this TXID lock as “Equality Covenants” as the resulting transactions must equal to the original transactions that were committed. It’s also called a deferred commitment covenant, as you can see that your UTXO has been committed to, but it isn’t yet placed on-chain.
The most known alternative is SH_APO [Any Previous Out or AnyPrevOut] which focuses on the payout commitment being ensured while allowing the pay-in method to be flexible. A few others discussed are OP_CCV [also known as MATT], OP_EXPIRE, TXHASH and TEMPLATE KEY.
When you mention “covenants usually refer to restrictions on how coins can be transferred,” can I understand it like this: Covenants are a method of specifying how funds can be used, or in other words, it’s a way of restricting where funds can be spent.
Yep, it effectively earmarks the UTXO to be distributed in a specific manner, once you commit to it, you can’t take it back, it’s now consensus bound, and only its new owner can decide how to spend their funds.
When a UTXO is created on-chain, our instinct is to assume that a single private key is holding that UTXO in place. But if it was a CTV bound UTXO, when the UTXO is spent, you’ll see an extra 32 byte hash paired with the new transaction that represents the hidden state that was inside the original UTXO.
You’ve mentioned “TXID lock/UTXO lock” multiple times. Can I understand it like this: To understand how CTV achieves their functionality, we need to understand what TXID lock is and how it works. TXID lock is a key mechanism.
Yes, It creates a strong foundation to build further schemes. The TXID is determined by the contents of a tx. And if you can add inputs to a tx, you can manipulate the TXID. CTV makes you lock the number of inputs and outputs. This is how we ensure that CTV commitments are trustless, if the TXID could be malleable, you could potentially be able to steal someone’s funds. Once you have a TXID locking mechanism, you combine it with other locking mechanisms such as the time locks to build even greater smart contracts.
Why do you think covenants are a rabbit hole?
I call covenants a rabbit hole because there’s so much you can do with simple restrictions on transactions such as a time lock or a TXID lock. We’ve managed to build the entire Lightning network with simple time locks and while it isn’t perfect, it is the only truly decentralized L2 in existence. I don’t like how it’s slowly shifting towards being custodial focused, but that’s exactly why I’ve started down this rabbit hole to begin with: To make our smart contracts more powerful. We refer to the TXID lock as a Template. With Taproot, we gained the ability to have signature aggregation. With Templates and CTV, we gain the ability to have transaction aggregation.
CTV serves as a replacement for a pre-signed transaction oracle, which eliminates the trust and interactivity requirements needed to create more sophisticated smart contracts that are needed for things like vaults and payment pools. The vaults and payment pools that you can make with CTV are technically possible today, but currently they’re precluded by the trust or interactivity needed to make it work. Moreover, with CTV, we can build channel factories, additional layer 2 solutions such as Ark, Timeout-Trees, Stakechains or Surfchains, and JIT fidelity bond solutions such as PathCoin.
Probably my favorite feature is Non-Interactive Channels [NIC’s] that we’ve also been referring to as Cold Channels. The basic idea is to take a normal lightning channel and simply place it in a CTV template. What makes this different from a normal lightning channel is that neither party actually needed to be online to create this channel. So if I need a channel with another person, I don’t need them to be online to create it, I don’t even need to tell them I made it until I’m ready to spend from it! This allows for cold storage capability on lightning because I don’t need a watchtower nor a node to safeguard my funds in any channels that aren’t yet active. Third-party coordinators can also establish NIC’s for two individuals so there’s a lot of flexibility in what’s possible.
As it stands, CTV won’t allow you to build a DEX on-chain, but I’m not sure if that is such a bad thing as people are currently trying to build DEX’s off-chain using the Lightning Network as it is today. I think this ties back into the “Verification vs Computation” discussion, how much do you really want on-chain versus how much do you need to verify on-chain. One concern I have about on-chain DEX’s, besides the excessive on-chain updates driving higher fees, is MEV. We’ve already spotted some MEV from BCH’s DEX’s transactions and as the market matures, this is bound to get worse.
Can you give an example to help us understand how CTV works?
Let’s say I am expecting to receive 5 BTC, as of right now, the only thing I can do is receive the payment and verify it on-chain. With CTV, I can commit to future addresses or to people and reduce it down to a simple pubkey that I give to my payer to pay me. They don’t know the details of it so it remains private to everyone but me. Once I can confirm that they’ve paid me, all of the actions I took using the CTV template have now also taken effect.
So if I had elected to create a channel with Bob, once Alice pays me, the channel with Bob is now committed, even though the channel with Bob is nowhere to be seen on-chain, it is only accessible by my template and the transaction that Alice had created. It’s only known to me until I share the channel details with Bob. Once I do share the details with Bob, we can use the channel as normal. When we cooperatively close the channel, instead of needing to place an open channel details on-chain, we just place the closing channel on-chain. This allows us to perform transaction cut-through, reducing the total number of transactions that need to be on-chain by at least half for layer 2 solutions.
The opening portion only needs a commitment, what we really care about are the closing details. If this was a shared UTXO with multiple people, we could collaborate to close our transactions together as well, reducing the number of on-chain transactions even further.
As you mentioned before, we can introduce different opcodes to implement covenants.
So if we re-introduced OP_CAT, I think it would allow for nearly every type of covenant possible as you can emulate any form of introspection for TXHASH. The more limited method would be to introduce opcodes representing the explicit behavior desired like with CTV, CSFS or CheckSeperateSignature. CTV is the ability to do deferred outputs. CSFS is the ability to do deferred signatures so you can defer the payment itself. They sound similar and in fact they work well together as building blocks to enable LN-Symmetry, but the commitments are happening at different levels.
TXHASH and TEMPLATE KEY both enable introspection and serve the same purpose, but TEMPLATE KEY uses a single-byte mode while TXHASH uses multi-byte flags. This allows for much more powerful capabilities inside script and smart contracts, but many are concerned about the side effects it could have. TXHASH and TEMPLATE KEY are more of a CTVv2, something that would make CTV more powerful and expressive.
I’ve noticed that there doesn’t seem to be a significant disagreement about whether to support the implementation of covenants. However, in comparison, there seems to be more significant divergence among people regarding which method or set of opcodes to add to implement covenants.
I think a large part is there’s different camps of thought. There’s a lot of the lack of understanding the intent behind each proposal as they have different goals in mind and are designed in completely different ways.
A lot of developers have only had their eye on Lightning and how it’s to evolve, they tend to favor opcodes like SH_APO since it enables LN-Symmetry. For a lot of developers that don’t particularly like Lightning due to its limitations such as Inbound Liquidity constraints or the requirement to be online, they tend to favor opcodes like OP_CAT, TXHASH as more expressive scaling solutions. The developers that prefer CTV are more neutral and are looking at it from a systems point of view, it doesn’t necessarily do any one thing perfectly but it greatly enhances everyone’s ability to do their preferred thing, whatever it may be without introducing risks that can’t be measured since it doesn’t introduce introspection.
Before discussing covenants, we talked about issues related to opcodes in scripting language and the problem of limited computation leading to state transition. We already know the relationship between covenants and opcodes. Now, let’s delve into the issue of state transition. I’m not sure if looking at covenants from the perspective of “state transition” is correct, but this perspective truly fascinates me.
Without covenants, the scripting language’s main function is to retrieve transactions’ signatures and verify them. The transaction can only be completed when the private key is correct, and there is no intermediate state. With covenants, a transaction can be completed when certain conditions are met. Moreover, a transaction can only be completed when specific conditions are satisfied (not just the correctness of the private key). Can we understand it this way: Covenants indirectly provide conditions for state transition.
The covenant is the template shell or the “state”. Inside of it, you’re going to need to make time locks and other functions to enable the desired functionality that you’re wanting, be that a vault, lightning channel or some other layer 2 solution.
So CTV allows for the state creation to occur, but you have to dynamically rebuild the state at each transition to keep it in homeostasis, we call this meta-recursive. Whereas something like SH_APO allows you to create a state and then periodically update that state, making it recursive. CTV can also create a chain of transactions that would allow you to “step-through” that state.
Can we understand it this way: Covenants implement a form of smart contract based on verification rather than computation?
Yes. Definitely. This smart contract is just comparing a transaction to an associated sha256 hash. Block speed verification would actually increase since there’s no signature operations.
One direction of development for blockchains is modularity, including off-chain computation. However, Bitcoin seems naturally designed for off-chain computation, appearing behind but actually leading the way. What do you think?
Time is a flat circle. It’s crazy how it seems like we’ve come full circle to what’s wanted in a blockchain. Bitcoin still seems to have some modularity issues and footprint issues. I wish we had better side-chains that weren’t simply multi-sig solutions and used actual cryptographic means to secure one’s funds and allowed for Unilateral Exits. I think that would help push the boundaries on Bitcoin’s modularity. Taproot has allowed for even more off-chain computation with things such as BitVM, which would allow us to compute almost anything off-chain. But unfortunately, it can’t emulate things inside Bitcoin such as CTV so it seems we still have progress to make.
What possibilities can be achieved by combining covenants with other opcodes like DLC?
DLC’s have a few problems that would be fixed with covenants such as increasing the flexibility of the parameters of the DLC by making many price points [if we’re wagering on the price of something such as Bitcoin]. Another one is that hardware wallets [HWW] can’t interact with a lot of DLC’s, the signing rounds for DLCs and attempting to do it with HWWs causes DLCs to take several minutes to open. With CTV, this delay to enter a DLC can be reduced down to seconds.
Are there any other points you’d like to introduce to the readers?
We went over a lot of concepts. We touched on how it can be used to mitigate excessive blockspace demand and potential ddos attacks. We discussed how people could save space by making Non-Interactive Channels. I think another good one to discuss is the “L2 exit problem”. If we managed to get everyone off of the L1 layer and get them onto a large L2, there’s currently no good way to get people off that L2 in an expedited manner. We could think of that L2 as Lightning [we call the potential mass exodus on Lightning, the “Thundering Herd problem”], or we could think of Coinbase, Binance or Liquid as the L2. There are people who hold claims to Bitcoin, but their only way to actually acquire that claim is by submitting a transaction to get it placed on-chain. There’s millions of people on Coinbase, I have no idea how to get them off of there and onto Bitcoin in any orderly fashion in today’s environment. There would be a mempool backlog of 6 months attempting to get people off the exchange. CTV can fix this.
Make an Ark or