diff --git a/README.md b/README.md index ce614b5..c29c577 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ At the moment only the `BN254` (aka. `alt-bn128`) curve is supported. - [ ] make it a nimble package - [ ] proper MSM implementation (I couldn't make constantine's one to work) -- [ ] proper polynomial implemention (constantine's one is essentially missing) - [ ] compare `.r1cs` to the "coeffs" section of `.zkey` -- [ ] make it work for different curves +- [ ] generate fake circuit-specific setup ourselves - [ ] multithreaded support (MSM, and possibly also FFT) - [ ] add Groth16 notes - [ ] document the `snarkjs` circuit-specific setup `H` points convention +- [ ] make it work for different curves diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..02ed808 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,2 @@ +build/ +example \ No newline at end of file diff --git a/example/example.nim b/example/example.nim new file mode 100644 index 0000000..d62933c --- /dev/null +++ b/example/example.nim @@ -0,0 +1,11 @@ + +import ../test_proof +import ../export_json + +let zkey_fname : string = "./build/product.zkey" +let wtns_fname : string = "./build/product.wtns" +let proof = testProveAndVerify( zkey_fname, wtns_fname) + +exportPublicIO( "./build/nim_public.json" , proof ) +exportProof( "./build/nim_proof.json" , proof ) + diff --git a/example/product.circom b/example/product.circom new file mode 100644 index 0000000..b1bb644 --- /dev/null +++ b/example/product.circom @@ -0,0 +1,40 @@ +pragma circom 2.0.0; + +// +// prove a simple factorization +// + +//------------------------------------------------------------------------------ + +template Product(n) { + signal input inp[n]; + signal output out; + + signal aux[n]; + aux[0] <== inp[0]; + for(var i=1; i prod.inp; + out <== prod.out + plus; + log("out =",out); + + out === 2023; +} + +//------------------------------------------------------------------------------ + +component main {public [plus]} = Main(3); \ No newline at end of file diff --git a/example/prove.sh b/example/prove.sh new file mode 100755 index 0000000..d000578 --- /dev/null +++ b/example/prove.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +ORIG=`pwd` +NAME="product" + +# --- create build directory --- +mkdir -p build + +# --- compile the circom code --- +circom --r1cs --wasm -o build ${NAME}.circom + +cd build + +# --- download powers-of-tau ceremony, if necessary --- +PTAU_FILE="power_of_tau_10.ptau" +if ! test -f ./${PTAU_FILE}; then + echo "downloading powers-of-tau..." + curl https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_10.ptau --output $PTAU_FILE +else + echo "powers-of-tau file already exists, skip downloading" +fi +PTAU_FILE="`pwd`/${PTAU_FILE}" + +# --- perform circuit-specific setup --- +snarkjs groth16 setup ${NAME}.r1cs $PTAU_FILE ${NAME}_0000.zkey +echo "foobar entropy" | \ +snarkjs zkey contribute ${NAME}_0000.zkey ${NAME}_0001.zkey --name="1st Contributor Name" -v +echo "baz entropy" | \ +snarkjs zkey contribute ${NAME}_0001.zkey ${NAME}_0002.zkey --name="2nd Contributor Name" -v +rm ${NAME}_0000.zkey +rm ${NAME}_0001.zkey +mv ${NAME}_0002.zkey ${NAME}.zkey + +# --- export vericiation key --- +snarkjs zkey export verificationkey ${NAME}.zkey ${NAME}_vkey.json + +# --- create public input --- +cd $ORIG +echo '{ "inp": [7,11,13] , "plus": 1022 }' >build/${NAME}_input.json + +# --- generate witness --- +cd $ORIG/build/${NAME}_js +node generate_witness.js ${NAME}.wasm ../${NAME}_input.json ../${NAME}.wtns +cd $ORIG/build + +# --- create proof with snarkjs --- +# echo "creating the proof with snarkjs..." +# snarkjs groth16 prove ${NAME}.zkey ${NAME}.wtns snarkjs_proof.json snarkjs_public.json + +# --- build & execute nim prover --- +echo "building and executing the Nim prover..." +cd $ORIG +nim c -r --processing:off example.nim + +cd $ORIG/build +echo "verifying the proof with snarkjs..." +snarkjs groth16 verify ${NAME}_vkey.json nim_public.json nim_proof.json + +cd $ORIG + diff --git a/export_json.nim b/export_json.nim index 68dda01..6872f4c 100644 --- a/export_json.nim +++ b/export_json.nim @@ -64,6 +64,8 @@ proc writeG2( f: File, p: G2 ) = writeFp2( f , ',' , oneFp2 ) f.writeLine(" ]") +#------------------------------------------------------------------------------- + # exports the proof into as a JSON file proc exportProof*( fpath: string, prf: Proof ) = @@ -79,6 +81,7 @@ proc exportProof*( fpath: string, prf: Proof ) = #------------------------------------------------------------------------------- +#[ func getFakeProof*() : Proof = let pub : seq[Fr] = map( [1,101,102,103,117,119] , intToFr ) let p = unsafeMkG1( intToFp(666) , intToFp(777) ) @@ -92,4 +95,6 @@ proc exportFakeProof*() = let prf = getFakeProof() exportPublicIO( "fake_pub.json" , prf ) exportProof( "fake_prf.json" , prf ) +]# +#------------------------------------------------------------------------------- diff --git a/test_proof.nim b/test_proof.nim index bf0493d..7c4bed7 100644 --- a/test_proof.nim +++ b/test_proof.nim @@ -7,22 +7,24 @@ import ./zkey_types #------------------------------------------------------------------------------- -proc testProveAndVerify*( zkey_fname, wtns_fname: string) = +proc testProveAndVerify*( zkey_fname, wtns_fname: string): Proof = echo("parsing witness & zkey files...") let witness = parseWitness( wtns_fname) let zkey = parseZKey( zkey_fname) echo("generating proof...") - let vkey = extractVKey( zkey) - let proof = generateProof( zkey, witness ) - - echo("exporting proof...") - exportPublicIO( "my_pub.json" , proof ) - exportProof( "my_prf.json" , proof ) + let vkey = extractVKey( zkey) + let proof = generateProof( zkey, witness ) echo("verifying the proof...") - let ok = verifyProof( vkey, proof) + let ok = verifyProof( vkey, proof) echo("verification succeeded = ",ok) + # echo("exporting proof...") + # exportPublicIO( "my_pub.json" , proof ) + # exportProof( "my_prf.json" , proof ) + + return proof + #-------------------------------------------------------------------------------