noir-lang / noir

Noir is a domain specific language for zero knowledge proofs
https://noir-lang.org
Apache License 2.0
821 stars 177 forks source link

0.30.0 Codegen Verifier Contract Not Working #5337

Closed hooperben closed 4 days ago

hooperben commented 4 days ago

Aim

I am building a circuit with nargo v0.30.0, but when exporting this to the verifier contract, I can never get the verifier contract to evaluate the proof successfully. However, if I change my nargo version to v0.29.0 and regenerate the verifier contract, the verifier contract will work as expected.

Expected Behavior

the following should pass with nargo v0.30.0 - but only passes with v0.29.0.

// circuits/src/main.nr

fn main(x: Field, y: pub Field) {
    assert(x != y);
}

#[test]
fn test_main() {
    main(1, 2);

    // Uncomment to make test fail
    // main(1, 1);
}
// contracts/UltraVerifier.sol
// (this file is copied and renamed from circuits/contract/circuits/plonk_vk.sol)
...
contract UltraVerifier is BaseUltraVerifier {
    function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) {
        return UltraVerificationKey.verificationKeyHash();
    }

    function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) {
        UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc);
    }
}
// nargo.test.ts
import { compile, createFileManager } from "@noir-lang/noir_wasm";
import { resolve } from "path";
import { CompiledCircuit } from "@noir-lang/types";
import { BarretenbergBackend } from "@noir-lang/backend_barretenberg";
import { Noir } from "@noir-lang/noir_js";

import { ethers } from "hardhat";

const getCircuit = async () => {
  const basePath = resolve("./circuits/");
  const fm = createFileManager(basePath);
  const result = await compile(fm);
  if (!("program" in result)) {
    throw new Error("Compilation failed");
  }
  return result.program as CompiledCircuit;
};

describe("Testing Nargo", function () {
  it("should let me prove circuit", async () => {
    const circuit = await getCircuit();

    const backend = new BarretenbergBackend(circuit);
    const noir = new Noir(circuit, backend);

    // next, we deploy our prover contract
    const UltraVerifier = await ethers.getContractFactory("UltraVerifier");
    const ultraVerifier = await UltraVerifier.deploy();
    await ultraVerifier.waitForDeployment();

    const proof = await noir.generateProof({ x: 1, y: 2 });

    // proof is valid
    console.log(proof);

    // now call the contract - but this will fail
    await ultraVerifier.verify(proof.proof, proof.publicInputs);

    console.log("works"); // doesn't actually work
  });
});

Bug

when noir version = 0.30.0 and running nargo codegen-verifier and using that plonk_vk.sol, it's the following error:


  1) Testing Nargo
       should let me prove circuit:
     Error: VM Exception while processing transaction: reverted with custom error 'PAIRING_FAILED()'
    at UltraVerifier.verify (contracts/UltraVerifier.sol:2763)
    at EdrProviderWrapper.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:446:41)
    at async staticCallResult (node_modules/ethers/src.ts/contract/contract.ts:337:22)
    at async staticCall (node_modules/ethers/src.ts/contract/contract.ts:303:24)
    at async Proxy.verify (node_modules/ethers/src.ts/contract/contract.ts:351:41)
    at async Context.<anonymous> (test/nargo.test.ts:37:5)

when noir version = 0.29.0 and running nargo codegen-verifier and using that plonk_vk.sol, it works fine:

works
    ✔ should let me prove circuit (1699ms)

To Reproduce

Clone this repo and have a look if you'd like:

https://github.com/hooperben/nargo-issue/

In order to test you'll have to do:

noirup --branch v0.29.0

to change to v0.29.0.

Project Impact

Blocker

Impact Context

Can't really use nargo v0.30.0 in smart contracts unless this is fixed.

Workaround

Yes

Workaround Description

Downgrade to v0.29.0

Additional Context

No response

Installation Method

Binary (noirup default)

Nargo Version

nargo version = 0.30.0 noirc version = 0.30.0+af57471035e4fa7eaffa71693219df6d029dbcde (git version hash: af57471035e4fa7eaffa71693219df6d029dbcde, is dirty: false)

NoirJS Version

^0.25.0

Would you like to submit a PR for this Issue?

Maybe

Support Needs

I'd like to fix the verifier contract but idk how that moon math works just yet lol

TomAFrench commented 4 days ago

Hey @hooperben, this issue is due to your project using multiple incompatible versions of the proving library barretenberg.

In your package.json, you're using the 0.25.0 release of Noir packages. this pulls in version 0.26.3 of bb.js

https://github.com/noir-lang/noir/blob/3f676051a6073d6eabdc7fee68e4b522334344f6/tooling/noir_js_backend_barretenberg/package.json#L45

Now when you're running nargo codegen-verifier, you're pulling in completely different versions of barretenberg from which to generate the smart contract with.

nargo 0.30.0: https://github.com/noir-lang/noir/blob/af57471035e4fa7eaffa71693219df6d029dbcde/tooling/bb_abstraction_leaks/build.rs#L13

nargo 0.29.0: https://github.com/noir-lang/noir/blob/2da28997dbedce4a00d2162eddb57564bdb23546/tooling/bb_abstraction_leaks/build.rs#L13

It's likely that there was a breaking change in barretenberg between versions 0.35.1 and 0.38.0 which means that it's no longer compatible with proofs generated using bb.js version 0.26.3.

Noir doesn't control the versioning of barretenberg so we can't provide any guarantees about compatibility between versions. We're currently removing some of the "magic" around interacting with barretenberg in order to make using compatible versions easier but for the time being I'd recommend making sure that nargo and any @noir-lang JS packages are on the same version as this ensures that they all use the same version of barretenberg.

TomAFrench commented 4 days ago

If you update the contents of your package.json to 0.30.0 then I would expect this issue to be solved.

hooperben commented 4 days ago

yep confirming this was it, thank you sir