diff --git a/contract-dev/techniques/groth16-examples.mdx b/contract-dev/techniques/groth16-examples.mdx new file mode 100644 index 000000000..30decb854 --- /dev/null +++ b/contract-dev/techniques/groth16-examples.mdx @@ -0,0 +1,194 @@ +--- +title: "How to verify Groth16 examples on TON" +sidebarTitle: "Groth16 examples" +--- + +import { Aside } from '/snippets/aside.jsx'; + +Run [Groth16](https://eprint.iacr.org/2016/260.pdf) verifier examples from [`zk-examples/zk-ton-examples`](https://github.com/zk-examples/zk-ton-examples) via [Circom](https://docs.circom.io/), [Noname](https://github.com/zksecurity/noname), [Gnark](https://github.com/Consensys/gnark), and [Arkworks](https://arkworks.rs/), then confirm the proof both locally and on-chain in TON. + +For the underlying export flow, see [Zero-knowledge proofs on TON](/contract-dev/techniques/zero-knowledge). + +## Objective + +The goal is run one of these upstream circuits on TON: + +- `Multiplier` from Circom +- `Sudoku` from Noname +- `cubic-gnark` from Gnark +- `MulCircuit` from Arkworks + +## Prerequisites + +- [Node.js](https://nodejs.org/en/download/) 18 or later LTS. +- One proving stack: [Circom](https://docs.circom.io/getting-started/installation/#installing-circom), [Noname](https://github.com/zksecurity/noname), [Go](https://go.dev/dl/), or [Rust](https://www.rust-lang.org/tools/install). + +## Clone the examples repository + +```bash +git clone https://github.com/zk-examples/zk-ton-examples.git +cd zk-ton-examples +npm install +``` + +## Choose an example + +| Example | Stack | Circuit | What the proof exposes publicly | Tolk test | +| ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------- | +| `Multiplier` | Circom | [`circuits/Multiplier`](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/Multiplier) | `c = a * b` | `npx blueprint test Verifier_multiplier_tolk` | +| `Sudoku` | Noname | [`circuits/Sudoku`](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/Sudoku) | A partially filled grid | `npx blueprint test Verifier_sudoku_tolk` | +| `cubic-gnark` | Gnark | [`circuits/cubic-gnark`](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/cubic-gnark) | `y = x^3 + x + 5` | `npx blueprint test Verifier_cubic_tolk` | +| `MulCircuit` | Arkworks | [`circuits/Arkworks/MulCircuit`](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/Arkworks/MulCircuit) | `z = x * y` | `npx blueprint test Verifier_ark_tolk` | + + + +## Run the `Multiplier` example + +Select `Multiplier` for a minimal end-to-end Groth16 verifier flow with two private inputs and one public output. +The proof is generated at test time from `Multiplier_js/Multiplier.wasm` and `Multiplier_final.zkey`. + +```bash +cd circuits/Multiplier +circom Multiplier.circom --r1cs --wasm --sym --prime bls12381 +PTAU_ENTROPY="$(openssl rand -hex 32)" +ZKEY_ENTROPY="$(openssl rand -hex 32)" +npx snarkjs powersoftau new bls12-381 10 pot10_0000.ptau -v +npx snarkjs powersoftau contribute pot10_0000.ptau pot10_0001.ptau --name="First contribution" -v -e="$PTAU_ENTROPY" +npx snarkjs powersoftau prepare phase2 pot10_0001.ptau pot10_final.ptau -v +npx snarkjs groth16 setup Multiplier.r1cs pot10_final.ptau Multiplier_0000.zkey +npx snarkjs zkey contribute Multiplier_0000.zkey Multiplier_final.zkey --name="1st Contributor" -v -e="$ZKEY_ENTROPY" +npx snarkjs zkey export verificationkey Multiplier_final.zkey verification_key.json +cd ../.. +npx export-ton-verifier ./circuits/Multiplier/Multiplier_final.zkey ./contracts/verifier_multiplier.tolk --tolk --contract-name multiplierVerifier +npx blueprint test Verifier_multiplier_tolk +``` + +Expected output + +```text +PASS tests/Verifier_multiplier_tolk.spec.ts +``` + +The checked-in upstream Tolk snapshot records `Verify = 88665` gas and code size `5829 bits / 11 cells`. + +## Run the `Sudoku` example + +Select `Sudoku` for a larger verification key and many public inputs. +The `Sudoku` source checks rows, columns, and diagonals. It does not check 3x3 boxes (subgrids). + +```bash +cd circuits/Sudoku +noname check +noname run --backend r1cs-bls12-381 --private-inputs "$SOLUTION_JSON" --public-inputs "$GRID_JSON" +PTAU_ENTROPY="$(openssl rand -hex 32)" +ZKEY_ENTROPY="$(openssl rand -hex 32)" +npx snarkjs powersoftau new bls12-381 14 pot14_0000.ptau -v +npx snarkjs powersoftau contribute pot14_0000.ptau pot14_0001.ptau --name="First contribution" -v -e="$PTAU_ENTROPY" +npx snarkjs powersoftau prepare phase2 pot14_0001.ptau pot14_final.ptau -v +npx snarkjs groth16 setup Sudoku.r1cs pot14_final.ptau Sudoku_0000.zkey +npx snarkjs zkey contribute Sudoku_0000.zkey Sudoku_final.zkey --name="1st Contributor" -v -e="$ZKEY_ENTROPY" +npx snarkjs zkey export verificationkey Sudoku_final.zkey verification_key.json +npx snarkjs groth16 prove Sudoku_final.zkey Sudoku.wtns proof.json public.json +cd ../.. +npx export-ton-verifier ./circuits/Sudoku/Sudoku_final.zkey ./contracts/verifier_sudoku.tolk --tolk +npx blueprint test Verifier_sudoku_tolk +``` + +Define placeholders + +- `SOLUTION_JSON` — JSON object with the private solved grid in the format expected by `circuits/Sudoku/src/main.no` +- `GRID_JSON` — JSON object with the public partially filled grid in the format expected by `circuits/Sudoku/src/main.no` + +Expected output + +```text +PASS tests/Verifier_sudoku_tolk.spec.ts +``` + +The checked-in upstream Tolk snapshot records `Verify = 857057` gas and code size `48111 bits / 79 cells`. + +## Run the `cubic-gnark` example + +Select `cubic-gnark` when the proving stack is Go. +The upstream `main.go` proves the public relation `y = x^3 + x + 5` and exports `proof.json` plus `verification_key.json` in `snarkjs` format. + +```bash +cd circuits/cubic-gnark +go run main.go +cd ../.. +npx export-ton-verifier ./circuits/cubic-gnark/verification_key.json ./contracts/verifier_cubic.tolk --tolk --contract-name Cubic +npx blueprint test Verifier_cubic_tolk +``` + +Expected output + +```text +PASS tests/Verifier_cubic_tolk.spec.ts +``` + +The checked-in upstream Tolk snapshot records `Verify = 88665` gas and code size `5829 bits / 11 cells`. + +## Run the `MulCircuit` example + +Select `MulCircuit` when the proving stack is Rust. +The upstream `main.rs` proves a multiplication circuit over `Bls12_381` and exports `json/proof.json` plus `json/verification_key.json`. + +```bash +cd circuits/Arkworks/MulCircuit +cargo run +cd ../../.. +npx export-ton-verifier ./circuits/Arkworks/MulCircuit/json/verification_key.json ./contracts/verifier_ark.tolk --tolk --contract-name arkVerifier +npx blueprint test Verifier_ark_tolk +``` + +Expected output + +```text +PASS tests/Verifier_ark_tolk.spec.ts +``` + +The checked-in upstream Tolk snapshot records `Verify = 88665` gas and code size `5829 bits / 11 cells`. + +## Verify + +Run-time verification succeeds when all the following are true: + +- [`snarkjs.groth16.verify(...)`](https://github.com/iden3/snarkjs#7-verify-the-proof) returns `true` +- The unnamed Sudoku verifier exposes a `getVerify()` getter, while named verifiers expose a suffixed getter, such as `getVerifyMultiplierVerifier()` — both should return `true` +- `npx blueprint test ...` exits with code `0` + +Not runnable. Partial snippet from the upstream Tolk tests: + +```ts +const okLocal = await snarkjs.groth16.verify(verificationKey, publicSignals, proof); +expect(okLocal).toBe(true); + +const { pi_a, pi_b, pi_c, pubInputs } = await groth16CompressProof(proof, publicSignals); + +expect(await verifier.getVerify({ pi_a, pi_b, pi_c, pubInputs })).toBe(true); + +const verifyResult = await verifier.sendVerify(deployer.getSender(), { + pi_a, + pi_b, + pi_c, + pubInputs, + value: toNano('0.15'), +}); +``` + +## Troubleshoot + +- If `npx blueprint test ...` fails because the Tolk contract is missing, rerun the matching `npx export-ton-verifier ... --tolk` command for that example. +- If `snarkjs.groth16.verify(...)` returns `false`, confirm that the proof, public signals, and verification key come from the same circuit build. +- If `export-ton-verifier` rejects the input file, confirm that the example uses Groth16 over `bls12-381`. + +## See also + +- [Zero-knowledge proofs on TON](/contract-dev/techniques/zero-knowledge) +- [`zk-examples/zk-ton-examples`](https://github.com/zk-examples/zk-ton-examples) +- [`mysteryon88/export-ton-verifier`](https://github.com/mysteryon88/export-ton-verifier) diff --git a/contract-dev/techniques/zero-knowledge.mdx b/contract-dev/techniques/zero-knowledge.mdx index c11e0ddc0..2c6a021a1 100644 --- a/contract-dev/techniques/zero-knowledge.mdx +++ b/contract-dev/techniques/zero-knowledge.mdx @@ -8,9 +8,9 @@ import { Aside } from '/snippets/aside.jsx'; Create, compile, and test a simple [Circom](https://docs.circom.io/) scheme and verify a [ZK-proof](https://en.wikipedia.org/wiki/Zero-knowledge_proof) using the [zk-SNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) [Groth16](https://eprint.iacr.org/2016/260.pdf) protocol. ## Prerequisites @@ -389,7 +389,7 @@ Use the gnark library to generate the proof and verification key, then convert t -## Useful Links +## Useful links - [The zk-ton-examples repository](https://github.com/zk-examples/zk-ton-examples/) contains additional examples of zk-SNARK circuits and their integration with TON. - [The export-ton-verifier repository](https://github.com/mysteryon88/export-ton-verifier) is a library that generates TON-compatible verifier contracts from snarkjs verification keys. diff --git a/docs.json b/docs.json index 1799c27b3..8edd5fa93 100644 --- a/docs.json +++ b/docs.json @@ -500,7 +500,8 @@ "contract-dev/techniques/random", "contract-dev/techniques/upgrades", "contract-dev/techniques/vanity", - "contract-dev/techniques/zero-knowledge" + "contract-dev/techniques/zero-knowledge", + "contract-dev/techniques/groth16-examples" ] }, { diff --git a/resources/dictionaries/custom.txt b/resources/dictionaries/custom.txt index 7b9f4f40e..70e828c97 100644 --- a/resources/dictionaries/custom.txt +++ b/resources/dictionaries/custom.txt @@ -305,11 +305,13 @@ gitbook Gitpod globals gnark +Gnark Goldschlag Golev Grafana grammY Groth +Groth16 GTon Gunicorn gusarich @@ -483,6 +485,7 @@ multicast Multicasting multichain Multichain +MulCircuit multiplatform Multiplatform multiset @@ -700,6 +703,7 @@ subexpressions subfolder subfolders subgraph +subgrids subinterval subnet subnets