Skip to content

Commit

Permalink
chore: add integration test for verifying a recursive proof onchain (#…
Browse files Browse the repository at this point in the history
…3167)

# Description

<!-- Thanks for taking the time to improve Noir! -->
<!-- Please fill out all fields marked with an asterisk (*). -->

## Problem\*

<!-- Describe the problem this Pull Request (PR) resolves / link to the
GitHub Issue that describes the problem. -->

Resolves <!-- Link to GitHub Issue -->

## Summary\*

<!-- Describe the changes in this PR. -->
<!-- Supplement code examples and highlight breaking changes, if
applicable. -->

## Documentation

- [ ] This PR requires documentation updates when merged.

  <!-- If checked, check one of the following: -->

  - [ ] I will submit a noir-lang/docs PR.

  <!-- Submit a PR on https://github.com/noir-lang/docs. Thank you! -->

- [ ] I will request for and support Dev Rel's help in documenting this
PR.

  <!-- List / highlight what should be documented. -->
<!-- Dev Rel will reach out for clarifications when needed. Thank you!
-->

## Additional Context

<!-- Supplement further information if applicable. -->

# PR Checklist\*

- [ ] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
TomAFrench authored Nov 30, 2023
1 parent beaf402 commit 08bef9e
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 11 deletions.
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

0 comments on commit 08bef9e

Please sign in to comment.