diff --git a/barretenberg/cpp/src/barretenberg/bb/api.hpp b/barretenberg/cpp/src/barretenberg/bb/api.hpp index f33568f1869..ab1a3628a4f 100644 --- a/barretenberg/cpp/src/barretenberg/bb/api.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/api.hpp @@ -8,6 +8,7 @@ class API { struct Flags { std::optional output_type; // bytes, fields, bytes_and_fields, fields_msgpack std::optional input_type; // compiletime_stack, runtime_stack + bool no_auto_verify; // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove }; virtual void prove(const Flags& flags, diff --git a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp index 37b251bd8cf..8576f918d40 100644 --- a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp @@ -141,8 +141,7 @@ class ClientIVCAPI : public API { ClientIVC ivc{ { E2E_FULL_TEST_STRUCTURE }, /*auto_verify_mode=*/true }; // Accumulate the entire program stack into the IVC - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel once - // databus has been integrated into noir kernel programs + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel bool is_kernel = false; for (Program& program : folding_stack) { // Construct a bberg circuit from the acir representation then accumulate it into the IVC @@ -163,6 +162,47 @@ class ClientIVCAPI : public API { return ivc; }; + static ClientIVC _accumulate_without_auto_verify(std::vector& folding_stack) + { + using Builder = MegaCircuitBuilder; + using Program = acir_format::AcirProgram; + + using namespace acir_format; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1163) set these dynamically + init_bn254_crs(1 << 20); + init_grumpkin_crs(1 << 15); + + // TODO(#7371) dedupe this with the rest of the similar code + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode + ClientIVC ivc{ { E2E_FULL_TEST_STRUCTURE }, /*auto_verify_mode=*/false }; + + // Accumulate the entire program stack into the IVC + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel once + // databus has been integrated into noir kernel programs + bool is_kernel = false; + for (Program& program : folding_stack) { + + Builder circuit; + + is_kernel = !program.constraints.ivc_recursion_constraints.empty(); + if (is_kernel) { + vinfo("Accumulating KERNEL."); + circuit = create_kernel_circuit(program.constraints, ivc, program.witness); + } else { + vinfo("Accumulating APP."); + circuit = create_circuit( + program.constraints, /*recursive=*/false, 0, program.witness, false, ivc.goblin.op_queue); + } + + // Do one step of ivc accumulator or, if there is only one circuit in the stack, prove that circuit. In this + // case, no work is added to the Goblin opqueue, but VM proofs for trivial inputs are produced. + ivc.accumulate(circuit, /*one_circuit=*/folding_stack.size() == 1); + } + + return ivc; + }; + public: void prove(const API::Flags& flags, const std::filesystem::path& bytecode_path, @@ -179,7 +219,19 @@ class ClientIVCAPI : public API { std::vector folding_stack = _build_folding_stack(*flags.input_type, bytecode_path, witness_path); - ClientIVC ivc = _accumulate(folding_stack); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1163) set these dynamically + init_bn254_crs(1 << 20); + init_grumpkin_crs(1 << 15); + + ClientIVC ivc; + if (flags.no_auto_verify) { + vinfo("performing accumulation WITHOUT auto-verify"); + ivc = _accumulate_without_auto_verify(folding_stack); + } else { + vinfo("performing accumulation with auto-verify"); + ivc = _accumulate(folding_stack); + } ClientIVC::Proof proof = ivc.prove(); // Write the proof and verification keys into the working directory in 'binary' format (in practice it seems diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 00b0b8a68e0..5b8bc5041fd 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -9,6 +9,7 @@ #include "barretenberg/constants.hpp" #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" +#include "barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp" #include "barretenberg/dsl/acir_format/proof_surgeon.hpp" #include "barretenberg/dsl/acir_proofs/acir_composer.hpp" #include "barretenberg/dsl/acir_proofs/honk_contract.hpp" @@ -833,6 +834,62 @@ void write_vk_honk(const std::string& bytecodePath, const std::string& outputPat } } +/** + * @brief Compute and write to file a MegaHonk VK for a circuit to be accumulated in the IVC + * @note This method differes from write_vk_honk in that it handles kernel circuits which require special + * treatment (i.e. construction of mock IVC state to correctly complete the kernel logic). + * + * @param bytecodePath + * @param witnessPath + */ +void write_vk_for_ivc(const std::string& bytecodePath, const std::string& outputPath) +{ + using Builder = ClientIVC::ClientCircuit; + using Prover = ClientIVC::MegaProver; + using DeciderProvingKey = ClientIVC::DeciderProvingKey; + using VerificationKey = ClientIVC::MegaVerificationKey; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1163) set these dynamically + init_bn254_crs(1 << 20); + init_grumpkin_crs(1 << 15); + + auto constraints = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + acir_format::WitnessVector witness = {}; + + TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; + + // The presence of ivc recursion constraints determines whether or not the program is a kernel + bool is_kernel = !constraints.ivc_recursion_constraints.empty(); + + Builder builder; + if (is_kernel) { + // Create a mock IVC instance based on the IVC recursion constraints in the kernel program + ClientIVC mock_ivc = create_mock_ivc_from_constraints(constraints.ivc_recursion_constraints, trace_settings); + builder = acir_format::create_kernel_circuit(constraints, mock_ivc, witness); + } else { + builder = acir_format::create_circuit( + constraints, /*recursive=*/false, 0, witness, /*honk_recursion=*/false); + } + // Add public inputs corresponding to pairing point accumulator + builder.add_pairing_point_accumulator(stdlib::recursion::init_default_agg_obj_indices(builder)); + + // Construct the verification key via the prover-constructed proving key with the proper trace settings + auto proving_key = std::make_shared(builder, trace_settings); + Prover prover{ proving_key }; + init_bn254_crs(prover.proving_key->proving_key.circuit_size); + VerificationKey vk(prover.proving_key->proving_key); + + // Write the VK to file as a buffer + auto serialized_vk = to_buffer(vk); + if (outputPath == "-") { + writeRawBytesToStdout(serialized_vk); + vinfo("vk written to stdout"); + } else { + write_file(outputPath, serialized_vk); + vinfo("vk written to: ", outputPath); + } +} + /** * @brief Write a toml file containing recursive verifier inputs for a given program + witness * @@ -1073,7 +1130,8 @@ int main(int argc, char* argv[]) const API::Flags flags = [&args]() { return API::Flags{ .output_type = get_option(args, "--output_type", "fields_msgpack"), - .input_type = get_option(args, "--input_type", "compiletime_stack") }; + .input_type = get_option(args, "--input_type", "compiletime_stack"), + .no_auto_verify = flag_present(args, "--no_auto_verify") }; }(); const std::string command = args[0]; @@ -1227,6 +1285,9 @@ int main(int argc, char* argv[]) } else if (command == "write_vk_mega_honk") { std::string output_path = get_option(args, "-o", "./target/vk"); write_vk_honk(bytecode_path, output_path, recursive); + } else if (command == "write_vk_for_ivc") { + std::string output_path = get_option(args, "-o", "./target/vk"); + write_vk_for_ivc(bytecode_path, output_path); } else if (command == "proof_as_fields_honk") { std::string output_path = get_option(args, "-o", proof_path + "_fields.json"); proof_as_fields_honk(proof_path, output_path); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index a0d24e70e0b..cae59733e3b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -656,6 +656,11 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, af.honk_recursion_constraints.push_back(c); af.original_opcode_indices.honk_recursion_constraints.push_back(opcode_index); break; + case OINK: + case PG: + af.ivc_recursion_constraints.push_back(c); + af.original_opcode_indices.ivc_recursion_constraints.push_back(opcode_index); + break; case AVM: af.avm_recursion_constraints.push_back(c); af.original_opcode_indices.avm_recursion_constraints.push_back(opcode_index); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp index 0549a1bbeed..d6bf0d93323 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp @@ -86,6 +86,8 @@ void create_block_constraints(MegaCircuitBuilder& builder, process_call_data_operations(builder, constraint, has_valid_witness_assignments, init); // The presence of calldata is used to indicate that the present circuit is a kernel. This is needed in the // databus consistency checks to indicate that the corresponding return data belongs to a kernel (else an app). + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1165): is_kernel must be known prior to this stage + // since we must determine whether to use create_circuit or create_kernel_circuit. Resolve. builder.databus_propagation_data.is_kernel = true; } break; case BlockType::ReturnData: { diff --git a/noir-projects/Earthfile b/noir-projects/Earthfile index 4627c747703..0a876ac39f7 100644 --- a/noir-projects/Earthfile +++ b/noir-projects/Earthfile @@ -20,6 +20,7 @@ source: RUN yarn COPY mega_honk_circuits.json . + COPY ivc_integration_circuits.json . COPY --dir aztec-nr noir-contracts noir-protocol-circuits mock-protocol-circuits scripts . build-contracts: diff --git a/noir-projects/ivc_integration_circuits.json b/noir-projects/ivc_integration_circuits.json new file mode 100644 index 00000000000..01971872d1f --- /dev/null +++ b/noir-projects/ivc_integration_circuits.json @@ -0,0 +1,8 @@ +[ + "mock_private_kernel_init", + "mock_private_kernel_inner", + "mock_private_kernel_reset.*", + "mock_private_kernel_tail.*", + "app_creator", + "app_reader" +] \ No newline at end of file diff --git a/noir-projects/mega_honk_circuits.json b/noir-projects/mega_honk_circuits.json index 37b25115596..1db696b11e6 100644 --- a/noir-projects/mega_honk_circuits.json +++ b/noir-projects/mega_honk_circuits.json @@ -1,6 +1,6 @@ [ - "private_kernel_init", - "private_kernel_inner", - "private_kernel_reset.*", - "private_kernel_tail.*" + "^private_kernel_init", + "^private_kernel_inner", + "^private_kernel_reset.*", + "^private_kernel_tail.*" ] \ No newline at end of file diff --git a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-init/src/main.nr b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-init/src/main.nr index 9a7b6ca0d63..f3ce82e3a98 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-init/src/main.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-init/src/main.nr @@ -1,11 +1,15 @@ use dep::mock_types::{ - AppPublicInputs, PrivateKernelPublicInputs, PrivateKernelPublicInputsBuilder, TxRequest, + AppPublicInputs, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, PrivateKernelPublicInputs, + PrivateKernelPublicInputsBuilder, PROOF_TYPE_OINK, TxRequest, }; fn main( tx: TxRequest, app_inputs: call_data(1) AppPublicInputs, + app_vk: [Field; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS], ) -> return_data PrivateKernelPublicInputs { + std::verify_proof_with_type(app_vk, [], [], 0, PROOF_TYPE_OINK); + let mut private_kernel_inputs = PrivateKernelPublicInputsBuilder::from_tx(tx); private_kernel_inputs.ingest_app_inputs(app_inputs); private_kernel_inputs.finish() diff --git a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-inner/src/main.nr b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-inner/src/main.nr index 4dee3d46e75..707dab8d84f 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-inner/src/main.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-inner/src/main.nr @@ -1,9 +1,17 @@ -use dep::mock_types::{AppPublicInputs, PrivateKernelPublicInputs, PrivateKernelPublicInputsBuilder}; +use dep::mock_types::{ + AppPublicInputs, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, PrivateKernelPublicInputs, + PrivateKernelPublicInputsBuilder, PROOF_TYPE_PG, +}; fn main( prev_kernel_public_inputs: call_data(0) PrivateKernelPublicInputs, + kernel_vk: [Field; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS], app_inputs: call_data(1) AppPublicInputs, + app_vk: [Field; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS], ) -> return_data PrivateKernelPublicInputs { + std::verify_proof_with_type(kernel_vk, [], [], 0, PROOF_TYPE_PG); + std::verify_proof_with_type(app_vk, [], [], 0, PROOF_TYPE_PG); + let mut private_kernel_inputs = PrivateKernelPublicInputsBuilder::from_previous_kernel(prev_kernel_public_inputs); private_kernel_inputs.ingest_app_inputs(app_inputs); diff --git a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-reset/src/main.nr b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-reset/src/main.nr index 6c27e065204..1444732a0e6 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-reset/src/main.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-reset/src/main.nr @@ -1,13 +1,17 @@ use dep::mock_types::{ - MAX_COMMITMENT_READ_REQUESTS_PER_TX, MAX_COMMITMENTS_PER_TX, PrivateKernelPublicInputs, + CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, MAX_COMMITMENT_READ_REQUESTS_PER_TX, + MAX_COMMITMENTS_PER_TX, PrivateKernelPublicInputs, PROOF_TYPE_PG, }; // Mock reset kernel that reset read requests. // It needs hints to locate the commitment that matches the read requests. fn main( mut prev_kernel_public_inputs: call_data(0) PrivateKernelPublicInputs, + kernel_vk: [Field; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS], commitment_read_hints: [u32; MAX_COMMITMENT_READ_REQUESTS_PER_TX], ) -> return_data PrivateKernelPublicInputs { + std::verify_proof_with_type(kernel_vk, [], [], 0, PROOF_TYPE_PG); + for i in 0..MAX_COMMITMENT_READ_REQUESTS_PER_TX { if commitment_read_hints[i] != MAX_COMMITMENTS_PER_TX { assert_eq( diff --git a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-tail/src/main.nr b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-tail/src/main.nr index acac4a95543..082dd428a22 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-tail/src/main.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-private-kernel-tail/src/main.nr @@ -1,11 +1,15 @@ use dep::mock_types::{ - KernelPublicInputs, MAX_COMMITMENT_READ_REQUESTS_PER_TX, PrivateKernelPublicInputs, + CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, KernelPublicInputs, + MAX_COMMITMENT_READ_REQUESTS_PER_TX, PrivateKernelPublicInputs, PROOF_TYPE_PG, }; // The tail kernel finishes the client IVC chain exposing the final public inputs with no remaining calls or unfulfilled read requests. fn main( prev_kernel_public_inputs: call_data(0) PrivateKernelPublicInputs, + kernel_vk: [Field; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS], ) -> pub KernelPublicInputs { + std::verify_proof_with_type(kernel_vk, [], [], 0, PROOF_TYPE_PG); + assert_eq(prev_kernel_public_inputs.remaining_calls, 0); for i in 0..MAX_COMMITMENT_READ_REQUESTS_PER_TX { assert_eq(prev_kernel_public_inputs.read_requests[i], 0); diff --git a/noir-projects/mock-protocol-circuits/crates/mock-types/Nargo.toml b/noir-projects/mock-protocol-circuits/crates/mock-types/Nargo.toml index d5f57873b0c..e9b0542224a 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-types/Nargo.toml +++ b/noir-projects/mock-protocol-circuits/crates/mock-types/Nargo.toml @@ -4,4 +4,5 @@ type = "lib" authors = [""] compiler_version = ">=0.32.0" -[dependencies] \ No newline at end of file +[dependencies] +protocol_types = { path = "../../../noir-protocol-circuits/crates/types" } diff --git a/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr b/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr index 933e812174a..c5f69e887a0 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr @@ -3,6 +3,10 @@ global MAX_COMMITMENTS_PER_TX: u32 = 4; global MAX_COMMITMENT_READ_REQUESTS_PER_CALL: u32 = 2; global MAX_COMMITMENT_READ_REQUESTS_PER_TX: u32 = 4; +pub use protocol_types::constants::{ + CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, PROOF_TYPE_OINK, PROOF_TYPE_PG, +}; + struct TxRequest { number_of_calls: u32, } diff --git a/noir-projects/scripts/generate_vk_json.js b/noir-projects/scripts/generate_vk_json.js index c891d1f7ca4..a2942e69cde 100644 --- a/noir-projects/scripts/generate_vk_json.js +++ b/noir-projects/scripts/generate_vk_json.js @@ -4,6 +4,7 @@ const child_process = require("child_process"); const crypto = require("crypto"); const megaHonkPatterns = require("../mega_honk_circuits.json"); +const ivcIntegrationPatterns = require("../ivc_integration_circuits.json"); const { readVKFromS3, writeVKToS3, @@ -32,13 +33,19 @@ async function getBytecodeHash(artifactPath) { return crypto.createHash("md5").update(bytecode).digest("hex"); } -async function getArtifactHash(artifactPath, isMegaHonk, isRecursive) { +async function getArtifactHash( + artifactPath, + isMegaHonk, + isIvcIntegration, + isRecursive +) { const bytecodeHash = await getBytecodeHash(artifactPath); const barretenbergHash = await getBarretenbergHash(); return generateArtifactHash( barretenbergHash, bytecodeHash, isMegaHonk, + isIvcIntegration, isRecursive ); } @@ -66,14 +73,21 @@ function isMegaHonkCircuit(artifactName) { artifactName.match(new RegExp(pattern)) ); } +function isIvcIntegrationCircuit(artifactName) { + return ivcIntegrationPatterns.some((pattern) => + artifactName.match(new RegExp(pattern)) + ); +} async function processArtifact(artifactPath, artifactName, outputFolder) { const isMegaHonk = isMegaHonkCircuit(artifactName); + const isIvcIntegration = isIvcIntegrationCircuit(artifactName); const isRecursive = true; const artifactHash = await getArtifactHash( artifactPath, isMegaHonk, + isIvcIntegration, isRecursive ); @@ -93,6 +107,7 @@ async function processArtifact(artifactPath, artifactName, outputFolder) { artifactPath, artifactHash, isMegaHonk, + isIvcIntegration, isRecursive ); await writeVKToS3(artifactName, artifactHash, JSON.stringify(vkData)); @@ -109,10 +124,13 @@ async function generateVKData( artifactPath, artifactHash, isMegaHonk, + isIvcIntegration, isRecursive ) { if (isMegaHonk) { console.log("Generating new mega honk vk for", artifactName); + } else if (isIvcIntegration) { + console.log("Generating new IVC vk for", artifactName); } else { console.log("Generating new vk for", artifactName); } @@ -123,16 +141,22 @@ async function generateVKData( ); const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - const writeVkCommand = `${BB_BIN_PATH} ${ - isMegaHonk ? "write_vk_mega_honk" : "write_vk_ultra_honk" - } -h -b "${artifactPath}" -o "${binaryVkPath}" ${ + function getVkCommand() { + if (isMegaHonk) return "write_vk_mega_honk"; + if (isIvcIntegration) return "write_vk_for_ivc"; + return "write_vk_ultra_honk"; + } + + const writeVkCommand = `${BB_BIN_PATH} ${getVkCommand()} -h -b "${artifactPath}" -o "${binaryVkPath}" ${ isRecursive ? "--recursive" : "" }`; console.log("WRITE VK CMD: ", writeVkCommand); const vkAsFieldsCommand = `${BB_BIN_PATH} ${ - isMegaHonk ? "vk_as_fields_mega_honk" : "vk_as_fields_ultra_honk" + isMegaHonk || isIvcIntegration + ? "vk_as_fields_mega_honk" + : "vk_as_fields_ultra_honk" } -k "${binaryVkPath}" -o "${jsonVkPath}"`; await new Promise((resolve, reject) => { diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index a14598863a9..1450fe215ac 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -202,6 +202,7 @@ export async function executeBbClientIvcProof( bytecodeStackPath: string, witnessStackPath: string, log: LogFn, + noAutoVerify = false, ): Promise { // Check that the working directory exists try { @@ -238,6 +239,9 @@ export async function executeBbClientIvcProof( '--input_type', 'runtime_stack', ]; + if (noAutoVerify) { + args.push('--no_auto_verify'); + } const timer = new Timer(); const logFunction = (message: string) => { log(`bb - ${message}`); diff --git a/yarn-project/ivc-integration/src/index.ts b/yarn-project/ivc-integration/src/index.ts index 93234564864..dab8804a187 100644 --- a/yarn-project/ivc-integration/src/index.ts +++ b/yarn-project/ivc-integration/src/index.ts @@ -1,3 +1,5 @@ +import { type CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS } from '@aztec/circuits.js'; + import { type ForeignCallOutput, Noir } from '@noir-lang/noir_js'; import createDebug from 'debug'; import { ungzip } from 'pako'; @@ -5,6 +7,12 @@ import { type Page } from 'playwright'; import MockAppCreatorCircuit from '../artifacts/app_creator.json' assert { type: 'json' }; import MockAppReaderCircuit from '../artifacts/app_reader.json' assert { type: 'json' }; +import MockAppCreatorVk from '../artifacts/keys/app_creator.vk.data.json' assert { type: 'json' }; +import MockAppReaderVk from '../artifacts/keys/app_reader.vk.data.json' assert { type: 'json' }; +import MockPrivateKernelInitVk from '../artifacts/keys/mock_private_kernel_init.vk.data.json' assert { type: 'json' }; +import MockPrivateKernelInnerVk from '../artifacts/keys/mock_private_kernel_inner.vk.data.json' assert { type: 'json' }; +import MockPrivateKernelResetVk from '../artifacts/keys/mock_private_kernel_reset.vk.data.json' assert { type: 'json' }; +import MockPrivateKernelTailVk from '../artifacts/keys/mock_private_kernel_tail.vk.data.json' assert { type: 'json' }; import MockPrivateKernelInitCircuit from '../artifacts/mock_private_kernel_init.json' assert { type: 'json' }; import MockPrivateKernelInnerCircuit from '../artifacts/mock_private_kernel_inner.json' assert { type: 'json' }; import MockPrivateKernelResetCircuit from '../artifacts/mock_private_kernel_reset.json' assert { type: 'json' }; @@ -14,6 +22,7 @@ import type { AppCreatorInputType, AppPublicInputs, AppReaderInputType, + FixedLengthArray, KernelPublicInputs, MockPrivateKernelInitInputType, MockPrivateKernelInnerInputType, @@ -33,6 +42,12 @@ export { MockPrivateKernelResetCircuit, MockPrivateKernelTailCircuit, MockPublicBaseCircuit, + MockAppCreatorVk, + MockAppReaderVk, + MockPrivateKernelInitVk, + MockPrivateKernelInnerVk, + MockPrivateKernelResetVk, + MockPrivateKernelTailVk, }; createDebug.enable('*'); @@ -126,6 +141,13 @@ export async function witnessGenMockPublicBaseCircuit(args: MockPublicBaseInputT }; } +export function getVkAsFields(vk: { + keyAsBytes: string; + keyAsFields: string[]; +}): FixedLengthArray { + return vk.keyAsFields as FixedLengthArray; +} + export async function generate3FunctionTestingIVCStack(): Promise<[string[], Uint8Array[]]> { const tx = { number_of_calls: '0x1', @@ -138,11 +160,13 @@ export async function generate3FunctionTestingIVCStack(): Promise<[string[], Uin const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({ app_inputs: appWitnessGenResult.publicInputs, tx, + app_vk: getVkAsFields(MockAppCreatorVk), }); logger('generated mock private kernel init witness'); const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({ prev_kernel_public_inputs: initWitnessGenResult.publicInputs, + kernel_vk: getVkAsFields(MockPrivateKernelResetVk), }); logger('generated mock private kernel tail witness'); @@ -168,10 +192,13 @@ export async function generate6FunctionTestingIVCStack(): Promise<[string[], Uin const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({ app_inputs: creatorAppWitnessGenResult.publicInputs, tx, + app_vk: getVkAsFields(MockAppCreatorVk), }); const innerWitnessGenResult = await witnessGenMockPrivateKernelInnerCircuit({ prev_kernel_public_inputs: initWitnessGenResult.publicInputs, app_inputs: readerAppWitnessGenResult.publicInputs, + app_vk: getVkAsFields(MockAppReaderVk), + kernel_vk: getVkAsFields(MockPrivateKernelInitVk), }); const resetWitnessGenResult = await witnessGenMockPrivateKernelResetCircuit({ @@ -182,10 +209,12 @@ export async function generate6FunctionTestingIVCStack(): Promise<[string[], Uin MOCK_MAX_COMMITMENTS_PER_TX.toString(), MOCK_MAX_COMMITMENTS_PER_TX.toString(), ], + kernel_vk: getVkAsFields(MockPrivateKernelInnerVk), }); const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({ prev_kernel_public_inputs: resetWitnessGenResult.publicInputs, + kernel_vk: getVkAsFields(MockPrivateKernelResetVk), }); // Create client IVC proof diff --git a/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts b/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts index 6f413b19a94..2b891891043 100644 --- a/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts +++ b/yarn-project/ivc-integration/src/native_client_ivc_integration.test.ts @@ -40,6 +40,7 @@ describe('Client IVC Integration', () => { path.join(bbWorkingDirectory, 'acir.msgpack'), path.join(bbWorkingDirectory, 'witnesses.msgpack'), logger.info, + true, ); if (provingResult.status === BB_RESULT.FAILURE) { diff --git a/yarn-project/ivc-integration/src/wasm_client_ivc_integration.test.ts b/yarn-project/ivc-integration/src/wasm_client_ivc_integration.test.ts index 44c3b7ba234..5f105b7f71e 100644 --- a/yarn-project/ivc-integration/src/wasm_client_ivc_integration.test.ts +++ b/yarn-project/ivc-integration/src/wasm_client_ivc_integration.test.ts @@ -6,11 +6,17 @@ import { ungzip } from 'pako'; import { MOCK_MAX_COMMITMENTS_PER_TX, MockAppCreatorCircuit, + MockAppCreatorVk, MockAppReaderCircuit, + MockAppReaderVk, MockPrivateKernelInitCircuit, + MockPrivateKernelInitVk, MockPrivateKernelInnerCircuit, + MockPrivateKernelInnerVk, MockPrivateKernelResetCircuit, + MockPrivateKernelResetVk, MockPrivateKernelTailCircuit, + getVkAsFields, witnessGenCreatorAppMockCircuit, witnessGenMockPrivateKernelInitCircuit, witnessGenMockPrivateKernelInnerCircuit, @@ -70,11 +76,13 @@ describe('Client IVC Integration', () => { const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({ app_inputs: appWitnessGenResult.publicInputs, tx, + app_vk: getVkAsFields(MockAppCreatorVk), }); logger.debug('generated mock private kernel init witness'); const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({ prev_kernel_public_inputs: initWitnessGenResult.publicInputs, + kernel_vk: getVkAsFields(MockPrivateKernelInitVk), }); logger.debug('generated mock private kernel tail witness'); @@ -112,10 +120,13 @@ describe('Client IVC Integration', () => { const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({ app_inputs: creatorAppWitnessGenResult.publicInputs, tx, + app_vk: getVkAsFields(MockAppCreatorVk), }); const innerWitnessGenResult = await witnessGenMockPrivateKernelInnerCircuit({ prev_kernel_public_inputs: initWitnessGenResult.publicInputs, app_inputs: readerAppWitnessGenResult.publicInputs, + app_vk: getVkAsFields(MockAppReaderVk), + kernel_vk: getVkAsFields(MockPrivateKernelInitVk), }); const resetWitnessGenResult = await witnessGenMockPrivateKernelResetCircuit({ @@ -126,10 +137,12 @@ describe('Client IVC Integration', () => { MOCK_MAX_COMMITMENTS_PER_TX.toString(), MOCK_MAX_COMMITMENTS_PER_TX.toString(), ], + kernel_vk: getVkAsFields(MockPrivateKernelInnerVk), }); const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({ prev_kernel_public_inputs: resetWitnessGenResult.publicInputs, + kernel_vk: getVkAsFields(MockPrivateKernelResetVk), }); // Create client IVC proof