diff --git a/compiler/integration-tests/circuits/recursion/src/main.nr b/compiler/integration-tests/circuits/recursion/src/main.nr index 7cf956d1950..e60e4e0b61a 100644 --- a/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/compiler/integration-tests/circuits/recursion/src/main.nr @@ -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 + ) } diff --git a/compiler/integration-tests/hardhat.config.ts b/compiler/integration-tests/hardhat.config.ts index 2c68b3fae0f..af4728c68ec 100644 --- a/compiler/integration-tests/hardhat.config.ts +++ b/compiler/integration-tests/hardhat.config.ts @@ -12,6 +12,9 @@ const config: HardhatUserConfig = { }, }, }, + mocha: { + timeout: 5 * 60 * 1000, + }, }; export default config; diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh index 13667038728..b3a52217271 100644 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -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 diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts new file mode 100644 index 00000000000..353678b470b --- /dev/null +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -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; +}); diff --git a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index 57199fc8667..7dafada0ffb 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -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)); diff --git a/cspell.json b/cspell.json index 90d3963566d..fc8d8d7e82c 100644 --- a/cspell.json +++ b/cspell.json @@ -82,6 +82,7 @@ "nixpkgs", "noirc", "noirup", + "nomicfoundation", "pedersen", "peekable", "plonkc", diff --git a/release-please-config.json b/release-please-config.json index 5f91fbae643..7995ea37381 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -79,37 +79,37 @@ }, { "type": "toml", - "path": "../Cargo.toml", + "path": "acir/Cargo.toml", "jsonpath": "$.workspace.dependencies.acir.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "acir_field/Cargo.toml", "jsonpath": "$.workspace.dependencies.acir_field.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "stdlib/Cargo.toml", "jsonpath": "$.workspace.dependencies.stdlib.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "brillig/Cargo.toml", "jsonpath": "$.workspace.dependencies.brillig.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "brillig_vm/Cargo.toml", "jsonpath": "$.workspace.dependencies.brillig_vm.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "blackbox_solver/Cargo.toml", "jsonpath": "$.workspace.dependencies.acvm_blackbox_solver.version" }, { "type": "toml", - "path": "../Cargo.toml", + "path": "barretenberg_blackbox_solver/Cargo.toml", "jsonpath": "$.workspace.dependencies.barretenberg_blackbox_solver.version" }, {