 Hello, my name is Dave Oja. Today I'm going to be talking about fractal, post-quantum recursive snarks. This is joint work with Alessandro Chiesa and Nick Spooner. So it's someone titled, I'm going to be talking about recursive snarks. I'm going to start off when he was familiar with what snarks are, but you may not be familiar with the recursively composing them. So recursion in this context means verifying a snark proof within a snark. And this comes up when you want to verify iterated function application that like, if you apply f, t times to x equals y. So here's a diagram of iterated function application. And strategy to prove this is going to be to prove iteration by iteration. First, I'm going to prove that f of z naught equals z one. And then to verify this, you just run the snark verifier on z one and pi one. And this convinces you that f of z naught equals z one. In the next iteration, we're going to prove that f of z one equals z two. And that the verifier accepts the proof for z one. So when you go to check the proof for z two, you're inductively convinced that z one is valid. And therefore z two equals f of f of z naught. And in the next iteration, you prove that f of z two equals z three. And the proof for z two is valid. And again, like inductively, you're convinced then that z three is correct. And this has a number of like very desirable properties. For example, the size of every statement you prove is independent of the number of times you apply the function. And similarly, the proof size is independent of the number of times you apply the function. And you can verify every intermediate proof. So if you have a confirmation that goes on forever, you can then verify the latest state. And also you can have different people that create proofs for different transitions in here. So some applications of recursive composition are succinct blockchains like Coda. There, what you do is you make f, your state machine transition function. And then you would, one way to do is to have your blocker poser provide a proof with every block they provide. Another application is continuous verifiable blade functions and snarks from app-reduced applications. So cryptographically, what we wanna build is two things. Incrementally verifiable computation, which is what I showed in the previous slide, and proof carrying data, which is a generalization to IVC. And proof carrying data, essentially you can recurse along any directed acyclic graph. So there's this theorem from a paper a couple of years ago that every adaptably secure succinct verifier snark can recurse. So this means is like you start the snark and you recurse to the natural sense and you'll get proof carrying data. And this compilation procedure preserves many properties of the underlying snark. We start with zero knowledge snark, you'll get zero knowledge PCD. It preserves a setup type. So if you have a trusted setup snark, you'll get trusted setup PCD and a transparent snark will yield a transparent PCD. But what about post-quantum? So PCCT13 says nothing about this. So we answer that, yes, if you have a post-quantum snark and you recurse it, you will get post-quantum PCD. This is not like a straightforward generalization of PCCT13. One of the problems is that quantum adversaries can generate their own randomness. So previously you would assume that like your adversaries deterministic because if you had a probabilistic one, you could just fix this randomness and get a deterministic adversary. Whereas here we have to fix that because in the quantum setting, that's not true. Adversaries can always generate their own randomness. So solution is to define a sufficient notion of post-quantum knowledge on this and then prove it secure for our construction in the quantum random model. So now when we want to recurse it in practice, that's we want to actually use these things. So here's a list of many snarks that we know. And here is a sync to barifar ones. So from PCCT13, we know all of these can asymptotically recurse. However, in practice, this is not what we see. Instead, it's just this much smaller set of graph 16, Planck, Sonic and Marlin that we've actually achieved practical PCCT for. And this is a very small set. So this is a question, what does that make snark suitable for recursion? All of these snarks are pairing-based, trusted setup snarks. Hopefully there's transparent PCD that we can get and post-quantum PCD that we can get. Now at this point, I do also want to note that with new techniques that came out very recently, Halo, you can recurse bulletproofs and get PCD, but this does not have a succinct verifier. I'm not going to spend any more time on that in this talk, but we do want to know what it is that made PCD practical for these succinct verifier snarks. And we identify what it is as pre-processing. So a pre-processing snark is one which your verifier is given a small digest of your circuit. And this implies efficient recursion. If you have a pre-processing snark, the cost of proving the recursive step is essentially the same as the cost of proving your original circuit. So we mean it's in a mathematical sense, like the recursive step has a sub-linear additive overhead over proving your original circuit. So if we compare this to the prior method of formalizing this recursion, you would start the snark for a machine relation. And then every time you wanted to go and prove it, you'd have to change, sorry, like do a recursive step, just to change the machine you're running. And then to get unbounded recursion, you would need to use a universal simulator. And this incurs a universal simulation overhead. So instead of it being one plus little one, it would be C times prove a time near original function. And the universal simulation overhead is a multi-factor greater than one. And practice is a very large multi-factor factor. So this is why like recursing these generic machines has not been achieved in practice. So it also tells us that if our goal is to create an efficient PCD scheme, we should focus on creating a pre-processing snark. So this is exactly what we do. We're going to create a post-quantum pre-processing snark for our ONCS. And moreover, it's going to be a transparent snark. So all prior constructions of pre-processing snarks were pre-quantum, no prior transfer setups. Here we're going to do it transparently and in the quantum random-mortical model. So our construction is called fractal. And it has the following asymptotics, like we have a quasi-linear prover, logarithmic verifier, and logarithmic proof size. And each of these matches the best known non-pre-processing post-quantum snark. Concretely, like these running times are, the prover times are in minutes, the verper times are in milliseconds, and that proof size is one 200 kilobytes. And we have an implementation of this. So we can actually see some concrete graphs of this. So to instantiate fractal, we have to fix a random-mortical. So here we're going to use Blake to be. And here I've plotted the verifier time of several snarks. So in black is fractal. Aurora is a state-of-the-art post-quantum snark for circuits that is a non-pre-processing. And then Marlin and Glossick's team are a state-of-the-art pairing-based trust setup snarks for circuits as well. So we see that for Aurora, it's non-pre-processing. It's a linear verifier time. Whereas amongst all of these pre-processing snarks, they're a constant logarithmic. And the actual constants running time are very similar, like around 10 milliseconds. And for proof size, we see that fractals, proof size is about twice as big as Aurora's. But in exchange, we've got this exponential verifier time improvement. So it's just quite nice. Here, I didn't plot the Marlin and Glossick's team proof sizes because they're extremely small, like one to two kilobytes. And then finally, the pooper times. So all of these grow in the same way as apothetically. It's n log n. And the difference between the slowest and fastest thing is like a factor of 10. But it's not like this can even be explained away with implementation differences, different finite field libraries, et cetera. There's not, I don't think there's too much interesting things going on there. It's, they're all remarkably similar. So now we have a fractal standalone stark. Let's look at how we get PCD. So we start with fractal in the quantum random oracle model. Then we apply the random oracle heuristic to get fractal in the uniform reference string. And the random oracle heuristic is instantiating the random oracle, the strong hash, and then assuming that security carries over. This is being used in increasingly many starks, like Sonic, Marlin, Planck, Bulletproofs, all of the post-quantum starks, et cetera. And then we apply theorem one. So then from fractal, from fractal we'll get PCD. So this is gonna be the first PCD construction with any of the following properties. Post-quantum security, a transparent setup, and support for arithmetic over any large smooth field, like binary fields and fields that don't support efficient optic curves, et cetera. So now we wanna go into real, actually using recursing fractal. So to recurse, you have to express the verifier in a language that the snark understands. And this will always lead to new efficiency considerations. For example, to recurse graph 16, you have to use pairing-friendly cycles of elliptic curves for efficiency. So in fractal, your verifier has two components, algebra and a bunch of hashes. And normally when you run it, these take about the same amount of time. But when you go to recurse, it actually looks like this. Hashes take over 99% of your constraint system size. So the choice of hash function and how you erythritize is extremely important. So if we use a standard hash like Blake or Shaw, they're optimized for computer hardware. So they take around 200 nanoseconds to actually run, which is incredibly fast. But in R1CS, they're pretty bad. They take around 20,000 constraints. So if you want to use this for fractal, and we'd have a constraint system size of over two to 28 gates. This is too expensive. Like we can't actually run snark's as big. So instead we have to look towards like algebraic hashes. It's a new line of work. This includes things like Poseidon, rescue, vision and mimsy. The time to execute these hashes on a hardware is much slower, like around 10 milliseconds. But in exchange, the constraints for every hash is much better, around like 300. So this means that the fractal constraint system size would be under two million constraints, which is something we can actually execute. So this is exciting. This means we can actually run the recurse fractal. And as a general rule, your biggest cost of doing recursion is going to be doing cryptography inside of your snark. So here what I've, I'm going to plot some, the cost of the fractal verifier using Poseidon as a random oracle. So in blue here, that's the number of constraints that we're proving. And in black, we have plotted the size of the verifier or in constraints. So it grows logarithically as expected because we have a logarithmic verifier time. So the crossover point at which the verifier constraint system size is less than the number of constraints like being proven is around one million constraints. So this blue shaded triangle is the practical region of recursing where like your verifier overhead is less than the original circuit you're proving. So taking a candidate point in here where your circuit size is six million, this blue thing. The size of your recursive step is going to be this blue value plus the black value, which is around eight million constraints. And since this black line is a verifier size is logarithmic, we can say that for regions that like we can, of circuits we can execute, the size of your recursive circuit is around your original circuit size plus two million constraints. I do want to note that like this recursive overhead represents an unoptimized proof of concept. And the prover is over 10 times slower than the standalone fractal because these algebraic hashes are much slower. But there's a lot of things you can do to improve both of these. So this is all I want to say about the theorems of our work. And now I want to go into a bit of how do you actually create a post quantum preprocessing snark? So all snarks have sort of looked like this. You start with information theoretic proof system and you have a cryptographic compiler. You combine these together and you'll get a snark. So because you want a post quantum snark, we're going to need a post quantum cryptographic compiler. And because you want to be preprocessing, we're going to need what's called a holographic proof system. Combining these, we'll get a post quantum preprocessing snark. So what is a holographic proof system? To explain this, I'm going to first fall back to explaining a PCP. So in a PCP, the prover wants to prove that it knows a witness such that the circuit is satisfied. So the prover gives you a very large proof string pi and the verifier uses the circuit and it will query the proof string pi at a couple of random locations. But the verifier has to know what is the circuit it is verifying. Therefore, the time from the verifier is at least linear in the circuit size. A holographic verifier is one in which the verifier has access to an error tolerant encoded version of the circuit. So in a holographic PCP, the verifier no longer has C as an input. It's just X the instance. And inside there's this third trust entity called the indexer who takes in the circuit and outputs an encoded version of it. And now to check a proof, the verifier is going to query both the proof string pi and the indexer's output of the circuit out of some random locations and be convinced if the prover does indeed know such a witness or not. So the time from the indexer is going to be at least linear in the circuit size. But now the verifier can run in time much smaller than the circuit size. So no longer has to have it as an input. And I mentioned the indexer is trusted. Well, we're going to make it into a preprocessing step. So how do we do this? First we start the holograph PCP and then we're going to get a holographic snark by applying the McCauley transformation. So what is this? You essentially take the proof string pi and the prover is going to miracleize it and send the miracle root to the verifier. And then the verifier is going to query the miracle root at a couple random locations, and sorry, the miracle tree and get values of the proof string pi and miracle truth authentication paths. But this new verifier v prime uses v as a black box. Like it's going to get the values of the proof string pi and then just run what it ran before. And so in particular, we didn't touch how it interacts with the indexer. So this is why it's a holographic snark. And then we're going to compile this into a preprocessing snark. What we do is we're going to use a miracle tree to compress the encoded circuit. And in the preprocessing phase, you're going to have this proof string or this like indexed out encoded circuit and miracleize it. And the verifier is just going to store the miracle root. And then the prover, whenever the verifier wants to query some coded circuit, the prover is going to supply an authentication path for the miracle root, the verifier is already preprocessed. And hence we get a preprocessing snark. And so this connection between holography and preprocessing is first noticed in Marlin. And in this work, we extend it to apply to a miracleizing your encoded circuit and therefore supporting the post quantum transparent use case. And we can replace Macaulay, Macaulay transformation from holograph PCP with any black box transformation. So what we're actually going to do is to use the BCS16 transformation, which is the analog for IOPs to get a preprocessing snark from a holographic IOP. So this just leaves us with, how do we get a holographic IOP? Or when do we get efficient holography? So holographic PCPs were first introduced in the 90s in the BFLS. And many protocols have like naturally holographic alternatives like GKR and Aurora. But the problem is this natural encoding is super late, which in GKR the encoded circuit would require a polynomial blowup. For Aurora, you deal with R1 CS matrices and these are like N by N matrices that typically only have a O of N non-zero entries. So the natural encoding of such a matrix is gonna be a bivariate polynomial of degree N by N such that like it encodes every position in the matrix. So this means that the encoding is gonna require writing down the entire matrix, which takes time at least N squared. We can't actually run that for sizable circuits. So it has way too high of a preprocessor time and a prouver time blowup. So instead we're going to need a linear sized encoding of these matrices because leverage is a fact of their sparse. So here's a candidate sparse matrix M. And essentially we're gonna write down three values for every non-zero entry. The value of entry, the row it's on and the column. So like to unpack this like we take a candidate location and you're like A, it appears in row three and column one. Hence this like slice of these vectors is a A three one. And each of these vectors has length linear in the number of non-zero entries. Since there's only three such vectors, we have a linear sized encoding. But now in order to actually use this in a snark, we're going to need an algebraic way of evaluating M at any of these points. So to do this or something choose the quality function where it returns one if it's two inputs are equal like quality I from I, right? And then otherwise return zero. So our authorization M is going to be as follows. We're going to iterate over every element and then the I coordinate is going to essentially correspond to the row we're looking at and the J value is going to correspond to the column we're looking at. Actually unpack this, it's evaluated at a point. So let's look at M of three one. So when K equals one, we're going to look at row of K or like row of one. And so that's this value right here three. So the quality of three and three is one. Similarly column of K, the column of one is one and this quality value is also one. So this term, the summation is going to be value of one or which is A but for every other term, it's going to be the case that either row of K is not three or column of K is not one. Hence one of these two quality polynomials is going to be zero. So every other term, the summation is zero. Therefore it equals A. And we can evaluate this expression using the univariate Sompchak protocol of Aurora. This is a quite technical slide. Now I'm going to take a second to zoom out and summarize what I've talked about. So we showed that post-quantum recursion yields post-quantum PCD. We also showed that pre-processing implies efficient recursion. And then we construct an efficient post-quantum pre-processing snark called fractal. And the way we construct fractal was by compiling a holographic IOP that uses sparse matrix encodings for holography. And now together, combining all of these, we get a construction of efficient post-quantum PCD. And as an implementation, we provide fractal as a pre-processing snark and fractal as a recursive snark that uses algebraic hashes. Thank you for your time. The paper and code are both online at these links.