NilFoundation / zkLLVM

Zero-Knowledge Proof Systems Circuit Compiler
https://docs.nil.foundation/zkllvm
278 stars 48 forks source link

Move native elliptic curve selection from assigner to compiler #517

Open aleasims opened 7 months ago

aleasims commented 7 months ago

Circuit and assignment table generation requires selection of a field (curve), which all the primitives will be build on (let's call it native field). This field is used later as a value type for all assigner runtime values.

Right now we compile code into LLVM assembly regardless the native field. Generated IR doesn't depend on this field. When you later run assigner, you provide it -e option, specifying desired field type (pallas and bls12381 are only supported now).

The problem arises when you come across non-native field types. Some of these types are going to be represented with more than one element of native field. E.g. ed25519 base field is represented with 4 elements of pallas base field. As a result, the size of our built-in field types depends on some runtime parameter. This results in some ugly memory manipulations in assigner at runtime, which we would really like to avoid, because they make it unnecessarily more complicated and error-prone.

The way to solve this is to make generated LLVM assembly depend on native field. Native field may be selected at compile-time and embedded into generated .ll file. This may be achieved by adding option for this to clang. Compiler will insert this information into target data layout, which will be read by assigner in the future.

As a result, instead of this:

clang ...
assigner -e pallas ...

you will have something like this:

clang -mnative-field=pallas ...
assigner ...