By the end of today’s lecture, you will learn:
Throughout this course, we have studied four fundamental topics.
Cryptocurrencies and the blockchains within them, which enable financial transactions in a decentralized way, without the need to give your money to intermediaries (like banks).
Broadcast protocols and agreement protocols in the (a)synchronous setting, which enable consensus over the Internet without needing to rely on intermediaries (like social media websites).
Encryption and its use to enable data sharing only to a specific person or server on the Internet, without the need to give your data to intermediaries (like Internet service providers).
Tools to perform data science without data sharing.
Before spring break we focused on integrity and availability. For the last few weeks, we have also considered the importance of data confidentiality. Still though, hopefully you see a theme across all four topics:
The tools in this course allow for data-driven decision making, without the need to place blind trust in another company or person.
To be clear: it’s perfectly fine to trust other people!
But it’s not so good if you are forced to trust a random intermediary just to get things done (either in the physical or digital world), and this problem is exacerbated if you cannot verify their behavior to know whether they are worthy of your trust.
By using these and other tools for data security and privacy, the goal is to:
“Cryptography is how people get things done when they need one another, don’t fully trust one another, and have adversaries actively trying to screw things up.”
– Ben Adida
These four topics of cryptocurrencies/blockchains, broadcast & consensus algorithms, encrypted communication, and protecting data in use are all of the topics I wanted to cover in this course. So in some sense, we are done!
…Well, not quite. So far we have studied each of these topics in isolation. For the last few classes of this semester, I want to look at:
To the latter point: we have a guest lecture on Thursday, April 24 by Prof. Andy Sellars of the BU Law school to talk about the connection between cryptography and the law. This lecture will not be recorded, so please attend in person.
Recall that a ZK proof allows a prover Peggy to convince verifier Victor that a statement is true, without revealing the evidence or reason why. It satisfies three properties: completeness, soundness, and zero-knowledgeness.
Prover Peggy\((x, w)\) | Verifier Victor\((x)\) | |
---|---|---|
|
\(\begin{array}{c} \underset{\longleftarrow}{\pi} \\ \longrightarrow \\ \vdots \\ \longrightarrow \end{array}\) |
|
output: Accept or Reject |
Let me give you a brief glimpse into the cutting-edge of ZK. There has been a substantial amount of work over the past decade to construct zk-SNARKs. These are:
The word “snark” comes from a poem by Lewis Carroll, in which several people are hunting a fictional animal that he calls a snark.
Also: for the purposes of this class, you should think of the words “proof” and “argument” as synonyms.
These proofs are very small, say just a few hundred bytes in size. This is true even if:
Here are some potential applications of zk-SNARKs:
Let me give you a glimpse into how zk-SNARKs are built. The main challenge is to provide succinctness and soundness together.
As a thought experiment: let’s think about what you might do to verify a computation done by someone else, if ZK and succinctness were not needed. Here is one approach:
Example. Suppose that you outsource to the cloud the act of calculating \(2^{20}\). For now, let’s pretend that the only way to calculate this number is to multiply a register by 2 a total of \(20\) times.
Question. But what if the cloud can only send you a small amount of data, of your choice. What should you request? (Asking for just part of the working state will not work, as the cloud could lie elsewhere.)
What you need is some way to bind together all of the cloud’s working state \(1, 2, 4, 8, \ldots\) into some object that is:
One mathematical object with this property is polynomials. They have the property that if you change a polynomial at even one point, then you end up changing it at nearly every point.
Or in other words:
Two different polynomials \(P\) and \(Q\), each of degree \(d\), intersect in at most \(d\) points.
Does this solve the problem?
The punchline here is:
If we can transform the action of “verifying an arbitrary program outsourced to the cloud” into “verifying some polynomial arithmetic,” we would be done!
Amazingly, this is possible to do!
Fortunately, there are ZK computer programs that handle the strange “moon math” of polynomials and R1CS behind the scenes.
Do not invest in cryptocurrencies! It is a great way to lose money.
Recall that Bitcoin transactions are “pseudonymous.”
Even if the blockchain itself doesn’t reveal the sender and receiver’s identity, it’s entirely possible that people can find out about your transaction in other ways. For instance:
Perhaps Alice reuses the same public key with many people. Now Mallory can track Alice’s other transactions, just as you all did in Challenge Problem 1.
Perhaps Mallory watches over Alice’ shoulder as she posts a cryptocurrency transaction to buy coffee.
Perhaps the sender just announces the transaction on the Internet.
Perhaps the amount of the transaction is so large that only a few people or organizations in the world could even produce it.
Perhaps Mallory is smart enough to connect many transactions on the blockchain together. For instance, consider this transaction posted not long after the previous one. Which of the two destination addresses do you think is the change address that is returning money back to the original sender?
Perhaps Mallory is clever enough to connect many transactions on the blockchain.
Bitcoin achieved its goal of a secure, decentralized ledger through replication – that is, making every financial transaction public to the world.
The problems of establishing consensus and preventing double spending are indeed hard, and we spent several lectures discussing them. But why do they require the whole world to know exactly when you buy coffee in the morning? One problem doesn’t seem related to the other.
Recall that in Bitcoin, you must maintain a secret key, from which you can derive a public key. As the name suggests, a public key can be posted to the world – it is safe to do so, in the sense that nobody will be able to calculate your secret key from it, so your coins are safe.
But just because you can publish a public key, doesn’t mean that you have to do so.
In Bitcoin, the hash of each public key is immediately posted to the ledger, and the real public key is posted whenever you want to spend a transaction. That’s why we see them on https://mempool.space.
But publishing your public key can lead to de-anonymization attacks, where others can figure out which real-world people correspond to which alphanumeric sequence of keys.
By contrast, the Zcash currency has two kinds of addresses:
If you and your friends only ever used transparent addresses in Zcash, everything would look basically the same as it does in Bitcoin.
There’s only one thing that might look a bit different to you: there is one account that stores an incredibly large amount of money in it.
That’s because the big pool of money is actually the sum total of all shielded accounts. Anyone with a shielded account can move some (but not all!) of the money in the pool.
Let’s look at a transaction between two shielded accounts. It has a transaction id, as normal. But the identity of the accounts is concealed. From the perspective of the public blockchain, no money has moved! All of it stayed in the giant money bag.
And here is a transaction that moves between the giant shielded money bag and a “normal” public account.
Public addresses on Zcash always begin with the letter t
, and shielded accounts begin with the letter z
(although we can’t see the shielded address here via the public view of the blockchain; only the account owner would see that).
[This portion of the lecture notes is derived from Electric Coin Company: How Transactions Between Shielded Addresses Work.]
In order to explain the transactions between shielded addresses, it is helpful to recall how transactions between transparent (Bitcoin-like) addresses work.
To simplify the story for now, let’s leave aside the scripting language, and suppose that a transaction only contains a digital signature.
Recall that Bitcoin is based on the unspent transaction (UTXO) model. For a transaction to be valid:
In other words, we can think of the blockchain as storing a table of hashed public keys and associated monetary amounts.
After the first two transactions in the above figure, the table would look something like this.
Hashed key | Amount |
---|---|
H(pk1) | 1.5 |
H(pk2) | 2.2 |
H(pk3) | 0.5 |
Here is the first change that Zcash makes, which on its own is relatively minor.
Hashed key | Amount |
---|---|
H(pk1, r1) | 1.5 |
H(pk2, r2) | 2.2 |
H(pk3, r3) | 0.5 |
When the third transaction is posted to the blockchain, suppose that the sender posts both a digital signature and the serial numbers of the just-spent coins.
Afterward, all nodes:
If all checks pass, the nodes update their record of the unspent transactions as follows.
Hashed key | Amount |
---|---|
H(pk3, r3) | 0.5 |
H(pk4, r4) | 1.8 |
The nodes also keep a list of spent serial numbers: in this case r1
and r2
. If serial numbers are unique, this is a quick way to check that nobody posts the same transaction twice.
The main idea of Zcash is to:
do the work described above in zero knowledge.
Concretely, the parties maintain a hashed version of the above table, so that nobody can read the keys or the amounts.
To make the above transaction, the sender posts hashes of the serial numbers H(r1)
and H(r2)
—which are called nullifiers in Zcash-lingo—along with a zero knowledge proof that:
The sender knows values pk1
and pk2
such that when you hash them together with the serial numbers, the results are the hashed keys H(pk1, r1)
and H(pk2, r2)
that are being spent.
The sender knows the secret keys corresponding to the public keys pk1
and pk2
. (This is essentially what the digital signature did before… in fact, a signature is a special case of a ZK proof.)
These nullifiers have never been used in a previous transaction. This is where the name comes from – posting H(r1)
effectively nullifies the coins held by pk1
to ensure that they aren’t spent twice.
The amount of money being sent to the recipient is less than or equal to the amount in the current account. (That is: the sender is only giving away the part of the giant money bag that it has the right to use.)
The sender creates a non-interactive zk-SNARK and posts it to the blockchain, and everyone verifies it. If so, they add H(r1)
and H(r2)
to their nullifier set.
The takeaway here is that:
The actual Zcash protocol includes many tricks to make this process more efficient. For instance: rather than storing a big table of all hashed keys and hashed amounts, instead all of that data is put into a Merkle tree.
Transactions that move money between shielded and transparent accounts work similarly. In this case, it is publicly visible that the size of the giant account is increasing or decreasing, but nobody knows who has control of the money that just entered/left.
But there is one unfortunate catch:
Remember that zero knowledge proofs enable the prover to demonstrate to the world that they possess some information, without the need to broadcast it to the world.
Here’s an intriguing question: what happens if the prover’s information itself includes a non-interactive zero knowledge proof that the prover received earlier from someone else?
Example. Suppose I ask everyone in the class to solve one Sudoku puzzle, and give me a non-interactive ZK proof that you know the solution. Then, I want to make a single ZK proof that all of the Sudoku puzzles are solveable.
I cannot prove the statement “I know the solution to all Sudoku puzzles,” because I don’t know the solutions.
But what I can do is prove “I have in my possession valid non-interactive ZK proofs of all Sudoku puzzles.” This is a perfectly valid thing to do! It is called a recursive zero knowledge proof, or proof-carrying data.
This is somewhat mind-blowing. You can attach a tiny proof to any piece of data that explains its full provenance – which raw data it came from, and what data analysis was performed in order to produce it.
This technique has a wide range of applications in data science. But today we will look at one application involving cryptocurrencies.
Every cryptocurrency we have seen so far – Bitcoin, Ethereum, and Zcash – fundamentally relies on a blockchain data structure.
The individual transactions might include digital signatures, smart contracts, or ZK proofs; no matter what, they are periodically grouped together into a block and appended to the existing chain.
As a result, the blockchain for each cryptocurrency grows linearly with the number of transactions that have ever been made. For instance, the Bitcoin blockchain is currently 653 GB in size.
Using recursive zero knowledge proofs, we can substantially reduce the size of the blockchain.
Let’s imagine that the following picture contains part of the Zcash blockchain. Each block contains a series of transactions, and suppose that each one is a zero knowledge proof corresponding to a private transaction.
Question. How can the miner reduce the size of a block?
Answer. The miner can produce a recursive proof of the following statement:
“I have seen a series of proofs by individual senders, and they are all valid, and they result in specific nullifiers being added to the set.”
Remember that a single zk-SNARK has constant size, independent of the complexity of the statement that produced it. So we can compress all signatures in a block effectively down to the size of a single transaction!
But why stop there? Recursion is such a powerful technique that we can use it between blocks too.
Recall that when a new client joins the cryptocurrency, the first thing it must do is to download the blockchain (or at least the headers) and verify all of them. That’s a lot of work, and we’re asking every new client to do the same thing.
So here is an idea: when a miner produces a block, it proves that all blocks since the start of time are valid.
That sounds like a lot of work, but actually it isn’t, thanks to the power of recursion. The miner of block \(N-1\) has already posted a proof that the first \(N-1\) blocks are valid. So the current miner can create a proof that:
“I have seen individual proofs that each transaction in block \(N\) are valid, and I have seen a proof that the first \(N-1\) blocks contain valid transactions as well.”
(It does take some computing work for the miners to build these proofs, but compared to the immense amount of work that miners already do to solve the proof-of-work puzzle, this is nothing.)
The amazing result of all this recursion is a succinct blockchain.
The Mina blockchain can be summarized in about 20kB of data, even though the number of transactions on the network is continually growing.
This is so small that anyone can easily download it and verify the entire blockchain.
Note that some people need to act as:
Fortunately, most people can act as ultralight clients. Thanks to the (recursive) ZK proofs, they only need the succinct summary of the blockchain in order to verify their balance, unlike with Bitcoin where the clients needed to place trust in the nodes/miners.
Today we have seen the privacy benefits that accrue when we combine zero knowledge proofs (part 4) with cryptocurrencies (part 1 of this course).
It turns out that combining consensus protocols (part 2) with cryptocurrencies also produces a huge win: we can replace the energy-intensive proof of work puzzles with an environmentally-friendly leader election protocol.
More generally: each of the cryptographic tools we have built in this course is powerful on their own. And they can become even more powerful when we find clever ways to use them together!
DS 653 — Lecture 23