Scaling Bitcoin To Billions Of Transactions Per Day
Date: February 23, 2015
Transcript By: Bryan Bishop
Scaling Bitcoin To Billions Of Transactions Per Day
We’re doing a presentation on the lightning network and micropayments. Right now bitcoin faces some interesting problems, like transactions aren’t instant, and micropayments don’t work. The transaction fees are 1/10th of a cent or higher depending on the exchange rate. And, “bitcoin doesn’t scale” especially if you have a lot of micropayments. One megabyte blocks? Well, let’s increase them. What happens? Well, you go from 7 transactons per second with 1 megabyte with about 220 million transactions per year. With a 7 billion population on the planet, that’s less than one transaction per year or substantially less.
What does bitcoin look like with more than 1 billion transactions per day? Well that’s 1.8 GB (1655 MB) and about 87 terabytes/year. You can store enough transactions from a year for a place maybe the size of San Francisco or another metro area. Well you might say okay, let’s up it even more. Then what happens? Well you get some centralization, right.
Mining sort of doesn’t work for this. You’re going to end up with one or two mining pools. They sort of have an incentive to create bigger blocks and it causes more centralization. An individual running a bitcoin node at home can’t do a full validation of all transactions. It’s not really bitcoin. It doesn’t work very well.
How do we solve this? Dump everything into a SQL database. Coinbase does this. But it’s very useful. Sometimes there’s a need for that. You can put everything into sidechains, and you could also use payment channels which is a one-to-one connection to another party. It’s like the Starbucks gift card model where you always have a single relationship with another entity.
These do face some problems. The SQL model is basically like MtGox redeemable codes. When you add custodial risk, that creates problems. Sidechains are interesting, but they aren’t really a scalability solution. Sidechains are more tricky. It works well for something like namecoin where you want it to use bitcoin instead of its own currency. It’s a promising technology. Sending funds between chains may exacerbate the problem if you want to send funds between them because it’s two transactions instead of one transaction now. If you have money on chain A and someone wants to receive money on chain B, you have to bridge them and this might require two transactions instead of one transaction. Payment channels are problematic because what if you want to send money to someone else?
What you really want is anyone-to-anyone payments. When a transaction hits the blockchain, anyone can send to anyone else because you can set the output. In the SQL database model where you give them all your money and they update database entries, you sort of need to give that one person your money. If someone wanted to receive money on Coinbase.com, you could send them a bitcoin transaction but that’s not scalable, so you have to put your money on Coinbase first and then send money in the Coinbase network. That’s a lot of centralization.
For sidechains, you have to be on the same sidechain or else you have the doubling of transactions as described earlier.
Inside a payment channel, you just need the same relationship. So what we propose is a payment channel between many parties in a multi-hop hub and spoke model, like internet routing. This uses minimally trusted intermedaries. They can’t take your coins. It does not involve a third-party custodian. This does require a small malleability soft-fork. We kind of need to fix malleability anyway. If we fix malleability, we can do this.
Tadge is going to introduce payment channels and then build off of that.
We were looking around to see who came up with payment channels. There’s some stuff in 2012. I don’t know who came up with the idea and we may never know. Anyway, it’s an old idea, well old for bitcoin.
Payment channels require multisig. It allows two entities to send transactions to each other rapidly without hitting the blockchain each time. I am going to go through the basics of setting up a two-party unidirectional payment channel. Alice can only send money to Bob through this. So what she does is she gets a refund transaction. There’s a multisig address that Alice and Bob both have control over. Alice wants to send 1 BTC to it. Before she does so, she gets Bob’s refund signature. So at worst, Alice loses access to her funds for 30 days. Bob creates this timelock refund transaction. Alice can either sign it herself, or it can wait half-signed. Alice keeps this on her hard drive because she knows that at the end of the month she can get her money back. Once she has this, she knows it’s safe and she sends bitcoin to the multisig address because she knows worst case she can get it back. Once it’s in the multisig address, she can commit to payments to Bob. Alice can sign this and then hand the transaction to Bob. She can give 0.9 BTC to Alice and 0.1 BTC to Bob. She will sign this transaction. It’s not valid because Bob has not signed it yet. Alice cannot push this to the blockchain because miners would ignore it. She can give this to Bob out-of-band. Bob can treat this as a payment. Bob can sign this at any time, and then broadcast it to the network, and in doing so close out the channel. Instead though, Bob will wait. He knows that the channel is going to be open for the rest of the month. The next time that Alice pays, she gives 0.8 BTC to herself and 0.2 BTC to Bob. He sees that this is better for himself, so he will broadcast this transaction instead of the earlier one. At some point, Alice might request the channel to be closed out and Bob could cooperate, or if Bob is a jerk he could wait until the end of the month to sign a transaction. If Bob waits too long, Alice gets all of her money back. So Bob is motivated to sign this at some point before the end of the month (the locktime expiry). The network only sees the multisig transaction with two outputs. So during that month period, she can send as many small microtransactions to Bob as she wants.
You can change the direction of channels after you create it. Setup the refund transaction, fund the multisig address. When Alice spends to Bob, she adds a locktime (nlocktime). So now Bob wants to pay Alice back for whatever reason, Bob says I am going to pay Alice now from the money that you were paying me. He can provably commit to a payment to Alice by overriding this transaction. He sets a lower locktime on the transaction. So this is a race between when people make a transaction published to the blockchain. You can’t do this a million times. You only have so many times you can use a shorter locktime. Changing the direction requires bringing the expiry closer to the present. They can both sign a new thing with no locktime if they cooperate.
Okay, so then I will transition briefly to 3-party payments. I will show the motivation and Joseph will talk about how it works. Let’s say that Bob is a big company or they are some kind of payment processor like Bitpay or something that people use a lot. Alice has a channel open. Carol has a channel open. Everyone has a connection to Bob, and Alice wants to send to Carol, and this is the future where sending a bitcoin transaction is expensive. It would be nice to send to Bob who can then send it to Carol instead of using an expensive bitcoin transaction. So Alice can send to Bob and hten Bob can send to Carol. This is a micropayment network.
But there’s some trust issues here. Bob might just take the bitcoin that Alice sent. And Carol could claim that she never got the coins, and there’s no real way to verify whether Bob took the money. So this doesn’t really work. It might work if you trust Bob but we’re trying to minimize trust. So Joseph is going to talk about how to actually do this.
Yeah that model works pretty well. You can use 2-of-3 multisig to help mitigate the problems. It would be nice to do this in a trustless way.
You can create a hashlock contract. A hash function is a undirectional cryptographic method whereby you take some input and you get some output that cannot be reversed. What you do is you take some random data R and you convert it through hash160 or whatever and you use that as a key and you need the lock which is the random data R in order to unlock the funds encumbered. And there’s a paper from 2013 called pay-to-contract and essentially if Alice has the data R which produces H, she can say I have paid you the money. She does that by the receiver writing some signed message effectively a contract that says if Alice knows R which produces H then at that point Alice has paid me 0.1 BTC and that works. And you might ask yourself, why not just check on the blockchain? You can’t. Because everything we’re discussing here is off-blockchain. So you need some way to prove that funds have been sent.
So essentially this right here is what Carol produces. She has some random data R. And she runs it through some hash function (like hash160) to produce H. She gives H to Alice. Now Alice knows H but doesn’t know R. And Carol knows both. Alice uses a payment channel payment to Bob but this is encumbered and can only be released if Bob can produce R. Let’s assume this work; if it doesn’t work then bitcoin has some problems. Bob does the same with Carol. What happens is that Carol has a payment from Bob that is encumbered. Carol can only use these funds if she gives R to Bob or broadcasts it to the blockchain. Carol might tell Bob R because she wants her money. Bob and Carol can broadcast the channel on to the blockchain, or they could agree to novate “I know you know R, I know you can put the funds on the blockchain, let’s not do that because it’s expensive, let’s do it in the channel”. If Bob is uncooperative then Carol can broadcast it on the blockchain. But assume Bob is nice. Now that he knows R, he can get the 1 bitcent from Alice. So Bob was acting as an intermediary, and it wasn’t a substantial risk. He can always pull funds from Alice and give them to Carol.
But the problem is that if Carol refuses to disclose R she could hold up funds in the channel. If Alice’s connection to Bob expires before Bob and Carol’s then Bob has already paid Carol… Alice and Bob’s channel has already hit the blockchain. Bob could be out of the money. That’s a problem. Also, Bob has to be sort of wealthy. So say Alice has 1 BTC, the channel has 1 BTC, Bob has 0 BTC. Alice can’t receive any more funds because she’s sort of full. If everyone gives money to Bob, you kind of want Bob to send money out, to create channels outside; if Bob sends money to Alice then that has a channel that can be spent so the system sort of works. The availability of funds that Bob has, has some implications for fees. Bob just needs to be really rich on a single hub-and-spoke model.
Say that Bob is rich. How do you mitigate the problem? You can do third-party multisig where the Alice and Bob payout is using a third-party escrow service. That could work fairly well today. You could also trust that Bob would be honest and send the money and not encumber everything. But what we really need is a trustless model. Corruptible custodians are undesirable. You want to make sure Bob is unable to steal funds. Complex chained transactions in bitcoin don’t really work because with malleability you can create hostage scenarios where if funds are locked in 2-of-2 multisig then the refund transactions are not spendable because the other transactions were mutated. So this creates a hostage scenario and one attack here involves the time value of money where one party might be able to tolerate a longer locktime in order to intimidate the other party…
To fix malleability, you basically need to introduce some sort of new sighash flags in a soft-fork, such as SIGHASH_NORMALIZED and or SIGHASH_NOINPUT. This would allow you to build a transaction without either party able to broadcast the parent on the blockchain. You could edit the sighash flags or you could use a new opcode. You can strip out the signatures with SIGHASH_NORMALIZED, or you can remove the txids completely. It’s slightly more risky if you’re spending to the same address multiple times but you shouldn’t be doing that anyway. NOINPUT is much more flexible with what it can do. NORMALIZED also lets a lot of these contracts work. Hopefully we can get both of these sighash flag types. I don’t think there’s a ton of controversy because we already have SIGHASH_NONE, so why not these? They are much safer anyway.
So in order to enforce Bob being able to send to Carol and Bob knowing that he can receive funds from Alice, you want to build this contract. What would be the terms of this contract? For example, if Bob can produce to Alice some input R where R is some random data that Bob generates, with input R from hash H within 3 days, then Alice will pay Bob 0.1 BTC. However, after 3 days the above clause is invalid meaning that within these 3 days if you can produce this hash then you will get 0.1 BTC but after 3 days the funds locked inside this output will be refunded and either party might agree to settle the terms using other methods, like instead of broadcasting on the blockchain perhaps they would settle on the channel. And violating the terms would incur a maximum penalty, so if Bob does something sneaky you can fix that.
So you create a transaction in bitcoin transactions using transaction outputs. So there would be a 0.1 BTC output between Alice and Bob. And the payment, is a payment with no locktime but requires R. So if this output is committed between Alice and Bob, and Bob produces R, then he can broadcast on the blockchain the transaction that spends from this output and Bob would have to broadcast both the output and the spend. However, after 3 days, Alice has an unencumbered transaction which does not require R, which is a refund of what Alice committed (the 0.1 BTC). So what happens is that Alice funds the 0.1 BTC, Bob doesn’t broadcast anything, if Bob produces something in 3 days he can get 0.1 BTC. And this is sort of what the script looks like for the output:
OP_DEPTH 3 OP_EQUAL OP_IF OP_HASH160 <R> OP_EQUALVERIFY OP_0 2 <AlicePubkey1> <BobPubkey1> 2 OP_CHECKMULTISIG OP_ELSE OP_0 2 <AlicePubkey2> <BobPubkey2> 2 OP_CHECKMULTISIG OP_END
The first one has 3 items the second one has 2 items.
So what happens is that when 3 days occurs and Bob doesn’t produce anything, Alice has the option of going to Bob and telling him that he didn’t produce anything. So she might propose updating the channel to remove that output entirely. If Bob doesn’t agree, Alice broadcasts the output and the refund on to the blockchain.
So what can you do? Let’s say that Alice wants to send funds to Dave through Bob and Carol. And perhaps Alice discovers Bob through cjdns or whatever. She knows that there’s some network that Bob and Carol is in. So maybe there’s 100s of Bobs and Carols. There’s a fair amount. Maybe more than today with card processors, but you know. There’s some route. And the blue lines are the individual channels between the participants. This will start looking like what it did before, Dave generates an R, gives an H to Alice, Alice creates a HTLC (hash timelocked contract) between her and Bob. It’s a hashed timelock contract with a 3-day locktime so that the funds are locked up for 3 days and if Bob can produce R in those 3 days then he can pull 1 bitcent from Alice but if he can’t, Alice gets her money back. Bob does the same with Carol, except it’s 2 days. And Carol does the same with Dave but it’s one day. Dave pulls the money because he knows R. Dave could broadcast it on the blockchain, and Carol could broadcast it on the blockchain, but in this case they agreed to remove the contract through the blockchain and they sent the funds atomically. Bob does the same with Carol, and Bob does the same with Alice. At no point has a transaction hit the blockchain.
What happens if Bob decides to not cooperate with Carol on day two? Instead of doing this, Bob just says I’m not going to talk to you Carol and just ignores them. Carol knowing R broadcasts the entire transaction chain on to the bitcoin blockchain. So what happens is that the blockchain now knows R because Alice has redeemed the funds. And at this point Bob has sent money to Carol on the blockchain (unwillingly) because Carol can unilaterally take the money. Bob doesn’t deserve that money, he looks on the blockchain and sees R, but if Bob’s not paying attention, then Alice after 3 days can say I want my money back and Alice gets it for free. Alice knowing R has technically paid Dave. Which is why you want to agree in general and be cooperative.
What does a timeout look like? Let’s say that Dave is going to sit on it and never broadcast R. Dave and Carol’s channel’s output closes first. And Carol is happy with this setup because she knows that her payment closes out, and the knowledge that she will close it out, before her money gets pulled. So the nice thing about this is that if Dave discloses R after the fact, Carol’s already closed out her channel, she doesn’t care, whether inside the channel or on the blockchain. And right now like, it closes out, it closes out, and it’s okay. It’s as if the transaction had never happened, after 3 days.
What are the implications of this? You can view bitcoin transactions as circuits instead of packets. Only uncooperative channels get broadcasted on the blockchain, other than expiry of course. But that means that you really have to look at bitcoin a little differently. If most of the transactions are happening off-chain then bitcoin’s view as a circuit there’s a lot of changes… I don’t want to go into a long rant about that right now. Nearly all transactions do occur off-chain securely and there’s nearly zero risk. The risks are largely about not broadcasting in time. There’s ways to mitigate this. If everyone broadcasts everything on-time, then there’s no situation where Carol has already paid Dave but can’t pull funds from Bob. That doesn’t happen. It’s pretty much near zero trust. It’s trustless. It’s different from giving custody of your funds to a third-party. Creating channels will become infrequent if you use something like this.
So a question would be, well these channels are operating between Alice and Bob and it will eventually expire, right? And then you create a new channel. Well that’s a lot of blockchain spam. You would have a tradeoff between channel expiry and time risk and time value of money. You could mitigate this with another soft-fork, for OP_RELATIVECHECKLOCKTIMEVERIFY where the transaction’s outputs have a relative timelock dependent on when it enters the blockchain instead of some hard blockheight. If you want more information, check out the paper. I don’t know if this will go into bitcoin, but it would be nice because you could have channels that span for years. You could leave it open for years. You could also say it closes next week, but you could roll-over to another time period or something without a transaction on the blockchain. Within those 2 weeks that you choose, you have a time to get a refund if you find it necessary.
Instant transactions work now. You can have funds committed within one second, there’s no backsies, there’s no double spending, etc. Micropayments become really scalable. You could send the equivalent of a tenth of a cent. You could pay for things by the megabyte. You could pay for every single website that you visit. You could pay a tenth of a cent. Totally feasible. Nothing hits the blockchain, why not?
Bitcoin could really scale with this. If you presume that channels wont be used and everyone uses bitcoin like we do today. If everyone in the world are making 2 bitcoin blockchain transactions per day, you’re looking at something like at best 24 gigabyte blocks. The bandwidth at best would be something like 50 megabits per node connection, at best. If you have channels instead and have this channel network and you presume that everyone has two channels for themselves, except for the core nodes and anyone could be a core node, then those people can make a lot of transactions, they can make nearly infinite transactions inside of 133 megabyte blocks. I think two channels per year, especially if you have a relative checklocktimeverify is generous; most people only have one or two bank accounts. It’s not a bank account because you don’t have custodial risk. You’re looking at something like 3 megabits per second per node connection, which is really reasonable. Well, 24 GB isn’t that bad. What happens if everyone is making 20 blockchain transactions per day? Well then you’re looking at 240 GB every 10 minutes. That’s not practical. I think especially if people start using micropayments a lot more, I think it’s very feasible for people to make 20 transactions per day. I think most people in the west probably do 5 to 10 per day. 20 is not that big of a jump. So you kind of want to solve that. Using that payment network, it’s the same- if people do more transactions, unless someone gets really rich or really poor and they need to make a new channel, it’s the same.
So what are the storage costs under this model? You’re looking at something like 7 TB/year for nearly unlimited transactions, which is about $300/year in blockchain archival storage. That’s only if you want to keep a full record of every single bitcoin blockchain transaction ever, for those 7 billion people. So if you want to front that $300/year, it’s not that expensive; it’s much more feasible than 240 GB blocks. And for most people, I think those of us developers miners etc are probably going to use the pruning patch where you keep the most recent 2 weeks, maybe 20 weeks, and the full utxo set and you’re looking at something like 2 TB which is common in current generation desktops. 2 to 4 TB is pretty common. And will only run you maybe $100-$150 and you’re good forever. For those of us with cellphones, you’re looking at several megabytes of storage. The SPV story is slightly easier; both clients create the channel, so they are only looking for txids so they could be an even more lightweight client. They only have to keep track of older blockheaders and older outputs.
A: Yes. That’s a two-part questions. Are you using multisig and hash-encumbered? This is the hash-encumbered part of this output. It has a multisig signature between Alice and Bob so it’s presumed that this output is pre-signed by both parties except for knowing R. So they know the output. And the second question was the relative checklocktime? That’s not an opcode that exists. That’s an opcode that we would like. Instead of just checklocktimeverify which just keeps going or fails, relative checklocktimeverify will return a depth in the blockchain. It would be something like return the depth of my input, if it’s less than something then fail the whole thing, otherwise include the number. This way it’s not dangerous for reorgs. You have a window of time for which it’s valid. It would need to be a script opcode.
Q: The question is usability.
A: The end user doesn’t need to know any of this. You’re not really sending to bitcoin addresses. You sort of need a direct connection. You use the internet. You need some kind of giant chat network or something so that everyone can talk to each other. But that already exists. In terms of the usability, it wont look too different from bitcoin wallets today, especially if you use a payment protocol where you’re sending to some domain name or URI, coinbase.com/username or something, so you would type that in and hit send. You could also do something more elaborate by using pubkeys instead, but irrespective of that, you need some sort of connection.
A: Bob can charge a small fee, it doesn’t matter, maybe one or two satoshis. Alice can have multiple connections to multiple Bobs and she can find the rate that meets her needs the best. Bob’s fee can be positive or negative. Perhaps he has a lot of build-up in one direction, so perhaps someone else sends a really large transaction in the other direction, and now it’s free for another spend, so he might want to give a negative fee to Alice. Bob knows the graph. The blockchain becomes very opaque, you only see two transactions per year per user, and they’re actually doing thousands and you just never see it. And Bob gets some visibility into some subset of transactions, perhaps he’s selling that to marketers or something. Right now every transaction is open, and in this model Bob gets to see more of the transactions than the other guys, so maybe Bob wants to do it for free because he gets that metadata.
A: As long as one of Bob and Carol agrees to rip up their records, nobody has to know what happened.
A: If everyone reports everything, there’s not much you can do. There might be ways to mitigate this.
A: You need the sighash soft-fork. It seems like the best way to fix malleability. From all the people I talk with, nobody disagrees. Most people that we’ve tlaked with think it should be made default. Bitcoin multisig is fundamentally broken; you can’t use a lot of that stuff today because you need to fund something before writing the contract. It’s sort of weird right now. Without any trusted third party, you both need to fund a transaction before you can create an output spent from it. So you can’t do chained multiple transactions. You need something like a 3-deep chain, and to do that you need to fix malleability.
Q: Changetip CEO has mentioned that before everything was on chain, and now everything has custodial model simply because of scalability and practicality, that micropayments are not feasible? So what are the next steps?
A: There’s a lot of stuff to do, and it’s going to have to come together. Even if you wanted to implement this today, you need a soft-fork. You could build a single Bob model using trust. That works today. You could start today, and have these workarounds and then hope that there’s a malleability fix later to really scale out. That’s probably okay. Right now you need this for micropayments, but that’s not a critical need. We could still scale up bitcoin by quite a bit before we start really needing to push things off-chain. We’re working on this. The developers need to be okay with the soft-fork. The miners need to be okay with it. I think everyone’s sort of okay with it already.
A: Yes, you can have micropayment channels from all your users. Bob also doesn’t need to receive money, he needs to have some money going out. That output gtoday can be mutated using some minor changes in bitcoin core v0.10, but Bob’s outputs to Alice, let’s say that Bob encumbers his 1 BTC to Alice, that part can be mutated and it could create a hostage scenario. But maybe in a couple months it will solve itself.
Q: Why can’t Alice’s payments to Carol be very small?
A: Well, you don’t want to trust Bob to a lot of money in transit. So perhaps you only send Bob 10 satoshis and Bob would send Carol 10 satoshis. You could send 10 at a time, since it’s not hitting the blockchain. It’s bandwidth overhead and latency… it would be nice if you had no risk so you could send arbitrary amounts, of course.
A: Bob needs a lot of money even with tiny bits going through. Say that Alice puts a BTC into the channel and Carol does the same. Alice wants to pay Carol, she can’t, because it’s Carol’s money in the channel with the Carol-Bob channel, so Bob can’t credibly push that back to Carol. So nobody would be able to pay each other; they can only pay Bob. So Carol would have to put 1 BTC into the channel and then Bob would put 1 BTC into the channel as well so that there could be bi-directional transactions. The advantage of multi-hop is that Bob doesn’t need to be rich. As long as it averages out, they don’t have to be rich.
Q: How many hops?
A: I think 2 intermedaries. I think 3 hops. I think that takes over the world. How many intermedaries do you need? I think there will be a fully connected graph between all the Bobs and Carols. Even with a thousand, that’s like a million different channels. But I think it is going to be more disconnected, like 3 in the middle. I think Bob and Carol do have money committed online and this is all hot wallets for Bob and Carol and so there’s maybe one entity that doesn’t want to expose itself too much… These are similar to existing financial security issues, like a bunch of valuable stuff and you don’t want to get hacked. Those are going to be the real questions for Alice and Bob. The other users could be offline and they could be using multisig. It pushes a lot of risk into the center, because they’re making fees off of it. With commodity money, your risk paid in the form of fees is effectively what the main focus is. But fiat is mostly debt, so the interest rate is mostly paid based on your counteparty risk. But with gold you’re taking on the security risks, so the fees are related to the security risk. The people that are more secure would probably charge lower fees.
Q: How much capital will Bob and Carol have to have, and how does this equate to the throughput?
A: I think it will solve itself. Just charge zero. Right now the time-value of bitcoin is sort of zero. Someone who has 20,000 BTC will just sit on it at the moment. Well, you could put those 20,000 BTC up here. This is a bitcoin lease rate with zero counterparty risk. It’s kind of great.
A: On blockchain is so much easier is that you first fill up the blocks, then you move to lightning network when the fees become prohibitive. I don’t think it’s a big risk. There’s interesting ways to increase the block size, if miners really get mad, they could prevent some of this stuff from happening. Miners are going to get fees no matter what, I think they will eventually restrict the block size in a way to get more fees, but I think the blockchain transaction fees are going to go up substantially. If you are dumping data on the blockchain because you think bitcoin transactions are going to stay cheap, well I think the transactions are going to go up to $5 per transaction or $10 per transaction.