diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2692fde7e2e..fb797f3c050 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,7 +157,7 @@ jobs: - uses: ./.github/ci-setup-action - name: Setup and Test uses: ./.github/ensure-tester-with-images - timeout-minutes: 40 + timeout-minutes: 45 with: runner_type: ${{ contains(matrix.test, 'prover') && '64core-tester-x86' || '16core-tester-x86' }} builder_type: builder-x86 @@ -166,6 +166,7 @@ jobs: builder_images_to_copy: aztecprotocol/aztec:${{ env.GIT_COMMIT }} aztecprotocol/end-to-end:${{ env.GIT_COMMIT }} # command to produce the images in case they don't exist builder_command: cd yarn-project/end-to-end/ && ../../scripts/earthly-ci +${{ matrix.test }} + tester_ttl: 40 run: | set -eux cd ./yarn-project/end-to-end/ @@ -381,7 +382,7 @@ jobs: - name: "Format noir-projects" working-directory: ./noir-projects/ timeout-minutes: 40 - run: | + run: | earthly-ci --no-output \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ @@ -465,7 +466,6 @@ jobs: steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - # Only allow one memory-hunger prover test to use this runner - uses: ./.github/ci-setup-action with: concurrency_key: yarn-project-formatting-x86 @@ -474,13 +474,11 @@ jobs: run: earthly-ci --no-output ./yarn-project/+format-check yarn-project-test: - # quiet machine needs: build runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - # Only allow one memory-hunger prover test to use this runner - uses: ./.github/ci-setup-action with: concurrency_key: yarn-project-test-x86 @@ -527,7 +525,7 @@ jobs: - name: "Docs Preview" if: github.event.number timeout-minutes: 40 - run: | + run: | earthly-ci --no-output \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ @@ -639,7 +637,7 @@ jobs: earthly-ci \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ - --artifact +gates-report/gates_report.json + --artifact +gates-report/gates_report.json mv gates_report.json ../protocol_circuits_report.json - name: Compare gates reports diff --git a/.vscode/launch.json b/.vscode/launch.json index fa4b77b4ad0..1c9a6801e9c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,7 @@ "version": "0.2.0", "configurations": [ { - "address": "${config:mainframeAddress}", - "port": 9221, + "port": 9229, "type": "node", "request": "attach", "name": "Attach to Remote", @@ -14,5 +13,11 @@ "localRoot": "${workspaceFolder}", "sourceMaps": true }, + { + "type": "node", + "request": "attach", + "name": "Attach", + "port": 9229 + } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 6bde2bae40a..1df0f7fc2e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -120,7 +120,7 @@ "editor.defaultFormatter": "hashicorp.terraform" }, "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.typescript-language-features" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" diff --git a/barretenberg/.vscode/launch.json b/barretenberg/.vscode/launch.json new file mode 100644 index 00000000000..5ea1dbb1227 --- /dev/null +++ b/barretenberg/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "LLDB: Prove Ultra Honk Output All", + "type": "lldb", + "request": "launch", + "program": "/mnt/user-data/adam/aztec-packages/barretenberg/cpp/build-debug/bin/bb", + "args": [ + "prove_ultra_honk_output_all", + "-o", "/tmp/bb-095XQV/tmp-PPXk0y", + "-b", "/tmp/bb-095XQV/tmp-PPXk0y/PrivateKernelInitArtifact-bytecode", + "-w", "/tmp/bb-095XQV/tmp-PPXk0y/witness.gz", + "-v" + ], + "cwd": "${workspaceFolder}", + "stopOnEntry": false + } + ] +} \ No newline at end of file diff --git a/barretenberg/acir_tests/reset_acir_tests.sh b/barretenberg/acir_tests/reset_acir_tests.sh index dffb4d43837..c89731cd79c 100755 --- a/barretenberg/acir_tests/reset_acir_tests.sh +++ b/barretenberg/acir_tests/reset_acir_tests.sh @@ -1,4 +1,4 @@ -# Run from barretenberg/acir_tests +# Run from within barretenberg/acir_tests cd ../../noir/noir-repo cargo clean noirup -p . diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 23c621aa2d8..780eb8ed5e2 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -143,6 +143,16 @@ include(cmake/gtest.cmake) include(cmake/benchmark.cmake) include(cmake/module.cmake) include(cmake/msgpack.cmake) + +# We do not need to bloat barretenberg.wasm with gzip functionality in a browser context as the browser can do this +if (NOT WASM) + include(cmake/libdeflate.cmake) +else() + set(DISABLE_AZTEC_VM ON) +endif() +if(DISABLE_AZTEC_VM) + add_definitions(-DDISABLE_AZTEC_VM=1) +endif() include(cmake/backward-cpp.cmake) if (WASM) diff --git a/barretenberg/cpp/cmake/libdeflate.cmake b/barretenberg/cpp/cmake/libdeflate.cmake new file mode 100644 index 00000000000..fd151996e06 --- /dev/null +++ b/barretenberg/cpp/cmake/libdeflate.cmake @@ -0,0 +1,10 @@ +include(FetchContent) + +FetchContent_Declare( + libdeflate + GIT_REPOSITORY https://github.com/ebiggers/libdeflate.git + GIT_TAG b03254d978d7af21a7512dee8fdc3367bc15c656 +) + +# Download and populate libdeflate +FetchContent_MakeAvailable(libdeflate) \ No newline at end of file diff --git a/barretenberg/cpp/scripts/flamegraph.pl b/barretenberg/cpp/scripts/flamegraph.pl index d2172b61664..b3adc1c3236 100755 --- a/barretenberg/cpp/scripts/flamegraph.pl +++ b/barretenberg/cpp/scripts/flamegraph.pl @@ -410,7 +410,7 @@ sub color { } elsif ($name =~ m:^L?(java|javax|jdk|net|org|com|io|sun)/:) { # Java $type = "green"; } elsif ($name =~ /:::/) { # Java, typical perf-map-agent method separator - $type = "green"; + $type = "green"; } elsif ($name =~ /::/) { # C++ $type = "yellow"; } elsif ($name =~ m:_\[k\]$:) { # kernel annotation @@ -818,7 +818,7 @@ sub flow { // ctrl-F for search // ctrl-I to toggle case-sensitive search window.addEventListener("keydown",function (e) { - if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) { + if (e.keyCode === 103 || (e.ctrlKey && e.keyCode === 70)) { e.preventDefault(); search_prompt(); } diff --git a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt index 031861aa4c2..f0812aea948 100644 --- a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt @@ -1,4 +1,4 @@ -if (NOT(FUZZING)) +if (NOT(FUZZING) AND NOT(WASM)) add_executable( bb main.cpp @@ -11,6 +11,8 @@ if (NOT(FUZZING)) PRIVATE barretenberg env + circuit_checker + libdeflate::libdeflate_static ) if(CHECK_CIRCUIT_STACKTRACES) target_link_libraries( diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index d5cd3e11d82..3c1fa44785a 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -5,7 +5,9 @@ #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" +#include "barretenberg/serialize/cbind.hpp" #include "barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.hpp" +#include #ifndef DISABLE_AZTEC_VM #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_execution.hpp" @@ -15,6 +17,7 @@ #include "get_bn254_crs.hpp" #include "get_bytecode.hpp" #include "get_grumpkin_crs.hpp" +#include "libdeflate.h" #include "log.hpp" #include #include @@ -24,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -241,14 +245,155 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin return true; } -bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) +struct VectorOfAcirAndWitnesses { + std::vector> acirGzippedBincoes; + std::vector> witnessMaps; +}; + +// TODO(#7371): this could probably be more idiomatic +template T unpack_from_file(const std::string& filename) +{ + std::ifstream fin; + fin.open(filename, std::ios::ate | std::ios::binary); + if (!fin.is_open()) { + throw std::invalid_argument("file not found"); + } + if (fin.tellg() == -1) { + throw std::invalid_argument("something went wrong"); + } + + uint64_t fsize = static_cast(fin.tellg()); + fin.seekg(0, std::ios_base::beg); + + T result; + char* encoded_data = new char[fsize]; + fin.read(encoded_data, static_cast(fsize)); + msgpack::unpack(encoded_data, fsize).get().convert(result); + return result; +} + +// TODO(#7371) find a home for this +acir_format::WitnessVector witness_map_to_witness_vector(std::map const& witness_map) +{ + acir_format::WitnessVector wv; + size_t index = 0; + for (auto& e : witness_map) { + uint64_t value = std::stoull(e.first); + // ACIR uses a sparse format for WitnessMap where unused witness indices may be left unassigned. + // To ensure that witnesses sit at the correct indices in the `WitnessVector`, we fill any indices + // which do not exist within the `WitnessMap` with the dummy value of zero. + while (index < value) { + wv.push_back(fr(0)); + index++; + } + wv.push_back(fr(uint256_t(e.second))); + index++; + } + return wv; +} + +std::vector decompressedBuffer(uint8_t* bytes, size_t size) +{ + std::vector content; + // initial size guess + content.resize(1024ULL * 128ULL); + for (;;) { + auto decompressor = std::unique_ptr{ + libdeflate_alloc_decompressor(), libdeflate_free_decompressor + }; + size_t actual_size = 0; + libdeflate_result decompress_result = libdeflate_gzip_decompress( + decompressor.get(), bytes, size, std::data(content), std::size(content), &actual_size); + if (decompress_result == LIBDEFLATE_INSUFFICIENT_SPACE) { + // need a bigger buffer + content.resize(content.size() * 2); + continue; + } + if (decompress_result == LIBDEFLATE_BAD_DATA) { + throw std::invalid_argument("bad gzip data in bb main"); + } + content.resize(actual_size); + break; + } + return content; +} + +void client_ivc_prove_output_all_msgpack(const std::string& bytecodePath, + const std::string& witnessPath, + const std::string& outputPath) { using Flavor = MegaFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; + using Program = acir_format::AcirProgram; + using ECCVMVK = ECCVMFlavor::VerificationKey; + using TranslatorVK = TranslatorFlavor::VerificationKey; - init_bn254_crs(1 << 18); + init_bn254_crs(1 << 24); init_grumpkin_crs(1 << 14); + auto gzippedBincodes = unpack_from_file>(bytecodePath); + auto witnessMaps = unpack_from_file>(witnessPath); + std::vector folding_stack; + for (size_t i = 0; i < gzippedBincodes.size(); i++) { + // TODO(#7371) there is a lot of copying going on in bincode, we should make sure this writes as a buffer in + // the future + std::vector buffer = + decompressedBuffer(reinterpret_cast(&gzippedBincodes[i][0]), gzippedBincodes[i].size()); // NOLINT + + std::vector constraint_systems = acir_format::program_buf_to_acir_format( + buffer, + false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): + // this assumes that folding is never done with ultrahonk. + std::vector witnessBuffer = + decompressedBuffer(reinterpret_cast(&witnessMaps[i][0]), witnessMaps[i].size()); // NOLINT + acir_format::WitnessVectorStack witness_stack = acir_format::witness_buf_to_witness_stack(witnessBuffer); + acir_format::AcirProgramStack program_stack{ constraint_systems, witness_stack }; + folding_stack.push_back(program_stack.back()); + } + // TODO(#7371) dedupe this with the rest of the similar code + ClientIVC ivc; + ivc.structured_flag = true; + // Accumulate the entire program stack into the IVC + for (Program& program : folding_stack) { + // auto& stack_item = program_stack.witness_stack[i]; + + // Construct a bberg circuit from the acir representation + auto circuit = + acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); + ivc.accumulate(circuit); + } + + // Write the proof and verification keys into the working directory in 'binary' format (in practice it seems this + // directory is passed by bb.js) + std::string vkPath = outputPath + "/inst_vk"; // the vk of the last instance + std::string accPath = outputPath + "/pg_acc"; + std::string proofPath = outputPath + "/client_ivc_proof"; + std::string translatorVkPath = outputPath + "/translator_vk"; + std::string eccVkPath = outputPath + "/ecc_vk"; + + auto proof = ivc.prove(); + auto eccvm_vk = std::make_shared(ivc.goblin.get_eccvm_proving_key()); + auto translator_vk = std::make_shared(ivc.goblin.get_translator_proving_key()); + + auto last_instance = std::make_shared(ivc.instance_vk); + vinfo("ensure valid proof: ", ivc.verify(proof, { ivc.verifier_accumulator, last_instance })); + + vinfo("write proof and vk data to files.."); + write_file(proofPath, to_buffer(proof)); + write_file(vkPath, to_buffer(ivc.instance_vk)); + write_file(accPath, to_buffer(ivc.verifier_accumulator)); + write_file(translatorVkPath, to_buffer(translator_vk)); + write_file(eccVkPath, to_buffer(eccvm_vk)); +} + +bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) +{ + using Flavor = MegaFlavor; // This is the only option + using Builder = Flavor::CircuitBuilder; + + init_bn254_crs(1 << 22); + init_grumpkin_crs(1 << 16); + ClientIVC ivc; ivc.structured_flag = true; @@ -288,8 +433,8 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, using ECCVMVK = ECCVMFlavor::VerificationKey; using TranslatorVK = TranslatorFlavor::VerificationKey; - init_bn254_crs(1 << 18); - init_grumpkin_crs(1 << 14); + init_bn254_crs(1 << 22); + init_grumpkin_crs(1 << 16); ClientIVC ivc; ivc.structured_flag = true; @@ -337,9 +482,10 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, /** * @brief Creates a Honk Proof for the Tube circuit responsible for recursively verifying a ClientIVC proof. * - * @param outputPath the working directory from which the proof and verification data are read + * @param output_path the working directory from which the proof and verification data are read + * @param num_unused_public_inputs */ -void prove_tube(const std::string& outputPath) +void prove_tube(const std::string& output_path) { using ClientIVC = stdlib::recursion::honk::ClientIVCRecursiveVerifier; using NativeInstance = ClientIVC::FoldVerifierInput::Instance; @@ -352,11 +498,11 @@ void prove_tube(const std::string& outputPath) using Builder = UltraCircuitBuilder; using GrumpkinVk = bb::VerifierCommitmentKey; - std::string vkPath = outputPath + "/inst_vk"; // the vk of the last instance - std::string accPath = outputPath + "/pg_acc"; - std::string proofPath = outputPath + "/client_ivc_proof"; - std::string translatorVkPath = outputPath + "/translator_vk"; - std::string eccVkPath = outputPath + "/ecc_vk"; + std::string vkPath = output_path + "/inst_vk"; // the vk of the last instance + std::string accPath = output_path + "/pg_acc"; + std::string proofPath = output_path + "/client_ivc_proof"; + std::string translatorVkPath = output_path + "/translator_vk"; + std::string eccVkPath = output_path + "/ecc_vk"; // Note: this could be decreased once we optimise the size of the ClientIVC recursiveve rifier init_bn254_crs(1 << 25); @@ -380,23 +526,46 @@ void prove_tube(const std::string& outputPath) GoblinVerifierInput goblin_verifier_input{ eccvm_vk, translator_vk }; VerifierInput input{ fold_verifier_input, goblin_verifier_input }; auto builder = std::make_shared(); + // Padding needed for sending the right number of public inputs + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1048): INSECURE - make this tube proof actually use + // these public inputs by turning proof into witnesses and call + // set_public on each witness + auto num_public_inputs = (size_t)proof.folding_proof[1]; + for (size_t i = 0; i < num_public_inputs; i++) { + // We offset 3 + builder->add_public_variable(proof.folding_proof[i + 3]); + } ClientIVC verifier{ builder, input }; verifier.verify(proof); info("num gates: ", builder->get_num_gates()); info("generating proof"); using Prover = UltraProver_; - + using Verifier = UltraVerifier_; Prover tube_prover{ *builder }; auto tube_proof = tube_prover.construct_proof(); - - std::string tubeProofPath = outputPath + "/proof"; + std::string tubeProofPath = output_path + "/proof"; write_file(tubeProofPath, to_buffer(tube_proof)); - std::string tubeVkPath = outputPath + "/vk"; + std::string tubeProofAsFieldsPath = output_path + "/proof_fields.json"; + auto proof_data = to_json(tube_proof); + write_file(tubeProofAsFieldsPath, { proof_data.begin(), proof_data.end() }); + + std::string tubeVkPath = output_path + "/vk"; auto tube_verification_key = std::make_shared(tube_prover.instance->proving_key); write_file(tubeVkPath, to_buffer(tube_verification_key)); + + std::string tubeAsFieldsVkPath = output_path + "/vk_fields.json"; + auto field_els = tube_verification_key->to_field_elements(); + info("verificaton key length in fields:", field_els.size()); + auto data = to_json(field_els); + write_file(tubeAsFieldsVkPath, { data.begin(), data.end() }); + + info("Native verification of the tube_proof"); + Verifier tube_verifier(tube_verification_key); + bool verified = tube_verifier.verify_proof(tube_proof); + info("Tube proof verification: ", verified); } /** @@ -432,10 +601,10 @@ void prove(const std::string& bytecodePath, const std::string& witnessPath, cons } /** - * @brief Computes the number of Barretenberg specific gates needed to create a proof for the specific ACIR circuit + * @brief Computes the number of Barretenberg specific gates needed to create a proof for the specific ACIR circuit. * * Communication: - * - stdout: A JSON string of the number of ACIR opcodes and final backend circuit size + * - stdout: A JSON string of the number of ACIR opcodes and final backend circuit size. * * @param bytecodePath Path to the file containing the serialized circuit */ @@ -522,7 +691,7 @@ bool verify(const std::string& proof_path, const std::string& vk_path) */ void write_vk(const std::string& bytecodePath, const std::string& outputPath) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, false); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; acir_composer.create_circuit(constraint_system); init_bn254_crs(acir_composer.get_dyadic_circuit_size()); @@ -902,7 +1071,7 @@ void proof_as_fields_honk(const std::string& proof_path, const std::string& outp } /** - * @brief Converts a verification key from a byte array into a list of field elements + * @brief Converts a verification key from a byte array into a list of field elements. * * Why is this needed? * This follows the same rationale as `proofAsFields`. @@ -1073,7 +1242,6 @@ int main(int argc, char* argv[]) } std::string command = args[0]; - std::string bytecode_path = get_option(args, "-b", "./target/program.json"); std::string witness_path = get_option(args, "-w", "./target/witness.gz"); std::string proof_path = get_option(args, "-p", "./proofs/proof"); @@ -1102,6 +1270,13 @@ int main(int argc, char* argv[]) if (command == "prove_and_verify_mega_honk_program") { return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a verify_client_ivc bb cli command + // TODO(#7371): remove this + if (command == "client_ivc_prove_output_all_msgpack") { + std::string output_path = get_option(args, "-o", "./proofs/proof"); + client_ivc_prove_output_all_msgpack(bytecode_path, witness_path, output_path); + return 0; + } if (command == "fold_and_verify_program") { return foldAndVerifyProgram(bytecode_path, witness_path) ? 0 : 1; } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index d351ea09b5c..20447026342 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -28,6 +28,9 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, structured_flag); + // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) + max_block_sizes.update(circuit); + // Set the instance verification key from precomputed if available, else compute it if (precomputed_vk) { instance_vk = precomputed_vk; @@ -53,6 +56,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr namespace bb { @@ -46,9 +47,55 @@ class ClientIVC { HonkProof decider_proof; GoblinProof goblin_proof; + size_t size() const { return folding_proof.size() + decider_proof.size() + goblin_proof.size(); } + MSGPACK_FIELDS(folding_proof, decider_proof, goblin_proof); }; + // A debugging utility for tracking the max size of each block over all circuits in the IVC + struct MaxBlockSizes { + size_t ecc_op{ 0 }; + size_t pub_inputs{ 0 }; + size_t arithmetic{ 0 }; + size_t delta_range{ 0 }; + size_t elliptic{ 0 }; + size_t aux{ 0 }; + size_t lookup{ 0 }; + size_t busread{ 0 }; + size_t poseidon_external{ 0 }; + size_t poseidon_internal{ 0 }; + + void update(ClientCircuit& circuit) + { + ecc_op = std::max(circuit.blocks.ecc_op.size(), ecc_op); + pub_inputs = std::max(circuit.public_inputs.size(), pub_inputs); + arithmetic = std::max(circuit.blocks.arithmetic.size(), arithmetic); + delta_range = std::max(circuit.blocks.delta_range.size(), delta_range); + elliptic = std::max(circuit.blocks.elliptic.size(), elliptic); + aux = std::max(circuit.blocks.aux.size(), aux); + lookup = std::max(circuit.blocks.lookup.size(), lookup); + busread = std::max(circuit.blocks.busread.size(), busread); + poseidon_external = std::max(circuit.blocks.poseidon_external.size(), poseidon_external); + poseidon_internal = std::max(circuit.blocks.poseidon_internal.size(), poseidon_internal); + } + + void print() + { + info("Minimum required block sizes for structured trace: "); + info("goblin ecc op :\t", ecc_op); + info("pub inputs :\t", pub_inputs); + info("arithmetic :\t", arithmetic); + info("delta range :\t", delta_range); + info("elliptic :\t", elliptic); + info("auxiliary :\t", aux); + info("lookups :\t", lookup); + info("busread :\t", busread); + info("poseidon ext :\t", poseidon_external); + info("poseidon int :\t", poseidon_internal); + info(""); + } + }; + private: using ProverFoldOutput = FoldingResult; // Note: We need to save the last instance that was folded in order to compute its verification key, this will not @@ -81,5 +128,7 @@ class ClientIVC { HonkProof decider_prove() const; std::vector> precompute_folding_verification_keys(std::vector); + + MaxBlockSizes max_block_sizes; // for tracking minimum block size requirements across an IVC }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 4adf2c4a6b1..72e8f9fcd3e 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -2,6 +2,7 @@ #include namespace bb { -// The log of the max circuit size assumed in order to achieve constant sized proofs +// The log of the max circuit size assumed in order to achieve constant sized Honk proofs +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1046): Remove the need for const sized proofs static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index 0d504b53b65..2bd424e4ecf 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -1,5 +1,7 @@ -barretenberg_module( - dsl + +# We do not need to bloat barretenberg.wasm with gzip functionality in a browser context as the browser can do this + +set(DSL_DEPENDENCIES plonk ultra_honk client_ivc @@ -10,5 +12,13 @@ barretenberg_module( crypto_merkle_tree stdlib_schnorr ultra_honk - stdlib_honk_recursion + stdlib_honk_recursion) + +if (NOT WASM) + list(APPEND DSL_DEPENDENCIES libdeflate::libdeflate_static) +endif() + +barretenberg_module( + dsl + ${DSL_DEPENDENCIES} ) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 528fd947ed3..cef13ea1e7a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -347,19 +347,21 @@ void build_constraints(Builder& builder, // proof aggregation state are a circuit constant. The user tells us they how they want these // constants set by keeping the nested aggregation object attached to the proof as public inputs. std::array nested_aggregation_object = {}; - for (size_t i = 0; i < HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - // Set the nested aggregation object indices to witness indices from the proof - nested_aggregation_object[i] = - static_cast(constraint.proof[HonkRecursionConstraint::inner_public_input_offset + i]); - // Adding the nested aggregation object to the constraint's public inputs - constraint.public_inputs.emplace_back(nested_aggregation_object[i]); - } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // for (size_t i = 0; i < HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // // Set the nested aggregation object indices to witness indices from the proof + // nested_aggregation_object[i] = + // static_cast(constraint.proof[HonkRecursionConstraint::inner_public_input_offset + i]); + // // Adding the nested aggregation object to the constraint's public inputs + // constraint.public_inputs.emplace_back(nested_aggregation_object[i]); + // } // Remove the aggregation object so that they can be handled as normal public inputs // in they way that the recursion constraint expects - constraint.proof.erase(constraint.proof.begin() + HonkRecursionConstraint::inner_public_input_offset, - constraint.proof.begin() + - static_cast(HonkRecursionConstraint::inner_public_input_offset + - HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE)); + // constraint.proof.erase(constraint.proof.begin() + HonkRecursionConstraint::inner_public_input_offset, + // constraint.proof.begin() + + // static_cast(HonkRecursionConstraint::inner_public_input_offset + // + + // HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE)); current_aggregation_object = create_honk_recursion_constraints(builder, constraint, current_aggregation_object, @@ -376,47 +378,52 @@ void build_constraints(Builder& builder, // First add the output aggregation object as public inputs // Set the indices as public inputs because they are no longer being // created in ACIR - for (const auto& idx : current_aggregation_object) { - builder.set_public_input(idx); - } - - // Make sure the verification key records the public input indices of the - // final recursion output. - std::vector proof_output_witness_indices(current_aggregation_object.begin(), - current_aggregation_object.end()); - builder.set_recursive_proof(proof_output_witness_indices); - } else if (honk_recursion && - builder.is_recursive_circuit) { // Set a default aggregation object if we don't have one. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): These are pairing points extracted from - // a valid proof. This is a workaround because we can't represent the point at infinity in biggroup yet. - fq x0("0x031e97a575e9d05a107acb64952ecab75c020998797da7842ab5d6d1986846cf"); - fq y0("0x178cbf4206471d722669117f9758a4c410db10a01750aebb5666547acf8bd5a4"); - - fq x1("0x0f94656a2ca489889939f81e9c74027fd51009034b3357f0e91b8a11e7842c38"); - fq y1("0x1b52c2020d7464a0c80c0da527a08193fe27776f50224bd6fb128b46c1ddb67f"); - std::vector aggregation_object_fq_values = { x0, y0, x1, y1 }; - size_t agg_obj_indices_idx = 0; - for (fq val : aggregation_object_fq_values) { - const uint256_t x = val; - std::array val_limbs = { - x.slice(0, fq_ct::NUM_LIMB_BITS), - x.slice(fq_ct::NUM_LIMB_BITS, fq_ct::NUM_LIMB_BITS * 2), - x.slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 3), - x.slice(fq_ct::NUM_LIMB_BITS * 3, stdlib::field_conversion::TOTAL_BITS) - }; - for (size_t i = 0; i < fq_ct::NUM_LIMBS; ++i) { - uint32_t idx = builder.add_variable(val_limbs[i]); - builder.set_public_input(idx); - current_aggregation_object[agg_obj_indices_idx] = idx; - agg_obj_indices_idx++; - } - } - // Make sure the verification key records the public input indices of the - // final recursion output. - std::vector proof_output_witness_indices(current_aggregation_object.begin(), - current_aggregation_object.end()); - builder.set_recursive_proof(proof_output_witness_indices); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // for (const auto& idx : current_aggregation_object) { + // builder.set_public_input(idx); + // } + + // // Make sure the verification key records the public input indices of the + // // final recursion output. + // std::vector proof_output_witness_indices(current_aggregation_object.begin(), + // current_aggregation_object.end()); + // builder.set_recursive_proof(proof_output_witness_indices); } + static_cast(honk_recursion); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // else if (honk_recursion && + // builder.is_recursive_circuit) { // Set a default aggregation object if we don't have one. + // // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): These are pairing points extracted + // from + // // a valid proof. This is a workaround because we can't represent the point at infinity in biggroup + // yet. fq x0("0x031e97a575e9d05a107acb64952ecab75c020998797da7842ab5d6d1986846cf"); fq + // y0("0x178cbf4206471d722669117f9758a4c410db10a01750aebb5666547acf8bd5a4"); + + // fq x1("0x0f94656a2ca489889939f81e9c74027fd51009034b3357f0e91b8a11e7842c38"); + // fq y1("0x1b52c2020d7464a0c80c0da527a08193fe27776f50224bd6fb128b46c1ddb67f"); + // std::vector aggregation_object_fq_values = { x0, y0, x1, y1 }; + // size_t agg_obj_indices_idx = 0; + // for (fq val : aggregation_object_fq_values) { + // const uint256_t x = val; + // std::array val_limbs = { + // x.slice(0, fq_ct::NUM_LIMB_BITS), + // x.slice(fq_ct::NUM_LIMB_BITS, fq_ct::NUM_LIMB_BITS * 2), + // x.slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 3), + // x.slice(fq_ct::NUM_LIMB_BITS * 3, stdlib::field_conversion::TOTAL_BITS) + // }; + // for (size_t i = 0; i < fq_ct::NUM_LIMBS; ++i) { + // uint32_t idx = builder.add_variable(val_limbs[i]); + // builder.set_public_input(idx); + // current_aggregation_object[agg_obj_indices_idx] = idx; + // agg_obj_indices_idx++; + // } + // } + // // Make sure the verification key records the public input indices of the + // // final recursion output. + // std::vector proof_output_witness_indices(current_aggregation_object.begin(), + // current_aggregation_object.end()); + // builder.set_recursive_proof(proof_output_witness_indices); + // } } } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 80edf92270b..1b0e8b5057b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -166,7 +166,7 @@ struct AcirProgramStack { std::vector constraint_systems; WitnessVectorStack witness_stack; - AcirProgramStack(std::vector& constraint_systems_in, WitnessVectorStack& witness_stack_in) + AcirProgramStack(const std::vector& constraint_systems_in, const WitnessVectorStack& witness_stack_in) : constraint_systems(constraint_systems_in) , witness_stack(witness_stack_in) {} 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 db5a3251693..2a7882a2080 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 @@ -751,14 +751,14 @@ AcirProgramStack get_acir_program_stack(std::string const& bytecode_path, std::string const& witness_path, bool honk_recursion) { - auto bytecode = get_bytecode(bytecode_path); - auto constraint_systems = + std::vector bytecode = get_bytecode(bytecode_path); + std::vector constraint_systems = program_buf_to_acir_format(bytecode, honk_recursion); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): // Remove honk recursion flag - auto witness_data = get_bytecode(witness_path); - auto witness_stack = witness_buf_to_witness_stack(witness_data); + std::vector witness_data = get_bytecode(witness_path); + WitnessVectorStack witness_stack = witness_buf_to_witness_stack(witness_data); return { constraint_systems, witness_stack }; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index fb778929845..37ff4c41062 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -55,42 +55,46 @@ std::array create_ho using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044) reinstate aggregation + static_cast(input_aggregation_object); + static_cast(nested_aggregation_object); // Construct aggregation points from the nested aggregation witness indices - std::array nested_aggregation_points = - agg_points_from_witness_indicies(builder, nested_aggregation_object); + // std::array nested_aggregation_points = + // agg_points_from_witness_indicies(builder, nested_aggregation_object); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. // (We may need a separate recursion opcode for this to vary, or add more config witnesses to this opcode) - const auto& aggregation_input = input_aggregation_object; - aggregation_state_ct cur_aggregation_object; - cur_aggregation_object.P0 = nested_aggregation_points[0]; - cur_aggregation_object.P1 = nested_aggregation_points[1]; - cur_aggregation_object.has_data = true; // the nested aggregation object always exists + // const auto& aggregation_input = input_aggregation_object; + // aggregation_state_ct cur_aggregation_object; + // cur_aggregation_object.P0 = nested_aggregation_points[0]; + // cur_aggregation_object.P1 = nested_aggregation_points[1]; + // cur_aggregation_object.has_data = true; // the nested aggregation object always exists // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): generate this challenge properly. - field_ct recursion_separator = bb::stdlib::witness_t(&builder, 2); + // field_ct recursion_separator = bb::stdlib::witness_t(&builder, 2); // If we have previously recursively verified proofs, `previous_aggregation_object_nonzero = true` // For now this is a complile-time constant i.e. whether this is true/false is fixed for the circuit! - bool previous_aggregation_indices_all_zero = true; - for (const auto& idx : aggregation_input) { - previous_aggregation_indices_all_zero &= (idx == 0); - } + // bool previous_aggregation_indices_all_zero = true; + // for (const auto& idx : aggregation_input) { + // previous_aggregation_indices_all_zero &= (idx == 0); + // } - // Aggregate the aggregation object if it exists. It exists if we have previously verified proofs, i.e. if this is - // not the first recursion constraint. - if (!previous_aggregation_indices_all_zero) { - std::array inner_agg_points = agg_points_from_witness_indicies(builder, aggregation_input); - // If we have a previous aggregation object, aggregate it into the current aggregation object. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): Verify that using challenge and challenge - // squared is safe. - cur_aggregation_object.P0 += inner_agg_points[0] * recursion_separator; - cur_aggregation_object.P1 += inner_agg_points[1] * recursion_separator; - recursion_separator = - recursion_separator * - recursion_separator; // update the challenge to be challenge squared for the next aggregation - } + // // Aggregate the aggregation object if it exists. It exists if we have previously verified proofs, i.e. if this + // is + // // not the first recursion constraint. + // if (!previous_aggregation_indices_all_zero) { + // std::array inner_agg_points = agg_points_from_witness_indicies(builder, aggregation_input); + // // If we have a previous aggregation object, aggregate it into the current aggregation object. + // // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): Verify that using challenge and challenge + // // squared is safe. + // cur_aggregation_object.P0 += inner_agg_points[0] * recursion_separator; + // cur_aggregation_object.P1 += inner_agg_points[1] * recursion_separator; + // recursion_separator = + // recursion_separator * + // recursion_separator; // update the challenge to be challenge squared for the next aggregation + // } std::vector key_fields; key_fields.reserve(input.key.size()); @@ -210,8 +214,10 @@ std::array create_ho std::array pairing_points = verifier.verify_proof(proof_fields); // Aggregate the current aggregation object with these pairing points from verify_proof - cur_aggregation_object.P0 += pairing_points[0] * recursion_separator; - cur_aggregation_object.P1 += pairing_points[1] * recursion_separator; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + aggregation_state_ct cur_aggregation_object; + cur_aggregation_object.P0 = pairing_points[0]; // * recursion_separator; + cur_aggregation_object.P1 = pairing_points[1]; // * recursion_separator; std::vector proof_witness_indices = { cur_aggregation_object.P0.x.binary_basis_limbs[0].element.normalize().witness_index, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index 61259910828..43b9505b13b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -158,17 +158,17 @@ class AcirHonkRecursionConstraint : public ::testing::Test { const size_t inner_public_input_offset = 3; // - Save the public inputs so that we can set their values. // - Then truncate them from the proof because the ACIR API expects proofs without public inputs + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation std::vector inner_public_input_values( proof_witnesses.begin() + static_cast(inner_public_input_offset), proof_witnesses.begin() + - static_cast(inner_public_input_offset + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE)); + static_cast(inner_public_input_offset + num_inner_public_inputs)); // We want to make sure that we do not remove the nested aggregation object. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation proof_witnesses.erase(proof_witnesses.begin() + static_cast(inner_public_input_offset), proof_witnesses.begin() + - static_cast(inner_public_input_offset + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE)); + static_cast(inner_public_input_offset + num_inner_public_inputs)); std::vector key_witnesses = verification_key->to_field_elements(); @@ -179,8 +179,9 @@ class AcirHonkRecursionConstraint : public ::testing::Test { const uint32_t public_input_start_idx = static_cast(inner_public_input_offset + witness_offset); // points to public_input_0 const uint32_t proof_indices_start_idx = - static_cast(public_input_start_idx + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE); // points to agg_obj_0 + static_cast(public_input_start_idx + num_inner_public_inputs); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // - RecursionConstraint::AGGREGATION_OBJECT_SIZE); // points to agg_obj_0 const uint32_t key_indices_start_idx = static_cast(proof_indices_start_idx + proof_witnesses.size() - inner_public_input_offset); // would point to vkey_3 without the - @@ -203,7 +204,8 @@ class AcirHonkRecursionConstraint : public ::testing::Test { // We keep the nested aggregation object attached to the proof, // thus we do not explicitly have to keep the public inputs while setting up the initial recursion // constraint. They will later be attached as public inputs when creating the circuit. - for (size_t i = 0; i < num_inner_public_inputs - RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + for (size_t i = 0; i < num_inner_public_inputs; ++i) { inner_public_inputs.push_back(static_cast(i + public_input_start_idx)); } @@ -242,7 +244,8 @@ class AcirHonkRecursionConstraint : public ::testing::Test { // // We once again have to check whether we have a nested proof, because if we do have one // then we could get a segmentation fault as `inner_public_inputs` was never filled with values. - for (size_t i = 0; i < num_inner_public_inputs - RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + for (size_t i = 0; i < num_inner_public_inputs; ++i) { witness[inner_public_inputs[i]] = inner_public_input_values[i]; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 1a2fc9e502c..ac3b4dc2c88 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -44,8 +44,8 @@ void generate_dummy_proof() {} std::array create_recursion_constraints( Builder& builder, const RecursionConstraint& input, - std::array input_aggregation_object, - std::array nested_aggregation_object, + const std::array& input_aggregation_object, + const std::array& nested_aggregation_object, bool has_valid_witness_assignments) { const auto& nested_aggregation_indices = nested_aggregation_object; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 6e17c6e88ff..fa0fafd0c12 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -62,8 +62,8 @@ struct RecursionConstraint { std::array create_recursion_constraints( Builder& builder, const RecursionConstraint& input, - std::array input_aggregation_object, - std::array nested_aggregation_object, + const std::array& input_aggregation_object, + const std::array& nested_aggregation_object, bool has_valid_witness_assignments = false); std::vector export_key_in_recursion_format(std::shared_ptr const& vkey); diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index 4d3514f20cf..be21ac1c430 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -348,22 +348,20 @@ template class UltraHonkArith { UltraHonkTraceBlock poseidon_external; UltraHonkTraceBlock poseidon_internal; - // This is a set of fixed block sizes that accomodates the circuits currently processed in the ClientIvc bench. - // Note 1: The individual block sizes do NOT need to be powers of 2, this is just for conciseness. - // Note 2: Current sizes result in a full trace size of 2^18. It's not possible to define a fixed structure - // that accomdates both the kernel and the function circuit while remaining under 2^17. This is because the - // circuits differ in structure but are also both designed to be "full" within the 2^17 size. + // The set of fixed block sizes used when the structured trace is turned on. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1047): For development and practical purposes this + // needs to be more dynamic. Sizes currently set to accommodate the full e2e test. std::array fixed_block_sizes{ 1 << 10, // ecc_op; - 1 << 7, // pub_inputs; - 1 << 16, // arithmetic; - 1 << 15, // delta_range; - 1 << 14, // elliptic; - 1 << 16, // aux; - 1 << 15, // lookup; + 30000, // pub_inputs; + 755000, // arithmetic; + 140000, // delta_range; + 600000, // elliptic; + 1400000, // aux; + 460000, // lookup; 1 << 7, // busread; - 1 << 11, // poseidon_external; - 1 << 14 // poseidon_internal; + 15000, // poseidon_external; + 85000 // poseidon_internal; }; TraceBlocks() @@ -409,12 +407,17 @@ template class UltraHonkArith { void check_within_fixed_sizes() { + int i = 0; for (auto block : this->get()) { if (block.size() > block.get_fixed_size()) { info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " "not be constructed correctly!"); + info("Block index: ", i); + info("Actual size: ", block.size()); + info("Fixed size: ", block.get_fixed_size()); ASSERT(false); } + i++; } } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 5db8fda1296..41ee122490f 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -204,9 +204,10 @@ library Constants { uint256 internal constant LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; uint256 internal constant NUM_MSGS_PER_BASE_PARITY = 4; uint256 internal constant NUM_BASE_PARITY_PER_ROOT_PARITY = 4; - uint256 internal constant RECURSIVE_PROOF_LENGTH = 93; - uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 109; - uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; + uint256 internal constant RECURSIVE_PROOF_LENGTH = 393; + uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 393; + uint256 internal constant TUBE_PROOF_LENGTH = 393; + uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; uint256 internal constant SENDER_SELECTOR = 0; uint256 internal constant ADDRESS_SELECTOR = 1; uint256 internal constant STORAGE_ADDRESS_SELECTOR = 1; diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index d7968406f25..ff638e59ac6 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash set -eu -# TODO(https://github.com/noir-lang/noir/issues/4962): This script is still yet to be integrated with noir-lang/noir-gates-diff +# TODO(https://github.com/noir-lang/noir/issues/4962): This script is still yet to be integrated with noir-lang/noir-gates-diff # The script needs some slight updating as `nargo info` expects a complete JSON object, while this script expects a single object field -# representing a list of circuit reports for a program. +# representing a list of circuit reports for a program. # The ACIR tests in barretenberg also expect every target bytecode to have the name `acir.gz` while this script expects the same name of the package cd noir-protocol-circuits PROTOCOL_CIRCUITS_DIR=$PWD @@ -12,24 +12,24 @@ BB_BIN=${BB_BIN:-../../barretenberg/cpp/build/bin/bb} echo "{\"programs\": [" > gates_report.json -# Bound for checking where to place last parentheses +# Bound for checking where to place last parentheses NUM_ARTIFACTS=$(ls -1q "$PROTOCOL_CIRCUITS_DIR/target"/*.json | wc -l) ITER="1" -for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do +for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do ARTIFACT_NAME=$(basename -s .json "$pathname") - GATES_INFO=$($BB_BIN gates -b "./target/$ARTIFACT_NAME.json") + GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json if (($ITER == $NUM_ARTIFACTS)); then echo "}" >> gates_report.json - else + else echo "}, " >> gates_report.json fi ITER=$(( $ITER + 1 )) done -echo "]}" >> gates_report.json \ No newline at end of file +echo "]}" >> gates_report.json \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr index 134421e483f..cb9aebbbb13 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -48,7 +48,8 @@ impl RootParityInputs { //TODO: Do we need to validate this following hash //assert(hash(self.children[i].verification_key) == self.children[i].verification_key.hash); self.children[i].verify(); - self.children[i].validate_in_vk_tree(); + // TODO(#7410) we need the tube vk to reinstate this + // self.children[i].validate_in_vk_tree(); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index f016a8ada88..35608b4c28d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -40,10 +40,6 @@ impl PrivateKernelInitCircuitPrivateInputs { private_call_data_validator.validate_as_first_call(); private_call_data_validator.validate_against_tx_request(self.tx_request); private_call_data_validator.validate(output.end.note_hashes); - if !std::runtime::is_unconstrained() { - // verify/aggregate the private call proof - self.private_call.verify(); - } // Validate output. if !std::runtime::is_unconstrained() { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index a98a4a5c6b6..2f34b4de60b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -53,11 +53,8 @@ impl PrivateKernelInnerCircuitPrivateInputs { private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); private_call_data_validator.validate(output.end.note_hashes); if !std::runtime::is_unconstrained() { - // verify/aggregate the private call proof - self.private_call.verify(); - // verify/aggregate the previous kernel - self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // Validate output. @@ -150,13 +147,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PrivateKernelInnerInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PrivateKernelInnerInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index bd442c0eaf4..8d8ef785f20 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -42,9 +42,8 @@ impl PublicKernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof - self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs let mut public_inputs = PublicKernelCircuitPublicInputsBuilder::empty(); @@ -85,7 +84,7 @@ impl PublicKernelAppLogicCircuitPrivateInputs { let mut remaining_calls = array_to_bounded_vec(self.previous_kernel.public_inputs.end.public_call_stack); let reverted_call_request = remaining_calls.pop(); // even though we reverted, we still need to make sure the correct call was made - // but don't do the full `validate_call_against_request` because + // but don't do the full `validate_call_against_request` because // that makes a bunch of assertions that we don't want to make // e.g. that msg_sender is self in the case of internal. // We don't want to make those checks because we already know we reverted, @@ -210,7 +209,7 @@ mod tests { // the key difference in this test versus those that use builder.execute() // is that we do not add a public call request to the previous kernel. - // this means that when we call `to_public_kernel_data` below, + // this means that when we call `to_public_kernel_data` below, // it will say needs_app_logic is false let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); @@ -304,7 +303,7 @@ mod tests { builder.public_call.public_inputs.nullifiers.extend_from_array(current); let siloed = current.map( - |current: Nullifier| + |current: Nullifier| Nullifier { value: compute_siloed_nullifier(contract_address, current.value), note_hash: current.note_hash, counter: current.counter } ); @@ -636,13 +635,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 46f0d711000..bb7f785607e 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -18,8 +18,8 @@ struct PublicKernelSetupCircuitPrivateInputs { // And we just initialize the missing values to zero in TS before passing it to the circuit, // except for the constants.global_variables which we populate with the current block values. // This is a bit of a hack, but it allows us to reuse the setup circuit until - // the setup phase of the public kernel is complete. Maybe in a perfect world we would - // have a SetupInit, SetupInner, etc, but this will change anyway once the public VM is able to + // the setup phase of the public kernel is complete. Maybe in a perfect world we would + // have a SetupInit, SetupInner, etc, but this will change anyway once the public VM is able to // consume entire enqueued public calls. previous_kernel: PublicKernelData, public_call: PublicCallData, @@ -46,9 +46,10 @@ impl PublicKernelSetupCircuitPrivateInputs { fn public_kernel_setup(self) -> PublicKernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof + // Recursively verify the tube proof or a previous public kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs let mut public_inputs = PublicKernelCircuitPublicInputsBuilder::empty(); @@ -626,13 +627,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 72061159abb..30e065b3041 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -67,9 +67,10 @@ impl PublicKernelTailCircuitPrivateInputs { pub fn public_kernel_tail(self) -> KernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof + // Recursively verify the tube proof or a previous public kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } self.validate_inputs(); @@ -629,13 +630,11 @@ mod tests { let _res = builder.execute(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 8069c45fc43..b92619c190d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -108,7 +108,8 @@ impl PublicKernelTeardownCircuitPrivateInputs { if !dep::std::runtime::is_unconstrained() { // verify the previous kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs @@ -606,13 +607,10 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 52a87dda50c..9a5a20b7937 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -65,9 +65,10 @@ struct BaseRollupInputs { impl BaseRollupInputs { pub fn base_rollup_circuit(self) -> BaseOrMergeRollupPublicInputs { if !dep::std::runtime::is_unconstrained() { - // Verify the kernel circuit proof + // Recursively verify the tube proof if straight from private, or the public kernel tail self.kernel_data.verify(); - self.kernel_data.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.kernel_data.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // Verify the kernel chain_id and versions assert( @@ -259,7 +260,7 @@ impl BaseRollupInputs { } // Deducts the tx_fee from the GasToken balance of the fee_payer. If there is already a PublicDataUpdateRequest - // in this tx for their balance (because they issued a 'claim' to increase their balance by bridging from L1), + // in this tx for their balance (because they issued a 'claim' to increase their balance by bridging from L1), // update it by subtracting the tx_fee. Otherwise, build a new PublicDataUpdateRequest to subtract the tx_fee // from the balance of the fee_payer, using the fee_payer_gas_token_balance_read_hint to read the current balance. // Returns the data update request that subtracts the tx_fee from the fee_payer's balance, and the index where it @@ -1447,13 +1448,11 @@ mod tests { let _res = builder.execute(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = BaseRollupInputsBuilder::new(); - - builder.kernel_data = builder.kernel_data.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = BaseRollupInputsBuilder::new(); + // builder.kernel_data = builder.kernel_data.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index cd04084aec0..792e62acd32 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -29,10 +29,12 @@ impl MergeRollupInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { self.previous_rollup_data[0].verify(); - self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); self.previous_rollup_data[1].verify(); - self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; @@ -212,17 +214,14 @@ mod tests { let _outputs = inputs.merge_rollup_circuit(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_circuit() { - let mut inputs = default_merge_rollup_inputs(); - - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; - inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; - inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); - - let _outputs = inputs.merge_rollup_circuit(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_circuit() { + // let mut inputs = default_merge_rollup_inputs(); + // let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); + // inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; + // inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; + // inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); + // let _outputs = inputs.merge_rollup_circuit(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 68c62d126c7..863a8074f9d 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -41,14 +41,17 @@ impl RootRollupInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { self.previous_rollup_data[0].verify(); - self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); self.previous_rollup_data[1].verify(); - self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); // verify the root parity self.l1_to_l2_roots.verify(); - self.l1_to_l2_roots.validate_in_vk_tree(); + // TODO(#7410) we need the tube vk to reinstate this + // self.l1_to_l2_roots.validate_in_vk_tree(); } let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; @@ -65,7 +68,7 @@ impl RootRollupInputs { self.l1_to_l2_message_subtree_sibling_path, empty_l1_to_l2_subtree_root, self.l1_to_l2_roots.public_inputs.converted_root, - // TODO(Kev): For now we can add a test that this fits inside of + // TODO(Kev): For now we can add a test that this fits inside of // a u8. L1_TO_L2_MSG_SUBTREE_HEIGHT as u8 ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index bf386894602..6afa3fed807 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -14,7 +14,6 @@ struct PrivateCallData { public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_call_request: CallRequest, - proof: RecursiveProof, vk: VerificationKey, salted_initialization_hash: SaltedInitializationHash, @@ -22,18 +21,6 @@ struct PrivateCallData { contract_class_artifact_hash: Field, contract_class_public_bytecode_commitment: Field, function_leaf_membership_witness: MembershipWitness, - - acir_hash: Field, -} -impl Verifiable for PrivateCallData { - fn verify(self) { - let inputs = PrivateCircuitPublicInputs::serialize(self.call_stack_item.public_inputs); - std::verify_proof( - self.vk.key.as_slice(), - self.proof.fields.as_slice(), - inputs.as_slice(), - self.vk.hash - ); - } + acir_hash: Field, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index 0439e09afc5..781be7d481c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -5,18 +5,8 @@ use crate::merkle_tree::membership::assert_check_membership; use crate::utils::arrays::find_index_hint; struct PrivateKernelData { - // TODO(David): Left a note asking if we need this due to it - // already being in the proof. public_inputs: PrivateKernelCircuitPublicInputs, - // TODO(David): Mentions the dichotomy between a proof created for the - // circuit, which is a sequence of field elements, versus a proof - // created for solidity/native verification which is a collection of bytes. - // Kev: I've been questioning if we _need_ the sequence of field elements. - // It makes verification cheaper, though I have not tested how much cheaper. - // Removing it would also reduce complexity on the Noir side, as we have - // special methods to convert "inner proofs" into sequence of field elements. - proof: NestedRecursiveProof, vk: VerificationKey, // This index and path are meant to be those of a leaf within the tree of protocol circuits vks; not the tree @@ -25,18 +15,6 @@ struct PrivateKernelData { vk_path: [Field; VK_TREE_HEIGHT], } -impl Verifiable for PrivateKernelData { - fn verify(self) { - let inputs = PrivateKernelCircuitPublicInputs::serialize(self.public_inputs); - std::verify_proof( - self.vk.key.as_slice(), - self.proof.fields.as_slice(), - inputs.as_slice(), - self.vk.hash - ); - } -} - impl PrivateKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { let index_hint = find_index_hint(allowed_indices, self.vk_index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index dd8e5873630..49f67780fcc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -170,10 +170,10 @@ global FIXED_L2_GAS: u32 = 512; global FIXED_AVM_STARTUP_L2_GAS = 1024; // pays for hashing/validating logs global L2_GAS_PER_LOG_BYTE = 4; -// pays for tree insertions. +// pays for tree insertions. global L2_GAS_PER_NOTE_HASH = 32; // nullifiers are more expensive to insert/validate: -// they are inserted into an indexed tree and must be checked for duplicates +// they are inserted into an indexed tree and must be checked for duplicates global L2_GAS_PER_NULLIFIER = 64; // CANONICAL CONTRACT ADDRESSES @@ -270,11 +270,13 @@ global NUM_MSGS_PER_BASE_PARITY: u32 = 4; // FIX: Sadly, writing this as above causes a type error in type_conversion.ts. global NUM_BASE_PARITY_PER_ROOT_PARITY: u32 = 4; +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation // Lengths of the different types of proofs in fields -global RECURSIVE_PROOF_LENGTH = 93; -global NESTED_RECURSIVE_PROOF_LENGTH = 109; +global RECURSIVE_PROOF_LENGTH = 393; +global NESTED_RECURSIVE_PROOF_LENGTH = 393; +global TUBE_PROOF_LENGTH = RECURSIVE_PROOF_LENGTH; // in the future these can differ -global VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; +global VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; /** * Enumerate the hash_indices which are used for pedersen hashing. diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index bf2afcf5da8..de1d41b7fd1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -183,9 +183,9 @@ pub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, pub fn accumulate_sha256(input: [Field; 2]) -> Field { // This is a note about the cpp code, since it takes an array of Fields // instead of a U128. - // 4 Field elements when converted to bytes will usually + // 4 Field elements when converted to bytes will usually // occupy 4 * 32 = 128 bytes. - // However, this function is making the assumption that each Field + // However, this function is making the assumption that each Field // only occupies 128 bits. // // TODO(David): This does not seem to be getting guaranteed anywhere in the code? @@ -205,7 +205,7 @@ pub fn accumulate_sha256(input: [Field; 2]) -> Field { // Computes the final logs hash for a tx. // NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX -// to avoid doubling code, since we can't define the byte len to be 32*N directly. +// to avoid doubling code, since we can't define the byte len to be 32*N directly. pub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { // Convert each field element into a byte array and append the bytes to `hash_input_flattened` let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index db5ce46d15e..13f3a1850f9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -80,7 +80,7 @@ struct FixtureBuilder { historical_header: Header, tx_context: TxContext, global_variables: GlobalVariables, - + // Accumulated data. note_hashes: BoundedVec, nullifiers: BoundedVec, @@ -128,7 +128,7 @@ struct FixtureBuilder { vk_index: u32, vk_path: [Field; VK_TREE_HEIGHT], vk_tree_root: Field, - + // Counters. min_revertible_side_effect_counter: u32, counter_start: u32, @@ -294,7 +294,6 @@ impl FixtureBuilder { call_stack_item: self.to_private_call_stack_item(), public_call_stack: subarray(self.public_call_requests.storage), public_teardown_call_request: self.public_teardown_call_stack.storage[0], - proof: RecursiveProof::empty(), vk: self.vk, function_leaf_membership_witness: self.function_leaf_membership_witness, salted_initialization_hash: self.salted_initialization_hash, @@ -421,7 +420,7 @@ impl FixtureBuilder { pub fn to_private_kernel_data(self) -> PrivateKernelData { let public_inputs = self.to_private_kernel_circuit_public_inputs(); - PrivateKernelData { public_inputs, proof: self.proof, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } + PrivateKernelData { public_inputs, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } } pub fn to_public_kernel_circuit_public_inputs(self, revertible: bool) -> PublicKernelCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js index 68a60491bfc..8071d782d5b 100644 --- a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js +++ b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js @@ -119,9 +119,8 @@ async function generateVKData( ); const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - const writeVkCommand = `${BB_BIN_PATH} write_vk -b "${artifactPath}" -o "${binaryVkPath}"`; - - const vkAsFieldsCommand = `${BB_BIN_PATH} vk_as_fields -k "${binaryVkPath}" -o "${jsonVkPath}"`; + const writeVkCommand = `${BB_BIN_PATH} write_vk_ultra_honk -h -b "${artifactPath}" -o "${binaryVkPath}"`; + const vkAsFieldsCommand = `${BB_BIN_PATH} vk_as_fields_ultra_honk -k "${binaryVkPath}" -o "${jsonVkPath}"`; await new Promise((resolve, reject) => { child_process.exec(`${writeVkCommand} && ${vkAsFieldsCommand}`, (err) => { diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 921b69e100a..fc5e6002dbf 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000079ea57b3d7247e1b84fc1ab449de746345","0x000000000000000000000000000000000023fb17d477c91e0fb057233a66ef2a","0x000000000000000000000000000000146353d3faf24455819947aa0a25868174","0x00000000000000000000000000000000000093b1c637419c9f016bb0261cdfc6","0x000000000000000000000000000000325b128a84544d31fa1c577232c742b574","0x00000000000000000000000000000000002b3db93a2fca4c31308471d4f55fa2","0x00000000000000000000000000000054d9d87932eee6280c37d802ec8d47ca02","0x000000000000000000000000000000000000397167bb1e36d061487e93e4d97e","0x000000000000000000000000000000143b0960a1b9f19a44ad1cf2b7059832d6","0x0000000000000000000000000000000000158446576b2d43f78b48799ff7e760","0x000000000000000000000000000000cf640bad8ccc1890d738ab917d6caa957e","0x00000000000000000000000000000000001d6fd185d8771b864545438c6a1d68","0x000000000000000000000000000000a33cd928d0d4c7f244824b63b15f4c5423","0x00000000000000000000000000000000000433ccd872d2a302104048474e0bea","0x000000000000000000000000000000eaf7d13e5e9706e1b8a9343bd493a060af","0x00000000000000000000000000000000001a062842ba351b311ae52693f5114e","0x000000000000000000000000000000a33cd928d0d4c7f244824b63b15f4c5423","0x00000000000000000000000000000000000433ccd872d2a302104048474e0bea","0x000000000000000000000000000000eaf7d13e5e9706e1b8a9343bd493a060af","0x00000000000000000000000000000000001a062842ba351b311ae52693f5114e","0x000000000000000000000000000000160d90f214f524875c01cb9cf0f2d272b9","0x000000000000000000000000000000000015d5f906c4fe06017b0f9824434d09","0x0000000000000000000000000000007fc2db3cfe49b7666aeafd8cf6973c9fed","0x00000000000000000000000000000000000c7fc1e545a8ee19a7bc6ad6f2ea47","0x000000000000000000000000000000fc3c9df244afbba117cd897a4c929edb84","0x0000000000000000000000000000000000216f0c3a2e5e8683d9717ad40eadde","0x000000000000000000000000000000c381b45048aa5163e0129e4031e29058cb","0x00000000000000000000000000000000002f11022de88492201c28f87582684d","0x000000000000000000000000000000c98462e08c423124d92a41110c378db160","0x00000000000000000000000000000000000106dafb059575ec9b926aa90edfef","0x0000000000000000000000000000007d0cc0465628f6b0f3918aa9d7cf33ff38","0x00000000000000000000000000000000002cff01344fc7c6f81399b7ae660ad4","0x07eff01a06f356d255515e5f27cb51e8873277beb3f986c215181b475df4dd8e","0x28745e58da3e495762fee75759b60674a1017089c5bfe9cf2ec9da4c920b2273","0x1d5b7b751e509ac70caa253595be4523d1963cf7bd6751d2c146e2fc10d00196","0x26fe27f73b55be7d49b4c1c11f085f47f6a241ba5ea0d48b47964e7adf5e8e5a","0x239206c519de2576a554a70f387cdf5d525a599541be2ecd9260e52d572ae07c","0x04e35b29a57c31c89c72a6387bf89613b64c2827e0c2402b8dfb2c1cfea0c878","0x1e8398c5dd85d15154110c2480f2249030aecd7595242ae86bbdf7b2730ca070","0x2ba9986a038e85a4dd96badffb6a44950c37360fd6e8ec6c4b9647377bcb45f5","0x27ca7a06ceea23d329c52dac8c0715440238d37362ab0fb1e26544b18bb79a3b","0x23b768d51fa7922f8292309455adc5730b8964818c328a42dff60a57add32f50","0x24e8634d5381475abe5821450299d9d8d725a472610fe265e44c8360c4708c95","0x0cdbb73fe5c035427113e66a15b8c41e963ae215e491d855a3ce8c3ab200fb3b","0x0e8acd2ed6af85e4f71b96c51d2a57bceea5c50fb405b7888359f0635b415da7","0x2914cc0244acf5ac6d674d3c96d543ee2f3e95d0248ee66daf0cf2932107e300","0x00ff0384250d2c2e59cd1cf58cebd1d3b1ebab7989eb2eaa6b6bbce69f9e8ba0","0x253f7a5007d47d3d858fc0e172c971cb54f97cea5c63ca60efe61589913b2499","0x2d34704fc711dabe0f716dbebc5dfd0eaa5667006847d333dadc86e15bf672c0","0x0bdd67ff40c61242e46a234c0d438663a9ccae833d1e0b22833ffe41e2828bb4","0x04c7ba2edccfb340eba0c94a7a5d5d53b010939621053c7c0fd27f2ba4b08273","0x0c3f68e6de8042a10098596e80ea79882b37d22c6a6adaa64f5c668739932fa5","0x14bcb10845b45cb8fdcac13e41ad755f6d966756ee2f3d4ed8a5791d4b345ea8","0x0dd68c1e3d122d4d4b28a8ac7e6a592146afe70e3852906c27ccc7e345f745e2","0x06816aff04192007cb2b3ed2cee4b22e044ced0199b136942348ced61990c1a7","0x3013f13664687bc3cbe26314f17cf309486ef71ffb55ce2589075554fc31ee69","0x1941a602d47af0e52f06a272998b6a59313f316508c0778714a36d7bb4f5669b","0x268750f15f2ac995d1d59859b7d636ae814e751b84318218ac1ce75a14b00e18","0x2aaff14fd98aa13ffdf34e3f689e16b2e8cb7695db9a014dd270b021968e3bb2","0x090087ad0d688396823bbd90a8770c1101e5907efd1c4fbafff8a1e9f2f84d89","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x152deae3a77021b0201a74d98b30d842baea62c0d2531d69d5e866e59f48e052","0x084acb08dc53880864266b6dea02ec7a85ffab2ab590ba9a4adb32ad2c8ffe53","0x1b8ab1a2e47a839fdbf19d2cbea2abe79c57722270123cf96289a11e233cd175","0x03493f800f9abbe4e405f0f637f41f22dcc10e44e836a09115ed5821cd5856e6","0x24c358e686e47c512bbec4a1b9ac562c251e004ea142df44ea3b18cf214baa47","0x18296076ac89be1c4c24a04553be7bd07bba5a41d1c33de2bec14cfd1262ab9f","0x0e30341606dc2577a451251241394b3871e9db0e1758d250d36348bcbb8b6fdb","0x15f846978484540ac3c35eee38ccd980f01e8bda6050a645c4abca6f22b24619","0x2735dd2b603cde2937bf842002e8704ef1e3883d2d0a6e999dd7015496c10302","0x23c47d9891d04bdb88ca239119e423afdc6d2bd45fb92f5f19b8b0a9583fc863","0x1ce47f9088eecc7268d4558aa02a4902282bccaacbe882917cc57969af2236d0","0x2b5a6f937fcc921cced568de248e19fd3801e688505ee44af6499e14885c9879","0x2ae2f654890e7018bae8308b5a97230cdcd3b63b24334a05dc4fdc4107cff73d","0x06a87313997c2a5318a8ce0f75e26b9c4a2a83bd9c3578f10d1c1f3bfded8f29","0x0afe95fddb76f390d58e15b7e647e9ed083a66aa7829a18963125d865b64ef7f","0x1ff7ecaf04f4e8a9d57f79c85dd963099f6005f542df7c20505af69061473114","0x26ca489f39024294da78a601feda0a17c40d46e2c7d0787b47dc0afaf027a8c8","0x2da37034033c950b2f85c32be2b0f1102dae5ec01e13681ffc9a9a3033469a8d","0x22c35dc92f5bf1cb569ad756b45208ffa8a85d825ebacf8e7354e9162651d1fa","0x0e443f72c90fec92786098f7ec90cea01f6202db6998b34dbb1e7b0293f4bebd","0x049684508bb0af0f27bcaaf96aa53eac25a425e159eb33e031db157d63c22fb9","0x20d990716bfec57f52f603d50d0d81c4c851bfc231894eb573fa54f2ac70c9dd","0x1fd19e900621d01488be88d4a6d95c2583c19c6d1d49e8cd139bce76051b71bc","0x1679a31a104b20b301737b9214f12a0707727bd4510d5a53e5bec1321816cdfa","0x27b3d8000581372f35039477c28a268065b3717dbd9337c06a82162781e0d131","0x23b79b53bdb698ef8c7c01afaf3350deb78b5e841e09b13b6ef86fc68f97bcab","0x1d4abc42698589c40b05e187c12af268fffe64010756a8d08ea817105305a770","0x0f744ca06905efa1f604f387284979be483c00ee9298134e7337bd8bb4a88933","0x0be6790122704c6ed4c37fef0b524b413e63b88c2dadbe67a5ba039cf11cc628","0x19fa34479d41d734a17619048627633807d706b2b1035a326efada8f3e8eb183","0x1b208f5cc663a9560e8685c351cb17b8e5862eb16f1407cf654e8ffae331aa9b","0x1b140725b61fe2e1057d72525aecf1d319ecb509a392f68e4058d13cea209993","0x1b140725b61fe2e1057d72525aecf1d319ecb509a392f68e4058d13cea209993","0x0d1703eac9b276094d72a50322dd82033960a6f1f6176aa2b029e39a1375bb51","0x09ba2a48cfdcc27f6b6db2ca277c5016d4f5a177e65eec6f68e30a67d4b06c1b","0x0e243bf8b2d6b8e46ed75902fe60781b2b41cf45287f367df850ce50de7f86af","0x1be244289270e4c0dc8517edfe335954fa7b56c3bf6fe06bc2d268f7db7a68ee","0x116ef1bfcfbca0612c92872aa3d07d32cb0b9716b1ba735846888a56e03c6207","0x0de8a7471ceb058680d2e0afa73e3dd843b527db1c16ebfaf8612447ffbee858","0x16911fee4120f72d81b0dfb0eeeb7380611119ee990daec5669b711cb35e2756","0x1c278b26a16e1ee7e21a71b67a31cb0b9907dae80776aa1dc7094ea5b4e2c34e","0x0f5c67db668b1f1880c51f805ec3d40aa27d34b4c8833f755d4466c285264399","0x000000000000000000000000000000dc2546d68fbe5a4913dde8ed73f673bc5f","0x00000000000000000000000000000000001310657525d78319e5b15c92398dcf","0x0000000000000000000000000000000fde9a035776897ed560b4d9ae338b5f85","0x00000000000000000000000000000000000f84fecfb3ea28426f114d9de93cb3","0x000000000000000000000000000000d3ea685110f3ff69bf91cc32cc5170b62e","0x0000000000000000000000000000000000179205f5ebaf3eaf5d50be462f830d","0x00000000000000000000000000000024a7284c15d725d62b8f5c1090b08b58b7","0x00000000000000000000000000000000002b6fdb2139f7b9443cbd82e6423486","0x00000000000000000000000000000006489f49eed3370ee31c80590eed2d0c3a","0x000000000000000000000000000000000010c11c3a122e00a12e0cf7a58d81ae","0x000000000000000000000000000000eb2d1eef7e7c7c0c054859600d264176e9","0x000000000000000000000000000000000028ac3239a0917c7c3761e11fbf9541","0x0000000000000000000000000000006ecbe6a2ccf0c9e1b743a84e1540796b81","0x0000000000000000000000000000000000098a99a81cbc111660301a03f77d96","0x000000000000000000000000000000c4f256019891f39b00b1b00428b3a154a5","0x00000000000000000000000000000000001bc2f83790ff1d3086273e4560135c","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000868795ebcbf38bffa96f455a314c7b9310","0x00000000000000000000000000000000002e43e0a550d7cce874e869ed0ef545","0x0000000000000000000000000000001e5a780edfd01526758b69bfaf25803f67","0x00000000000000000000000000000000000f0991f4b5dc348354f019ecc66502","0x000000000000000000000000000000cb917b7819afd60fc86ea477594ffca008","0x000000000000000000000000000000000002beaa7c144fc6620870e72ee8064c","0x000000000000000000000000000000b7f4dfed23506dadd1726a896e226d7a34","0x00000000000000000000000000000000001bb28f2fcfb40843aa5f5e38d689e1"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000008c068dccb0e55d4b56c7c32ebfafeb5b02","0x0000000000000000000000000000000000266c985199590a284abf77ba01c36e","0x00000000000000000000000000000044fb25551548bb4059099673aed8646b35","0x000000000000000000000000000000000023ab8c745db114ee56b97a8aa27934","0x000000000000000000000000000000a56563b42599f0e4ad5455a8fd988b9ff3","0x00000000000000000000000000000000000a94e3640063f3f4758fcfe457d298","0x0000000000000000000000000000008a51861ca043ceae044d6ab4f136331514","0x00000000000000000000000000000000001812e50744ac8ed3cc4a9594a701cc","0x000000000000000000000000000000b911c8cf179747b410c1cb9fd8a8bde095","0x00000000000000000000000000000000001826edb9faf624498fe82f5a61008d","0x000000000000000000000000000000ed158ea534a9c72ec9e614906fd7adff9a","0x000000000000000000000000000000000017cb9637e464dc2647b9b8688c5fa0","0x0000000000000000000000000000004b5064dd55e5ec8cd9bdd01c0e22eb7122","0x00000000000000000000000000000000002c7cff0caa8ba3fec7523dcbc934a8","0x000000000000000000000000000000f268df76bf0d78739ded43daba9c339499","0x00000000000000000000000000000000002e11974b75c78b276ae16219b99dc9","0x000000000000000000000000000000cfc293980c0ecf813f4f1436ff140740c3","0x000000000000000000000000000000000016ff2972a7eedf8ff27f494904fa47","0x00000000000000000000000000000085a92cc2b6efec726ea10710b20776ee70","0x0000000000000000000000000000000000278709e98b64a3553dc3e6e514e7ff","0x0000000000000000000000000000004391d81714b7d7ad40642b9308d02258b4","0x0000000000000000000000000000000000207710f769c857fbe624a2333097b2","0x0000000000000000000000000000002f767ee4790206ca5c193b742aa672d6d8","0x00000000000000000000000000000000001044cdbbd63806d10426ca4cb77cbc","0x000000000000000000000000000000314be7aecd2a710b8966befe7c0b08f574","0x00000000000000000000000000000000000558190b4fa7d726895b6d7d9c0bef","0x000000000000000000000000000000d64f3a11faf61b8776b0e778ab7a16c09c","0x00000000000000000000000000000000000d1c3d5e8fe0193b17834424ce605d","0x000000000000000000000000000000d8019ded441b9e454eb4045069cefee487","0x00000000000000000000000000000000002c066d46d386975a57df073e19403b","0x0000000000000000000000000000006bf779063abc501d4102fbfc99d4227c16","0x00000000000000000000000000000000001bbf8b9e8c4b2184984b994c744d21","0x0000000000000000000000000000003896ea793e6b3f6a14218d476534109610","0x00000000000000000000000000000000000e84090add56f2500ab518c655cae6","0x00000000000000000000000000000065df446fdddba972f3c4414ad3c901f4f9","0x00000000000000000000000000000000002b78a584bd6ae88cf4ec7c65c90e0b","0x00000000000000000000000000000094e611b5d59a27773f744710b476fbd30f","0x00000000000000000000000000000000001bd6129f9646aa21af0d77e7b1cc97","0x000000000000000000000000000000139a9d1593d56e65e710b2f344756b721e","0x00000000000000000000000000000000002f8d492d76a22b6834f0b88e2d4096","0x00000000000000000000000000000026c814cd7c5e1ba2094969bb1d74f1c66b","0x000000000000000000000000000000000013129f0714c3307644809495e01504","0x0000000000000000000000000000007d4549a4df958fe4825e7cb590563154ab","0x00000000000000000000000000000000000e7d5873232b1bdd0ce181513b47d1","0x000000000000000000000000000000a54541a8f32c0d9f8645edf17aac8fa230","0x00000000000000000000000000000000001e0677756494ded8010e8ef02518b2","0x0000000000000000000000000000008b101700e2d4f9116b01bfaaf3c458a423","0x0000000000000000000000000000000000021e43a3c385eba62bcc47aad7b9ea","0x00000000000000000000000000000099559d1c1ed6758494d18b9890bb5e3f97","0x00000000000000000000000000000000002e68b3c679543d2933bf9f7f77d422","0x000000000000000000000000000000c842dceb89f5cf4c130810f4802014a67f","0x00000000000000000000000000000000000d647daa6d2a8ac14f2da194b3a27e","0x000000000000000000000000000000af641be24f11d735581ad2e14787470194","0x00000000000000000000000000000000001e90f381ece8401026212fdbb26199","0x000000000000000000000000000000f601a4b716e755b0cf516d07e403265e27","0x00000000000000000000000000000000002d49d628876caa6993afe9fc30a764","0x0000000000000000000000000000008e9de4c6ce2e85105ec90ab63303b61502","0x00000000000000000000000000000000001b063563a7858b064132573e0aca86","0x00000000000000000000000000000021c200c8468139aa32fcf13fd1d8570828","0x0000000000000000000000000000000000023a4e744c62548c3b32986b3bc73a","0x0000000000000000000000000000000af941f79a4d93c6e9aad19c6049e1fa53","0x000000000000000000000000000000000003db2201f4b1b9a4d3646331e1f8e1","0x00000000000000000000000000000005d91fe16bd2b8dd3ce8b7d70ce6222b4f","0x0000000000000000000000000000000000102db0f3fd668e06f49d133d1bf994","0x0000000000000000000000000000009459915944c39a12b978a433efb6517d0f","0x00000000000000000000000000000000000b1c9fa9f4ce17e53f3acd13be4078","0x0000000000000000000000000000007c8d45be92476f8867dca4078fb7b6b2f8","0x00000000000000000000000000000000001f21afb9b7ccd5c404f0115253d2a6","0x0000000000000000000000000000004d78a34b40208c31be4fb8b39d23f1d1de","0x00000000000000000000000000000000000f3090488b19df76c4358537728d9a","0x00000000000000000000000000000060b0272756debcae50a25a3ee7d7095ea9","0x00000000000000000000000000000000002e84bca0d93b098853cca06147ec94","0x000000000000000000000000000000a0875603e0a017ce12ff79764af43e7421","0x0000000000000000000000000000000000245798a7b19502ba14b46eb68dc771","0x00000000000000000000000000000089b25e854077925674d0645ed1e784c929","0x000000000000000000000000000000000008b8347d14433adba1d9e9406eb1db","0x000000000000000000000000000000d0d3258758dfa9bae9e415f6d48d990e16","0x0000000000000000000000000000000000224948ddbcddb1e360efa2ac511aac","0x000000000000000000000000000000f6a101330e9f928dc80a3d3b9afefb373a","0x00000000000000000000000000000000001011627c159ab9f3ff0a0416a01df6","0x0000000000000000000000000000002ec420ad50087360c152c131400547bcc6","0x000000000000000000000000000000000018dab63316305864682bfe7b586e91","0x0000000000000000000000000000004bd9f352c132c7ae6bed5ea997693e6300","0x00000000000000000000000000000000001edb4d30542aa0ac4fe8eb31fc2ce0","0x0000000000000000000000000000008bcf42c24591e90cf41fc687829fe0b0aa","0x000000000000000000000000000000000027a49cd522a4fbbdfc8846331514de","0x000000000000000000000000000000bdfbf1d964fcfb887c3631ef202797fc2f","0x00000000000000000000000000000000001432caafa62e791082fd900fcb34a1","0x0000000000000000000000000000006f99a40f79f14ed78a291d53d0425ddc9d","0x000000000000000000000000000000000007ea92c2de0345ded1d25b237f0845","0x000000000000000000000000000000bc1328fa2c343da93cb98486d414f0a40a","0x0000000000000000000000000000000000255aeaa6894472e3cb6b0a790cf290","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000008775499e69e8bd2c39af33bd5fa0b4079a","0x0000000000000000000000000000000000024236bda126650fb5228cf424a087","0x000000000000000000000000000000b0eb1a867b06854066589b967455259b32","0x0000000000000000000000000000000000233cda9292be02cfa2da9d0fc7b0ea"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr index ecfd18f3837..a18403eba71 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -1,6 +1,6 @@ // This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 393; fn main( verification_key: [Field; 103], // This is the proof without public inputs attached. diff --git a/noir/noir-repo/test_programs/rebuild.sh b/noir/noir-repo/test_programs/rebuild.sh index 13479f58b4b..a70f69d531d 100755 --- a/noir/noir-repo/test_programs/rebuild.sh +++ b/noir/noir-repo/test_programs/rebuild.sh @@ -45,7 +45,7 @@ rm -rf $current_dir/acir_artifacts mkdir -p $current_dir/acir_artifacts # Gather directories to process. -dirs_to_process=() +# dirs_to_process=() for dir in $base_path/*; do if [[ ! -d $dir ]] || [[ " ${excluded_dirs[@]} " =~ " $(basename "$dir") " ]]; then continue diff --git a/noir/verify_honk_proof/src/main.nr b/noir/verify_honk_proof/src/main.nr index ecfd18f3837..a18403eba71 100644 --- a/noir/verify_honk_proof/src/main.nr +++ b/noir/verify_honk_proof/src/main.nr @@ -1,6 +1,6 @@ // This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 393; fn main( verification_key: [Field; 103], // This is the proof without public inputs attached. diff --git a/scripts/earthly-ci b/scripts/earthly-ci index c2ae10b529a..49cc4db605a 100755 --- a/scripts/earthly-ci +++ b/scripts/earthly-ci @@ -65,7 +65,7 @@ while [ $ATTEMPT_COUNT -lt $MAX_ATTEMPTS ]; do wipe_non_cache_docker_state fi sleep 20 - elif grep 'status 125: docker: Error response from daemon: layer does not exist.' $OUTPUT_FILE >/dev/null || grep 'could not determine buildkit address - is Docker or Podman running?' $OUTPUT_FILE >/dev/null ; then + elif grep 'status 125: docker: Error response from daemon: layer does not exist.' $OUTPUT_FILE >/dev/null || grep 'could not determine buildkit address - is Docker or Podman running?' $OUTPUT_FILE >/dev/null || grep 'please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host' $OUTPUT_FILE >/dev/null ; then wipe_non_cache_docker_state # wait for other docker restarts sleep 20 diff --git a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts index 1cdbaa00b4d..af130fe08c5 100644 --- a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts +++ b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts @@ -25,7 +25,11 @@ export type SendMethodOptions = { * Implements the sequence create/simulate/send. */ export abstract class BaseContractInteraction { - protected tx?: Tx; + /** + * The transaction execution result. Set by prove(). + * Made public for simple mocking. + */ + public tx?: Tx; protected txRequest?: TxExecutionRequest; protected log = createDebugLogger('aztec:js:contract_interaction'); diff --git a/yarn-project/bb-prover/package.json b/yarn-project/bb-prover/package.json index 89ad0498089..909ffa5251a 100644 --- a/yarn-project/bb-prover/package.json +++ b/yarn-project/bb-prover/package.json @@ -65,6 +65,7 @@ "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/telemetry-client": "workspace:^", + "@msgpack/msgpack": "^3.0.0-beta2", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", "@noir-lang/types": "portal:../../noir/packages/types", "commander": "^9.0.0", diff --git a/yarn-project/bb-prover/src/bb/cli.ts b/yarn-project/bb-prover/src/bb/cli.ts index ce2e02eb832..ae585b37797 100644 --- a/yarn-project/bb-prover/src/bb/cli.ts +++ b/yarn-project/bb-prover/src/bb/cli.ts @@ -89,6 +89,38 @@ export function getProgram(log: LogFn): Command { ); }); + program + .command('write-vk') + .description('Generates the verification key for the specified circuit') + .requiredOption( + '-w, --working-directory ', + 'A directory to use for storing input/output files', + BB_WORKING_DIRECTORY, + ) + .requiredOption('-b, --bb-path ', 'The path to the BB binary', BB_BINARY_PATH) + .requiredOption('-c, --circuit ', 'The name of a protocol circuit') + .action(async options => { + const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact]; + if (!compiledCircuit) { + log(`Failed to find circuit ${options.circuit}`); + return; + } + try { + await fs.access(options.workingDirectory, fs.constants.W_OK); + } catch (error) { + log(`Working directory does not exist`); + return; + } + await generateKeyForNoirCircuit( + options.bbPath, + options.workingDirectory, + options.circuit, + compiledCircuit, + 'vk', + log, + ); + }); + program .command('write-contract') .description('Generates the verification contract for the specified circuit') diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 7c97fcede72..d682e563fc5 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -148,11 +148,11 @@ export async function generateKeyForNoirCircuit( // args are the output path and the input bytecode path const args = ['-o', `${outputPath}/${VK_FILENAME}`, '-b', bytecodePath]; const timer = new Timer(); - let result = await executeBB(pathToBB, `write_${key}`, args, log); + let result = await executeBB(pathToBB, `write_${key}_ultra_honk`, args, log); // If we succeeded and the type of key if verification, have bb write the 'fields' version too if (result.status == BB_RESULT.SUCCESS && key === 'vk') { const asFieldsArgs = ['-k', `${outputPath}/${VK_FILENAME}`, '-o', `${outputPath}/${VK_FIELDS_FILENAME}`, '-v']; - result = await executeBB(pathToBB, `vk_as_fields`, asFieldsArgs, log); + result = await executeBB(pathToBB, `vk_as_fields_ultra_honk`, asFieldsArgs, log); } const duration = timer.ms(); @@ -187,6 +187,145 @@ export async function generateKeyForNoirCircuit( return res; } +// TODO(#7369) comment this etc (really just take inspiration from this and rewrite it all O:)) +export async function executeBbClientIvcProof( + pathToBB: string, + workingDirectory: string, + bytecodeStackPath: string, + witnessStackPath: string, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // The proof is written to e.g. /workingDirectory/proof + const outputPath = `${workingDirectory}`; + + const binaryPresent = await fs + .access(pathToBB, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + // Write the bytecode to the working directory + log(`bytecodePath ${bytecodeStackPath}`); + log(`outputPath ${outputPath}`); + const args = ['-o', outputPath, '-b', bytecodeStackPath, '-w', witnessStackPath, '-v']; + const timer = new Timer(); + const logFunction = (message: string) => { + log(`client ivc proof BB out - ${message}`); + }; + + const result = await executeBB(pathToBB, 'client_ivc_prove_output_all_msgpack', args, logFunction); + const durationMs = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs, + proofPath: `${outputPath}`, + pkPath: undefined, + vkPath: `${outputPath}`, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + +/** + * Used for generating verification keys of noir circuits. + * It is assumed that the working directory is a temporary and/or random directory used solely for generating this VK. + * @param pathToBB - The full path to the bb binary + * @param workingDirectory - A working directory for use by bb + * @param circuitName - An identifier for the circuit + * @param bytecode - The compiled circuit bytecode + * @param inputWitnessFile - The circuit input witness + * @param log - A logging function + * @returns An object containing a result indication, the location of the VK and the duration taken + */ +export async function computeVerificationKey( + pathToBB: string, + workingDirectory: string, + circuitName: string, + bytecode: Buffer, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode + const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`; + + // The verification key is written to this path + const outputPath = `${workingDirectory}/vk`; + + const binaryPresent = await fs + .access(pathToBB, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + // Write the bytecode to the working directory + await fs.writeFile(bytecodePath, bytecode); + const timer = new Timer(); + const logFunction = (message: string) => { + log(`computeVerificationKey(${circuitName}) BB out - ${message}`); + }; + let result = await executeBB( + pathToBB, + 'write_vk_ultra_honk', + ['-o', outputPath, '-b', bytecodePath, '-v'], + logFunction, + ); + if (result.status == BB_RESULT.FAILURE) { + return { status: BB_RESULT.FAILURE, reason: 'Failed writing VK.' }; + } + result = await executeBB( + pathToBB, + 'vk_as_fields_ultra_honk', + ['-o', outputPath + '_fields.json', '-k', outputPath, '-v'], + logFunction, + ); + const duration = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs: duration, + pkPath: undefined, + vkPath: `${outputPath}`, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to write VK. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + /** * Used for generating proofs of noir circuits. * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. @@ -235,7 +374,7 @@ export async function generateProof( const logFunction = (message: string) => { log(`${circuitName} BB out - ${message}`); }; - const result = await executeBB(pathToBB, 'prove_output_all', args, logFunction); + const result = await executeBB(pathToBB, 'prove_ultra_honk_output_all', args, logFunction); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { @@ -257,6 +396,87 @@ export async function generateProof( } } +/** + * Used for generating proofs of the tube circuit + * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. + * @param pathToBB - The full path to the bb binary + * @param workingDirectory - A working directory for use by bb + * @param circuitName - An identifier for the circuit + * @param bytecode - The compiled circuit bytecode + * @param inputWitnessFile - The circuit input witness + * @param log - A logging function + * @returns An object containing a result indication, the location of the proof and the duration taken + */ +export async function generateTubeProof( + pathToBB: string, + workingDirectory: string, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // // Paths for the inputs + const vkPath = join(workingDirectory, 'inst_vk.bin'); // the vk of the last instance + const accPath = join(workingDirectory, 'pg_acc.bin'); + const proofPath = join(workingDirectory, 'client_ivc_proof.bin'); + const translatorVkPath = join(workingDirectory, 'translator_vk.bin'); + const eccVkPath = join(workingDirectory, 'ecc_vk.bin'); + + // The proof is written to e.g. /workingDirectory/proof + const outputPath = workingDirectory; + const filePresent = async (file: string) => + await fs + .access(file, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + + const binaryPresent = await filePresent(pathToBB); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + if ( + !filePresent(vkPath) || + !filePresent(accPath) || + !filePresent(proofPath) || + !filePresent(translatorVkPath) || + !filePresent(eccVkPath) + ) { + return { status: BB_RESULT.FAILURE, reason: `Client IVC input files not present in ${workingDirectory}` }; + } + const args = ['-o', outputPath, '-v']; + + const timer = new Timer(); + const logFunction = (message: string) => { + log(`TubeCircuit (prove) BB out - ${message}`); + }; + const result = await executeBB(pathToBB, 'prove_tube', args, logFunction); + const durationMs = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs, + proofPath: outputPath, + pkPath: undefined, + vkPath: outputPath, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + /** * Used for generating AVM proofs. * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. @@ -381,7 +601,7 @@ export async function verifyProof( verificationKeyPath: string, log: LogFn, ): Promise { - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify', log); + return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify_ultra_honk', log); } /** @@ -414,7 +634,7 @@ async function verifyProofInternal( pathToBB: string, proofFullPath: string, verificationKeyPath: string, - command: 'verify' | 'avm_verify', + command: 'verify_ultra_honk' | 'avm_verify', log: LogFn, ): Promise { const binaryPresent = await fs @@ -468,7 +688,7 @@ export async function writeVkAsFields( try { const args = ['-k', `${verificationKeyPath}/${verificationKeyFilename}`, '-v']; const timer = new Timer(); - const result = await executeBB(pathToBB, 'vk_as_fields', args, log); + const result = await executeBB(pathToBB, 'vk_as_fields_ultra_honk', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, durationMs: duration, vkPath: verificationKeyPath }; @@ -510,7 +730,7 @@ export async function writeProofAsFields( try { const args = ['-p', `${proofPath}/${proofFileName}`, '-k', vkFilePath, '-v']; const timer = new Timer(); - const result = await executeBB(pathToBB, 'proof_as_fields', args, log); + const result = await executeBB(pathToBB, 'proof_as_fields_honk', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, durationMs: duration, proofPath: proofPath }; diff --git a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts similarity index 66% rename from yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts rename to yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 31686b6f2a6..e15f4e99507 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -1,9 +1,12 @@ -import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; -import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { - AGGREGATION_OBJECT_LENGTH, + type AppCircuitSimulateOutput, + type PrivateKernelProver, + type PrivateKernelSimulateOutput, +} from '@aztec/circuit-types'; +import { type CircuitSimulationStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; +import { + ClientIvcProof, Fr, - NESTED_RECURSIVE_PROOF_LENGTH, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -12,7 +15,6 @@ import { type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, Proof, - RECURSIVE_PROOF_LENGTH, RecursiveProof, type VerificationKeyAsFields, type VerificationKeyData, @@ -40,20 +42,29 @@ import { import { WASMSimulator } from '@aztec/simulator'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; +import { encode } from '@msgpack/msgpack'; import { serializeWitness } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; import * as fs from 'fs/promises'; -import { join } from 'path'; +import path from 'path'; -import { BB_RESULT, PROOF_FIELDS_FILENAME, PROOF_FILENAME, generateProof, verifyProof } from '../bb/execute.js'; +import { + BB_RESULT, + PROOF_FIELDS_FILENAME, + PROOF_FILENAME, + computeVerificationKey, + executeBbClientIvcProof, + verifyProof, +} from '../bb/execute.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; import { extractVkData } from '../verification_key/verification_key_data.js'; /** * This proof creator implementation uses the native bb binary. * This is a temporary implementation until we make the WASM version work. + * TODO(#7368): this class grew 'organically' aka it could use a look at its resposibilities */ -export class BBNativeProofCreator implements ProofCreator { +export class BBNativePrivateKernelProver implements PrivateKernelProver { private simulator = new WASMSimulator(); private verificationKeys: Map> = new Map< @@ -67,16 +78,59 @@ export class BBNativeProofCreator implements ProofCreator { private log = createDebugLogger('aztec:bb-native-prover'), ) {} + private async _createClientIvcProof( + directory: string, + acirs: Buffer[], + witnessStack: WitnessMap[], + ): Promise { + // TODO(#7371): Longer term we won't use this hacked together msgpack format + // and instead properly create the bincode serialization from rust + await fs.writeFile(path.join(directory, 'acir.msgpack'), encode(acirs)); + await fs.writeFile( + path.join(directory, 'witnesses.msgpack'), + encode(witnessStack.map(map => serializeWitness(map))), + ); + const provingResult = await executeBbClientIvcProof( + this.bbBinaryPath, + directory, + path.join(directory, 'acir.msgpack'), + path.join(directory, 'witnesses.msgpack'), + this.log.info, + ); + + if (provingResult.status === BB_RESULT.FAILURE) { + this.log.error(`Failed to generate client ivc proof`); + throw new Error(provingResult.reason); + } + + const proof = await ClientIvcProof.readFromOutputDirectory(directory); + + this.log.info(`Generated IVC proof`, { + duration: provingResult.durationMs, + eventName: 'circuit-proving', + }); + + return proof; + } + + async createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise { + this.log.info(`Generating Client IVC proof`); + const operation = async (directory: string) => { + return await this._createClientIvcProof(directory, acirs, witnessStack); + }; + return await runInDirectory(this.bbWorkingDirectory, operation); + } + public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } - public async createProofInit( + public async simulateProofInit( inputs: PrivateKernelInitCircuitPrivateInputs, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, 'PrivateKernelInitArtifact', convertPrivateKernelInitInputsToWitnessMap, @@ -84,10 +138,10 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofInner( + public async simulateProofInner( inputs: PrivateKernelInnerCircuitPrivateInputs, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, 'PrivateKernelInnerArtifact', convertPrivateKernelInnerInputsToWitnessMap, @@ -95,10 +149,10 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofReset( + public async simulateProofReset( inputs: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, PrivateResetTagToArtifactName[inputs.sizeTag], convertPrivateKernelResetInputsToWitnessMap, @@ -106,18 +160,18 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofTail( + public async simulateProofTail( inputs: PrivateKernelTailCircuitPrivateInputs, - ): Promise> { + ): Promise> { if (!inputs.isForPublic()) { - return await this.createSafeProof( + return await this.simulate( inputs, 'PrivateKernelTailArtifact', convertPrivateKernelTailInputsToWitnessMap, convertPrivateKernelTailOutputsFromWitnessMap, ); } - return await this.createSafeProof( + return await this.simulate( inputs, 'PrivateKernelTailToPublicArtifact', convertPrivateKernelTailToPublicInputsToWitnessMap, @@ -125,23 +179,13 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createAppCircuitProof( - partialWitness: WitnessMap, + public async computeAppCircuitVerificationKey( bytecode: Buffer, appCircuitName?: string, - ): Promise { + ): Promise { const operation = async (directory: string) => { this.log.debug(`Proving app circuit`); - const proofOutput = await this.createProof(directory, partialWitness, bytecode, 'App', appCircuitName); - if (proofOutput.proof.proof.length != RECURSIVE_PROOF_LENGTH) { - throw new Error(`Incorrect proof length`); - } - const proof = proofOutput.proof as RecursiveProof; - const output: AppCircuitProofOutput = { - proof, - verificationKey: proofOutput.verificationKey, - }; - return output; + return await this.computeVerificationKey(directory, bytecode, 'App', appCircuitName); }; return await runInDirectory(this.bbWorkingDirectory, operation); @@ -192,7 +236,7 @@ export class BBNativeProofCreator implements ProofCreator { * @param filePath - The directory containing the verification key data files * @param circuitType - The type of circuit to which the verification key corresponds */ - private async updateVerificationKeyAfterProof(filePath: string, circuitType: ClientProtocolArtifact) { + private async updateVerificationKeyAfterSimulation(filePath: string, circuitType: ClientProtocolArtifact) { let promise = this.verificationKeys.get(circuitType); if (!promise) { promise = extractVkData(filePath); @@ -202,28 +246,12 @@ export class BBNativeProofCreator implements ProofCreator { return await promise; } - private async createSafeProof Buffer }, O extends { toBuffer: () => Buffer }>( - inputs: I, - circuitType: ClientProtocolArtifact, - convertInputs: (inputs: I) => WitnessMap, - convertOutputs: (outputs: WitnessMap) => O, - ): Promise> { - const operation = async (directory: string) => { - return await this.generateWitnessAndCreateProof(inputs, circuitType, directory, convertInputs, convertOutputs); - }; - return await runInDirectory(this.bbWorkingDirectory, operation); - } - - private async generateWitnessAndCreateProof< - I extends { toBuffer: () => Buffer }, - O extends { toBuffer: () => Buffer }, - >( + private async simulate Buffer }, O extends { toBuffer: () => Buffer }>( inputs: I, circuitType: ClientProtocolArtifact, - directory: string, convertInputs: (inputs: I) => WitnessMap, convertOutputs: (outputs: WitnessMap) => O, - ): Promise> { + ): Promise> { this.log.debug(`Generating witness for ${circuitType}`); const compiledCircuit: NoirCompiledCircuit = ClientCircuitArtifacts[circuitType]; @@ -240,99 +268,69 @@ export class BBNativeProofCreator implements ProofCreator { outputSize: output.toBuffer().length, } satisfies CircuitWitnessGenerationStats); - const proofOutput = await this.createProof( - directory, - outputWitness, - Buffer.from(compiledCircuit.bytecode, 'base64'), - circuitType, + // TODO(#7410) we dont need to generate vk's for these circuits, they are in the vk tree + const { verificationKey } = await runInDirectory(this.bbWorkingDirectory, dir => + this.computeVerificationKey(dir, Buffer.from(compiledCircuit.bytecode, 'base64'), circuitType), ); - if (proofOutput.proof.proof.length != NESTED_RECURSIVE_PROOF_LENGTH) { - throw new Error(`Incorrect proof length`); - } - const nestedProof = proofOutput.proof as RecursiveProof; - - const kernelOutput: KernelProofOutput = { + const kernelOutput: PrivateKernelSimulateOutput = { publicInputs: output, - proof: nestedProof, - verificationKey: proofOutput.verificationKey, + verificationKey, + outputWitness, }; return kernelOutput; } - private async createProof( + private async computeVerificationKey( directory: string, - partialWitness: WitnessMap, bytecode: Buffer, circuitType: ClientProtocolArtifact | 'App', appCircuitName?: string, ): Promise<{ - proof: RecursiveProof | RecursiveProof; verificationKey: VerificationKeyAsFields; }> { - const compressedBincodedWitness = serializeWitness(partialWitness); - - const inputsWitnessFile = join(directory, 'witness.gz'); - - await fs.writeFile(inputsWitnessFile, compressedBincodedWitness); - - this.log.debug(`Written ${inputsWitnessFile}`); - const dbgCircuitName = appCircuitName ? `(${appCircuitName})` : ''; - this.log.info(`Proving ${circuitType}${dbgCircuitName} circuit...`); + this.log.info(`Computing VK of ${circuitType}${dbgCircuitName} circuit...`); const timer = new Timer(); - const provingResult = await generateProof( - this.bbBinaryPath, - directory, - circuitType, - bytecode, - inputsWitnessFile, - this.log.debug, - ); + const vkResult = await computeVerificationKey(this.bbBinaryPath, directory, circuitType, bytecode, this.log.debug); - if (provingResult.status === BB_RESULT.FAILURE) { - this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${provingResult.reason}`); - throw new Error(provingResult.reason); + if (vkResult.status === BB_RESULT.FAILURE) { + this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${vkResult.reason}`); + throw new Error(vkResult.reason); } - this.log.info(`Generated ${circuitType}${dbgCircuitName} circuit proof in ${Math.ceil(timer.ms())} ms`); + this.log.info(`Generated ${circuitType}${dbgCircuitName} VK in ${Math.ceil(timer.ms())} ms`); if (circuitType === 'App') { const vkData = await extractVkData(directory); - const proof = await this.readProofAsFields(directory, circuitType, vkData); - this.log.debug(`Generated proof`, { - eventName: 'circuit-proving', + this.log.debug(`Computed verification key`, { circuitName: 'app-circuit', - duration: provingResult.durationMs, - inputSize: compressedBincodedWitness.length, - proofSize: proof.binaryProof.buffer.length, - appCircuitName, + duration: vkResult.durationMs, + eventName: 'circuit-simulation', + inputSize: bytecode.length, + outputSize: vkData.keyAsBytes.length, circuitSize: vkData.circuitSize, numPublicInputs: vkData.numPublicInputs, - } as CircuitProvingStats); + } as CircuitSimulationStats); - return { proof, verificationKey: vkData.keyAsFields }; + return { verificationKey: vkData.keyAsFields }; } - const vkData = await this.updateVerificationKeyAfterProof(directory, circuitType); - - const proof = await this.readProofAsFields(directory, circuitType, vkData); + const vkData = await this.updateVerificationKeyAfterSimulation(directory, circuitType); - await this.verifyProofForProtocolCircuit(circuitType, proof.binaryProof); - - this.log.debug(`Generated proof`, { + this.log.debug(`Computed verification key`, { circuitName: mapProtocolArtifactNameToCircuitName(circuitType), - duration: provingResult.durationMs, - eventName: 'circuit-proving', - inputSize: compressedBincodedWitness.length, - proofSize: proof.binaryProof.buffer.length, + duration: vkResult.durationMs, + eventName: 'circuit-simulation', + inputSize: bytecode.length, + outputSize: vkData.keyAsBytes.length, circuitSize: vkData.circuitSize, numPublicInputs: vkData.numPublicInputs, - } as CircuitProvingStats); + } as CircuitSimulationStats); - return { proof, verificationKey: vkData.keyAsFields }; + return { verificationKey: vkData.keyAsFields }; } /** @@ -352,10 +350,12 @@ export class BBNativeProofCreator implements ProofCreator { ]); const json = JSON.parse(proofString); const fields = json.map(Fr.fromString); - const numPublicInputs = - circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const numPublicInputs = vkData.numPublicInputs; + // const numPublicInputs = + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; const fieldsWithoutPublicInputs = fields.slice(numPublicInputs); - this.log.debug( + this.log.info( `Circuit type: ${circuitType}, complete proof length: ${fields.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, ); const proof = new RecursiveProof( diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 419469cf2f6..625c8a59fc9 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -9,7 +9,6 @@ import { } from '@aztec/circuit-types'; import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { - AGGREGATION_OBJECT_LENGTH, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, @@ -30,6 +29,8 @@ import { type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + TUBE_PROOF_LENGTH, + TubeInputs, type VerificationKeyAsFields, type VerificationKeyData, makeRecursiveProofFromBinary, @@ -62,6 +63,7 @@ import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-cl import { abiEncode } from '@noir-lang/noirc_abi'; import { type Abi, type WitnessMap } from '@noir-lang/types'; +import crypto from 'crypto'; import * as fs from 'fs/promises'; import * as path from 'path'; @@ -75,6 +77,7 @@ import { generateAvmProof, generateKeyForNoirCircuit, generateProof, + generateTubeProof, verifyAvmProof, verifyProof, writeProofAsFields, @@ -222,6 +225,16 @@ export class BBNativeRollupProver implements ServerCircuitProver { kernelRequest.inputs.previousKernel.vk, ); + // PUBLIC KERNEL: kernel request should be nonempty at start of public kernel proving but it is not + // TODO(#7369): We should properly enqueue the tube in the public kernel lifetime + if (!kernelRequest.inputs.previousKernel.clientIvcProof.isEmpty()) { + const { tubeVK, tubeProof } = await this.getTubeProof( + new TubeInputs(kernelRequest.inputs.previousKernel.clientIvcProof), + ); + kernelRequest.inputs.previousKernel.vk = tubeVK; + kernelRequest.inputs.previousKernel.proof = tubeProof; + } + await this.verifyWithKey( kernelRequest.inputs.previousKernel.vk, kernelRequest.inputs.previousKernel.proof.binaryProof, @@ -267,23 +280,27 @@ export class BBNativeRollupProver implements ServerCircuitProver { /** * Simulates the base rollup circuit from its inputs. - * @param input - Inputs to the circuit. + * @param baseRollupInput - Inputs to the circuit. * @returns The public inputs as outputs of the simulation. */ public async getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, // TODO: remove tail proof from here ): Promise> { // We may need to convert the recursive proof into fields format - input.kernelData.proof = await this.ensureValidProof( - input.kernelData.proof, + logger.debug(`kernel Data proof: ${baseRollupInput.kernelData.proof}`); + logger.info(`in getBaseRollupProof`); + logger.info(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`); + logger.info(`Number of public inputs ${baseRollupInput.kernelData.publicInputs}`); + baseRollupInput.kernelData.proof = await this.ensureValidProof( + baseRollupInput.kernelData.proof, 'BaseRollupArtifact', - input.kernelData.vk, + baseRollupInput.kernelData.vk, ); const { circuitOutput, proof } = await this.createRecursiveProof( - input, + baseRollupInput, // BaseRollupInputs 'BaseRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_PROOF_LENGTH, // WORKTODO: this should be BASE_ROLLUP_PROOF_LENGTH or something like this convertBaseRollupInputsToWitnessMap, convertBaseRollupOutputsFromWitnessMap, ); @@ -356,6 +373,20 @@ export class BBNativeRollupProver implements ServerCircuitProver { return emptyPrivateKernelProof; } + public async getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + ): Promise> { + const emptyNested = await this.getEmptyNestedProof(); + const emptyPrivateKernelProof = await this.getEmptyTubeProofFromEmptyNested( + PrivateKernelEmptyInputs.from({ + ...inputs, + emptyNested, + }), + ); + + return emptyPrivateKernelProof; + } + private async getEmptyNestedProof(): Promise { const inputs = new EmptyNestedCircuitInputs(); const { proof } = await this.createRecursiveProof( @@ -368,11 +399,15 @@ export class BBNativeRollupProver implements ServerCircuitProver { const verificationKey = await this.getVerificationKeyDataForCircuit('EmptyNestedArtifact'); await this.verifyProof('EmptyNestedArtifact', proof.binaryProof); + // logger.debug(`EmptyNestedData proof size: ${proof.proof.length}`); + // logger.debug(`EmptyNestedData proof: ${proof.proof}`); + // logger.debug(`EmptyNestedData vk size: ${verificationKey.keyAsFields.key.length}`); + // logger.debug(`EmptyNestedData vk: ${verificationKey.keyAsFields.key}`); return new EmptyNestedData(proof, verificationKey.keyAsFields); } - private async getEmptyPrivateKernelProofFromEmptyNested( + private async getEmptyTubeProofFromEmptyNested( inputs: PrivateKernelEmptyInputs, ): Promise> { const { circuitOutput, proof } = await this.createRecursiveProof( @@ -382,7 +417,24 @@ export class BBNativeRollupProver implements ServerCircuitProver { convertPrivateKernelEmptyInputsToWitnessMap, convertPrivateKernelEmptyOutputsFromWitnessMap, ); + // info(`proof: ${proof.proof}`); + const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact'); + await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof); + return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); + } + + private async getEmptyPrivateKernelProofFromEmptyNested( + inputs: PrivateKernelEmptyInputs, + ): Promise> { + const { circuitOutput, proof } = await this.createRecursiveProof( + inputs, + 'PrivateKernelEmptyArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertPrivateKernelEmptyInputsToWitnessMap, + convertPrivateKernelEmptyOutputsFromWitnessMap, + ); + //info(`proof: ${proof.proof}`); const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact'); await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof); @@ -513,6 +565,22 @@ export class BBNativeRollupProver implements ServerCircuitProver { return provingResult; } + private async generateTubeProofWithBB(bbWorkingDirectory: string, input: TubeInputs): Promise { + logger.debug(`Proving tube...`); + + const hasher = crypto.createHash('sha256'); + hasher.update(input.toBuffer()); + + await input.clientIVCData.writeToOutputDirectory(bbWorkingDirectory); + const provingResult = await generateTubeProof(this.config.bbBinaryPath, bbWorkingDirectory, logger.verbose); + + if (provingResult.status === BB_RESULT.FAILURE) { + logger.error(`Failed to generate proof for tube proof: ${provingResult.reason}`); + throw new Error(provingResult.reason); + } + return provingResult; + } + private async createAvmProof(input: AvmCircuitInputs): Promise { const cleanupDir: boolean = !process.env.AVM_PROVING_PRESERVE_WORKING_DIR; const operation = async (bbWorkingDirectory: string): Promise => { @@ -554,8 +622,34 @@ export class BBNativeRollupProver implements ServerCircuitProver { return await runInDirectory(this.config.bbWorkingDirectory, operation, cleanupDir); } + public async getTubeProof( + input: TubeInputs, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + // this probably is gonna need to call client ivc + const operation = async (bbWorkingDirectory: string) => { + logger.debug(`createTubeProof: ${bbWorkingDirectory}`); + const provingResult = await this.generateTubeProofWithBB(bbWorkingDirectory, input); + + // Read the proof as fields + const tubeVK = await extractVkData(provingResult.vkPath!); + const tubeProof = await this.readTubeProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH); + // Sanity check the tube proof (can be removed later) + await this.verifyWithKey(tubeVK, tubeProof.binaryProof); + + // TODO(#7369): properly time tube construction + logger.info( + `Generated proof for tubeCircuit in ${Math.ceil(provingResult.durationMs)} ms, size: ${ + tubeProof.proof.length + } fields`, + ); + + return { tubeVK, tubeProof }; + }; + return await runInDirectory(this.config.bbWorkingDirectory, operation); + } + /** - * Executes a circuit and returns it's outputs and corresponding proof with embedded aggregation object + * Executes a circuit and returns its outputs and corresponding proof with embedded aggregation object * @param witnessMap - The input witness * @param circuitType - The type of circuit to be executed * @param proofLength - The length of the proof to be generated. This is a dummy parameter to aid in type checking @@ -574,6 +668,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { convertInput: (input: CircuitInputType) => WitnessMap, convertOutput: (outputWitness: WitnessMap) => CircuitOutputType, ): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof }> { + // this probably is gonna need to call client ivc const operation = async (bbWorkingDirectory: string) => { const { provingResult, @@ -619,6 +714,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) { const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType); + // info(`vkey in: ${verificationKey.keyAsFields.key}`); return await this.verifyWithKey(verificationKey, proof); } @@ -691,7 +787,8 @@ export class BBNativeRollupProver implements ServerCircuitProver { } const operation = async (bbWorkingDirectory: string) => { - const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + // const numPublicInputs = vk.numPublicInputs; + const numPublicInputs = vk.numPublicInputs; // - AGGREGATION_OBJECT_LENGTH; const proofFullFilename = path.join(bbWorkingDirectory, PROOF_FILENAME); const vkFullFilename = path.join(bbWorkingDirectory, VK_FILENAME); @@ -723,7 +820,10 @@ export class BBNativeRollupProver implements ServerCircuitProver { encoding: 'utf-8', }); const json = JSON.parse(proofString); - const fields = json.slice(numPublicInputs).map(Fr.fromString); + const fields = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); return new RecursiveProof( fields, new Proof(proof.binaryProof.buffer, vk.numPublicInputs), @@ -800,13 +900,21 @@ export class BBNativeRollupProver implements ServerCircuitProver { if (!vkData) { throw new Error(`Invalid verification key for ${circuitType}`); } - const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType) - ? vkData.numPublicInputs - : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; - const fieldsWithoutPublicInputs = json.slice(numPublicInputs).map(Fr.fromString); + const numPublicInputs = vkData.numPublicInputs; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType) + // ? vkData.numPublicInputs + // : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const fieldsWithoutPublicInputs = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); logger.debug( - `Circuit type: ${circuitType}, complete proof length: ${json.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, + `num pub inputs ${vkData.numPublicInputs} and without aggregation ${CIRCUITS_WITHOUT_AGGREGATION.has( + circuitType, + )}`, ); + const proof = new RecursiveProof( fieldsWithoutPublicInputs, new Proof(binaryProof, numPublicInputs), @@ -818,4 +926,46 @@ export class BBNativeRollupProver implements ServerCircuitProver { return proof; } + + /** + * Parses and returns a tube proof stored in the specified directory. TODO merge wih above + * @param filePath - The directory containing the proof data + * @param circuitType - The type of circuit proven + * @returns The proof + * TODO(#7369) This is entirely redundant now with the above method, deduplicate + */ + private async readTubeProofAsFields( + filePath: string, + vkData: VerificationKeyData, + proofLength: PROOF_LENGTH, + ): Promise> { + const proofFilename = path.join(filePath, PROOF_FILENAME); + const proofFieldsFilename = path.join(filePath, PROOF_FIELDS_FILENAME); + + const [binaryProof, proofString] = await Promise.all([ + fs.readFile(proofFilename), + fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }), + ]); + + const json = JSON.parse(proofString); + + const numPublicInputs = vkData.numPublicInputs; + if (numPublicInputs === 0) { + throw new Error(`Tube proof should have public inputs (e.g. the number of public inputs from PrivateKernelTail)`); + } + + const proofFields = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); + logger.debug( + `Circuit type: tube circuit, complete proof length: ${json.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, + ); + const proof = new RecursiveProof(proofFields, new Proof(binaryProof, numPublicInputs), true); + if (proof.proof.length !== proofLength) { + throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`); + } + + return proof; + } } diff --git a/yarn-project/bb-prover/src/prover/index.ts b/yarn-project/bb-prover/src/prover/index.ts index e3f2298b127..61453485089 100644 --- a/yarn-project/bb-prover/src/prover/index.ts +++ b/yarn-project/bb-prover/src/prover/index.ts @@ -1,2 +1,2 @@ export * from './bb_prover.js'; -export * from './bb_native_proof_creator.js'; +export * from './bb_private_kernel_prover.js'; diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index be9c0be794c..814bdd2e911 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -20,10 +20,13 @@ import { type Proof, type PublicKernelCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, + type RecursiveProof, RootParityInput, type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + TUBE_PROOF_LENGTH, + type TubeInputs, VerificationKeyData, makeEmptyProof, makeEmptyRecursiveProof, @@ -41,6 +44,7 @@ import { convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, convertPrivateKernelEmptyInputsToWitnessMap, + convertPrivateKernelEmptyOutputsFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -107,6 +111,34 @@ export class TestCircuitProver implements ServerCircuitProver { ); } + public async getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + ): Promise> { + const emptyNested = new EmptyNestedData( + makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + ProtocolCircuitVks['EmptyNestedArtifact'].keyAsFields, + ); + const kernelInputs = new PrivateKernelEmptyInputs( + emptyNested, + inputs.header, + inputs.chainId, + inputs.version, + inputs.vkTreeRoot, + ); + const witnessMap = convertPrivateKernelEmptyInputsToWitnessMap(kernelInputs); + const witness = await this.wasmSimulator.simulateCircuit( + witnessMap, + SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact, + ); + const result = convertPrivateKernelEmptyOutputsFromWitnessMap(witness); + + return makePublicInputsAndRecursiveProof( + result, + makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + VerificationKeyData.makeFake(), + ); + } + /** * Simulates the base parity circuit from its inputs. * @param inputs - Inputs to the circuit. @@ -217,6 +249,16 @@ export class TestCircuitProver implements ServerCircuitProver { ProtocolCircuitVks['BaseRollupArtifact'], ); } + + public getTubeProof( + _tubeInput: TubeInputs, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + return Promise.resolve({ + tubeVK: VerificationKeyData.makeFake(), + tubeProof: makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), + }); + } + /** * Simulates the merge rollup circuit from its inputs. * @param input - Inputs to the circuit. diff --git a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts index 8f773859052..b2fe18cc5e1 100644 --- a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts +++ b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts @@ -25,11 +25,7 @@ export async function extractVkData(vkDirectoryPath: string): Promise, - vkHash, - ); + const vkAsFields = new VerificationKeyAsFields(fields as Tuple, vkHash); const vk = new VerificationKeyData(vkAsFields, rawBinary); return vk; } diff --git a/yarn-project/bb-prover/src/verifier/bb_verifier.ts b/yarn-project/bb-prover/src/verifier/bb_verifier.ts index 0c34e7bccec..3c13a699948 100644 --- a/yarn-project/bb-prover/src/verifier/bb_verifier.ts +++ b/yarn-project/bb-prover/src/verifier/bb_verifier.ts @@ -128,18 +128,19 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { return fs.readFile(result.contractPath!, 'utf-8'); } - async verifyProof(tx: Tx): Promise { - const { proof, data } = tx; - const expectedCircuit: ClientProtocolArtifact = data.forPublic + verifyProof(tx: Tx): Promise { + const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact'; try { - await this.verifyProofForCircuit(expectedCircuit, proof); - return true; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a proper verify flow for clientIvcProof + // For now we handle only the trivial blank data case + // await this.verifyProofForCircuit(expectedCircuit, proof); + return Promise.resolve(!tx.clientIvcProof.isEmpty()); } catch (err) { this.logger.warn(`Failed to verify ${expectedCircuit} proof for tx ${Tx.getHash(tx)}: ${String(err)}`); - return false; + return Promise.resolve(false); } } } diff --git a/yarn-project/circuit-types/src/interfaces/index.ts b/yarn-project/circuit-types/src/interfaces/index.ts index 33a88a846c5..34c08cca316 100644 --- a/yarn-project/circuit-types/src/interfaces/index.ts +++ b/yarn-project/circuit-types/src/interfaces/index.ts @@ -8,4 +8,4 @@ export * from './prover-client.js'; export * from './proving-job.js'; export * from './block-prover.js'; export * from './server_circuit_prover.js'; -export * from './proof_creator.js'; +export * from './private_kernel_prover.js'; diff --git a/yarn-project/circuit-types/src/interfaces/proof_creator.ts b/yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts similarity index 73% rename from yarn-project/circuit-types/src/interfaces/proof_creator.ts rename to yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts index 82c57b993c2..282984690d7 100644 --- a/yarn-project/circuit-types/src/interfaces/proof_creator.ts +++ b/yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts @@ -1,5 +1,5 @@ import { - type NESTED_RECURSIVE_PROOF_LENGTH, + type ClientIvcProof, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -7,8 +7,6 @@ import { type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - type RECURSIVE_PROOF_LENGTH, - type RecursiveProof, type VerificationKeyAsFields, } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; @@ -19,37 +17,31 @@ import { type WitnessMap } from '@noir-lang/acvm_js'; * Represents the output of the proof creation process for init and inner private kernel circuit. * Contains the public inputs required for the init and inner private kernel circuit and the generated proof. */ -export type KernelProofOutput = { +export type PrivateKernelSimulateOutput = { /** * The public inputs required for the proof generation process. */ publicInputs: PublicInputsType; - /** - * The zk-SNARK proof for the kernel execution. - */ - proof: RecursiveProof; + + clientIvcProof?: ClientIvcProof; verificationKey: VerificationKeyAsFields; + + outputWitness: WitnessMap; }; /** - * Represents the output of the proof creation process for init and inner private kernel circuit. - * Contains the public inputs required for the init and inner private kernel circuit and the generated proof. + * Represents the output of the circuit simulation process for init and inner private kernel circuit. */ -export type AppCircuitProofOutput = { - /** - * The zk-SNARK proof for the kernel execution. - */ - proof: RecursiveProof; - +export type AppCircuitSimulateOutput = { verificationKey: VerificationKeyAsFields; }; /** - * ProofCreator provides functionality to create and validate proofs, and retrieve + * PrivateKernelProver provides functionality to simulate and validate circuits, and retrieve * siloed commitments necessary for maintaining transaction privacy and security on the network. */ -export interface ProofCreator { +export interface PrivateKernelProver { /** * Computes the siloed commitments for a given set of public inputs. * @@ -64,9 +56,9 @@ export interface ProofCreator { * @param privateKernelInputsInit - The private data structure for the initial iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofInit( + simulateProofInit( privateKernelInputsInit: PrivateKernelInitCircuitPrivateInputs, - ): Promise>; + ): Promise>; /** * Creates a proof output for a given previous kernel data and private call data for an inner iteration. @@ -74,9 +66,9 @@ export interface ProofCreator { * @param privateKernelInputsInner - The private input data structure for the inner iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofInner( + simulateProofInner( privateKernelInputsInner: PrivateKernelInnerCircuitPrivateInputs, - ): Promise>; + ): Promise>; /** * Creates a proof output by resetting the arrays using the reset circuit. @@ -84,9 +76,9 @@ export interface ProofCreator { * @param privateKernelInputsTail - The private input data structure for the reset circuit. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofReset( + simulateProofReset( privateKernelInputsReset: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise>; + ): Promise>; /** * Creates a proof output based on the last inner kernel iteration kernel data for the final ordering iteration. @@ -94,9 +86,16 @@ export interface ProofCreator { * @param privateKernelInputsTail - The private input data structure for the final ordering iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofTail( + simulateProofTail( privateKernelInputsTail: PrivateKernelTailCircuitPrivateInputs, - ): Promise>; + ): Promise>; + + /** + * Based of a program stack, create a folding proof. + * @param acirs The program bytecode. + * @param witnessStack The witnessses for each program bytecode. + */ + createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise; /** * Creates a proof for an app circuit. @@ -106,9 +105,5 @@ export interface ProofCreator { * @param appCircuitName - Optionally specify the name of the app circuit * @returns A Promise resolving to a Proof object */ - createAppCircuitProof( - partialWitness: WitnessMap, - bytecode: Buffer, - appCircuitName?: string, - ): Promise; + computeAppCircuitVerificationKey(bytecode: Buffer, appCircuitName?: string): Promise; } diff --git a/yarn-project/circuit-types/src/interfaces/proving-job.ts b/yarn-project/circuit-types/src/interfaces/proving-job.ts index e68eff265ac..bed8fdf7831 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job.ts @@ -15,6 +15,8 @@ import { type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + type TUBE_PROOF_LENGTH, + type TubeInputs, type VerificationKeyData, } from '@aztec/circuits.js'; @@ -31,6 +33,12 @@ export type PublicInputsAndRecursiveProof = { verificationKey: VerificationKeyData; }; +export type PublicInputsAndTubeProof = { + inputs: T; + proof: RecursiveProof; + verificationKey: VerificationKeyData; +}; + export function makePublicInputsAndRecursiveProof( inputs: T, proof: RecursiveProof, @@ -62,6 +70,8 @@ export enum ProvingRequestType { BASE_PARITY, ROOT_PARITY, + // Recursive Client IVC verification to connect private -> public or rollup + TUBE_PROOF, } export type ProvingRequest = @@ -102,6 +112,10 @@ export type ProvingRequest = | { type: ProvingRequestType.PRIVATE_KERNEL_EMPTY; inputs: PrivateKernelEmptyInputData; + } + | { + type: ProvingRequestType.TUBE_PROOF; + inputs: TubeInputs; }; export type ProvingRequestPublicInputs = { @@ -117,6 +131,8 @@ export type ProvingRequestPublicInputs = { [ProvingRequestType.BASE_PARITY]: RootParityInput; [ProvingRequestType.ROOT_PARITY]: RootParityInput; + // TODO(#7369) properly structure tube proof flow + [ProvingRequestType.TUBE_PROOF]: { tubeVK: VerificationKeyData; tubeProof: RecursiveProof<393> }; }; export type ProvingRequestResult = ProvingRequestPublicInputs[T]; diff --git a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts index 0bf3e3a7932..69c096cca47 100644 --- a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts @@ -1,6 +1,7 @@ import { type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, + type PublicInputsAndTubeProof, type PublicKernelNonTailRequest, type PublicKernelTailRequest, type Tx, @@ -16,10 +17,13 @@ import { type PrivateKernelEmptyInputData, type PublicKernelCircuitPublicInputs, type RECURSIVE_PROOF_LENGTH, + type RecursiveProof, type RootParityInput, type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + type TubeInputs, + type VerificationKeyData, } from '@aztec/circuits.js'; /** @@ -49,10 +53,19 @@ export interface ServerCircuitProver { * @param input - Input to the circuit. */ getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, signal?: AbortSignal, ): Promise>; + /** + * Get a recursively verified client IVC proof (making it a compatible honk proof for the rest of the rollup). + * @param input - Input to the circuit. + */ + getTubeProof( + tubeInput: TubeInputs, + signal?: AbortSignal, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }>; + /** * Creates a proof for the given input. * @param input - Input to the circuit. @@ -94,6 +107,11 @@ export interface ServerCircuitProver { signal?: AbortSignal, ): Promise>; + getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + signal?: AbortSignal, + ): Promise>; + /** * Create a proof for the AVM circuit. * @param inputs - Inputs to the AVM circuit. diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 48f60ba5567..5059012ffb5 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -1,6 +1,7 @@ import { AztecAddress, CallRequest, + ClientIvcProof, GasSettings, LogHash, MAX_NULLIFIERS_PER_TX, @@ -12,7 +13,6 @@ import { PublicCallRequest, computeContractClassId, getContractClassFromArtifact, - makeEmptyProof, } from '@aztec/circuits.js'; import { makeCombinedAccumulatedData, @@ -162,7 +162,7 @@ export const mockTx = ( const tx = new Tx( data, - makeEmptyProof(), + ClientIvcProof.empty(), noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index edf5228603c..2f89ec1434b 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -3,6 +3,7 @@ import { EncryptedTxL2Logs, PublicDataWrite, type PublicInputsAndRecursiveProof, + type PublicInputsAndTubeProof, type SimulationError, type Tx, TxEffect, @@ -11,20 +12,20 @@ import { } from '@aztec/circuit-types'; import { type AvmExecutionHints, + ClientIvcProof, Fr, type Gas, type GasFees, type Header, KernelCircuitPublicInputs, type NESTED_RECURSIVE_PROOF_LENGTH, - type Proof, type PublicDataUpdateRequest, type PublicKernelCircuitPrivateInputs, type PublicKernelCircuitPublicInputs, type PublicKernelTailCircuitPrivateInputs, type RecursiveProof, + type TUBE_PROOF_LENGTH, type VerificationKeyData, - makeEmptyProof, } from '@aztec/circuits.js'; import { type CircuitName } from '../stats/stats.js'; @@ -69,7 +70,7 @@ export type PublicProvingRequest = AvmProvingRequest | PublicKernelRequest; * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. */ -export type ProcessedTx = Pick & { +export type ProcessedTx = Pick & { /** * Output of the private tail or public tail kernel circuit for this tx. */ @@ -151,7 +152,6 @@ export type FailedTx = { export function makeProcessedTx( tx: Tx, kernelOutput: KernelCircuitPublicInputs, - proof: Proof, publicProvingRequests: PublicProvingRequest[], revertReason?: SimulationError, gasUsed: ProcessedTx['gasUsed'] = {}, @@ -160,7 +160,7 @@ export function makeProcessedTx( return { hash: tx.getTxHash(), data: kernelOutput, - proof, + clientIvcProof: tx.clientIvcProof, // TODO(4712): deal with non-revertible logs here noteEncryptedLogs: tx.noteEncryptedLogs, encryptedLogs: tx.encryptedLogs, @@ -178,6 +178,11 @@ export type PaddingProcessedTx = ProcessedTx & { recursiveProof: RecursiveProof; }; +export type PaddingProcessedTxFromTube = ProcessedTx & { + verificationKey: VerificationKeyData; + recursiveProof: RecursiveProof; +}; + /** * Makes a padding empty tx with a valid proof. * @returns A valid padding processed tx. @@ -192,7 +197,32 @@ export function makePaddingProcessedTx( encryptedLogs: EncryptedTxL2Logs.empty(), unencryptedLogs: UnencryptedTxL2Logs.empty(), data: kernelOutput.inputs, - proof: kernelOutput.proof.binaryProof, + clientIvcProof: ClientIvcProof.empty(), + isEmpty: true, + revertReason: undefined, + publicProvingRequests: [], + gasUsed: {}, + finalPublicDataUpdateRequests: [], + verificationKey: kernelOutput.verificationKey, + recursiveProof: kernelOutput.proof, + }; +} + +/** + * Makes a padding empty tx with a valid proof. + * @returns A valid padding processed tx. + */ +export function makePaddingProcessedTxFromTubeProof( + kernelOutput: PublicInputsAndTubeProof, +): PaddingProcessedTxFromTube { + const hash = new TxHash(Fr.ZERO.toBuffer()); + return { + hash, + noteEncryptedLogs: EncryptedNoteTxL2Logs.empty(), + encryptedLogs: EncryptedTxL2Logs.empty(), + unencryptedLogs: UnencryptedTxL2Logs.empty(), + data: kernelOutput.inputs, + clientIvcProof: ClientIvcProof.empty(), isEmpty: true, revertReason: undefined, publicProvingRequests: [], @@ -213,7 +243,6 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr, v emptyKernelOutput.constants.txContext.chainId = chainId; emptyKernelOutput.constants.txContext.version = version; emptyKernelOutput.constants.vkTreeRoot = vkTreeRoot; - const emptyProof = makeEmptyProof(); const hash = new TxHash(Fr.ZERO.toBuffer()); return { @@ -222,7 +251,7 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr, v encryptedLogs: EncryptedTxL2Logs.empty(), unencryptedLogs: UnencryptedTxL2Logs.empty(), data: emptyKernelOutput, - proof: emptyProof, + clientIvcProof: ClientIvcProof.empty(), isEmpty: true, revertReason: undefined, publicProvingRequests: [], diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index b71e99074d5..39e0184f659 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -1,7 +1,7 @@ import { + ClientIvcProof, ContractClassRegisteredEvent, PrivateKernelTailCircuitPublicInputs, - Proof, PublicCallRequest, type PublicKernelCircuitPublicInputs, } from '@aztec/circuits.js'; @@ -25,8 +25,10 @@ export class Tx { public readonly data: PrivateKernelTailCircuitPublicInputs, /** * Proof from the private kernel circuit. + * TODO(#7368): This client IVC object currently contains various VKs that will eventually be more like static data. + * */ - public readonly proof: Proof, + public readonly clientIvcProof: ClientIvcProof, /** * Encrypted note logs generated by the tx. */ @@ -72,7 +74,7 @@ export class Tx { const reader = BufferReader.asReader(buffer); return new Tx( reader.readObject(PrivateKernelTailCircuitPublicInputs), - reader.readObject(Proof), + reader.readObject(ClientIvcProof), reader.readObject(EncryptedNoteTxL2Logs), reader.readObject(EncryptedTxL2Logs), reader.readObject(UnencryptedTxL2Logs), @@ -88,7 +90,7 @@ export class Tx { toBuffer() { return serializeToBuffer([ this.data, - this.proof, + this.clientIvcProof, this.noteEncryptedLogs, this.encryptedLogs, this.unencryptedLogs, @@ -108,7 +110,7 @@ export class Tx { noteEncryptedLogs: this.noteEncryptedLogs.toBuffer().toString('hex'), encryptedLogs: this.encryptedLogs.toBuffer().toString('hex'), unencryptedLogs: this.unencryptedLogs.toBuffer().toString('hex'), - proof: this.proof.toBuffer().toString('hex'), + clientIvcProof: this.clientIvcProof.toBuffer().toString('hex'), enqueuedPublicFunctions: this.enqueuedPublicFunctionCalls.map(f => f.toBuffer().toString('hex')) ?? [], publicTeardownFunctionCall: this.publicTeardownFunctionCall.toBuffer().toString('hex'), }; @@ -133,14 +135,14 @@ export class Tx { const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(obj.noteEncryptedLogs, 'hex')); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(obj.encryptedLogs, 'hex')); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(Buffer.from(obj.unencryptedLogs, 'hex')); - const proof = Buffer.from(obj.proof, 'hex'); + const clientIvcProof = ClientIvcProof.fromBuffer(Buffer.from(obj.clientIvcProof, 'hex')); const enqueuedPublicFunctions = obj.enqueuedPublicFunctions ? obj.enqueuedPublicFunctions.map((x: string) => PublicCallRequest.fromBuffer(Buffer.from(x, 'hex'))) : []; const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(Buffer.from(obj.publicTeardownFunctionCall, 'hex')); return new Tx( publicInputs, - Proof.fromBuffer(proof), + clientIvcProof, noteEncryptedLogs, encryptedLogs, unencryptedLogs, @@ -176,7 +178,7 @@ export class Tx { newCommitmentCount: this.data.getNonEmptyNoteHashes().length, newNullifierCount: this.data.getNonEmptyNullifiers().length, - proofSize: this.proof.buffer.length, + proofSize: this.clientIvcProof.clientIvcProofBuffer.length, size: this.toBuffer().length, feePaymentMethod: @@ -199,7 +201,7 @@ export class Tx { getSize() { return ( this.data.getSize() + - this.proof.buffer.length + + this.clientIvcProof.clientIvcProofBuffer.length + this.noteEncryptedLogs.getSerializedLength() + this.encryptedLogs.getSerializedLength() + this.unencryptedLogs.getSerializedLength() + @@ -233,7 +235,7 @@ export class Tx { */ static clone(tx: Tx): Tx { const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(tx.data.toBuffer()); - const proof = Proof.fromBuffer(tx.proof.toBuffer()); + const clientIvcProof = ClientIvcProof.fromBuffer(tx.clientIvcProof.toBuffer()); const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(tx.noteEncryptedLogs.toBuffer())); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(tx.encryptedLogs.toBuffer()); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer()); @@ -243,7 +245,7 @@ export class Tx { const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(tx.publicTeardownFunctionCall.toBuffer()); return new Tx( publicInputs, - proof, + clientIvcProof, noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 38eb09c6f9f..308495143d7 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -188,9 +188,10 @@ export const L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 256; export const LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; export const NUM_MSGS_PER_BASE_PARITY = 4; export const NUM_BASE_PARITY_PER_ROOT_PARITY = 4; -export const RECURSIVE_PROOF_LENGTH = 93; -export const NESTED_RECURSIVE_PROOF_LENGTH = 109; -export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; +export const RECURSIVE_PROOF_LENGTH = 393; +export const NESTED_RECURSIVE_PROOF_LENGTH = 393; +export const TUBE_PROOF_LENGTH = 393; +export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; export const SENDER_SELECTOR = 0; export const ADDRESS_SELECTOR = 1; export const STORAGE_ADDRESS_SELECTOR = 1; diff --git a/yarn-project/circuits.js/src/structs/client_ivc_proof.ts b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts new file mode 100644 index 00000000000..313a49b5f81 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts @@ -0,0 +1,95 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import * as fs from 'fs/promises'; +import path from 'path'; + +/** + * TODO(https://github.com/AztecProtocol/aztec-packages/issues/7370) refactory this to + * eventually we read all these VKs from the data tree instead of passing them + */ +export class ClientIvcProof { + constructor( + // produced by the sequencer when making the tube proof + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7370): Need to precompute private kernel tail VK so we can verify this immediately in the tx pool + // which parts of these are needed to quickly verify that we have a correct IVC proof + public instVkBuffer: Buffer, + public pgAccBuffer: Buffer, + public clientIvcProofBuffer: Buffer, + public translatorVkBuffer: Buffer, + public eccVkBuffer: Buffer, + ) {} + + public isEmpty() { + return this.clientIvcProofBuffer.length === 0; + } + + static empty() { + return new ClientIvcProof(Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')); + } + + /** + * TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs + * Create a ClientIvcProof from the result of client_ivc_prove_output_all or client_ivc_prove_output_all_msgpack + * @param directory the directory of results + * @returns the encapsulated client ivc proof + */ + static async readFromOutputDirectory(directory: string) { + const [instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer] = await Promise.all( + ['inst_vk', 'pg_acc', 'client_ivc_proof', 'translator_vk', 'ecc_vk'].map(fileName => + fs.readFile(path.join(directory, fileName)), + ), + ); + return new ClientIvcProof(instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer); + } + + /** + * TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs + * Serialize a ClientIvcProof to the files expected by prove_tube + * + * Example usage: + * await runInDirectory(bbWorkingDirectory, async (dir: string) => { + * await privateTx.clientIvcProof!.writeToOutputDirectory(bbWorkingDirectory); + * const result = await generateTubeProof(bbPath, dir, logger.info) + * expect(result.status).toBe(BB_RESULT.SUCCESS) + * }); + * @param proof the ClientIvcProof from readFromOutputDirectory + * @param directory the directory of results + */ + async writeToOutputDirectory(directory: string) { + const { instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer } = this; + const fileData = [ + ['inst_vk', instVkBuffer], + ['pg_acc', pgAccBuffer], + ['client_ivc_proof', clientIvcProofBuffer], + ['translator_vk', translatorVkBuffer], + ['ecc_vk', eccVkBuffer], + ] as const; + await Promise.all(fileData.map(([fileName, buffer]) => fs.writeFile(path.join(directory, fileName), buffer))); + } + + static fromBuffer(buffer: Buffer | BufferReader): ClientIvcProof { + const reader = BufferReader.asReader(buffer); + return new ClientIvcProof( + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + ); + } + + public toBuffer() { + return serializeToBuffer( + this.instVkBuffer.length, + this.instVkBuffer, + this.pgAccBuffer.length, + this.pgAccBuffer, + this.clientIvcProofBuffer.length, + this.clientIvcProofBuffer, + this.translatorVkBuffer.length, + this.translatorVkBuffer, + this.eccVkBuffer.length, + this.eccVkBuffer, + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index d90356a074a..15dff650a62 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -3,6 +3,7 @@ export * from './avm/avm.js'; export * from './call_context.js'; export * from './call_request.js'; export * from './caller_context.js'; +export * from './client_ivc_proof.js'; export * from './complete_address.js'; export * from './content_commitment.js'; export * from './context/private_context_inputs.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts index 2bcf52b7453..855ad7f8866 100644 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts @@ -2,12 +2,13 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyData } from '../verification_key.js'; import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; +// TODO: less ambiguous name export class KernelData { constructor( /** @@ -15,9 +16,9 @@ export class KernelData { */ public publicInputs: KernelCircuitPublicInputs, /** - * Proof of the previous kernel. + * The previous kernel's proof (may be a tube proof or public kernel proof). */ - public proof: RecursiveProof, + public proof: RecursiveProof, /** * Verification key of the previous kernel. */ @@ -35,7 +36,7 @@ export class KernelData { static empty(): KernelData { return new this( KernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), @@ -46,7 +47,7 @@ export class KernelData { const reader = BufferReader.asReader(buffer); return new this( reader.readObject(KernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyData), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts index c00d927fb5b..d01fefe28ab 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts @@ -2,15 +2,10 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { - FUNCTION_TREE_HEIGHT, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - RECURSIVE_PROOF_LENGTH, -} from '../../constants.gen.js'; +import { FUNCTION_TREE_HEIGHT, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { MembershipWitness } from '../membership_witness.js'; import { PrivateCallStackItem } from '../private_call_stack_item.js'; -import { RecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; /** @@ -30,10 +25,6 @@ export class PrivateCallData { * The public call request for the teardown function. */ public publicTeardownCallRequest: CallRequest, - /** - * The proof of the execution of this private call. - */ - public proof: RecursiveProof, /** * The verification key for the function being invoked. */ @@ -74,7 +65,6 @@ export class PrivateCallData { fields.callStackItem, fields.publicCallStack, fields.publicTeardownCallRequest, - fields.proof, fields.vk, fields.contractClassArtifactHash, fields.contractClassPublicBytecodeCommitment, @@ -108,7 +98,6 @@ export class PrivateCallData { reader.readObject(PrivateCallStackItem), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, CallRequest), reader.readObject(CallRequest), - RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), reader.readObject(Fr), reader.readObject(Fr), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts index bb4081c6b94..33bced5e4d5 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts @@ -2,8 +2,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; -import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; +import { VK_TREE_HEIGHT } from '../../constants.gen.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyAsFields } from '../verification_key.js'; import { PrivateKernelCircuitPublicInputs } from './private_kernel_circuit_public_inputs.js'; @@ -12,15 +11,13 @@ import { PrivateKernelCircuitPublicInputs } from './private_kernel_circuit_publi * Data of the previous kernel iteration in the chain of kernels. */ export class PrivateKernelData { + // NOTE: as of move to honk and client IVC, previous private kernels no longer come with their proof + // as we do client IVC not recursive verification. We need to ensure the public inputs here is properly constrained, TODO(https://github.com/AztecProtocol/barretenberg/issues/1048) constructor( /** * Public inputs of the previous kernel. */ public publicInputs: PrivateKernelCircuitPublicInputs, - /** - * Proof of the previous kernel. - */ - public proof: RecursiveProof, /** * Verification key of the previous kernel. */ @@ -40,14 +37,13 @@ export class PrivateKernelData { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath); + return serializeToBuffer(this.publicInputs, this.vk, this.vkIndex, this.vkPath); } static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelData { const reader = BufferReader.asReader(buffer); return new this( reader.readObject(PrivateKernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), @@ -57,7 +53,6 @@ export class PrivateKernelData { static empty(): PrivateKernelData { return new PrivateKernelData( PrivateKernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), VerificationKeyAsFields.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts index 190593832db..b55aec38f24 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts @@ -1,5 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { PublicCallData } from './public_call_data.js'; import { PublicKernelData } from './public_kernel_data.js'; @@ -12,6 +13,8 @@ export class PublicKernelCircuitPrivateInputs { * Kernels are recursive and this is the data from the previous kernel. */ public readonly previousKernel: PublicKernelData, + + public readonly clientIvcProof: ClientIvcProof, /** * Public calldata assembled from the execution result and proof. */ @@ -23,7 +26,7 @@ export class PublicKernelCircuitPrivateInputs { * @returns - Buffer representation of the object. */ toBuffer() { - return serializeToBuffer(this.previousKernel, this.publicCall); + return serializeToBuffer(this.previousKernel, this.clientIvcProof, this.publicCall); } /** @@ -42,8 +45,9 @@ export class PublicKernelCircuitPrivateInputs { static fromBuffer(buffer: BufferReader | Buffer) { const reader = BufferReader.asReader(buffer); const previousKernel = reader.readObject(PublicKernelData); + const clientIvcProof = reader.readObject(ClientIvcProof); const publicCall = reader.readObject(PublicCallData); - return new PublicKernelCircuitPrivateInputs(previousKernel, publicCall); + return new PublicKernelCircuitPrivateInputs(previousKernel, clientIvcProof, publicCall); } /** diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts index 50e2c5101dd..7a1608f9a8e 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts @@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyData } from '../verification_key.js'; @@ -33,6 +34,11 @@ export class PublicKernelData { * Sibling path of the previous kernel's vk in a tree of vks. */ public vkPath: Tuple, + + /** + * TODO(https://github.com/AztecProtocol/aztec-packages/issues/7369) this should be tube-proved for the first iteration and replace proof above + */ + public clientIvcProof: ClientIvcProof = ClientIvcProof.empty(), ) {} static fromBuffer(buffer: Buffer | BufferReader): PublicKernelData { @@ -43,6 +49,7 @@ export class PublicKernelData { reader.readObject(VerificationKeyData), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), + reader.readObject(ClientIvcProof), ); } @@ -53,6 +60,7 @@ export class PublicKernelData { VerificationKeyData.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), + ClientIvcProof.empty(), ); } @@ -61,6 +69,6 @@ export class PublicKernelData { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath); + return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath, this.clientIvcProof); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts index fbe008cc036..4e7ef406af3 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -8,6 +8,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, } from '../../constants.gen.js'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { GlobalVariables } from '../global_variables.js'; import { KernelData } from '../kernel/kernel_data.js'; import { MembershipWitness } from '../membership_witness.js'; @@ -194,3 +195,57 @@ export class BaseRollupInputs { ); } } + +export class TubeInputs { + constructor(public clientIVCData: ClientIvcProof) {} + + static from(fields: FieldsOf): TubeInputs { + return new TubeInputs(...TubeInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.clientIVCData] as const; + } + + /** + * Serializes the inputs to a buffer. + * @returns The inputs serialized to a buffer. + */ + toBuffer() { + return serializeToBuffer(...TubeInputs.getFields(this)); + } + + /** + * Serializes the inputs to a hex string. + * @returns The instance serialized to a hex string. + */ + toString() { + return this.toBuffer().toString('hex'); + } + + /** + * Deserializes the inputs from a buffer. + * @param buffer - The buffer to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromBuffer(buffer: Buffer | BufferReader): TubeInputs { + const reader = BufferReader.asReader(buffer); + return new TubeInputs(reader.readObject(ClientIvcProof)); + } + + isEmpty(): boolean { + return this.clientIVCData.isEmpty(); + } + /** + * Deserializes the inputs from a hex string. + * @param str - A hex string to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromString(str: string) { + return TubeInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + static empty() { + return new TubeInputs(ClientIvcProof.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index 4e66c1e5a82..2baffbf8039 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -74,9 +74,10 @@ export class CommitmentMap { } } -export const CIRCUIT_SIZE_INDEX = 3; -export const CIRCUIT_PUBLIC_INPUTS_INDEX = 4; -export const CIRCUIT_RECURSIVE_INDEX = 5; +// TODO: find better home for these constants +export const CIRCUIT_SIZE_INDEX = 0; +export const CIRCUIT_PUBLIC_INPUTS_INDEX = 1; +export const CIRCUIT_RECURSIVE_INDEX = 0; /** * Provides a 'fields' representation of a circuit's verification key diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 9e7154f9393..9df75d8d6ad 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -27,6 +27,7 @@ import { CallContext, CallRequest, CallerContext, + ClientIvcProof, CombineHints, CombinedAccumulatedData, CombinedConstantData, @@ -129,6 +130,7 @@ import { ScopedReadRequest, StateDiffHints, StateReference, + TUBE_PROOF_LENGTH, TxContext, TxRequest, VK_TREE_HEIGHT, @@ -608,7 +610,7 @@ export function makePublicKernelData(seed = 1, kernelPublicInputs?: PublicKernel export function makeRollupKernelData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs): KernelData { return new KernelData( kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH, seed + 0x80), + makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x80), VerificationKeyData.makeFake(), 0x42, makeTuple(VK_TREE_HEIGHT, fr, 0x1000), @@ -694,7 +696,11 @@ export function makePublicCallData(seed = 1, full = false): PublicCallData { * @returns Public kernel inputs. */ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCircuitPrivateInputs { - return new PublicKernelCircuitPrivateInputs(makePublicKernelData(seed), makePublicCallData(seed + 0x1000)); + return new PublicKernelCircuitPrivateInputs( + makePublicKernelData(seed), + ClientIvcProof.empty(), + makePublicCallData(seed + 0x1000), + ); } export function makeCombineHints(seed = 1): CombineHints { @@ -748,7 +754,7 @@ export function makePublicKernelInputsWithTweak( const kernelCircuitPublicInputs = makePublicKernelCircuitPublicInputs(seed, false); const previousKernel = makePublicKernelData(seed, kernelCircuitPublicInputs); const publicCall = makePublicCallData(seed + 0x1000); - const publicKernelInputs = new PublicKernelCircuitPrivateInputs(previousKernel, publicCall); + const publicKernelInputs = new PublicKernelCircuitPrivateInputs(previousKernel, ClientIvcProof.empty(), publicCall); if (tweak) { tweak(publicKernelInputs); } diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index fe4762ed479..c60db38d6f9 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -16,6 +16,7 @@ "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:debug": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json" }, diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index 7dde1b74f29..7a714d1a343 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -1,5 +1,5 @@ import { getSchnorrAccount, getSchnorrWallet } from '@aztec/accounts/schnorr'; -import { PublicFeePaymentMethod, TxStatus } from '@aztec/aztec.js'; +import { PublicFeePaymentMethod, TxStatus, sleep } from '@aztec/aztec.js'; import { type AccountWallet } from '@aztec/aztec.js/wallet'; import { CompleteAddress, Fq, Fr, GasSettings } from '@aztec/circuits.js'; import { FPCContract, GasTokenContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -144,6 +144,9 @@ describe('benchmarks/proving', () => { provingPxes.push(pxe); } + /*TODO(post-honk): We wait 5 seconds for a race condition in setting up 4 nodes. + What is a more robust solution? */ + await sleep(5000); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 9c0ee2dfaa4..59656c44182 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -29,7 +29,7 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PublicDataUpdateRequest, } from '@aztec/circuits.js'; -import { fr, makeProof } from '@aztec/circuits.js/testing'; +import { fr } from '@aztec/circuits.js/testing'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; import { makeTuple, range } from '@aztec/foundation/array'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -183,7 +183,7 @@ describe('L1Publisher integration', () => { seed + 0x500, ); - const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); + const processedTx = makeProcessedTx(tx, kernelOutput, []); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200); diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 3bb9d05de91..9fd48ad4607 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -11,6 +11,7 @@ import { type Wallet, computeSecretHash, retryUntil, + sleep, } from '@aztec/aztec.js'; import { ChildContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -44,6 +45,9 @@ describe('e2e_2_pxes', () => { ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode!, {}, undefined, true)); [walletB] = await createAccounts(pxeB, 1); + /*TODO(post-honk): We wait 5 seconds for a race condition in setting up two nodes. + What is a more robust solution? */ + await sleep(5000); }); afterEach(async () => { diff --git a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts index 4f65251ed01..b98823ebe95 100644 --- a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts @@ -11,18 +11,18 @@ import { type PXE, type TxHash, computeSecretHash, - createDebugLogger, - deployL1Contract, + createDebugLogger, // TODO(#7373): Deploy honk solidity verifier + // deployL1Contract, } from '@aztec/aztec.js'; import { BBCircuitVerifier } from '@aztec/bb-prover'; -import { RollupAbi } from '@aztec/l1-artifacts'; +// import { RollupAbi } from '@aztec/l1-artifacts'; import { TokenContract } from '@aztec/noir-contracts.js'; import { type PXEService } from '@aztec/pxe'; -// @ts-expect-error solc-js doesn't publish its types https://github.com/ethereum/solc-js/issues/689 -import solc from 'solc'; -import { getContract } from 'viem'; - +// TODO(#7373): Deploy honk solidity verifier +// // @ts-expect-error solc-js doesn't publish its types https://github.com/ethereum/solc-js/issues/689 +// import solc from 'solc'; +// import { getContract } from 'viem'; import { waitRegisteredAccountSynced } from '../benchmarks/utils.js'; import { getACVMConfig } from '../fixtures/get_acvm_config.js'; import { getBBConfig } from '../fixtures/get_bb_config.js'; @@ -287,56 +287,58 @@ export class FullProverTest { ); } - async deployVerifier() { + deployVerifier() { if (!this.circuitProofVerifier) { throw new Error('No verifier'); } - const { walletClient, publicClient, l1ContractAddresses } = this.context.deployL1ContractsValues; - - const contract = await this.circuitProofVerifier.generateSolidityContract( - 'RootRollupArtifact', - 'UltraVerifier.sol', - ); - - const input = { - language: 'Solidity', - sources: { - 'UltraVerifier.sol': { - content: contract, - }, - }, - settings: { - // we require the optimizer - optimizer: { - enabled: true, - runs: 200, - }, - evmVersion: 'paris', - outputSelection: { - '*': { - '*': ['evm.bytecode.object', 'abi'], - }, - }, - }, - }; - - const output = JSON.parse(solc.compile(JSON.stringify(input))); - - const abi = output.contracts['UltraVerifier.sol']['UltraVerifier'].abi; - const bytecode: string = output.contracts['UltraVerifier.sol']['UltraVerifier'].evm.bytecode.object; - - const verifierAddress = await deployL1Contract(walletClient, publicClient, abi, `0x${bytecode}`); - - this.logger.info(`Deployed Real verifier at ${verifierAddress}`); - - const rollup = getContract({ - abi: RollupAbi, - address: l1ContractAddresses.rollupAddress.toString(), - client: walletClient, - }); - - await rollup.write.setVerifier([verifierAddress.toString()]); - this.logger.info('Rollup only accepts valid proofs now'); + // TODO(#7373): Deploy honk solidity verifier + return Promise.resolve(); + // const { walletClient, publicClient, l1ContractAddresses } = this.context.deployL1ContractsValues; + + // const contract = await this.circuitProofVerifier.generateSolidityContract( + // 'RootRollupArtifact', + // 'UltraVerifier.sol', + // ); + + // const input = { + // language: 'Solidity', + // sources: { + // 'UltraVerifier.sol': { + // content: contract, + // }, + // }, + // settings: { + // // we require the optimizer + // optimizer: { + // enabled: true, + // runs: 200, + // }, + // evmVersion: 'paris', + // outputSelection: { + // '*': { + // '*': ['evm.bytecode.object', 'abi'], + // }, + // }, + // }, + // }; + + // const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // const abi = output.contracts['UltraVerifier.sol']['UltraVerifier'].abi; + // const bytecode: string = output.contracts['UltraVerifier.sol']['UltraVerifier'].evm.bytecode.object; + + // const verifierAddress = await deployL1Contract(walletClient, publicClient, abi, `0x${bytecode}`); + + // this.logger.info(`Deployed Real verifier at ${verifierAddress}`); + + // const rollup = getContract({ + // abi: RollupAbi, + // address: l1ContractAddresses.rollupAddress.toString(), + // client: walletClient, + // }); + + // await rollup.write.setVerifier([verifierAddress.toString()]); + // this.logger.info('Rollup only accepts valid proofs now'); } } diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 93d3e0bd3be..9c086c80044 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -28,7 +28,7 @@ import { } from '@aztec/aztec.js'; import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; -import { type BBNativeProofCreator } from '@aztec/bb-prover'; +import { type BBNativePrivateKernelProver } from '@aztec/bb-prover'; import { CANONICAL_AUTH_REGISTRY_ADDRESS, CANONICAL_KEY_REGISTRY_ADDRESS, @@ -161,7 +161,7 @@ export async function setupPXEService( opts: Partial = {}, logger = getLogger(), useLogSuffix = false, - proofCreator?: BBNativeProofCreator, + proofCreator?: BBNativePrivateKernelProver, ): Promise<{ /** * The PXE instance. diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 210acd1a56e..45ad64d3e7a 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -976,7 +976,6 @@ export function mapPrivateCallDataToNoir(privateCallData: PrivateCallData): Priv call_stack_item: mapPrivateCallStackItemToNoir(privateCallData.callStackItem), public_call_stack: mapTuple(privateCallData.publicCallStack, mapCallRequestToNoir), public_teardown_call_request: mapCallRequestToNoir(privateCallData.publicTeardownCallRequest), - proof: mapRecursiveProofToNoir(privateCallData.proof), vk: mapVerificationKeyToNoir(privateCallData.vk), function_leaf_membership_witness: mapMembershipWitnessToNoir(privateCallData.functionLeafMembershipWitness), contract_class_artifact_hash: mapFieldToNoir(privateCallData.contractClassArtifactHash), @@ -1552,7 +1551,6 @@ export function mapPrivateKernelCircuitPublicInputsToNoir( export function mapPrivateKernelDataToNoir(privateKernelInnerData: PrivateKernelData): PrivateKernelDataNoir { return { public_inputs: mapPrivateKernelCircuitPublicInputsToNoir(privateKernelInnerData.publicInputs), - proof: mapRecursiveProofToNoir(privateKernelInnerData.proof), vk: mapVerificationKeyToNoir(privateKernelInnerData.vk), vk_index: mapFieldToNoir(new Fr(privateKernelInnerData.vkIndex)), vk_path: mapTuple(privateKernelInnerData.vkPath, mapFieldToNoir), diff --git a/yarn-project/noir-protocol-circuits-types/src/vks.ts b/yarn-project/noir-protocol-circuits-types/src/vks.ts index 2d56ff679a9..9cd86bc3fa6 100644 --- a/yarn-project/noir-protocol-circuits-types/src/vks.ts +++ b/yarn-project/noir-protocol-circuits-types/src/vks.ts @@ -59,9 +59,10 @@ function keyJsonToVKData(json: VkJson): VerificationKeyData { return new VerificationKeyData( new VerificationKeyAsFields( assertLength( - keyAsFields.slice(1).map((str: string) => new Fr(Buffer.from(str.slice(2), 'hex'))), + keyAsFields.map((str: string) => new Fr(Buffer.from(str.slice(2), 'hex'))), VERIFICATION_KEY_LENGTH_IN_FIELDS, ), + // TODO(#7410) what should be the vk hash here? new Fr(Buffer.from(keyAsFields[0].slice(2), 'hex')), ), Buffer.from(keyAsBytes, 'hex'), @@ -157,7 +158,8 @@ export function getVKIndex(vk: VerificationKeyData | VerificationKeyAsFields | F const index = getVKTree().getIndex(hash.toBuffer()); if (index < 0) { - throw new Error(`VK index for ${hash.toString()} not found in VK tree`); + //throw new Error(`VK index for ${hash.toString()} not found in VK tree`); + return 0; // faked for now } return index; } diff --git a/yarn-project/p2p/src/service/tx_messages.test.ts b/yarn-project/p2p/src/service/tx_messages.test.ts index 108fb148416..007cfe739af 100644 --- a/yarn-project/p2p/src/service/tx_messages.test.ts +++ b/yarn-project/p2p/src/service/tx_messages.test.ts @@ -5,9 +5,9 @@ import { expect } from '@jest/globals'; import { fromTxMessage, toTxMessage } from './tx_messages.js'; const verifyTx = (actual: Tx, expected: Tx) => { - expect(actual.data!.toBuffer()).toEqual(expected.data?.toBuffer()); - expect(actual.proof!.toBuffer()).toEqual(expected.proof!.toBuffer()); - expect(actual.encryptedLogs!.toBuffer()).toEqual(expected.encryptedLogs?.toBuffer()); + expect(actual.data.toBuffer()).toEqual(expected.data.toBuffer()); + expect(actual.clientIvcProof.toBuffer()).toEqual(expected.clientIvcProof.toBuffer()); + expect(actual.encryptedLogs.toBuffer()).toEqual(expected.encryptedLogs.toBuffer()); }; describe('Messages', () => { diff --git a/yarn-project/p2p/src/service/tx_messages.ts b/yarn-project/p2p/src/service/tx_messages.ts index 53fa7442faf..cec7a59f5a4 100644 --- a/yarn-project/p2p/src/service/tx_messages.ts +++ b/yarn-project/p2p/src/service/tx_messages.ts @@ -1,5 +1,5 @@ import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, Tx, UnencryptedTxL2Logs } from '@aztec/circuit-types'; -import { PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest } from '@aztec/circuits.js'; +import { ClientIvcProof, PrivateKernelTailCircuitPublicInputs, PublicCallRequest } from '@aztec/circuits.js'; import { numToUInt32BE } from '@aztec/foundation/serialize'; import { type SemVer } from 'semver'; @@ -67,7 +67,7 @@ export function toTxMessage(tx: Tx): Buffer { }; const messageBuffer = Buffer.concat([ createMessageComponent(tx.data), - createMessageComponent(tx.proof), + createMessageComponent(tx.clientIvcProof), createMessageComponent(tx.noteEncryptedLogs), createMessageComponent(tx.encryptedLogs), createMessageComponent(tx.unencryptedLogs), @@ -113,9 +113,9 @@ export function fromTxMessage(buffer: Buffer): Tx { // this is the opposite of the 'toMessage' function // so the first 4 bytes is the complete length, skip it const publicInputs = toObject(buffer.subarray(4), PrivateKernelTailCircuitPublicInputs); - const proof = toObject(publicInputs.remainingData, Proof); + const clientIvcProof = toObject(publicInputs.remainingData, ClientIvcProof); - const noteEncryptedLogs = toObject(proof.remainingData, EncryptedNoteTxL2Logs); + const noteEncryptedLogs = toObject(clientIvcProof.remainingData, EncryptedNoteTxL2Logs); if (!noteEncryptedLogs.obj) { noteEncryptedLogs.obj = new EncryptedNoteTxL2Logs([]); } @@ -133,7 +133,7 @@ export function fromTxMessage(buffer: Buffer): Tx { const publicTeardownCall = toObject(publicCalls.remainingData, PublicCallRequest); return new Tx( publicInputs.obj!, - proof.obj!, + clientIvcProof.obj!, noteEncryptedLogs.obj, encryptedLogs.obj, unencryptedLogs.obj, diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index c10f9d42140..e960506c43f 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -21,7 +21,7 @@ import { PublicDataTreeLeaf, PublicDataUpdateRequest, } from '@aztec/circuits.js'; -import { fr, makeProof } from '@aztec/circuits.js/testing'; +import { fr } from '@aztec/circuits.js/testing'; import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; @@ -113,7 +113,7 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se seed + 0x600, ); - const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); + const processedTx = makeProcessedTx(tx, kernelOutput, []); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100000); diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index fd1c2e82746..c0aaba59c46 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -13,7 +13,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MergeRollupInputs, - NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_PROOF_LENGTH, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, @@ -30,16 +30,17 @@ import { PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, + type RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootParityInput, RootRollupInputs, type RootRollupPublicInputs, StateDiffHints, type StateReference, + type TUBE_PROOF_LENGTH, VK_TREE_HEIGHT, type VerificationKeyAsFields, type VerificationKeyData, - makeRecursiveProofFromBinary, } from '@aztec/circuits.js'; import { assertPermutation, makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -60,6 +61,7 @@ export type TreeNames = BaseTreeNames | 'L1ToL2MessageTree' | 'Archive'; // Builds the base rollup inputs, updating the contract, nullifier, and data trees in the process export async function buildBaseRollupInput( tx: ProcessedTx, + proof: RecursiveProof, globalVariables: GlobalVariables, db: MerkleTreeOperations, kernelVk: VerificationKeyData, @@ -158,7 +160,7 @@ export async function buildBaseRollupInput( ); return BaseRollupInputs.from({ - kernelData: getKernelDataFor(tx, kernelVk), + kernelData: getKernelDataFor(tx, kernelVk, proof), start, stateDiffHints, feePayerGasTokenBalanceReadHint, @@ -286,17 +288,18 @@ export async function getTreeSnapshot(id: MerkleTreeId, db: MerkleTreeOperations return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size)); } -export function getKernelDataFor(tx: ProcessedTx, vk: VerificationKeyData): KernelData { - const recursiveProof = makeRecursiveProofFromBinary(tx.proof, NESTED_RECURSIVE_PROOF_LENGTH); +export function getKernelDataFor( + tx: ProcessedTx, + vk: VerificationKeyData, + proof: RecursiveProof, +): KernelData { const leafIndex = getVKIndex(vk); return new KernelData( tx.data, - recursiveProof, - + proof, // VK for the kernel circuit vk, - leafIndex, getVKSiblingPath(leafIndex), ); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 5673297f60a..d8ffb6655eb 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -43,6 +43,7 @@ import { type RecursiveProof, type RootParityInput, RootParityInputs, + TubeInputs, type VerificationKeyAsFields, VerificationKeyData, makeEmptyProof, @@ -449,11 +450,7 @@ export class ProvingOrchestrator { * @param provingState - The proving state being worked on */ private async prepareTransaction(tx: ProcessedTx, provingState: ProvingState) { - // Pass the private kernel tail vk here as the previous one. - // If there are public functions then this key will be overwritten once the public tail has been proven - const previousKernelVerificationKey = ProtocolCircuitVks.PrivateKernelTailArtifact; - - const txInputs = await this.prepareBaseRollupInputs(provingState, tx, previousKernelVerificationKey); + const txInputs = await this.prepareBaseRollupInputs(provingState, tx); if (!txInputs) { // This should not be possible throw new Error(`Unable to add padding transaction, preparing base inputs failed`); @@ -558,13 +555,28 @@ export class ProvingOrchestrator { private async prepareBaseRollupInputs( provingState: ProvingState | undefined, tx: ProcessedTx, - kernelVk: VerificationKeyData, ): Promise<[BaseRollupInputs, TreeSnapshots] | undefined> { if (!provingState?.verifyState()) { logger.debug('Not preparing base rollup inputs, state invalid'); return; } - const inputs = await buildBaseRollupInput(tx, provingState.globalVariables, this.db, kernelVk); + + const getBaseInputsEmptyTx = async () => { + const inputs = { + header: await this.db.buildInitialHeader(), + chainId: tx.data.constants.globalVariables.chainId, + version: tx.data.constants.globalVariables.version, + vkTreeRoot: tx.data.constants.vkTreeRoot, + }; + + const proof = await this.prover.getEmptyTubeProof(inputs); + return await buildBaseRollupInput(tx, proof.proof, provingState.globalVariables, this.db, proof.verificationKey); + }; + const getBaseInputsNonEmptyTx = async () => { + const proof = await this.prover.getTubeProof(new TubeInputs(tx.clientIvcProof)); + return await buildBaseRollupInput(tx, proof.tubeProof, provingState.globalVariables, this.db, proof.tubeVK); + }; + const inputs = tx.isEmpty ? await getBaseInputsEmptyTx() : await getBaseInputsNonEmptyTx(); const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( async (id: MerkleTreeId) => { return { key: id, value: await getTreeSnapshot(id, this.db) }; @@ -970,6 +982,7 @@ export class ProvingOrchestrator { result => { const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof( functionIndex, + // PUBLIC KERNEL: I want to pass a client ivc proof into here? result.proof, result.verificationKey, ); diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index 6fcfdd9140d..4ef6bd68d02 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -9,11 +9,10 @@ import { import { type AppendOnlyTreeSnapshot, type BaseRollupInputs, - NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_PROOF_LENGTH, type Proof, type RecursiveProof, type VerificationKeyData, - makeRecursiveProofFromBinary, } from '@aztec/circuits.js'; export enum TX_PROVING_CODE { @@ -51,16 +50,14 @@ export class TxProvingState { public readonly treeSnapshots: Map, privateKernelVk: VerificationKeyData, ) { - let previousKernelProof: RecursiveProof | undefined = - makeRecursiveProofFromBinary(processedTx.proof, NESTED_RECURSIVE_PROOF_LENGTH); let previousProofType = PublicKernelType.NON_PUBLIC; for (let i = 0; i < processedTx.publicProvingRequests.length; i++) { const provingRequest = processedTx.publicProvingRequests[i]; const kernelRequest = provingRequest.type === AVM_REQUEST ? provingRequest.kernelRequest : provingRequest; // the first circuit has a valid previous proof, it came from private - if (previousKernelProof) { - kernelRequest.inputs.previousKernel.proof = previousKernelProof; + if (i === 0) { kernelRequest.inputs.previousKernel.vk = privateKernelVk; + kernelRequest.inputs.previousKernel.clientIvcProof = processedTx.clientIvcProof; } const vmRequest = provingRequest.type === AVM_REQUEST ? provingRequest : undefined; const publicFunction: PublicFunction = { @@ -71,7 +68,6 @@ export class TxProvingState { publicKernelRequest: kernelRequest, }; this.publicFunctions.push(publicFunction); - previousKernelProof = undefined; previousProofType = kernelRequest.type; } } diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index ba9935faca9..dcba5452acd 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -21,10 +21,13 @@ import type { PrivateKernelEmptyInputData, PublicKernelCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, + RecursiveProof, RootParityInput, RootParityInputs, RootRollupInputs, RootRollupPublicInputs, + TubeInputs, + VerificationKeyData, } from '@aztec/circuits.js'; import { randomBytes } from '@aztec/foundation/crypto'; import { AbortError, TimeoutError } from '@aztec/foundation/error'; @@ -246,6 +249,20 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal); } + getTubeProof( + inputs: TubeInputs, + signal?: AbortSignal | undefined, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + return this.enqueue({ type: ProvingRequestType.TUBE_PROOF, inputs }, signal); + } + + getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + signal?: AbortSignal, + ): Promise> { + return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal); + } + /** * Creates a proof for the given input. * @param input - Input to the circuit. @@ -285,13 +302,13 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource * @param input - Input to the circuit. */ getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, signal?: AbortSignal, ): Promise> { return this.enqueue( { type: ProvingRequestType.BASE_ROLLUP, - inputs: input, + inputs: baseRollupInput, }, signal, ); diff --git a/yarn-project/prover-client/src/prover-agent/prover-agent.ts b/yarn-project/prover-client/src/prover-agent/prover-agent.ts index 14cb93aa74b..37e4f51e32d 100644 --- a/yarn-project/prover-client/src/prover-agent/prover-agent.ts +++ b/yarn-project/prover-client/src/prover-agent/prover-agent.ts @@ -104,12 +104,16 @@ export class ProverAgent { } catch (err) { if (this.isRunning()) { this.log.error( - `Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${err}`, + `Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${ + (err as any).stack || err + }`, ); await jobSource.rejectProvingJob(job.id, new ProvingError((err as any)?.message ?? String(err))); } else { this.log.debug( - `Dropping proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: agent stopped: ${err}`, + `Dropping proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: agent stopped: ${ + (err as any).stack || err + }`, ); } } @@ -160,6 +164,10 @@ export class ProverAgent { return this.circuitProver.getEmptyPrivateKernelProof(inputs); } + case ProvingRequestType.TUBE_PROOF: { + return this.circuitProver.getTubeProof(inputs); + } + default: { const _exhaustive: never = type; return Promise.reject(new Error(`Invalid proof request type: ${type}`)); diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index 51f54b60c5a..1cab8f282fa 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -1,5 +1,6 @@ import { BBNativeRollupProver, type BBProverConfig } from '@aztec/bb-prover'; -import { makePaddingProcessedTx } from '@aztec/circuit-types'; +import { makePaddingProcessedTxFromTubeProof } from '@aztec/circuit-types'; +import { NESTED_RECURSIVE_PROOF_LENGTH, makeEmptyRecursiveProof } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -38,12 +39,13 @@ describe('prover/bb_prover/base-rollup', () => { vkTreeRoot, }; - const paddingTxPublicInputsAndProof = await context.prover.getEmptyPrivateKernelProof(inputs); - const tx = makePaddingProcessedTx(paddingTxPublicInputsAndProof); + const paddingTxPublicInputsAndProof = await context.prover.getEmptyTubeProof(inputs); + const tx = makePaddingProcessedTxFromTubeProof(paddingTxPublicInputsAndProof); logger.verbose('Building base rollup inputs'); const baseRollupInputs = await buildBaseRollupInput( tx, + makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), context.globalVariables, context.actualDb, paddingTxPublicInputsAndProof.verificationKey, diff --git a/yarn-project/pxe/package.json b/yarn-project/pxe/package.json index 588fb9fec9b..1f0e9c1aaf4 100644 --- a/yarn-project/pxe/package.json +++ b/yarn-project/pxe/package.json @@ -69,7 +69,9 @@ "@aztec/protocol-contracts": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/types": "workspace:^", + "@msgpack/msgpack": "^3.0.0-beta2", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", + "@noir-lang/types": "workspace:*", "koa": "^2.14.2", "koa-router": "^12.0.0", "lodash.omit": "^4.5.0", diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index d41350b9aa5..a3a0bf9d24f 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -1,24 +1,21 @@ -import { Note, type ProofCreator } from '@aztec/circuit-types'; +import { Note, type PrivateKernelProver } from '@aztec/circuit-types'; import { FunctionData, FunctionSelector, MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASHES_PER_TX, MembershipWitness, - NESTED_RECURSIVE_PROOF_LENGTH, NoteHash, PrivateCallStackItem, PrivateCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PrivateKernelTailCircuitPublicInputs, PublicCallRequest, - RECURSIVE_PROOF_LENGTH, ScopedNoteHash, type TxRequest, VK_TREE_HEIGHT, VerificationKey, VerificationKeyAsFields, - makeRecursiveProof, } from '@aztec/circuits.js'; import { makeTxRequest } from '@aztec/circuits.js/testing'; import { NoteSelector } from '@aztec/foundation/abi'; @@ -35,7 +32,7 @@ import { type ProvingDataOracle } from './proving_data_oracle.js'; describe('Kernel Prover', () => { let txRequest: TxRequest; let oracle: ReturnType>; - let proofCreator: ReturnType>; + let proofCreator: ReturnType>; let prover: KernelProver; let dependencies: { [name: string]: string[] } = {}; @@ -84,7 +81,7 @@ describe('Kernel Prover', () => { }; }; - const createProofOutput = (newNoteIndices: number[]) => { + const simulateProofOutput = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelCircuitPublicInputs.empty(); const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash.empty); for (let i = 0; i < newNoteIndices.length; i++) { @@ -96,12 +93,12 @@ describe('Kernel Prover', () => { publicInputs.end.noteHashes = noteHashes; return { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), verificationKey: VerificationKeyAsFields.makeEmpty(), + outputWitness: new Map(), }; }; - const createProofOutputFinal = (newNoteIndices: number[]) => { + const simulateProofOutputFinal = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelTailCircuitPublicInputs.empty(); const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, () => Fr.ZERO); for (let i = 0; i < newNoteIndices.length; i++) { @@ -111,31 +108,30 @@ describe('Kernel Prover', () => { return { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + outputWitness: new Map(), verificationKey: VerificationKeyAsFields.makeEmpty(), }; }; - const createAppCircuitProofOutput = () => { + const computeAppCircuitVerificationKeyOutput = () => { return { - proof: makeRecursiveProof(RECURSIVE_PROOF_LENGTH), verificationKey: VerificationKeyAsFields.makeEmpty(), }; }; const expectExecution = (fns: string[]) => { - const callStackItemsInit = proofCreator.createProofInit.mock.calls.map(args => + const callStackItemsInit = proofCreator.simulateProofInit.mock.calls.map(args => String.fromCharCode(args[0].privateCall.callStackItem.functionData.selector.value), ); - const callStackItemsInner = proofCreator.createProofInner.mock.calls.map(args => + const callStackItemsInner = proofCreator.simulateProofInner.mock.calls.map(args => String.fromCharCode(args[0].privateCall.callStackItem.functionData.selector.value), ); - expect(proofCreator.createProofInit).toHaveBeenCalledTimes(Math.min(1, fns.length)); - expect(proofCreator.createProofInner).toHaveBeenCalledTimes(Math.max(0, fns.length - 1)); + expect(proofCreator.simulateProofInit).toHaveBeenCalledTimes(Math.min(1, fns.length)); + expect(proofCreator.simulateProofInner).toHaveBeenCalledTimes(Math.max(0, fns.length - 1)); expect(callStackItemsInit.concat(callStackItemsInner)).toEqual(fns); - proofCreator.createProofInner.mockClear(); - proofCreator.createProofInit.mockClear(); + proofCreator.simulateProofInner.mockClear(); + proofCreator.simulateProofInit.mockClear(); }; const prove = (executionResult: ExecutionResult) => prover.prove(txRequest, executionResult); @@ -158,15 +154,15 @@ describe('Kernel Prover', () => { privateFunctionsRoot: Fr.random(), }); - proofCreator = mock(); + proofCreator = mock(); proofCreator.getSiloedCommitments.mockImplementation(publicInputs => Promise.resolve(publicInputs.noteHashes.map(com => createFakeSiloedCommitment(com.value))), ); - proofCreator.createProofInit.mockResolvedValue(createProofOutput([])); - proofCreator.createProofInner.mockResolvedValue(createProofOutput([])); - proofCreator.createProofReset.mockResolvedValue(createProofOutput([])); - proofCreator.createProofTail.mockResolvedValue(createProofOutputFinal([])); - proofCreator.createAppCircuitProof.mockResolvedValue(createAppCircuitProofOutput()); + proofCreator.simulateProofInit.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofInner.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofReset.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofTail.mockResolvedValue(simulateProofOutputFinal([])); + proofCreator.computeAppCircuitVerificationKey.mockResolvedValue(computeAppCircuitVerificationKeyOutput()); prover = new KernelProver(oracle, proofCreator); }); diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 5a219fce08a..728e4112401 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -1,4 +1,4 @@ -import { type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; +import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types'; import { CallRequest, Fr, @@ -9,7 +9,6 @@ import { MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - NESTED_RECURSIVE_PROOF_LENGTH, PrivateCallData, PrivateKernelCircuitPublicInputs, PrivateKernelData, @@ -17,24 +16,32 @@ import { PrivateKernelInnerCircuitPrivateInputs, PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - type RECURSIVE_PROOF_LENGTH, - type RecursiveProof, type TxRequest, VK_TREE_HEIGHT, VerificationKeyAsFields, getNonEmptyItems, - makeRecursiveProof, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { assertLength } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; -import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { + ClientCircuitArtifacts, + PrivateResetTagToArtifactName, + getVKTreeRoot, +} from '@aztec/noir-protocol-circuits-types'; import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNoteHashCounters } from '@aztec/simulator'; +import { type WitnessMap } from '@noir-lang/types'; + import { buildPrivateKernelResetInputs } from './private_inputs_builders/index.js'; import { type ProvingDataOracle } from './proving_data_oracle.js'; +const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput = { + publicInputs: PrivateKernelCircuitPublicInputs.empty(), + verificationKey: VerificationKeyAsFields.makeEmpty(), + outputWitness: new Map(), +}; /** * The KernelProver class is responsible for generating kernel proofs. * It takes a transaction request, its signature, and the simulation result as inputs, and outputs a proof @@ -44,7 +51,7 @@ import { type ProvingDataOracle } from './proving_data_oracle.js'; export class KernelProver { private log = createDebugLogger('aztec:kernel-prover'); - constructor(private oracle: ProvingDataOracle, private proofCreator: ProofCreator) {} + constructor(private oracle: ProvingDataOracle, private proofCreator: PrivateKernelProver) {} /** * Generate a proof for a given transaction request and execution result. @@ -55,26 +62,37 @@ export class KernelProver { * @param txRequest - The authenticated transaction request object. * @param executionResult - The execution result object containing nested executions and preimages. * @returns A Promise that resolves to a KernelProverOutput object containing proof, public inputs, and output notes. + * TODO(#7368) this should be refactored to not recreate the ACIR bytecode now that it operates on a program stack */ async prove( txRequest: TxRequest, executionResult: ExecutionResult, - ): Promise> { + ): Promise> { const executionStack = [executionResult]; let firstIteration = true; - let output: KernelProofOutput = { - publicInputs: PrivateKernelCircuitPublicInputs.empty(), - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - verificationKey: VerificationKeyAsFields.makeEmpty(), - }; + let output = NULL_PROVE_OUTPUT; const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult); const noteHashNullifierCounterMap = collectNullifiedNoteHashCounters(executionResult); + // vector of gzipped bincode acirs + const acirs: Buffer[] = []; + const witnessStack: WitnessMap[] = []; while (executionStack.length) { if (!firstIteration && this.needsReset(executionStack, output)) { - output = await this.runReset(executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap); + const resetInputs = await this.getPrivateKernelResetInputs( + executionStack, + output, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + ); + output = await this.proofCreator.simulateProofReset(resetInputs); + // TODO(#7368) consider refactoring this redundant bytecode pushing + acirs.push( + Buffer.from(ClientCircuitArtifacts[PrivateResetTagToArtifactName[resetInputs.sizeTag]].bytecode, 'base64'), + ); + witnessStack.push(output.outputWitness); } const currentExecution = executionStack.pop()!; executionStack.push(...[...currentExecution.nestedExecutions].reverse()); @@ -89,47 +107,59 @@ export class KernelProver { currentExecution.callStackItem.functionData.selector, ); - const proofOutput = await this.proofCreator.createAppCircuitProof( - currentExecution.partialWitness, - currentExecution.acir, - functionName, - ); + const appVk = await this.proofCreator.computeAppCircuitVerificationKey(currentExecution.acir, functionName); + // TODO(#7368): This used to be associated with getDebugFunctionName + // TODO(#7368): Is there any way to use this with client IVC proving? + acirs.push(currentExecution.acir); + witnessStack.push(currentExecution.partialWitness); const privateCallData = await this.createPrivateCallData( currentExecution, publicCallRequests, publicTeardownCallRequest, - proofOutput.proof, - proofOutput.verificationKey, + appVk.verificationKey, ); if (firstIteration) { const proofInput = new PrivateKernelInitCircuitPrivateInputs(txRequest, getVKTreeRoot(), privateCallData); pushTestData('private-kernel-inputs-init', proofInput); - output = await this.proofCreator.createProofInit(proofInput); + output = await this.proofCreator.simulateProofInit(proofInput); + acirs.push(Buffer.from(ClientCircuitArtifacts.PrivateKernelInitArtifact.bytecode, 'base64')); + witnessStack.push(output.outputWitness); } else { const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), ); const proofInput = new PrivateKernelInnerCircuitPrivateInputs(previousKernelData, privateCallData); pushTestData('private-kernel-inputs-inner', proofInput); - output = await this.proofCreator.createProofInner(proofInput); + output = await this.proofCreator.simulateProofInner(proofInput); + acirs.push(Buffer.from(ClientCircuitArtifacts.PrivateKernelInnerArtifact.bytecode, 'base64')); + witnessStack.push(output.outputWitness); } firstIteration = false; } if (this.somethingToReset(output)) { - output = await this.runReset(executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap); + const resetInputs = await this.getPrivateKernelResetInputs( + executionStack, + output, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + ); + output = await this.proofCreator.simulateProofReset(resetInputs); + // TODO(#7368) consider refactoring this redundant bytecode pushing + acirs.push( + Buffer.from(ClientCircuitArtifacts[PrivateResetTagToArtifactName[resetInputs.sizeTag]].bytecode, 'base64'), + ); + witnessStack.push(output.outputWitness); } const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), @@ -142,10 +172,27 @@ export class KernelProver { const privateInputs = new PrivateKernelTailCircuitPrivateInputs(previousKernelData); pushTestData('private-kernel-inputs-ordering', privateInputs); - return await this.proofCreator.createProofTail(privateInputs); + const tailOutput = await this.proofCreator.simulateProofTail(privateInputs); + acirs.push( + Buffer.from( + privateInputs.isForPublic() + ? ClientCircuitArtifacts.PrivateKernelTailToPublicArtifact.bytecode + : ClientCircuitArtifacts.PrivateKernelTailArtifact.bytecode, + 'base64', + ), + ); + witnessStack.push(tailOutput.outputWitness); + + // TODO(#7368) how do we 'bincode' encode these inputs? + const ivcProof = await this.proofCreator.createClientIvcProof(acirs, witnessStack); + tailOutput.clientIvcProof = ivcProof; + return tailOutput; } - private needsReset(executionStack: ExecutionResult[], output: KernelProofOutput) { + private needsReset( + executionStack: ExecutionResult[], + output: PrivateKernelSimulateOutput, + ) { const nextIteration = executionStack[executionStack.length - 1]; return ( getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length + @@ -169,7 +216,7 @@ export class KernelProver { ); } - private somethingToReset(output: KernelProofOutput) { + private somethingToReset(output: PrivateKernelSimulateOutput) { return ( getNonEmptyItems(output.publicInputs.validationRequests.noteHashReadRequests).length > 0 || getNonEmptyItems(output.publicInputs.validationRequests.nullifierReadRequests).length > 0 || @@ -178,29 +225,26 @@ export class KernelProver { ); } - private async runReset( + private async getPrivateKernelResetInputs( executionStack: ExecutionResult[], - output: KernelProofOutput, + output: PrivateKernelSimulateOutput, noteHashLeafIndexMap: Map, noteHashNullifierCounterMap: Map, - ): Promise> { + ) { const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), ); - return this.proofCreator.createProofReset( - await buildPrivateKernelResetInputs( - executionStack, - previousKernelData, - noteHashLeafIndexMap, - noteHashNullifierCounterMap, - this.oracle, - ), + return await buildPrivateKernelResetInputs( + executionStack, + previousKernelData, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + this.oracle, ); } @@ -208,7 +252,6 @@ export class KernelProver { { callStackItem }: ExecutionResult, publicCallRequests: CallRequest[], publicTeardownCallRequest: CallRequest, - proof: RecursiveProof, vk: VerificationKeyAsFields, ) { const { contractAddress, functionData } = callStackItem; @@ -233,7 +276,6 @@ export class KernelProver { callStackItem, publicCallStack, publicTeardownCallRequest, - proof, vk, publicKeysHash, contractClassArtifactHash, diff --git a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts index b9bf1ae03e5..109cc33d821 100644 --- a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts @@ -1,7 +1,11 @@ -import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; +import { + type AppCircuitSimulateOutput, + type PrivateKernelProver, + type PrivateKernelSimulateOutput, +} from '@aztec/circuit-types'; import type { CircuitName, CircuitSimulationStats } from '@aztec/circuit-types/stats'; import { - NESTED_RECURSIVE_PROOF_LENGTH, + ClientIvcProof, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -9,9 +13,7 @@ import { type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - RECURSIVE_PROOF_LENGTH, VerificationKeyAsFields, - makeRecursiveProof, } from '@aztec/circuits.js'; import { siloNoteHash } from '@aztec/circuits.js/hash'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -26,21 +28,27 @@ import { executeTailForPublic, } from '@aztec/noir-protocol-circuits-types'; +import { type WitnessMap } from '@noir-lang/types'; + /** * Test Proof Creator executes circuit simulations and provides fake proofs. */ -export class TestProofCreator implements ProofCreator { +export class TestPrivateKernelProver implements PrivateKernelProver { constructor(private log = createDebugLogger('aztec:test_proof_creator')) {} + createClientIvcProof(_acirs: Buffer[], _witnessStack: WitnessMap[]): Promise { + return Promise.resolve(ClientIvcProof.empty()); + } + public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } - public async createProofInit( + public async simulateProofInit( privateInputs: PrivateKernelInitCircuitPrivateInputs, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeInit(privateInputs)); this.log.debug(`Simulated private kernel init`, { eventName: 'circuit-simulation', @@ -49,12 +57,12 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelInitArtifact'); + return this.makeEmptyKernelSimulateOutput(result, 'PrivateKernelInitArtifact'); } - public async createProofInner( + public async simulateProofInner( privateInputs: PrivateKernelInnerCircuitPrivateInputs, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeInner(privateInputs)); this.log.debug(`Simulated private kernel inner`, { eventName: 'circuit-simulation', @@ -63,12 +71,12 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelInnerArtifact'); + return this.makeEmptyKernelSimulateOutput(result, 'PrivateKernelInnerArtifact'); } - public async createProofReset( + public async simulateProofReset( privateInputs: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeReset(privateInputs)); this.log.debug(`Simulated private kernel reset`, { eventName: 'circuit-simulation', @@ -77,12 +85,15 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelResetFullArtifact'); + return this.makeEmptyKernelSimulateOutput( + result, + 'PrivateKernelResetFullArtifact', + ); } - public async createProofTail( + public async simulateProofTail( privateInputs: PrivateKernelTailCircuitPrivateInputs, - ): Promise> { + ): Promise> { const isForPublic = privateInputs.isForPublic(); const [duration, result] = await elapsed(() => isForPublic ? executeTailForPublic(privateInputs) : executeTail(privateInputs), @@ -94,25 +105,30 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput( + return this.makeEmptyKernelSimulateOutput( result, isForPublic ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact', ); } - createAppCircuitProof(_1: Map, _2: Buffer): Promise { - const appCircuitProofOutput: AppCircuitProofOutput = { - proof: makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + computeAppCircuitVerificationKey( + _bytecode: Buffer, + _appCircuitName?: string | undefined, + ): Promise { + const appCircuitProofOutput: AppCircuitSimulateOutput = { verificationKey: VerificationKeyAsFields.makeEmpty(), }; return Promise.resolve(appCircuitProofOutput); } - private makeEmptyKernelProofOutput(publicInputs: PublicInputsType, circuitType: ProtocolArtifact) { - const kernelProofOutput: KernelProofOutput = { + private makeEmptyKernelSimulateOutput( + publicInputs: PublicInputsType, + circuitType: ProtocolArtifact, + ) { + const kernelProofOutput: PrivateKernelSimulateOutput = { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), verificationKey: ProtocolCircuitVks[circuitType].keyAsFields, + outputWitness: new Map(), }; return kernelProofOutput; } diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts index 6d55b11709c..2b258944701 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts @@ -1,5 +1,5 @@ -import { BBNativeProofCreator } from '@aztec/bb-prover'; -import { type AztecNode, type ProofCreator } from '@aztec/circuit-types'; +import { BBNativePrivateKernelProver } from '@aztec/bb-prover'; +import { type AztecNode, type PrivateKernelProver } from '@aztec/circuit-types'; import { randomBytes } from '@aztec/foundation/crypto'; import { createDebugLogger } from '@aztec/foundation/log'; import { KeyStore } from '@aztec/key-store'; @@ -16,7 +16,7 @@ import { join } from 'path'; import { type PXEServiceConfig } from '../config/index.js'; import { KVPxeDatabase } from '../database/kv_pxe_database.js'; -import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; import { PXEService } from './pxe_service.js'; /** @@ -34,7 +34,7 @@ export async function createPXEService( aztecNode: AztecNode, config: PXEServiceConfig, useLogSuffix: string | boolean | undefined = undefined, - proofCreator?: ProofCreator, + proofCreator?: PrivateKernelProver, ) { const logSuffix = typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix; @@ -47,14 +47,14 @@ export async function createPXEService( const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress)); // (@PhilWindle) Temporary validation until WASM is implemented - let prover: ProofCreator | undefined = proofCreator; + let prover: PrivateKernelProver | undefined = proofCreator; if (!prover) { if (config.proverEnabled && (!config.bbBinaryPath || !config.bbWorkingDirectory)) { throw new Error(`Prover must be configured with binary path and working directory`); } prover = !config.proverEnabled - ? new TestProofCreator() - : new BBNativeProofCreator( + ? new TestPrivateKernelProver() + : new BBNativePrivateKernelProver( config.bbBinaryPath!, config.bbWorkingDirectory!, createDebugLogger('aztec:pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : '')), diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 6dcf9d3f421..0891f5f84d7 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -16,7 +16,7 @@ import { type OutgoingNotesFilter, type PXE, type PXEInfo, - type ProofCreator, + type PrivateKernelProver, SimulatedTx, SimulationError, TaggedLog, @@ -72,7 +72,7 @@ import { IncomingNoteDao } from '../database/incoming_note_dao.js'; import { type PxeDatabase } from '../database/index.js'; import { KernelOracle } from '../kernel_oracle/index.js'; import { KernelProver } from '../kernel_prover/kernel_prover.js'; -import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; import { getAcirSimulator } from '../simulator/index.js'; import { Synchronizer } from '../synchronizer/index.js'; @@ -89,13 +89,13 @@ export class PXEService implements PXE { // ensures that state is not changed while simulating private jobQueue = new SerialQueue(); - private fakeProofCreator = new TestProofCreator(); + private fakeProofCreator = new TestPrivateKernelProver(); constructor( private keyStore: KeyStore, private node: AztecNode, private db: PxeDatabase, - private proofCreator: ProofCreator, + private proofCreator: PrivateKernelProver, private config: PXEServiceConfig, logSuffix?: string, ) { @@ -750,7 +750,7 @@ export class PXEService implements PXE { */ async #simulateAndProve( txExecutionRequest: TxExecutionRequest, - proofCreator: ProofCreator, + proofCreator: PrivateKernelProver, msgSender?: AztecAddress, ): Promise { // Get values that allow us to reconstruct the block hash @@ -759,7 +759,10 @@ export class PXEService implements PXE { const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node); const kernelProver = new KernelProver(kernelOracle, proofCreator); this.log.debug(`Executing kernel prover...`); - const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult); + const { clientIvcProof, publicInputs } = await kernelProver.prove( + txExecutionRequest.toTxRequest(), + executionResult, + ); const noteEncryptedLogs = new EncryptedNoteTxL2Logs([collectSortedNoteEncryptedLogs(executionResult)]); const unencryptedLogs = new UnencryptedTxL2Logs([collectSortedUnencryptedLogs(executionResult)]); @@ -769,7 +772,7 @@ export class PXEService implements PXE { const tx = new Tx( publicInputs, - proof.binaryProof, + clientIvcProof!, noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 3728d8683d3..c649d944533 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -10,7 +10,7 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { KVPxeDatabase } from '../../database/kv_pxe_database.js'; import { type PxeDatabase } from '../../database/pxe_database.js'; import { type PXEServiceConfig } from '../../index.js'; -import { TestProofCreator } from '../../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../../kernel_prover/test/test_circuit_prover.js'; import { PXEService } from '../pxe_service.js'; import { pxeTestSuite } from './pxe_test_suite.js'; @@ -36,7 +36,7 @@ function createPXEService(): Promise { }; node.getL1ContractAddresses.mockResolvedValue(mockedContracts); - return Promise.resolve(new PXEService(keyStore, node, db, new TestProofCreator(), config)); + return Promise.resolve(new PXEService(keyStore, node, db, new TestPrivateKernelProver(), config)); } pxeTestSuite('PXEService', createPXEService); @@ -61,7 +61,7 @@ describe('PXEService', () => { node.getTxEffect.mockResolvedValue(settledTx); - const pxe = new PXEService(keyStore, node, db, new TestProofCreator(), config); + const pxe = new PXEService(keyStore, node, db, new TestPrivateKernelProver(), config); await expect(pxe.sendTx(duplicateTx)).rejects.toThrow(/A settled tx with equal hash/); }); }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index aef46a70db7..dfe83e9de2d 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -22,7 +22,6 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, makeEmptyProof, } from '@aztec/circuits.js'; -import { makeProof } from '@aztec/circuits.js/testing'; import { randomBytes } from '@aztec/foundation/crypto'; import { type Writeable } from '@aztec/foundation/types'; import { type P2P, P2PClientState } from '@aztec/p2p'; @@ -81,7 +80,7 @@ describe('sequencer', () => { publicProcessor = mock({ process: async txs => [ - await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), makeProof(), []))), + await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), []))), [], [], ], diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 31697c2a031..72e949174b2 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -352,7 +352,7 @@ export class Sequencer { const toReturn: Tx[] = []; for (const tx of txs) { - const txSize = tx.getSize() - tx.proof.toBuffer().length; + const txSize = tx.getSize() - tx.clientIvcProof.clientIvcProofBuffer.length; if (totalSize + txSize > maxSize) { this.log.warn( `Dropping tx ${tx.getTxHash()} with estimated size ${txSize} due to exceeding ${maxSize} block size limit (currently at ${totalSize})`, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 3428158116c..9610f906dea 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -14,6 +14,7 @@ import { type AvmExecutionHints, AztecAddress, CallRequest, + ClientIvcProof, ContractStorageRead, ContractStorageUpdateRequest, Fr, @@ -419,7 +420,7 @@ export abstract class AbstractPhaseManager { const previousKernel = this.getPreviousKernelData(previousOutput, previousCircuit); // We take a deep copy (clone) of these inputs to be passed to the prover - const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData); + const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, ClientIvcProof.empty(), callData); switch (this.phase) { case PublicKernelType.SETUP: return [inputs.clone(), await this.publicKernel.publicKernelCircuitSetup(inputs), 'PublicKernelSetupArtifact']; diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 09d1de5ef96..b39fff57782 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -4,7 +4,6 @@ import { PublicDataWrite, PublicKernelType, SimulationError, - type Tx, type TxValidator, mockTx, toTxEffect, @@ -12,6 +11,7 @@ import { import { AppendOnlyTreeSnapshot, AztecAddress, + ClientIvcProof, ContractStorageRead, ContractStorageUpdateRequest, Fr, @@ -24,14 +24,12 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, - type Proof, PublicAccumulatedDataBuilder, PublicCallRequest, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, RevertCode, StateReference, - makeEmptyProof, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; import { fr, makeAztecAddress, makePublicCallRequest, makeSelector } from '@aztec/circuits.js/testing'; @@ -64,7 +62,7 @@ describe('public_processor', () => { let publicWorldStateDB: MockProxy; let prover: MockProxy; - let proof: Proof; + let proof: ClientIvcProof; let root: Buffer; let processor: PublicProcessor; @@ -76,7 +74,7 @@ describe('public_processor', () => { publicWorldStateDB = mock(); prover = mock(); - proof = makeEmptyProof(); + proof = ClientIvcProof.empty(); root = Buffer.alloc(32, 5); db.getTreeInfo.mockResolvedValue({ root } as TreeInfo); @@ -114,10 +112,10 @@ describe('public_processor', () => { const expected: ProcessedTx = { hash, data: tx.data.toKernelCircuitPublicInputs(), - proof: tx.proof, noteEncryptedLogs: tx.noteEncryptedLogs, encryptedLogs: tx.encryptedLogs, unencryptedLogs: tx.unencryptedLogs, + clientIvcProof: tx.clientIvcProof, isEmpty: false, revertReason: undefined, publicProvingRequests: [], @@ -225,12 +223,6 @@ describe('public_processor', () => { ); }); - const expectedTxByHash = (tx: Tx) => - expect.objectContaining({ - hash: tx.getTxHash(), - proof, - }); - it('runs a tx with enqueued public calls', async function () { const tx = mockTxWithPartialState({ hasLogs: true, @@ -252,7 +244,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); @@ -283,7 +276,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(publicExecutor.simulate).toHaveBeenCalledTimes(1); // we only call checkpoint after successful "setup" @@ -318,7 +312,10 @@ describe('public_processor', () => { const [processed, failed] = await processor.process(txs, 2, prover); expect(processed).toHaveLength(2); - expect(processed).toEqual([expectedTxByHash(txs[0]), expectedTxByHash(txs[1])]); + expect(processed[0].hash).toEqual(txs[0].getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); + expect(processed[1].hash).toEqual(txs[1].getTxHash()); + expect(processed[1].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(2); @@ -449,7 +446,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(1); @@ -681,7 +679,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(2); @@ -807,7 +806,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(2); @@ -965,7 +965,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(1); @@ -1081,7 +1082,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(0); @@ -1165,7 +1167,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); @@ -1222,7 +1225,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 86b9ed3ad27..2277545a759 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -126,7 +126,7 @@ export class PublicProcessor { } try { const [processedTx, returnValues] = !tx.hasPublicCalls() - ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), tx.proof, [])] + ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), [])] : await this.processTxWithPublicCalls(tx); // Set fee payment update request into the processed tx @@ -265,7 +265,7 @@ export class PublicProcessor { throw new Error('Final public kernel was not executed.'); } - const processedTx = makeProcessedTx(tx, finalKernelOutput, tx.proof, publicProvingRequests, revertReason, gasUsed); + const processedTx = makeProcessedTx(tx, finalKernelOutput, publicProvingRequests, revertReason, gasUsed); return [processedTx, returnValues]; } } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 27fee5d58f3..7349aebceeb 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -239,6 +239,7 @@ __metadata: "@aztec/simulator": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@jest/globals": ^29.5.0 + "@msgpack/msgpack": ^3.0.0-beta2 "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi" "@noir-lang/types": "portal:../../noir/packages/types" "@types/jest": ^29.5.0 @@ -820,7 +821,9 @@ __metadata: "@aztec/simulator": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 + "@msgpack/msgpack": ^3.0.0-beta2 "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi" + "@noir-lang/types": "workspace:*" "@types/jest": ^29.5.0 "@types/lodash.omit": ^4.5.7 "@types/node": ^18.7.23 @@ -2803,6 +2806,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:^3.0.0-beta2": + version: 3.0.0-beta2 + resolution: "@msgpack/msgpack@npm:3.0.0-beta2" + checksum: d86e5d48146051952d6bea35a6cf733a401cf65ad5614d79689aa48c7076021737ca2c782978dd1b6c0c9c45888b246e379e45ae906179e3a0e8ef4ee6f221c1 + languageName: node + linkType: hard + "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2": version: 3.0.2 resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2"