-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What do we want the Core language to be? #83
Comments
I agree that since it is a low-level language it makes sense to give full control to programmer. Simplicity is important here. If the programmer can implement the optimization himself, then a simpler compiler seems crucial, at least at this stage, and in particular because of mentioned cons. The compiler will provide privacy, but the programmer should be the one responsible for performance. |
@jakzale asked about compilation of the following expression:
which made me think about
compiles to the following IR:
The important part here is that the What this means is that we are allowed to have a Moreover, allowing So it's perfectly fine to nest But of course the fact that we can compile such programs does not mean that we have to allow the user to compile them. In
is So there's no notion of local scope for a
So it still makes sense to distinguish between the top level and local scopes as assertions can only be compiled efficiently at the top level. Of course we also have the problem of compiling division in local scopes as that operation may fail, i.e. it's effectful in the same way as
Summarizing: we should allow
|
Note however that it's not necessary as we don't lose any generality by not supporting this. Any kind of general strategy that we could implement for compiling And when it comes to division we can provide a We do lose some convenience by not supporting And obviously compiling assertions in local scopes efficiently requires handling a myriad of corner cases, so plenty of non-trivial research that nobody asked us to perform. So I believe we either shouldn't bother with |
Quoting a slack discussion (just to have it documented here):
Another example is range checks with negative numbers. We can potentially compile
via
but that same logic does not work with comparisons, because requiring That only applies to the Core language. Whether supporting |
Currently we have a "typed" language (it's a GADT at the moment, but we could potentially change that, but I don't see why bother).
I believe the current language already accurately reflects what a source langauge for compilation to the R1CS/Sonic constraint system has to be. I also believe that the design space is really narrow and there aren't many opportunities for design choices.
However @jakzale mentioned one possibility and it's having a single
assert
storing a boolean expression in CNF.Pros:
Cons:
let
s andassert
s and calling eachassert
as early as possible. It's not clear how critical it would be if we deferred all calls toassert
until every singlelet
is computed as we don't care about the performance of the prover that much (we mostly care about the performance of the verifier), but it does feel wrong to introduce such an inefficiency just for the sake of having a more minimalistic system. Interleavedlet
s andassert
s do reflect better the nature of the computation that the prover is supposed to performBut in Zonk I implemented it like this (where
/
is supposed to be compiled without ensuring that the divisor is zero, because it can't be zero):R1CS and Sonic are extremely similar, almost identical, yet I had to completely rewrite the whole thing in order to make compilation efficient. It looks like we'd need to implement a specific form of CSE for each possible zero knowledge backend, which is a lot of highly non-trivial research and development just to solve a task that nobody asked us to solve, as the programmer writing the actual code in Zonk likely already knows what expressions make bindings.
Note also that sometimes we don't want to perform CSE over certain subexpressions. For example, the following program:
can be more efficient than if we bind
a + b
to a variable as that would increase the number of constraints. Although given that we're supposed to produce compressed Sonic vectors it's not really clear if having an additional constraint here will make things slower, but then why commit to a single way of handling things, if it's not clear which option is better. The programmer can decide for themselves, particularly given the fact that efficiency concerns are all backend-specific.Moreover if we did this single
assert
thing, the output of the first few stages of compilation would basically be obfuscated and completely indecipherable for any non-hello-world program. The programmer writes a program, introduces certain names and logic and we just inline everything and then come up with our own bindings and their bodies, not related in any way to the original program. That would make any kind of visual inspection of intermediate programs completely infeasible, i.e. we'd be less likely to catch an error if it appears somewhere in the logic of the compiler.And our language is fairly low-level. The programmer should be given full control over what expressions stay bound to variables, what bindings get inlined. I believe that writing an algorithm that consistently outperforms a dedicated human being requires plenty of research and even if we had one, it'd have to be optional. Efficiency (in terms of the number of constraints in the final result) is critically important as that determines how much time is spent on verification and we do want to allow the programmer to fine-tune the output for their specific needs in a predictable way.
Finally, we simply have a ton of quite more vital stuff to do and don't have enough bandwidth for any non-essential and at the same time non-trivial research.
So I believe we shouldn't even attempt investigating this single
assert
idea any time soon.The text was updated successfully, but these errors were encountered: