Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add integration test for verifying a recursive proof onchain #3167

Merged
merged 9 commits into from
Nov 30, 2023
23 changes: 13 additions & 10 deletions compiler/integration-tests/circuits/recursion/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use dep::std;

fn main(
verification_key: [Field; 114],
proof: [Field; 94],
public_inputs: [Field; 1],
key_hash: Field,
input_aggregation_object: [Field; 16]
) -> pub [Field; 16] {
let vk : [Field] = verification_key;
let p : [Field] = proof;
let pi : [Field] = public_inputs;
std::verify_proof(vk, p, pi, key_hash, input_aggregation_object)
verification_key : [Field; 114],
proof : [Field; 94],
public_inputs : [Field; 1],
key_hash : Field,
) -> pub [Field;16]{
let input_aggregation_object = [0; 16];
std::verify_proof(
verification_key.as_slice(),
proof.as_slice(),
public_inputs.as_slice(),
key_hash,
input_aggregation_object
)
}
3 changes: 3 additions & 0 deletions compiler/integration-tests/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const config: HardhatUserConfig = {
},
},
},
mocha: {
timeout: 5 * 60 * 1000,
},
};

export default config;
6 changes: 6 additions & 0 deletions compiler/integration-tests/scripts/codegen-verifiers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ nargo --program-dir $mul_dir codegen-verifier
assert_statement_dir=$repo_root/test_programs/execution_success/assert_statement
nargo --program-dir $assert_statement_dir codegen-verifier

# Run codegen-verifier for recursion
recursion_dir=$repo_root/compiler/integration-tests/circuits/recursion
nargo --program-dir $recursion_dir codegen-verifier

# Copy compiled contracts from the root of compiler/integration-tests
contracts_dir=$self_path/../contracts
rm -rf $contracts_dir
mkdir $contracts_dir

cp $mul_dir/contract/1_mul/plonk_vk.sol $contracts_dir/1_mul.sol
cp $assert_statement_dir/contract/assert_statement/plonk_vk.sol $contracts_dir/assert_statement.sol
cp $recursion_dir/contract/recursion/plonk_vk.sol $contracts_dir/recursion.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { expect } from 'chai';
import { ethers } from 'hardhat';

import { readFileSync } from 'node:fs';
import { resolve } from 'path';
import toml from 'toml';

import { compile, CompiledProgram, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm';
import { Noir } from '@noir-lang/noir_js';
import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg';
import { Field, InputMap } from '@noir-lang/noirc_abi';

compilerLogLevel('INFO');

it(`smart contract can verify a recursive proof`, async () => {
const inner_source_path = resolve(`../../test_programs/execution_success/assert_statement/src/main.nr`);
const inner_program = (compile(inner_source_path) as { program: CompiledProgram }).program;

const recursion_source_path = resolve(`./circuits/recursion/src/main.nr`);
const recursion_program = (compile(recursion_source_path) as { program: CompiledProgram }).program;

// Intermediate proof

const inner_backend = new BarretenbergBackend(inner_program);
const inner = new Noir(inner_program);

const inner_prover_toml = readFileSync(
resolve(`../../test_programs/execution_success/assert_statement/Prover.toml`),
).toString();
const inner_inputs = toml.parse(inner_prover_toml);

const { witness: main_witness } = await inner.execute(inner_inputs);
const intermediate_proof = await inner_backend.generateIntermediateProof(main_witness);

expect(await inner_backend.verifyIntermediateProof(intermediate_proof)).to.be.true;

const { proofAsFields, vkAsFields, vkHash } = await inner_backend.generateIntermediateProofArtifacts(
intermediate_proof,
1, // 1 public input
);

// Final proof

const recursion_backend = new BarretenbergBackend(recursion_program);
const recursion = new Noir(recursion_program, recursion_backend);

const recursion_inputs: InputMap = {
verification_key: vkAsFields,
proof: proofAsFields,
public_inputs: [inner_inputs.y as Field],
key_hash: vkHash,
};

const recursion_proof = await recursion.generateFinalProof(recursion_inputs);
expect(await recursion.verifyFinalProof(recursion_proof)).to.be.true;

// Smart contract verification

const contract = await ethers.deployContract('contracts/recursion.sol:UltraVerifier', []);

const result = await contract.verify.staticCall(
recursion_proof.proof,
flattenPublicInputs(recursion_proof.publicInputs),
);

expect(result).to.be.true;
});
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ test_cases.forEach((testInfo) => {

// Smart contract verification

const contract = await ethers.deployContract(testInfo.compiled, [], {});
const contract = await ethers.deployContract(testInfo.compiled, []);

const result = await contract.verify(proofData.proof, flattenPublicInputs(proofData.publicInputs));

Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"nixpkgs",
"noirc",
"noirup",
"nomicfoundation",
"pedersen",
"peekable",
"plonkc",
Expand Down
Loading