zk-SNARKs are a method for generating zero-knowledge proofs of arbitrary functions, as long as these functions can be expressed as the result of a R1CS (a rank-one constraint system). However, one still needs to convert functions into R1CS form. As this is a laborious process (though still far easier than starting from scratch), Ecne, named after the Celtic god of wisdom, is a tool that can be used to translate functions into R1CS form, in its current form, by verifying that R1CS equations uniquely determine outputs given inputs (i.e. that the constraints are sound).
The goal of Ecne is to make it easier to convert functions into R1CS form. As of right now, Ecne is used to verify that certain sets of R1CS constraints uniquely identify functions. Ecne also supports adding certain functions to a trusted codebase, so that they do not need to be re-verified after they've been verified once. Eventually, we hope to have Ecne not only show that R1CS constraints have unique solutions, but also show that they correspond to formally specified mathematical functions as well.
The primary user facing function is solveWithTrustedFunctions
. The function takes in the R1CS file of the equation you want (which specifies functions you want) and the r1cs files of Trusted functions with their names. It returns true
when able to verify the soundness of the constraints, and false
otherwise. Note that false
does not mean that the constraints aren't sound, it just means that Ecne is unable to prove that the constraints are sound.
See here for algorithmic details.
First, clone the repository:
git clone https://github.com/franklynwang/EcneProject
Then, clone the circomlib library in Circom_Functions/
git clone https://github.com/iden3/circomlib
The following requirements must be present in your environment.
- Julia 1.7+
- Just: a command runner
Then, run the following command to instantiate the Julia package environment.
just install
To run the interactive Julia REPL or open a Pluto notebook server, use the following commands:
just repl # open Julia REPL (can add packages here)
just notebook # start server (try opening hard_solve.jl)
If you make edits and would like to check that all tests still pass, please use
just test
To verify the correctness of the ECDSA privToPub circuit given the correctness of the SECP circuit, first, we will need to obtain the R1CS file for the ECDSA circuit, which is unfortunately too large to include in this repository. To generate it, you need the Circom Library, after which you run the following command in Circom_Functions:
circom ecdsa.circom --r1cs --O0
Note the O0 compilation is needed to make abstraction possible. Note that this means using optimized constraints in production assumes the correctness of the Circom Compiler, and that the optimized constraints are equivalent to the non-optimized ones.
Finally, simply run julia --project=. examples/ecdsa_secp_abstraction.jl
to show that ECDSA has sound constraints given if we trust the Secp256k1AddUnequal
command
To verify the correctness of the SECP circuit given BigMultModP and BigLessThan, simply run julia --project=. examples/secpk1_abstraction.jl
To see benchmarks on several circuits, run just bench
.
The src/
directory contains a Julia script that can be used to invoke Ecne from
the command line:
$ julia --project=. src/Ecne.jl --help
usage: Ecne.jl --r1cs R1CS --name NAME --sym SYM [--trusted TRUSTED]
[-h]
Ecne command-line helper
optional arguments:
--r1cs R1CS de-optimized R1CS file to verify
--name NAME Circuit name
--sym SYM symbol file with labels
--trusted TRUSTED Optional trusted R1CS file
-h, --help show this help message and exit
With a R1CS file that has been de-optimizedi and its symbol file, Ecne can be invoked via:
$ julia --project=. src/Ecne.jl --r1cs target/division.r1cs --name division --sym target/division.sym
[...]
constraint #2
(-1 * main.y2) * (1 * main.x3) = (-1 * main.y1)
constraint #3
0 * 0 = (-1 * main.x4 + -1 * main.out + 1 * main.y2)
("R1CS function division has potentially unsound constraints",)
Moreover, external tools can trigger verifications via the REST API defined at src/Server.jl
. You can find an example at scripts/launch_post.sh:
curl -X POST http://127.0.0.1:8000/verify -H 'Content-Type: application/json' -d '{"r1cs":"target/division.r1cs","sym":"target/division.sym", "id":"division"}'
Made by Franklyn Wang