> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-run-liteserver.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How to verify Groth16 examples on TON

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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`        |

<Aside type="caution" title="Run locally first">
  This page follows the upstream Tolk verifier tests and runs in the Blueprint sandbox by default, not on TON Mainnet. When adapting the examples to TON Testnet or TON Mainnet, start on TON Testnet with small amounts. The trusted-setup commands are for local tests; production circuits need a dedicated multi-party ceremony with fresh high-entropy contributions.
</Aside>

## 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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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 theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
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)
