Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time

Name: Jeremy Rubin


Location: Chaincode Labs Podcast

Date: February 11th 2020


CTV BIP review workshop transcript:


Jonas: Welcome to the podcast Jeremy.

Jeremy: Thanks for having me on.

Jonas: I think to start us off tell us a bit about your background, how you got into Bitcoin and we’ll take it from there.

Jeremy: I first heard about Bitcoin in 2011. I was interning at MIT during high school and I was doing what interns do which is read Hacker News. I saw an article about Bitcoin and I thought it was pretty cool. I remember asking some other people in the lab “What do you think about this?”. People were like “Bitcoin is stupid.” That is kind of interesting. Later that fall I went into my senior year of high school and I started seeing more stuff about Bitcoin. I knew some people who were buying some things online with Bitcoin. I was like “This is interesting.” I booted up a second laptop and I turned on CG miner, something like that. I started mining a little bit of Bitcoin. I was like “Wait a minute. I am trying to sleep and this fan is really loud.” So I turned that off and ignored Bitcoin but watched. I was like “Should I buy some on Mt Gox?” and I was like “I don’t want to link my bank account to this sketchy Japanese website”.

Jonas: That ended up working out alright.

Jeremy: I kept an eye on it for a few years. Fast forward to the summer of 2013 I had finished my freshman year of college. I started getting more interested in Bitcoin. I bought a little bit on Mt Gox that I eventually lost and started thinking “This is actually really cool.” In the fall of 2013 I decided to start doing some projects. I had learnt a little bit more, I was a bit of a better programmer. I started a project called Tidbit which was a way to replace advertising on website with cryptocurrency mining. It was a neat project. We had the messaging drilled down where it is about fixing the internet, bringing it back to the people, getting rid of these evil ads that are bad for democracy, bad for journalism. We were maybe a little bit ahead of our time. Then we received a really nasty subpoena from the state of New Jersey which was not exactly them suing us or making any charges but they copy and pasted language out of their version of the Computer Fraud & Abuse Act. It was basically all these felony statutes where it is like “Did you do….?” and that is a thing that is a felony and has mandatory sentencing. We were pretty freaked. We got the support of some various legal non-profits like the Electronic Frontier Foundation. I think that was a big crossroads for me where it is like “This Bitcoin stuff, it’s cool but is it going to be a big problem to work on.” That was the point where I decided to double down and stick to Bitcoin. From there I did a number of projects at MIT including the Bitcoin Airdrop with some of the other Chaincode guys. They helped out there too. We gave every undergraduate 100 dollars of Bitcoin. We gave in 2014 like 4000 undergraduates 100 dollars of Bitcoin and looked to see what happened. Then I started the MIT Digital Currency Initiative, the MIT Bitcoin Expo. Then when I was graduating and deciding what I wanted to do I figured out that I had been doing a lot of Bitcoin related stuff and research and community organizing but now I am out of classes I have time to do more full time open source contribution. That has been since 2016 what I have been doing.


Jonas: Very good. What’s CTV?

Jeremy: So CTV stands for CheckTemplateVerify. It has previously gone by other names.

Jonas: What are those other names?

Jeremy: I used to call it originally COSHV which stood for CheckOutputsHashVerify but I realized that there were some bugs in that implementation and you needed to hash more than just outputs and so I changed the name. Then I called it SecureTheBag pending have a more sane name. But I kind of liked the name for various metaphorical reasons. But not every shared that so eventually to do whatever it takes to get people to adopt it, it is now called CheckTemplateVerify which I think people are relatively happy with.

John: From a higher level what is CTV doing?

Jeremy: CTV is a way of enabling a really rudimentary form of covenants in Bitcoin.

John: What is a covenant?

Jeremy: A covenant is a way of restricting the way that you can spend a coin. This sounds like a little bit of a weird property and something that maybe already exists in Bitcoin. If I spend to a specific key haven’t I fundamentally restricted to somebody who knows that key? You have. With CTV what you are doing is you are not just restricting to somebody who has that key, once somebody has that key you are restricting what they can do with it. Which is a little bit of a departure. We have some precedence for this in Bitcoin. If you have a CheckSequenceVerify or CheckLockTimeVerify opcode you are saying to somebody I am giving you this coin but you can only spend it after a certain amount of time. We have restricted what actions they can take. CheckTemplateVerify is even more restrictive. You are saying to somebody that this coin can only be spent in this specific transaction. You’ve restricted it to a specific transaction that can happen. That itself is a little bit of an odd property. You might think “If we are restricting to a specific transaction why not just do that transaction right away?” It turns out that there is a useful way that you can program at the transaction level if you allow transactions to be played out in this way. That is at the heart of what CTV is accomplishing is allowing people to program Bitcoin at the transaction level instead of at the script level.

History of covenant proposals

John: The concept of covenants has been around for a few years now in Bitcoin. Can you give us a bit of historic context? What have the previous proposals been and how does CTV differ from those?

Jeremy: The discussion of covenants I think originally took place maybe in 2013 on Bitcointalk in a much more advanced form that what CTV is. At that point it was what if we allow arbitrary zero knowledge proofs to determine what the transaction should be and you just satisfy the zero knowledge proof and then the transaction matches that pattern? What is the worst thing that you could do? People came up with all sorts of weird ideas. You could make a function that looks at all the blockchain state and determines if something has happened before you are allowed to spend. Or the government’s key gets added to all of your coins and that is perpetuated every single time. You have some sort of recursive nature of these. People at that point were like “Covenants are maybe a scary thing and maybe shouldn’t be added to Bitcoin.” Following that in I want to say 2016 some researchers out of Cornell and a few other institutions, one of the Israeli universities, put out a paper which was doing a different type of covenant which was just a simple pattern matching based one. You essentially have a regular expression that would say “Does the output of this transaction match what I’ve specified?” These were relatively powerful but because they were doing this weird transaction introspection and they enabled recursion people didn’t feel they were appropriate for Bitcoin. It sort of violated the abstraction layers that they wanted to keep. Those were not adopted. People also were worried given the previous 2013 discussion that it was wrong and fundamentally bad for Bitcoin. So even though there were some interesting use cases that had been proposed for these covenants in that paper they didn’t see any push to get that proposed opcode into Bitcoin. Fast forward to 2017 I gave a talk at the Stanford Blockchain Conference saying “Let’s think about covenants in programming at the transaction level.” A lot of people told me that that was a really good talk and they found that that talk explained a lot of things that they hadn’t been thinking about before. They felt that Ethereum is really exciting and you can do all these programming things. In Bitcoin you can just do transactions. Now people were thinking “Wait a minute. There are maybe some easy steps we could take to enable a lot of programmability inside of Bitcoin.” But I didn’t have a concrete proposal of how we would add these things. I spent some time over the next few years thinking what can we do? I thought about doing pre-signed transactions where you delete the keys. I was unhappy with that. I thought about instead of pre-signed transactions where you delete keys what about doing multiparty signatures where you just need one person to delete the key? But then you have this weird online multiparty computation and it gets really messy. Then last year I said “What if instead of trying to dance around the issue I just find the minimal most conservative thing that I can that accomplishes these goals?” I came up originally with COSHV now CheckTemplateVerify. This thing is really hard to work with. It has a minimal set of features. It can’t do all these pie in the sky things that people want. However with just this small kernel of capability there are a lot of nuanced things that come out. You can make really powerful contracts in Bitcoin without imposing on the ecosystem too much bloat or complexity.

John: Specifically CTV wouldn’t allow you to make these infectious covenants that run with the transaction and last forever?

Jeremy: Correct. That was one of the design goals originally of CTV. That has since been slightly been relaxed. I had originally made a version of CTV which provably with other extensions to Bitcoin would also not introduce this behavior. But if people later wanted to add some other opcodes that would may be purposely trying to introduce recursive covenants it would also be able to add it. Things like OP_CAT that we know enable all sorts of weird use cases that are unexpectedly complicated.

Covenant use cases

John: That is a high level historic tour of covenants. Why are people interested in covenants? What are some of the use cases that people have been talking about?

Jeremy: There are a number of use cases. I guess maybe now is a good time to plug the website. If you go to there is a lot of information that has nice diagrams so you can get a bit more intuition. Just hearing about these things I think can be a little bit tough to follow. There are a lot of things that people are excited about. I think being here at Chaincode this week people are very excited about vaults. A vault is something that was potentially proposed earlier but it was at least discussed heavily in this paper that came out in 2016, MES 16. The idea behind a vault, there are different structures for them. I want to encumber my coin inside of a contract that gives me an opportunity to undo a mistake. The original one says “What if somebody steals my private key? What do I do?” The idea was that you have a recovery key. As long as you have the recovery key you can basically keep playing this transaction which prevents the attacker from actually stealing your coin. Maybe if you are cycling through keys that are yours you can eventually get to a key that has been backed up and the attacker doesn’t have. That lets you recover your coin. Or if they stole your master private key seed you can just keep on moving the coins, waiting for a timeout and the attacker can’t steal your money. Then if you think what an attacker’s incentives are if your coins are in a vault and they can only ever keep you from spending your money but not get money for themselves maybe you are less of a juicy target. That sort of vault is possible with CheckTemplateVerify but you can also do more nuanced types of vaults that give you other properties. The type that I’m really excited about is something that models an annuity. What you do is you set up a CTV vault that pays out a certain amount of Bitcoin on some interval. Let’s say once a week it spends one Bitcoin and then you have to wait another week before you can spend Bitcoin from this vault again. This is a really powerful idea for an exchange where I can say “I have some liquidity constraint where I need to be adding Bitcoin to my hot wallet on some scheduled program but I don’t want to have to go to my cold storage every time I want to do that. Instead if I can estimate what my liquidity needs are I can set up this vault and I can allow some junior employee to move the funds from the cold storage to the hot storage without worrying that they are going to subvert the whole process. Meanwhile if you notice that one of these withdrawals has been hacked and somebody has tried to steal your coins you can prematurely halt the execution of this vault and send all the funds back into your super secure cold storage. This is a pretty exciting idea for Bitcoin because this gives people much more flexibility in how they move their coins around and more security and safety, this feeling that they are not going to have messed up. I’m pretty excited about vaults as a potential for that.

John: I think both on an institutional level and as an individual Bitcoin user the idea of having some way of securing your Bitcoin in a way that if your private key gets compromised you can still claw it back.

Jonas: How are exchanges doing this now? What is the architecture in their set ups?

Jeremy: Usually for an exchange, I’ve never worked at an exchange and they are a little bit secretive on what their exact set ups are, I think they typically rely on plain multisig that some key employees have. That handles the cold storage, that is for a lot of money. Then maybe one of those key holders is like their attorney’s office, things like that. Then they will have hot wallets that are a reduced amount where more people have access. They will have a really hot wallet which is just a server and if anyone logged into that server they could maybe steal a million dollars but you would see who logged in and whose key it was, things like that. They would be able to trace it but the money would be gone. I think that is a typical architecture. That is almost what we are trying to emulate here. At the end of the day at some point you want to be able to get an unencumbered coin. You want to be able to say “We have moved the funds back to cold storage. Nobody can touch them except for a set of people.” The goal for these vaults is to make that operation much less necessary and less frequent. The idea that you need to access these cold keys hopefully would be something that you only have to do once a year in exceptional cases. Rather than anytime you need to add liquidity to your hot wallet. I think to John’s earlier point about this being for both institutions and for individuals, institutions have a lot of money to create these complicated systems that have people and checks and balances. But individuals don’t. If I’m an individual and I don’t want to trust other third parties setting one of these things up with multisig it can be quite complicated. Who do I trust to be part of my multisig set? With CheckTemplateVerify what is rather nice is you don’t have to have those other people involved necessarily. You can have these flows and you are the only person in control after you have made that decision. That resonates with one of the Bitcoin branding and marketing phrases early on which was “Be your own bank.” I like to think of that as not just holding your own money but also provide your own financial services. I think CTV helps people do that.

Jonas: The Bitcoin trust fund babies will thank you in the future. They will get their allowances and things like that.

Jeremy: Exactly. I think that is a fun way to think of it. If you are thinking of how do I leave Bitcoin to my family? We know that maybe multisig wouldn’t be good because inheritance schemes, people are always arguing about who has the right to spend. But if you said “I think this money would corrupt my family and I want them to have a reasonable amount of money but not limited” you could set them up in a program to receive let’s say a Bitcoin a month for the rest of their life if you have a lot of Bitcoin. That may be a more robust way of ensuring some sort of inheritance.

Payment pools

John: Moving onto other applications of simple covenants, not CTV. There is something called payment pools. Can you tell us what that is?

Jeremy: A payment pool is not a well defined specification in the same way as channels are not the Lightning Network. The Lightning Network has like a hundred BOLTs that tell you exactly what you are going to do. Payment pools are a general concept that a group of n people are sharing a single UTXO. Whenever someone says that they no longer want to share the UTXO you will create a UTXO for them. Otherwise you will rebalance funds among the remaining participants. That is the core idea behind a payment pool. There are multiple ways of implementing that. Where CTV comes in in helping to design payment pools is that CTV enables you to create these non-interactively constructed contracts. What that means is that right now if I wanted to create a payment pool, before I do that I have to get from all participants which coins they want to spend. I have to get a signature from them for the first state of this payment pool. With CTV if I’m say Coinbase I can just say “Ok these hundred people have requested a payment. I am going to group them into a payment pool and I’m going to send them those funds. They will know they have a redemption receipt inside of this payment pool automatically without requiring any signature. If somebody is offline permanently and they just requested this one withdrawal you kick them out the pool. Otherwise the remaining people can sign off on a number of update transactions to that pool, hopefully saving total UTXOs.

John: I think that primitive is very interesting. Any construction where you have multiple people, multiple agents controlling a single UTXO and they are able to rebalance amongst themselves without changing the UTXO set of the Bitcoin network gives us the opportunity to scale Bitcoin much more massively than we can right now. Lightning Network is maybe the first iteration of that where two parties control a single UTXO. These payment pools where multiple parties control a single UTXO would allow us to do things like payment channel factories for example and have a lot more constructions of how to lift payments offchain.

Jeremy: The basic way that I have been thinking that you would want to construct payment pools is that you would have a tree of Lightning channels. There are various constructions, people are thinking about what is best. Some people like where it is not actually a tree, you emit one person at a time. I think what is nice about the tree of channels is that at the lowest layer channels, they are just two party. It is compatible with Lightning existing. You can route around the entire network. Also you get a privacy benefit. Right now every update to the payment pool if it is not a tree you have to involve everyone and get a signature from everyone. But if you have a tree of channels then it is just two people have to agree. When you want to do a higher order transfer between two people who don’t have a route or who have maxed out their balances, you percolate up that tree of channels to coordinate. If somebody is offline then you would need to go onchain. If you look at the probabilities of different things you can prove in the sense of being roughly equivalent even though it might generate a couple more transactions, logarithmic versus linear.

CTV with Taproot and SIGHASH_NOINPUT

John: Another interesting thing is that OP_CTV seems to me to play quite nicely with Taproot and SIGHASH_NOINPUT. Taproot allows you to have this tree of different spending conditions and each one of those could contain a OP_CTV encumbered output. Only one of which would ever be redeemed. Then SIGHASH_NOINPUT or equivalent allows these layer 2 protocols to act a lot like Layer 1 protocols. They can be updated sequentially.

Jeremy: In terms of Taproot there are definitely strong synergies. When I originally imagined this I thought I would deploy it as a new Taproot script opcode. Then I realized not only was there an uncertain timeline for Taproot and I wanted to make the changes independently but also there are strong reasons that you might want to use this in bare Script. So you don’t necessarily want to do it inside of a Taproot spend. So they became separate things. But originally there was a strong idea that with Taproot this enables a lot of really cool things. The reason why Taproot enables something fundamentally different than what you can do with CTV already is that Taproot allows you to put as many possible spending conditions as you want and only pay if you know some probabilities of how frequently you are going to use one of these conditions. O(1) for that. It is no extra overhead but you get to have a number of transactions that you’re committing to. You can say “We can do transaction A or transaction B or transaction C” and now you have defined a program that has state transitions that are not just a single transition but multiple options. You can do that in Script already with IF ELSE branches but those grow linearly with the number of things you want rather than with Taproot where we can do it in O(1).

John: You also get a privacy benefit.

Jeremy: There’s also a privacy benefit. One of the nice things with Taproot is baked into it is the idea that you have a multisignature that you can agree to. If you imagine that you had that payment pool I described earlier where there is a tree of channels and people are routing. If people at a higher layer in that tree want to agree to something there is already a multisignature baked in and so that helps you sign off on the redemption transaction. In the optimistic case you don’t need to go through any of the actual contract resolution. I think that that is a pretty powerful idea. I’ll know CTV is really successful if I never see them onchain. If people are not actually using it these payment pools work and people are getting enough coordination but what CTV is fundamentally doing is allowing people to not have to trust. Being able to coordinate without coordinating. I think that is a neat idea. Then in regards to your other question about SIGHASH_NOINPUT, ANYPREVOUT, ANYSCRIPT type stuff what is really fascinating is that we have a proof that if you were to enable SIGHASH_NOINPUT you would also enable CTV. You would enable a very similar behavior to what CTV is providing. There are strong reasons that you would want those separate changes. CTV is more performant and takes up less space and is the correct abstraction for the job. But strictly speaking there is an equivalence. What that means later on down the line is when people are advocating for an actual implementation of ANYPREVOUT or ANYSCRIPT which I think is still pending, they are making less of a leap from what Bitcoin is already doing. It makes this ANYPREVOUT, ANYSCRIPT which is viewed I think by a lot of people as a very non-conservative change. It changes a lot of things that people really care about. That leap is going to be a little bit smaller. It will help that go through as well I think.

Jonas: But not obsolete. There are additional benefits to ANYPREVOUT.

Jeremy: Yes. It doesn’t obsolete ANYPREVOUT. ANYPREVOUT can fundamentally help with updating state in a different way than CTV does. In these payment pools you might be using this ANYPREVOUT, ANYSCRIPT once you have already committed to a CTV internally. That would be the way that you balance it out. CTV also has greater flexibility that if other opcodes like OP_CAT get introduced to Bitcoin you can do all sorts of other types of covenants. Whereas with SIGHASH_NOINPUT you might not be able to do some of those more fancy covenants. You would still be restricted to just what CTV can do without OP_CAT. There are some additional features that could be coming down the pipeline with CTV but not with just SIGHASH_NONINPUT.

CTV and Lightning

Jonas: Can you tell us a little bit about how you imagine CTV working with Lightning channels?

Jeremy: There are several use cases that are pretty compelling with Lightning. Payment pools is the prime first obvious one. We are going to create all these channels and if we can get people online to agree we will update the channel construction themselves, that is pretty useful. But I think before that gets rolled out because that is a pretty complicated ecosystem change to support that, you can also create a tree of channels. That allows you to only have to redeem the channels that you need to redeem. It makes channel creation more efficient. People have looked at channel factories. CTV allows you to pretty easily without having to get people online create a bunch of channels for them. Coinbase could when people withdraw pay out into channels. People already have liquidity. The other idea that I like is that when you create these channels, they are not just everybody gets one channel, you can actually create a tree of channels that is linked to the existing Lightning Network so you are adding liquidity. If we’ve got this big liquidity crunch in the Lightning Network and we need to create a thousand new channels, now it is a single UTXO to create those thousand channels. You can redeem them over time when they are needed to be pulled out. But now you have added this spot fix. You can also add routing in between the channels internally in this tree so people get a very liquid network of payment options which I think is a pretty powerful idea. The other thing that it does for the existing Lightning specification is that you can replace the HTLC outputs in each transaction with a tree of HTLC output transactions that resolves to some base case. This is nice because if you only have to pull out a single HTLC you no longer have the bandwidth consideration that you had before. Now it grows instead of O(n) it grows O(log(n)) and so if you want to increase that number drastically… I think right now it was previously set to 12 as a limit, now there is wumbo which I think increases that limit. This makes it more efficient for people who need to make really big numbers of HTLCs, they’re not as worried about getting stuck in the mempool which would be really bad for their channel.

John: What that actually means for Lightning is that within an individual channel having multiple payments routing through that channel simultaneously. Is that correct?

Jeremy: The number of HTLCs sort of directly corresponds to how routable your channel is. When you are limited to 12, I think they increased those limits, there is a fundamental constraint on how much liquidity you can route through there.

John: Because if the payments fail or the channel fails you need to be able to put that transaction back onchain and each HTLC adds to the size of the transaction?

Jeremy: Yes. Then this reduces how much it is adding to the chain such that you can resolve the HTLCs in priority order. You can say “I want to resolve the HTLCs in order of which ones have the most money in.” Maybe you can imagine a protocol where the later ones you still want to resolve them but you want to lock up the money that is problematic first and then deal with the ones that are less problematic that haven’t recently been routed through or something. A lot of these things are things that shouldn’t come up. These are only in the non-optimistic case that somebody has cheated on a route. That can happen but this makes it easier to know that you are going to get your funds back and less chance of getting stuck and somebody snipes your output. I think that that overall improves the security while also improving the number of routes. In turn if you can have more routes collateralizing a Lightning channel is more efficient. If you have this money locked up you can increase the amount of fees that you can collect as a routing node which means people have an incentive to put more money in. It also means right now that if people have a lot of HTLCs that they want to create they create many, many channels. Even maybe redundant because they want to have isolation between Channel A and Channel B. If something goes wrong in Channel A, Channel B doesn’t also get taken down. CTV can help with this by saying “You don’t need to create all these channels. Just create a single channel and we can do that fragmentation inside of the channel not worrying about the HTLC element.” It helps with the use cases.

CTV implementation

John: Moving onto implementation details for CTV. You have talked a couple of times about the happy case where only a single signature ends up being put onchain. Obviously when we are designing these protocols we need to consider the unhappy case where you have this Layer 2 protocol and you have a lot of state there from your OP_CTV. You might have a lot of transactions and child transactions and descendant transactions. As you have been proposing this new opcode OP_CTV you have also been making changes to Bitcoin Core, opening PRs in Bitcoin Core. Can you talk a bit about those?

Jeremy: I think there are two topics there. The first is in the unhappy case what happens. One of the things I have been studying to simulate and loosely suggest but not prove because it is just a simulation, in these unhappy cases CTV really helps with the congestion of a network. It makes it easier for somebody who wants to confirm some result that may make many outputs get that result confirmed and then deal with the creation of the resolution later. But lock in the result of that resolution. I think that is important for protocols being a little bit more agnostic to what the chain weather is, whether the fees are high or low they are kind of isolated from that. When you create a channel and you don’t know what the fees are going to be in the future, if you get stuck and there is a fee spike you can get locked out. Using CTV you can ameliorate that case. I’ve done some analysis suggesting that CTV has a good impact in this regard. Specifically when you get to the changes in Core that are coming to make this work a little bit better. The mempool is a data structure in Bitcoin that stores transactions that have not yet been mined. Every time that you call this function CreateNewBlock what it does is ask the mempool “What are the best transactions that I can mine right now.”

John: That is what the miners are doing. If you are just running a full node you are not doing that. But miners are trying to create the optimal block for them to collect the most fees.

Jeremy: If you are running a node you are storing the data structure that encodes the information to efficiently run this procedure CreateNewBlock but you yourself are not necessarily calling that. You are maintaining the list, you could answer this question pretty easily but you are not actually asking for it. Most nodes do retain this information and do this sort. The reason why is kind of non-obvious. Everyone in the network is hopefully relaying these transactions and you only want to be relaying and storing things that are likely to get mined and providing value to the network. The more rational the mining pool is the better blocks it will construct and also the less things that won’t ever get mined that it is storing. A provably optimal mempool would be impossible to implement but what it would do is store every transaction that it has ever seen and then it would solve a NP hard problem to assemble the optimal block that spends those. It is a NP hard problem, that means even if Bitcoin Core developers, Bitcoin developers generally, Bitcoin miners are really smart and working really hard we will never right now assemble one that is optimal, that is not going to happen. We might if computers get fast enough. With the size of the problem it is probably intractable. Instead we write heuristics and we do a best effort job. What happens to be the case is that best effort job in a lot of cases is not good enough. We have heuristics for when we evict transactions and sometimes we evict a transaction or don’t accept a transaction that otherwise actually might be good if you compare to this infinite backlog mempool that picks things optimally. What I have been working on, in one part, is to help that become more rational and help it more closely emulate this perfect mempool.

Jonas: What places to learn more? How can people get in touch with you, ask questions and leave comments?

Jeremy: I have been assembling a lot of resources on the website. You can go there and check it out. That has a lot of diagrams, use cases, little articles about CTV and what the progress is. If you happen to be in San Francisco on February 1st we are going to have a workshop. Maybe the first of a few. That will be an opportunity to review the BIP and talk about what deployment of this would look like. I am also available on Twitter, @jeremyrubin. Definitely reach out, tweet or DM me and I’ll try to respond.