From 46bcabc04d0ccc6473eea9cf6e303bd63dd16143 Mon Sep 17 00:00:00 2001 From: ludamad Date: Fri, 4 Jul 2025 21:44:41 +0000 Subject: [PATCH 01/30] rename bbrpc => bbapi --- .../src/barretenberg/api/api_client_ivc.cpp | 122 +++++++++----- .../barretenberg/api/api_client_ivc.test.cpp | 64 ++++---- ...{bbrpc_commands.hpp => bbapi_commands.hpp} | 12 +- .../{bbrpc_execute.hpp => bbapi_execute.hpp} | 150 ++++++++++++++---- 4 files changed, 238 insertions(+), 110 deletions(-) rename barretenberg/cpp/src/barretenberg/api/{bbrpc_commands.hpp => bbapi_commands.hpp} (96%) rename barretenberg/cpp/src/barretenberg/api/{bbrpc_execute.hpp => bbapi_execute.hpp} (57%) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 9bf60226321f..e6ba8589f910 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -1,4 +1,6 @@ #include "api_client_ivc.hpp" +#include "barretenberg/api/bbapi_commands.hpp" +#include "barretenberg/api/bbapi_execute.hpp" #include "barretenberg/api/file_io.hpp" #include "barretenberg/api/log.hpp" #include "barretenberg/api/write_prover_output.hpp" @@ -16,12 +18,13 @@ #include namespace bb { +namespace {} // anonymous namespace 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) { + for (const auto& e : witness_map) { uint64_t value = 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 @@ -58,12 +61,23 @@ void write_standalone_vk(const std::string& output_data_type, const std::string& output_path) { - acir_format::AcirProgram program{ get_constraint_system(bytecode_path), /*witness=*/{} }; - std::shared_ptr proving_key = get_acir_program_decider_proving_key(program); - auto verification_key = std::make_shared(proving_key->get_precomputed()); - PubInputsProofAndKey to_write{ .key = verification_key }; + bbapi::BBApiRequest request; + + auto response = bbapi::execute(bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }); + + if (!response.error_message.empty()) { + throw_or_abort("Failed to compute standalone VK: " + response.error_message); + } - write(to_write, output_data_type, "vk", output_path); + if (output_format == "bytes") { + write_file(output_path / "vk", response.vk_bytes); + } else if (output_format == "fields") { + std::string json = bbapi::field_elements_to_json(response.vk_fields); + write_file(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); + } else { + throw_or_abort("Unsupported output format for standalone vk: " + output_format); + } } size_t get_num_public_inputs_in_circuit(const std::filesystem::path& bytecode_path) @@ -83,19 +97,10 @@ void write_vk_for_ivc(const std::string& output_format, ClientIVC ivc{ /*num_circuits=*/2, { AZTEC_TRACE_STRUCTURE } }; ClientIVCMockCircuitProducer circuit_producer; - // Initialize the IVC with an arbitrary circuit - // We segfault if we only call accumulate once - static constexpr size_t SMALL_ARBITRARY_LOG_CIRCUIT_SIZE{ 5 }; - MegaCircuitBuilder circuit_0 = circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE); - ivc.accumulate(circuit_0); + bbapi::BBApiRequest request; - // Create another circuit and accumulate - MegaCircuitBuilder circuit_1 = - circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE, num_public_inputs_in_final_circuit); - ivc.accumulate(circuit_1); - - // Construct the hiding circuit and its VK (stored internally in the IVC) - ivc.construct_hiding_circuit_key(); + auto vk = bbapi::compute_vk_for_ivc(request, num_public_inputs_in_final_circuit); + const auto buf = to_buffer(vk); const bool output_to_stdout = output_dir == "-"; const auto buf = to_buffer(ivc.get_vk()); @@ -111,9 +116,27 @@ void write_vk_for_ivc(const std::string& output_data_type, const std::string& bytecode_path, const std::filesystem::path& output_dir) { - const size_t num_public_inputs_in_final_circuit = get_num_public_inputs_in_circuit(bytecode_path); - info("num_public_inputs_in_final_circuit: ", num_public_inputs_in_final_circuit); - write_vk_for_ivc(output_data_type, num_public_inputs_in_final_circuit, output_dir); + if (output_data_type != "bytes") { + throw_or_abort("Unsupported output format for ClientIVC vk: " + output_data_type); + } + + auto bytecode = get_bytecode(bytecode_path); + + bbapi::BBApiRequest request; + + auto response = bbapi::execute( + bbapi::ClientIvcComputeIvcVk{ .circuit = { .name = "final_circuit", .bytecode = std::move(bytecode) } }); + + if (!response.error_message.empty()) { + throw_or_abort("Failed to compute IVC VK: " + response.error_message); + } + + const bool output_to_stdout = output_dir == "-"; + if (output_to_stdout) { + write_bytes_to_stdout(response.vk_bytes); + } else { + write_file(output_dir / "vk", response.vk_bytes); + } } void ClientIVCAPI::prove(const Flags& flags, @@ -121,17 +144,32 @@ void ClientIVCAPI::prove(const Flags& flags, const std::filesystem::path& output_dir) { - PrivateExecutionSteps steps; - steps.parse(PrivateExecutionStepRaw::load_and_decompress(input_path)); + bbapi::BBApiRequest request; - std::shared_ptr ivc = steps.accumulate(); - ClientIVC::Proof proof = ivc->prove(); + auto start_response = bbapi::execute(request, bbapi::ClientIvcStart{}); + if (!start_response.error_message.empty()) { + throw_or_abort("Failed to start ClientIVC: " + start_response.error_message); + } + + for (const auto& step : raw_steps) { + auto load_response = bbapi::execute( + request, + bbapi::ClientIvcLoad{ + .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } }); + if (!load_response.error_message.empty()) { + throw_or_abort("Failed to load circuit: " + load_response.error_message); + } - // We verify this proof. Another bb call to verify has the overhead of loading the SRS, - // and it is mysterious if this transaction fails later in the lifecycle. - // The files are still written in case they are needed to investigate this failure. - if (!ivc->verify(proof)) { - THROW std::runtime_error("Failed to verify the private (ClientIVC) transaction proof!"); + info("ClientIVC: accumulating " + step.function_name); + auto acc_response = bbapi::execute(request, bbapi::ClientIvcAccumulate{ .witness = step.witness }); + if (!acc_response.error_message.empty()) { + throw_or_abort("Failed to accumulate circuit: " + acc_response.error_message); + } + } + + auto prove_response = bbapi::execute(request, bbapi::ClientIvcProve{}); + if (!prove_response.error_message.empty()) { + throw_or_abort("Failed to prove: " + prove_response.error_message); } // We'd like to use the `write` function that UltraHonkAPI uses, but there are missing functions for creating @@ -199,16 +237,24 @@ bool ClientIVCAPI::check_precomputed_vks(const std::filesystem::path& input_path PrivateExecutionSteps steps; steps.parse(PrivateExecutionStepRaw::load_and_decompress(input_path)); - for (auto [program, precomputed_vk, function_name] : - zip_view(steps.folding_stack, steps.precomputed_vks, steps.function_names)) { - if (precomputed_vk == nullptr) { - info("FAIL: Expected precomputed vk for function ", function_name); + bbapi::BBApiRequest request; + + for (const auto& step : raw_steps) { + if (step.vk.empty()) { + info("FAIL: Expected precomputed vk for function ", step.function_name); return false; } - std::shared_ptr proving_key = get_acir_program_decider_proving_key(program); - auto computed_vk = std::make_shared(proving_key->get_precomputed()); - std::string error_message = "FAIL: Precomputed vk does not match computed vk for function " + function_name; - if (!msgpack::msgpack_check_eq(*computed_vk, *precomputed_vk, error_message)) { + + auto response = bbapi::execute( + request, + bbapi::ClientIvcCheckPrecomputedVk{ + .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk }, + .function_name = step.function_name }); + + if (!response.error_message.empty() || !response.valid) { + if (!response.error_message.empty()) { + info(response.error_message); + } return false; } } diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp index 6b2f4d97d6ae..30213923d158 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp @@ -1,6 +1,6 @@ #include "api_client_ivc.hpp" -#include "barretenberg/api/bbrpc_commands.hpp" -#include "barretenberg/api/bbrpc_execute.hpp" +#include "barretenberg/api/bbapi_commands.hpp" +#include "barretenberg/api/bbapi_execute.hpp" #include "barretenberg/api/file_io.hpp" #include "barretenberg/client_ivc/acir_bincode_mocks.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" @@ -44,24 +44,22 @@ void create_test_private_execution_steps(const std::filesystem::path& output_pat auto [app_bytecode, app_witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); // Get the VK for the app circuit - bbrpc::BBRpcRequest request; + bbapi::BBApiRequest request; - auto app_vk = - bbrpc::execute(request, - bbrpc::ClientIvcComputeVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode }, - .standalone = true }) - .verification_key; + auto app_vk = bbapi::execute(request, + bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }) + .vk_bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Now create a kernel circuit that verifies the app circuit auto kernel_bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/true); auto kernel_witness_data = acir_bincode_mocks::create_kernel_witness(app_vk_fields); - auto kernel_vk = - bbrpc::execute(request, - bbrpc::ClientIvcComputeVk{ .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode }, - .standalone = true }) - .verification_key; + auto kernel_vk = bbapi::execute(request, + bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode } }) + .vk_bytes; // Create PrivateExecutionStepRaw for the kernel std::vector raw_steps; @@ -103,13 +101,11 @@ std::vector compress(const std::vector& input); ClientIVC::MegaVerificationKey get_ivc_vk(const std::filesystem::path& test_dir) { auto [app_bytecode, app_witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); - bbrpc::BBRpcRequest request; - // First create an app standalone VK. - auto app_vk = - bbrpc::execute(request, - bbrpc::ClientIvcComputeVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode }, - .standalone = true }) - .verification_key; + bbapi::BBApiRequest request; + auto app_vk = bbapi::execute(request, + bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }) + .vk_bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Use this to get the size of the vk. auto bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/false); @@ -173,7 +169,7 @@ TEST_F(ClientIVCAPITests, ProveAndVerifyFileBasedFlow) EXPECT_TRUE(verify_proof()); } -// WORKTODO(bbrpc): Expand on this. +// WORKTODO(bbapi): Expand on this. TEST_F(ClientIVCAPITests, WriteVkFieldsSmokeTest) { // Create a simple circuit bytecode @@ -267,23 +263,21 @@ TEST_F(ClientIVCAPITests, CheckPrecomputedVksMismatch) // Create a simple circuit auto [bytecode, witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); - bbrpc::BBRpcRequest request; - size_t vk_size = - from_buffer( - bbrpc::execute(request, - bbrpc::ClientIvcComputeVk{ .circuit = { .name = "simple_circuit", .bytecode = bytecode }, - .standalone = true }) - .verification_key) - .to_field_elements() - .size(); + bbapi::BBApiRequest request; + size_t vk_size = from_buffer( + bbapi::execute(request, + bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "simple_circuit", .bytecode = bytecode } }) + .vk_bytes) + .to_field_elements() + .size(); // Create a WRONG verification key (use a different circuit) auto different_bytecode = acir_bincode_mocks::create_simple_kernel(vk_size, /*is_init_kernel=*/true); - auto vk = bbrpc::execute( - request, - bbrpc::ClientIvcComputeVk{ .circuit = { .name = "different_circuit", .bytecode = different_bytecode }, - .standalone = true }) - .verification_key; + auto vk = bbapi::execute(request, + bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "different_circuit", .bytecode = different_bytecode } }) + .vk_bytes; // Create PrivateExecutionStepRaw with wrong VK std::vector raw_steps; diff --git a/barretenberg/cpp/src/barretenberg/api/bbrpc_commands.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp similarity index 96% rename from barretenberg/cpp/src/barretenberg/api/bbrpc_commands.hpp rename to barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp index 1963a7961050..21ef691983d5 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbrpc_commands.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp @@ -1,6 +1,6 @@ #pragma once /** - * @file bbrpc.hpp + * @file bbapi.hpp * @brief Barretenberg RPC provides a stateful API for all core barretenberg proving functions. * Not included: * - Solidity verifier generation @@ -11,7 +11,7 @@ #include "barretenberg/honk/proof_system/types/proof.hpp" #include -namespace bb::bbrpc { +namespace bb::bbapi { /** * @struct CircuitInputNoVK @@ -496,6 +496,12 @@ using CommandResponse = NamedUnion; +// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve +// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. +template +concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + /** * @brief Convert oracle hash type string to enum for internal use */ @@ -512,4 +518,4 @@ inline OracleHashType parse_oracle_hash_type(const std::string& type) return OracleHashType::POSEIDON2; // default } -} // namespace bb::bbrpc +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbrpc_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp similarity index 57% rename from barretenberg/cpp/src/barretenberg/api/bbrpc_execute.hpp rename to barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index c9ef03a7afed..1eb375ef824c 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbrpc_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -1,6 +1,6 @@ #pragma once -#include "barretenberg/api/bbrpc_commands.hpp" +#include "barretenberg/api/bbapi_commands.hpp" #include "barretenberg/api/write_prover_output.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" @@ -18,9 +18,20 @@ #include #include -namespace bb::bbrpc { +namespace bb::bbapi { -struct BBRpcRequest { +/** + * @brief Convert a vector of field elements to JSON array format + */ +inline std::string field_elements_to_json(const std::vector& fields) +{ + if (fields.empty()) { + return "[]"; + } + return format("[", join(transform::map(fields, [](auto fr) { return format("\"", fr, "\""); })), "]"); +} + +struct BBApiRequest { TraceSettings trace_settings{ AZTEC_TRACE_STRUCTURE }; // Current depth of the IVC stack for this request uint32_t ivc_stack_depth = 0; @@ -38,85 +49,107 @@ inline const std::string& get_error_message(const CommandResponse& response) return response.visit([](const auto& resp) -> const std::string& { return resp.error_message; }); } -inline CircuitProve::Response execute(BB_UNUSED BBRpcRequest& request, CircuitProve&& command) +inline CircuitProve::Response execute(BB_UNUSED BBApiRequest& request, CircuitProve&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline CircuitComputeVk::Response execute(BB_UNUSED BBRpcRequest& request, CircuitComputeVk&& command) +inline CircuitComputeVk::Response execute(BB_UNUSED BBApiRequest& request, CircuitComputeVk&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline CircuitVerify::Response execute(BB_UNUSED BBRpcRequest& request, CircuitVerify&& command) +inline CircuitVerify::Response execute(BB_UNUSED BBApiRequest& request, CircuitVerify&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline CircuitInfo::Response execute(BB_UNUSED BBRpcRequest& request, CircuitInfo&& command) +inline CircuitInfo::Response execute(BB_UNUSED BBApiRequest& request, CircuitInfo&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline CircuitCheck::Response execute(BB_UNUSED BBRpcRequest& request, CircuitCheck&& command) +inline CircuitCheck::Response execute(BB_UNUSED BBApiRequest& request, CircuitCheck&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline ProofAsFields::Response execute(BB_UNUSED BBRpcRequest& request, ProofAsFields&& command) +inline ProofAsFields::Response execute(BB_UNUSED BBApiRequest& request, ProofAsFields&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline VkAsFields::Response execute(BB_UNUSED BBRpcRequest& request, VkAsFields&& command) +inline VkAsFields::Response execute(BB_UNUSED BBApiRequest& request, VkAsFields&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline ClientIvcStart::Response execute(BBRpcRequest& request, BB_UNUSED ClientIvcStart&& command) +inline ClientIvcStart::Response execute(BBApiRequest& request, BB_UNUSED ClientIvcStart&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline ClientIvcLoad::Response execute(BBRpcRequest& request, ClientIvcLoad&& command) +inline ClientIvcLoad::Response execute(BBApiRequest& request, ClientIvcLoad&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline ClientIvcAccumulate::Response execute(BBRpcRequest& request, ClientIvcAccumulate&& command) +inline ClientIvcAccumulate::Response execute(BBApiRequest& request, ClientIvcAccumulate&& command) { (void)request; (void)command; throw_or_abort("code in progress! should not be called"); } -inline ClientIvcProve::Response execute(BBRpcRequest& request, ClientIvcProve&& command) +inline ClientIvcProve::Response execute(BBApiRequest& request, BB_UNUSED ClientIvcProve&& command) { - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); + if (!request.ivc_in_progress) { + return ClientIvcProve::Response{ .proof = {}, + .error_message = "ClientIVC not started. Call ClientIvcStart first." }; + } + + if (request.ivc_stack_depth == 0) { + return ClientIvcProve::Response{ .proof = {}, + .error_message = "No circuits accumulated. Call ClientIvcAccumulate first." }; + } + + info("ClientIvcProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits"); + + ClientIVC::Proof proof = request.ivc_in_progress->prove(); + + // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS, + // and it is mysterious if this transaction fails later in the lifecycle. + // The files are still written in case they are needed to investigate this failure. + if (!request.ivc_in_progress->verify(proof)) { + return ClientIvcProve::Response{ .proof = {}, .error_message = "Failed to verify the generated proof!" }; + } + + request.ivc_in_progress.reset(); + request.ivc_stack_depth = 0; + + return ClientIvcProve::Response{ .proof = std::move(proof), .error_message = "" }; } inline std::shared_ptr get_acir_program_decider_proving_key( - const BBRpcRequest& request, acir_format::AcirProgram& program) + const BBApiRequest& request, acir_format::AcirProgram& program) { ClientIVC::ClientCircuit builder = acir_format::create_circuit(program); @@ -124,7 +157,7 @@ inline std::shared_ptr get_acir_program_decider_pr return std::make_shared(builder, request.trace_settings); } -inline ClientIVC::VerificationKey compute_vk_for_ivc(const BBRpcRequest& request, +inline ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit) { ClientIVC ivc{ /*num_circuits=*/2, request.trace_settings }; @@ -147,7 +180,7 @@ inline ClientIVC::VerificationKey compute_vk_for_ivc(const BBRpcRequest& request return ivc.get_vk(); } -inline ClientIvcComputeVk::Response execute(BBRpcRequest& request, ClientIvcComputeVk&& command) +inline ClientIvcComputeStandaloneVk::Response execute(BBApiRequest& request, ClientIvcComputeStandaloneVk&& command) { info("ClientIvcComputeVk - deriving VK for circuit '", command.circuit.name, "', standalone: ", command.standalone); @@ -169,10 +202,43 @@ inline ClientIvcComputeVk::Response execute(BBRpcRequest& request, ClientIvcComp info("ClientIvcComputeVk - full IVC VK derived, size: ", vk_data.size(), " bytes"); } - return ClientIvcComputeVk::Response{ .verification_key = vk_data, .error_message = "" }; + acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; + std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); + auto verification_key = std::make_shared(proving_key->proving_key); + + response.vk_bytes = to_buffer(*verification_key); + response.vk_fields = verification_key->to_field_elements(); + + info("ClientIvcComputeStandaloneVk - VK derived, size: ", response.vk_bytes.size(), " bytes"); + + response.error_message = ""; + return response; +} + +inline ClientIvcComputeIvcVk::Response execute(BBApiRequest& request, ClientIvcComputeIvcVk&& command) +{ + info("ClientIvcComputeIvcVk - deriving IVC VK for circuit '", command.circuit.name, "'"); + + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(command.circuit.bytecode)); + + ClientIvcComputeIvcVk::Response response; + + auto vk = compute_vk_for_ivc(request, constraint_system.public_inputs.size()); + response.vk_bytes = to_buffer(vk); + + info("ClientIvcComputeIvcVk - IVC VK derived, size: ", response.vk_bytes.size(), " bytes"); + + response.error_message = ""; + return response; +} + +template inline typename T::Response execute(T&& command) +{ + BBApiRequest request; + return execute_or_throw(request, std::forward(command)); } -inline ClientIvcCheckPrecomputedVk::Response execute(BBRpcRequest& request, ClientIvcCheckPrecomputedVk&& command) +inline ClientIvcCheckPrecomputedVk::Response execute(BBApiRequest& request, ClientIvcCheckPrecomputedVk&& command) { (void)request; (void)command; @@ -186,23 +252,14 @@ inline ClientIvcCheckPrecomputedVk::Response execute(BBRpcRequest& request, Clie * @param request The circuit registry (acting as the request context). * @return A variant of all possible command responses. */ -inline CommandResponse execute(BBRpcRequest& request, Command&& command) +inline CommandResponse execute(BBApiRequest& request, Command&& command) { return std::move(command).visit( [&request](auto&& cmd) -> CommandResponse { return execute(request, std::forward(cmd)); }); } -template typename T::Response execute_or_throw(BBRpcRequest& request, T&& command) -{ - auto response = execute(request, std::forward(command)); - if (!response.error_message.empty()) { - throw_or_abort(response.error_message); - } - return response; -} - // Can only be called from the execution thread (the same as the main thread, except in threaded WASM). -inline std::vector execute_request(BBRpcRequest&& request, std::vector&& commands) +inline std::vector execute_request(BBApiRequest&& request, std::vector&& commands) { std::vector responses; responses.reserve(commands.size()); @@ -216,4 +273,29 @@ inline std::vector execute_request(BBRpcRequest&& request, std: return responses; } -} // namespace bb::bbrpc +} // namespace bb::bbapi + +namespace bb { +template +inline typename T::Response do_bbapi(T&& command) + requires(!bbapi::RequiresBBApiRequest) +{ + bbapi::BBApiRequest request; + typename T::Response result = execute(request, std::forward(command)); + const std::string& error_message = bbapi::get_error_message(result); + if (error_message.empty()) { + return result; + } + throw std::runtime_error{ error_message }; +} + +template inline typename T::Response do_bbapi(bbapi::BBApiRequest& request, T&& command) +{ + typename T::Response result = execute(request, std::forward(command)); + const std::string& error_message = bbapi::get_error_message(result); + if (error_message.empty()) { + return result; + } + throw std::runtime_error{ error_message }; +} +} // namespace bb From 4b2deb96922c7c5afd40fd0492c7a80b85cbbe3a Mon Sep 17 00:00:00 2001 From: ludamad Date: Fri, 4 Jul 2025 22:38:07 +0000 Subject: [PATCH 02/30] interim --- .../src/barretenberg/api/bbapi_commands.hpp | 521 ------------------ .../src/barretenberg/api/bbapi_execute.hpp | 265 +-------- 2 files changed, 17 insertions(+), 769 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp deleted file mode 100644 index 21ef691983d5..000000000000 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_commands.hpp +++ /dev/null @@ -1,521 +0,0 @@ -#pragma once -/** - * @file bbapi.hpp - * @brief Barretenberg RPC provides a stateful API for all core barretenberg proving functions. - * Not included: - * - Solidity verifier generation - * - Raw cryptography functions exposed by WASM BB - */ -#include "barretenberg/client_ivc/client_ivc.hpp" -#include "barretenberg/common/named_union.hpp" -#include "barretenberg/honk/proof_system/types/proof.hpp" -#include - -namespace bb::bbapi { - -/** - * @struct CircuitInputNoVK - * @brief A circuit to be used in either ultrahonk or chonk (ClientIVC+honk) verification key derivation. - */ -struct CircuitInputNoVK { - /** - * @brief Human-readable name for the circuit - * - * This name is not used for processing but serves as a debugging aid and - * provides context for circuit identification in logs and diagnostics. - */ - std::string name; - - /** - * @brief Serialized bytecode representation of the circuit - * - * Contains the ACIR program in serialized form. The format (bincode or msgpack) - * is determined by examining the first byte of the bytecode. - */ - std::vector bytecode; -}; - -/** - * @struct CircuitInput - * @brief A circuit to be used in either ultrahonk or ClientIVC-honk proving. - */ -struct CircuitInput { - /** - * @brief Human-readable name for the circuit - * - * This name is not used for processing but serves as a debugging aid and - * provides context for circuit identification in logs and diagnostics. - */ - std::string name; - - /** - * @brief Serialized bytecode representation of the circuit - * - * Contains the ACIR program in serialized form. The format (bincode or msgpack) - * is determined by examining the first byte of the bytecode. - */ - std::vector bytecode; - - /** - * @brief Verification key of the circuit. This could be derived, but it is more efficient to have it fixed ahead of - * time. As well, this guards against unexpected changes in the verification key. - */ - std::vector verification_key; -}; - -struct ProofSystemSettings { - /** - * @brief Optional flag to indicate if the proof should be generated with IPA accumulation (i.e. for rollup - * circuits). - */ - bool ipa_accumulation = false; - - /** - * @brief The oracle hash type to be used for the proof. - * - * This is used to determine the hash function used in the proof generation. - * Valid values are "poseidon2", "keccak", and "starknet". - */ - std::string oracle_hash_type = "poseidon2"; - - /** - * @brief Flag to disable blinding of the proof. - * Useful for cases that don't require privacy, such as when all inputs are public or zk-SNARK proofs themselves. - */ - bool disable_zk = false; - - /** - * @brief Honk recursion setting. - * 0 = no recursion, 1 = UltraHonk recursion, 2 = UltraRollupHonk recursion. - * Controls whether pairing point accumulators and IPA claims are added to public inputs. - */ - uint32_t honk_recursion = 0; - - /** - * @brief Flag to indicate if this circuit will be recursively verified. - */ - bool recursive = false; -}; - -/** - * @struct CircuitProve - * @brief Represents a request to generate a proof. - * Currently, UltraHonk is the only proving system supported by BB (after plonk was deprecated and removed). - * This is used for one-shot proving, not our "IVC" scheme, ClientIVC-honk. For that, use the ClientIVC* commands. - * - * This structure is used to encapsulate all necessary parameters for generating a proof - * for a specific circuit, including the circuit bytecode, verification key, witness data, and options for the proving - * process. - */ -struct CircuitProve { - static constexpr const char* NAME = "CircuitProve"; - - /** - * @brief Contains proof and public inputs. - * Both are given as vectors of fields. To be used for verification. - * Example uses of this Response would be verification in native BB, WASM BB, solidity or recursively through Noir. - */ - struct Response { - static constexpr const char* NAME = "CircuitProveResponse"; - - PublicInputsVector public_inputs; - HonkProof proof; - // Empty if successful. - std::string error_message; - }; - - CircuitInput circuit; - std::vector witness; - ProofSystemSettings settings; -}; - -struct CircuitComputeVk { - static constexpr const char* NAME = "CircuitComputeVk"; - - struct Response { - static constexpr const char* NAME = "CircuitComputeVkResponse"; - - /** - * @brief Serialized verification key. - */ - std::vector verification_key; - // Empty if successful. - std::string error_message; - }; - - CircuitInputNoVK circuit; - ProofSystemSettings settings; -}; - -/** Compute verification key, Treat the previously loaded circuit as either a standalone circuit - * or a common final circuit used to verify all of IVC. */ -struct CircuitComputeIvcVk { - static constexpr const char* NAME = "CircuitComputeIvcVk"; - - struct Response { - static constexpr const char* NAME = "CircuitComputeIvcVkResponse"; - - /** - * @brief Serialized verification key. - */ - std::vector verification_key; - // Empty if successful. - std::string error_message; - }; - bool standalone; -}; - -/** Compute verification key, Treat the previously loaded circuit as either a standalone circuit - * or a common final circuit used to verify all of IVC. */ -struct ClientIvcComputeVk { - static constexpr const char* NAME = "ClientIvcComputeVk"; - - struct Response { - static constexpr const char* NAME = "ClientIvcComputeVkResponse"; - - /** - * @brief Serialized verification key. - */ - std::vector verification_key; - // Empty if successful. - std::string error_message; - }; - - CircuitInputNoVK circuit; - bool standalone; -}; - -/** - * @brief - * Note, only one IVC request can be made at a time for each batch_request. - */ -struct ClientIvcStart { - static constexpr const char* NAME = "ClientIvcStart"; - - struct Response { - static constexpr const char* NAME = "ClientIvcStartResponse"; - - // Empty if successful. - std::string error_message; - }; -}; - -struct ClientIvcLoad { - static constexpr const char* NAME = "ClientIvcLoad"; - - struct Response { - static constexpr const char* NAME = "ClientIvcLoadResponse"; - - // Empty if successful. - std::string error_message; - }; - - CircuitInput circuit; -}; - -struct ClientIvcAccumulate { - static constexpr const char* NAME = "ClientIvcAccumulate"; - - struct Response { - static constexpr const char* NAME = "ClientIvcAccumulateResponse"; - - // Empty if successful. - std::string error_message; - }; - - // Serialized witness for the last loaded circuit. - std::vector witness; -}; - -struct ClientIvcProve { - static constexpr const char* NAME = "ClientIvcProve"; - - struct Response { - static constexpr const char* NAME = "ClientIvcProveResponse"; - - ClientIVC::Proof proof; - // Empty if successful. - std::string error_message; - }; -}; - -/** - * @struct CircuitInfo - * @brief Consolidated command for retrieving circuit information. - * Combines gate count, circuit size, and other metadata into a single command. - */ -struct CircuitInfo { - static constexpr const char* NAME = "CircuitInfo"; - - struct Response { - static constexpr const char* NAME = "CircuitInfoResponse"; - - uint32_t total_gates; - uint32_t subgroup_size; - // Optional: gate counts per opcode - std::map gates_per_opcode; - // Empty if successful. - std::string error_message; - }; - - CircuitInput circuit; - bool include_gates_per_opcode = false; - ProofSystemSettings settings; -}; - -/** - * @struct CircuitCheck - * @brief Verify that a witness satisfies a circuit's constraints. - * For debugging and validation purposes. - */ -struct CircuitCheck { - static constexpr const char* NAME = "CircuitCheck"; - - struct Response { - static constexpr const char* NAME = "CircuitCheckResponse"; - - bool satisfied; - // Empty if successful, contains constraint failure details if not satisfied. - std::string error_message; - }; - - CircuitInput circuit; - std::vector witness; - ProofSystemSettings settings; -}; - -/** - * @struct CircuitVerify - * @brief Verify a proof against a verification key and public inputs. - */ -struct CircuitVerify { - static constexpr const char* NAME = "CircuitVerify"; - - struct Response { - static constexpr const char* NAME = "CircuitVerifyResponse"; - - bool verified; - // Empty if successful. - std::string error_message; - }; - - std::vector verification_key; - PublicInputsVector public_inputs; - HonkProof proof; - ProofSystemSettings settings; -}; - -/** - * @struct ProofAsFields - * @brief Convert a proof to field elements representation. - */ -struct ProofAsFields { - static constexpr const char* NAME = "ProofAsFields"; - - struct Response { - static constexpr const char* NAME = "ProofAsFieldsResponse"; - - std::vector fields; - // Empty if successful. - std::string error_message; - }; - - HonkProof proof; -}; - -/** - * @struct VkAsFields - * @brief Convert a verification key to field elements representation. - */ -struct VkAsFields { - static constexpr const char* NAME = "VkAsFields"; - - struct Response { - static constexpr const char* NAME = "VkAsFieldsResponse"; - - std::vector fields; - // Empty if successful. - std::string error_message; - }; - - std::vector verification_key; - bool is_mega_honk = false; -}; - -/** - * @brief Command to generate Solidity verifier contract - */ -struct CircuitWriteSolidityVerifier { - static constexpr const char* NAME = "CircuitWriteSolidityVerifier"; - - struct Response { - static constexpr const char* NAME = "CircuitWriteSolidityVerifierResponse"; - - std::string solidity_code; - std::string error_message; - }; - - std::vector verification_key; - ProofSystemSettings settings; -}; - -/** - * @brief Command to prove and verify in one step - */ -struct CircuitProveAndVerify { - static constexpr const char* NAME = "CircuitProveAndVerify"; - - struct Response { - static constexpr const char* NAME = "CircuitProveAndVerifyResponse"; - - bool verified; - std::vector proof; // The generated proof - std::vector public_inputs; // Extracted public inputs - std::string error_message; - }; - - CircuitInput circuit; - std::vector witness; - ProofSystemSettings settings; -}; - -/** - * @brief Command to write circuit bytecode in various formats - */ -struct CircuitWriteBytecode { - static constexpr const char* NAME = "CircuitWriteBytecode"; - - struct Response { - static constexpr const char* NAME = "CircuitWriteBytecodeResponse"; - - std::vector bytecode; - std::string formatted_output; // For hex/base64 - std::string error_message; - }; - - CircuitInput circuit; - std::string format = "binary"; // binary, hex, base64 -}; - -/** - * @brief Command to validate circuit structure - */ -struct CircuitValidate { - static constexpr const char* NAME = "CircuitValidate"; - - struct Response { - static constexpr const char* NAME = "CircuitValidateResponse"; - - bool is_valid; - std::vector validation_errors; - std::string error_message; - }; - - CircuitInput circuit; - ProofSystemSettings settings; - bool check_recursive_structure = false; -}; - -/** - * @brief Command to benchmark circuit operations - */ -struct CircuitBenchmark { - static constexpr const char* NAME = "CircuitBenchmark"; - - struct Response { - static constexpr const char* NAME = "CircuitBenchmarkResponse"; - - double witness_generation_time_ms; - double proving_time_ms; - double verification_time_ms; - uint64_t peak_memory_bytes; - std::string error_message; - }; - - CircuitInput circuit; - std::vector witness; - ProofSystemSettings settings; - uint32_t num_iterations = 1; - bool benchmark_witness_generation = true; - bool benchmark_proving = true; -}; - -/** - * @brief Command to check if a precomputed VK matches the circuit - */ -struct ClientIvcCheckPrecomputedVk { - static constexpr const char* NAME = "ClientIvcCheckPrecomputedVk"; - - struct Response { - static constexpr const char* NAME = "ClientIvcCheckPrecomputedVkResponse"; - - bool valid; - std::string error_message; - }; - - // Circuit with its precomputed VK - CircuitInput circuit; - std::string function_name; -}; - -using Command = NamedUnion; - -using CommandResponse = NamedUnion; - -// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve -// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. -template -concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v; - -/** - * @brief Convert oracle hash type string to enum for internal use - */ -enum class OracleHashType { POSEIDON2, KECCAK, STARKNET }; - -inline OracleHashType parse_oracle_hash_type(const std::string& type) -{ - if (type == "keccak") { - return OracleHashType::KECCAK; - } - if (type == "starknet") { - return OracleHashType::STARKNET; - } - return OracleHashType::POSEIDON2; // default -} - -} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index 1eb375ef824c..adad556b9cd5 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -1,22 +1,8 @@ #pragma once -#include "barretenberg/api/bbapi_commands.hpp" -#include "barretenberg/api/write_prover_output.hpp" -#include "barretenberg/circuit_checker/circuit_checker.hpp" -#include "barretenberg/client_ivc/client_ivc.hpp" -#include "barretenberg/client_ivc/mock_circuit_producer.hpp" -#include "barretenberg/common/compiler_hints.hpp" -#include "barretenberg/common/log.hpp" +#include "barretenberg/api/bbapi.hpp" #include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/dsl/acir_format/acir_format.hpp" -#include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" -#include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" -#include "barretenberg/honk/execution_trace/mega_execution_trace.hpp" -#include "barretenberg/serialize/msgpack_check_eq.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include -#include +#include namespace bb::bbapi { @@ -31,220 +17,6 @@ inline std::string field_elements_to_json(const std::vector& fields) return format("[", join(transform::map(fields, [](auto fr) { return format("\"", fr, "\""); })), "]"); } -struct BBApiRequest { - TraceSettings trace_settings{ AZTEC_TRACE_STRUCTURE }; - // Current depth of the IVC stack for this request - uint32_t ivc_stack_depth = 0; - std::shared_ptr ivc_in_progress; - // Name of the last loaded circuit - std::string last_circuit_name; - // Store the parsed constraint system to get ahead of parsing before accumulate - std::optional last_circuit_constraints; - // Store the verification key passed with the circuit - std::vector last_circuit_vk; -}; - -inline const std::string& get_error_message(const CommandResponse& response) -{ - return response.visit([](const auto& resp) -> const std::string& { return resp.error_message; }); -} - -inline CircuitProve::Response execute(BB_UNUSED BBApiRequest& request, CircuitProve&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline CircuitComputeVk::Response execute(BB_UNUSED BBApiRequest& request, CircuitComputeVk&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline CircuitVerify::Response execute(BB_UNUSED BBApiRequest& request, CircuitVerify&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline CircuitInfo::Response execute(BB_UNUSED BBApiRequest& request, CircuitInfo&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline CircuitCheck::Response execute(BB_UNUSED BBApiRequest& request, CircuitCheck&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline ProofAsFields::Response execute(BB_UNUSED BBApiRequest& request, ProofAsFields&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline VkAsFields::Response execute(BB_UNUSED BBApiRequest& request, VkAsFields&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline ClientIvcStart::Response execute(BBApiRequest& request, BB_UNUSED ClientIvcStart&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline ClientIvcLoad::Response execute(BBApiRequest& request, ClientIvcLoad&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline ClientIvcAccumulate::Response execute(BBApiRequest& request, ClientIvcAccumulate&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - -inline ClientIvcProve::Response execute(BBApiRequest& request, BB_UNUSED ClientIvcProve&& command) -{ - if (!request.ivc_in_progress) { - return ClientIvcProve::Response{ .proof = {}, - .error_message = "ClientIVC not started. Call ClientIvcStart first." }; - } - - if (request.ivc_stack_depth == 0) { - return ClientIvcProve::Response{ .proof = {}, - .error_message = "No circuits accumulated. Call ClientIvcAccumulate first." }; - } - - info("ClientIvcProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits"); - - ClientIVC::Proof proof = request.ivc_in_progress->prove(); - - // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS, - // and it is mysterious if this transaction fails later in the lifecycle. - // The files are still written in case they are needed to investigate this failure. - if (!request.ivc_in_progress->verify(proof)) { - return ClientIvcProve::Response{ .proof = {}, .error_message = "Failed to verify the generated proof!" }; - } - - request.ivc_in_progress.reset(); - request.ivc_stack_depth = 0; - - return ClientIvcProve::Response{ .proof = std::move(proof), .error_message = "" }; -} - -inline std::shared_ptr get_acir_program_decider_proving_key( - const BBApiRequest& request, acir_format::AcirProgram& program) -{ - ClientIVC::ClientCircuit builder = acir_format::create_circuit(program); - - // Construct the verification key via the prover-constructed proving key with the proper trace settings - return std::make_shared(builder, request.trace_settings); -} - -inline ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, - size_t num_public_inputs_in_final_circuit) -{ - ClientIVC ivc{ /*num_circuits=*/2, request.trace_settings }; - ClientIVCMockCircuitProducer circuit_producer; - - // Initialize the IVC with an arbitrary circuit - // We segfault if we only call accumulate once - static constexpr size_t SMALL_ARBITRARY_LOG_CIRCUIT_SIZE{ 5 }; - MegaCircuitBuilder circuit_0 = circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE); - ivc.accumulate(circuit_0); - - // Create another circuit and accumulate - MegaCircuitBuilder circuit_1 = - circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE, num_public_inputs_in_final_circuit); - ivc.accumulate(circuit_1); - - // Construct the hiding circuit and its VK (stored internally in the IVC) - ivc.construct_hiding_circuit_key(); - - return ivc.get_vk(); -} - -inline ClientIvcComputeStandaloneVk::Response execute(BBApiRequest& request, ClientIvcComputeStandaloneVk&& command) -{ - info("ClientIvcComputeVk - deriving VK for circuit '", command.circuit.name, "', standalone: ", command.standalone); - - // Parse the circuit - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(command.circuit.bytecode)); - - // Create verification key based on whether it's standalone or not - std::vector vk_data; - if (command.standalone) { - // For standalone, we just need the circuit's verification key (not the full IVC VK) - acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - std::shared_ptr proving_key = - get_acir_program_decider_proving_key(request, program); - auto verification_key = std::make_shared(proving_key->get_precomputed()); - vk_data = to_buffer(*verification_key); - info("ClientIvcComputeVk - standalone VK derived, size: ", vk_data.size(), " bytes"); - } else { - vk_data = to_buffer(compute_vk_for_ivc(request, constraint_system.public_inputs.size())); - info("ClientIvcComputeVk - full IVC VK derived, size: ", vk_data.size(), " bytes"); - } - - acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); - auto verification_key = std::make_shared(proving_key->proving_key); - - response.vk_bytes = to_buffer(*verification_key); - response.vk_fields = verification_key->to_field_elements(); - - info("ClientIvcComputeStandaloneVk - VK derived, size: ", response.vk_bytes.size(), " bytes"); - - response.error_message = ""; - return response; -} - -inline ClientIvcComputeIvcVk::Response execute(BBApiRequest& request, ClientIvcComputeIvcVk&& command) -{ - info("ClientIvcComputeIvcVk - deriving IVC VK for circuit '", command.circuit.name, "'"); - - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(command.circuit.bytecode)); - - ClientIvcComputeIvcVk::Response response; - - auto vk = compute_vk_for_ivc(request, constraint_system.public_inputs.size()); - response.vk_bytes = to_buffer(vk); - - info("ClientIvcComputeIvcVk - IVC VK derived, size: ", response.vk_bytes.size(), " bytes"); - - response.error_message = ""; - return response; -} - -template inline typename T::Response execute(T&& command) -{ - BBApiRequest request; - return execute_or_throw(request, std::forward(command)); -} - -inline ClientIvcCheckPrecomputedVk::Response execute(BBApiRequest& request, ClientIvcCheckPrecomputedVk&& command) -{ - (void)request; - (void)command; - throw_or_abort("code in progress! should not be called"); -} - /** * @brief Executes a command by visiting a variant of all possible commands. * @@ -254,8 +26,14 @@ inline ClientIvcCheckPrecomputedVk::Response execute(BBApiRequest& request, Clie */ inline CommandResponse execute(BBApiRequest& request, Command&& command) { - return std::move(command).visit( - [&request](auto&& cmd) -> CommandResponse { return execute(request, std::forward(cmd)); }); + return std::move(command).visit([&request](auto&& cmd) -> CommandResponse { + using CmdType = std::decay_t; + if constexpr (RequiresBBApiRequest) { + return cmd.execute(request); + } else { + return cmd.execute(request); + } + }); } // Can only be called from the execution thread (the same as the main thread, except in threaded WASM). @@ -264,10 +42,11 @@ inline std::vector execute_request(BBApiRequest&& request, std: std::vector responses; responses.reserve(commands.size()); for (Command& command : commands) { - responses.push_back(execute(request, std::move(command))); - if (!get_error_message(responses.back()).empty()) { + try { + responses.push_back(execute(request, std::move(command))); + } catch (const std::exception& e) { // If there was an error, we stop processing further commands. - break; + throw_or_abort(e.what()); } } return responses; @@ -281,21 +60,11 @@ inline typename T::Response do_bbapi(T&& command) requires(!bbapi::RequiresBBApiRequest) { bbapi::BBApiRequest request; - typename T::Response result = execute(request, std::forward(command)); - const std::string& error_message = bbapi::get_error_message(result); - if (error_message.empty()) { - return result; - } - throw std::runtime_error{ error_message }; + return command.execute(request); } template inline typename T::Response do_bbapi(bbapi::BBApiRequest& request, T&& command) { - typename T::Response result = execute(request, std::forward(command)); - const std::string& error_message = bbapi::get_error_message(result); - if (error_message.empty()) { - return result; - } - throw std::runtime_error{ error_message }; + return command.execute(request); } -} // namespace bb +} // namespace bb \ No newline at end of file From 73a367ebc3b77dd4a635e0fbb7d193a911167ee0 Mon Sep 17 00:00:00 2001 From: ludamad Date: Fri, 4 Jul 2025 22:38:14 +0000 Subject: [PATCH 03/30] interim --- .../cpp/src/barretenberg/api/bbapi.hpp | 60 ++++ .../src/barretenberg/api/bbapi_client_ivc.cpp | 186 ++++++++++++ .../src/barretenberg/api/bbapi_client_ivc.hpp | 114 ++++++++ .../cpp/src/barretenberg/api/bbapi_shared.hpp | 131 +++++++++ .../src/barretenberg/api/bbapi_ultra_honk.cpp | 217 ++++++++++++++ .../src/barretenberg/api/bbapi_ultra_honk.hpp | 273 ++++++++++++++++++ 6 files changed, 981 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi.hpp create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp create mode 100644 barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi.hpp new file mode 100644 index 000000000000..eb3d4df1b8f0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi.hpp @@ -0,0 +1,60 @@ +#pragma once +/** + * @file bbapi_commands.hpp + * @brief Central command definitions BB's outward-facing API. + * + * This file includes and exports all command structures from specialized headers + * and provides unified Command and CommandResponse types for the API. + */ +#include "barretenberg/api/bbapi_client_ivc.hpp" +#include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/api/bbapi_ultra_honk.hpp" +#include "barretenberg/common/named_union.hpp" + +namespace bb::bbapi { +using Command = NamedUnion; + +using CommandResponse = NamedUnion; + +// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve +// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. +template +concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp new file mode 100644 index 000000000000..af1cfba80fc2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -0,0 +1,186 @@ +#include "barretenberg/api/bbapi_client_ivc.hpp" +#include "barretenberg/client_ivc/mock_circuit_producer.hpp" +#include "barretenberg/common/log.hpp" +#include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/dsl/acir_format/acir_format.hpp" +#include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" +#include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" +#include "barretenberg/serialize/msgpack_check_eq.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" + +namespace bb::bbapi { + +ClientIvcStart::Response ClientIvcStart::execute(BBApiRequest& request) const +{ + request.ivc_in_progress = std::make_shared(request.trace_settings); + request.ivc_stack_depth = 0; + return Response{}; +} + +ClientIvcLoad::Response ClientIvcLoad::execute(BBApiRequest& request) const +{ + if (!request.ivc_in_progress) { + throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); + } + + request.last_circuit_name = circuit.name; + request.last_circuit_constraints = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + request.last_circuit_vk = circuit.verification_key; + + info("ClientIvcLoad - loaded circuit '", request.last_circuit_name, "'"); + + return Response{}; +} + +ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request) const +{ + if (!request.ivc_in_progress) { + throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); + } + + if (!request.last_circuit_constraints.has_value()) { + throw_or_abort("No circuit loaded. Call ClientIvcLoad first."); + } + + acir_format::WitnessVector witness_data = acir_format::witness_buf_to_witness_data(witness); + acir_format::AcirProgram program{ std::move(request.last_circuit_constraints.value()), std::move(witness_data) }; + + const acir_format::ProgramMetadata metadata{ request.ivc_in_progress }; + auto circuit = acir_format::create_circuit(program, metadata); + + std::shared_ptr precomputed_vk; + if (!request.last_circuit_vk.empty()) { + precomputed_vk = from_buffer>(request.last_circuit_vk); + } + + info("ClientIvcAccumulate - accumulating circuit '", request.last_circuit_name, "'"); + request.ivc_in_progress->accumulate(circuit, precomputed_vk); + request.ivc_stack_depth++; + + request.last_circuit_constraints.reset(); + request.last_circuit_vk.clear(); + + return Response{}; +} + +ClientIvcProve::Response ClientIvcProve::execute(BBApiRequest& request) const +{ + if (!request.ivc_in_progress) { + throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); + } + + if (request.ivc_stack_depth == 0) { + throw_or_abort("No circuits accumulated. Call ClientIvcAccumulate first."); + } + + info("ClientIvcProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits"); + + ClientIVC::Proof proof = request.ivc_in_progress->prove(); + + // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS, + // and it is mysterious if this transaction fails later in the lifecycle. + if (!request.ivc_in_progress->verify(proof)) { + throw_or_abort("Failed to verify the generated proof!"); + } + + request.ivc_in_progress.reset(); + request.ivc_stack_depth = 0; + + Response response; + response.proof = std::move(proof); + return response; +} + +static std::shared_ptr get_acir_program_decider_proving_key( + const BBApiRequest& request, acir_format::AcirProgram& program) +{ + ClientIVC::ClientCircuit builder = acir_format::create_circuit(program); + + // Construct the verification key via the prover-constructed proving key with the proper trace settings + return std::make_shared(builder, request.trace_settings); +} + +static ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, + size_t num_public_inputs_in_final_circuit) +{ + ClientIVC ivc{ request.trace_settings }; + ClientIVCMockCircuitProducer circuit_producer; + + // Initialize the IVC with an arbitrary circuit + // We segfault if we only call accumulate once + static constexpr size_t SMALL_ARBITRARY_LOG_CIRCUIT_SIZE{ 5 }; + MegaCircuitBuilder circuit_0 = circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE); + ivc.accumulate(circuit_0); + + // Create another circuit and accumulate + MegaCircuitBuilder circuit_1 = + circuit_producer.create_next_circuit(ivc, SMALL_ARBITRARY_LOG_CIRCUIT_SIZE, num_public_inputs_in_final_circuit); + ivc.accumulate(circuit_1); + + // Construct the hiding circuit and its VK (stored internally in the IVC) + ivc.construct_hiding_circuit_key(); + + return ivc.get_vk(); +} + +ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(const BBApiRequest& request) const +{ + info("ClientIvcComputeStandaloneVk - deriving VK for circuit '", circuit.name, "'"); + + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + + acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; + std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); + auto verification_key = std::make_shared(proving_key->proving_key); + + Response response; + response.bytes = to_buffer(*verification_key); + response.fields = verification_key->to_field_elements(); + + info("ClientIvcComputeStandaloneVk - VK derived, size: ", response.bytes.size(), " bytes"); + + return response; +} + +ClientIvcComputeIvcVk::Response ClientIvcComputeIvcVk::execute(const BBApiRequest& request) const +{ + info("ClientIvcComputeIvcVk - deriving IVC VK for circuit '", circuit.name, "'"); + + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + + auto vk = compute_vk_for_ivc(request, constraint_system.public_inputs.size()); + + Response response; + response.bytes = to_buffer(vk); + + info("ClientIvcComputeIvcVk - IVC VK derived, size: ", response.bytes.size(), " bytes"); + + return response; +} + +ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const BBApiRequest& request) const +{ + acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(circuit.bytecode), + /*witness=*/{} }; + + std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); + auto computed_vk = std::make_shared(proving_key->proving_key); + + if (circuit.verification_key.empty()) { + info("FAIL: Expected precomputed vk for function ", function_name); + throw_or_abort("Missing precomputed VK"); + } + + auto precomputed_vk = from_buffer>(circuit.verification_key); + + std::string error_message = "Precomputed vk does not match computed vk for function " + function_name; + if (!msgpack::msgpack_check_eq(*computed_vk, *precomputed_vk, error_message)) { + throw_or_abort(error_message); + } + + Response response; + response.valid = true; + return response; +} + +} // namespace bb::bbapi \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp new file mode 100644 index 000000000000..d71937991b99 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -0,0 +1,114 @@ +#pragma once +/** + * @file bbapi_client_ivc.hpp + * @brief ClientIVC-specific command definitions for the Barretenberg RPC API. + * + * This file contains command structures for ClientIVC (Client-side Incrementally Verifiable Computation) + * operations including circuit loading, accumulation, proving, and verification key computation. + */ +#include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/common/named_union.hpp" +#include "barretenberg/honk/proof_system/types/proof.hpp" +#include + +namespace bb::bbapi { + +/** + * @brief + * Note, only one IVC request can be made at a time for each batch_request. + */ +struct ClientIvcStart { + static constexpr const char* NAME = "ClientIvcStart"; + + struct Response { + static constexpr const char* NAME = "ClientIvcStartResponse"; + // Empty response - success indicated by no exception + }; + Response execute(BBApiRequest& request) const; +}; + +struct ClientIvcLoad { + static constexpr const char* NAME = "ClientIvcLoad"; + + struct Response { + static constexpr const char* NAME = "ClientIvcLoadResponse"; + // Empty response - success indicated by no exception + }; + + CircuitInput circuit; + Response execute(BBApiRequest& request) const; +}; + +struct ClientIvcAccumulate { + static constexpr const char* NAME = "ClientIvcAccumulate"; + + struct Response { + static constexpr const char* NAME = "ClientIvcAccumulateResponse"; + // Empty response - success indicated by no exception + }; + + // Serialized witness for the last loaded circuit. + std::vector witness; + Response execute(BBApiRequest& request) const; +}; + +struct ClientIvcProve { + static constexpr const char* NAME = "ClientIvcProve"; + + struct Response { + static constexpr const char* NAME = "ClientIvcProveResponse"; + + ClientIVC::Proof proof; + }; + Response execute(BBApiRequest& request) const; +}; + +/** Compute standalone verification key for a circuit */ +struct ClientIvcComputeStandaloneVk { + static constexpr const char* NAME = "ClientIvcComputeStandaloneVk"; + + struct Response { + static constexpr const char* NAME = "ClientIvcComputeStandaloneVkResponse"; + + std::vector bytes; // Serialized verification key + std::vector fields; // Verification key as field elements + }; + + CircuitInputNoVK circuit; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** Compute IVC verification key */ +struct ClientIvcComputeIvcVk { + static constexpr const char* NAME = "ClientIvcComputeIvcVk"; + + struct Response { + static constexpr const char* NAME = "ClientIvcComputeIvcVkResponse"; + + std::vector bytes; // Serialized IVC verification key + }; + + CircuitInputNoVK circuit; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to check if a precomputed VK matches the circuit + */ +struct ClientIvcCheckPrecomputedVk { + static constexpr const char* NAME = "ClientIvcCheckPrecomputedVk"; + + struct Response { + static constexpr const char* NAME = "ClientIvcCheckPrecomputedVkResponse"; + + bool valid; + }; + + // Circuit with its precomputed VK + CircuitInput circuit; + std::string function_name; + Response execute(const BBApiRequest& request = {}) const; +}; + +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp new file mode 100644 index 000000000000..ca4c50528717 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp @@ -0,0 +1,131 @@ +#pragma once +/** + * @file bbapi_shared.hpp + * @brief Shared type definitions for the Barretenberg RPC API. + * + * This file contains common data structures used across multiple bbapi modules, + * including circuit input types and proof system settings. + */ +#include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/dsl/acir_format/acir_format.hpp" +#include "barretenberg/honk/execution_trace/mega_execution_trace.hpp" +#include +#include +#include + +namespace bb::bbapi { + +/** + * @struct CircuitInputNoVK + * @brief A circuit to be used in either ultrahonk or chonk (ClientIVC+honk) verification key derivation. + */ +struct CircuitInputNoVK { + /** + * @brief Human-readable name for the circuit + * + * This name is not used for processing but serves as a debugging aid and + * provides context for circuit identification in logs and diagnostics. + */ + std::string name; + + /** + * @brief Serialized bytecode representation of the circuit + * + * Contains the ACIR program in serialized form. The format (bincode or msgpack) + * is determined by examining the first byte of the bytecode. + */ + std::vector bytecode; +}; + +/** + * @struct CircuitInput + * @brief A circuit to be used in either ultrahonk or ClientIVC-honk proving. + */ +struct CircuitInput { + /** + * @brief Human-readable name for the circuit + * + * This name is not used for processing but serves as a debugging aid and + * provides context for circuit identification in logs and diagnostics. + */ + std::string name; + + /** + * @brief Serialized bytecode representation of the circuit + * + * Contains the ACIR program in serialized form. The format (bincode or msgpack) + * is determined by examining the first byte of the bytecode. + */ + std::vector bytecode; + + /** + * @brief Verification key of the circuit. This could be derived, but it is more efficient to have it fixed ahead of + * time. As well, this guards against unexpected changes in the verification key. + */ + std::vector verification_key; +}; + +struct ProofSystemSettings { + /** + * @brief Optional flag to indicate if the proof should be generated with IPA accumulation (i.e. for rollup + * circuits). + */ + bool ipa_accumulation = false; + + /** + * @brief The oracle hash type to be used for the proof. + * + * This is used to determine the hash function used in the proof generation. + * Valid values are "poseidon2", "keccak", and "starknet". + */ + std::string oracle_hash_type = "poseidon2"; + + /** + * @brief Flag to disable blinding of the proof. + * Useful for cases that don't require privacy, such as when all inputs are public or zk-SNARK proofs themselves. + */ + bool disable_zk = false; + + /** + * @brief Honk recursion setting. + * 0 = no recursion, 1 = UltraHonk recursion, 2 = UltraRollupHonk recursion. + * Controls whether pairing point accumulators and IPA claims are added to public inputs. + */ + uint32_t honk_recursion = 0; + + /** + * @brief Flag to indicate if this circuit will be recursively verified. + */ + bool recursive = false; +}; + +/** + * @brief Convert oracle hash type string to enum for internal use + */ +enum class OracleHashType { POSEIDON2, KECCAK, STARKNET }; + +inline OracleHashType parse_oracle_hash_type(const std::string& type) +{ + if (type == "keccak") { + return OracleHashType::KECCAK; + } + if (type == "starknet") { + return OracleHashType::STARKNET; + } + return OracleHashType::POSEIDON2; // default +} + +struct BBApiRequest { + TraceSettings trace_settings{ AZTEC_TRACE_STRUCTURE }; + // Current depth of the IVC stack for this request + uint32_t ivc_stack_depth = 0; + std::shared_ptr ivc_in_progress; + // Name of the last loaded circuit + std::string last_circuit_name; + // Store the parsed constraint system to get ahead of parsing before accumulate + std::optional last_circuit_constraints; + // Store the verification key passed with the circuit + std::vector last_circuit_vk; +}; + +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp new file mode 100644 index 000000000000..5b46f2cba33c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -0,0 +1,217 @@ +#include "barretenberg/api/bbapi_ultra_honk.hpp" +#include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/common/serialize.hpp" +#include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/dsl/acir_format/acir_format.hpp" +#include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" +#include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" +#include "barretenberg/honk/proof_system/ultra_prover.hpp" +#include "barretenberg/honk/proof_system/ultra_verifier.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/ultra_honk/mega_composer.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" +#include +#include + +namespace bb::bbapi { + +// Helper functions for format conversions +static std::string bytes_to_hex(const std::vector& bytes) +{ + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (uint8_t b : bytes) { + ss << std::setw(2) << static_cast(b); + } + return ss.str(); +} + +static std::string bytes_to_base64(const std::vector& bytes) +{ + // TODO: Implement base64 encoding + throw_or_abort("Base64 encoding not implemented"); +} + +CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) const +{ + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto witness = acir_format::witness_buf_to_witness_data(this->witness); + + acir_format::AcirProgram program{ constraint_system, witness }; + auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + + auto composer = UltraComposer(); + auto prover = composer.create_prover(builder); + auto proof = prover.construct_proof(); + + Response response; + response.proof = proof; + response.public_inputs = builder.get_public_inputs(); + + return response; +} + +CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request) const +{ + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; + + auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + auto composer = UltraComposer(); + auto proving_key = composer.compute_proving_key(builder); + auto verification_key = composer.compute_verification_key(proving_key); + + Response response; + response.bytes = to_buffer(*verification_key); + + return response; +} + +CircuitComputeIvcVk::Response CircuitComputeIvcVk::execute(const BBApiRequest& request) const +{ + throw_or_abort("CircuitComputeIvcVk not implemented yet"); +} + +CircuitInfo::Response CircuitInfo::execute(const BBApiRequest& request) const +{ + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; + + auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + + Response response; + response.total_gates = static_cast(builder.get_num_gates()); + response.subgroup_size = static_cast(builder.get_circuit_subgroup_size()); + + if (include_gates_per_opcode) { + // TODO: Implement gate counting per opcode + response.gates_per_opcode = {}; + } + + return response; +} + +CircuitCheck::Response CircuitCheck::execute(const BBApiRequest& request) const +{ + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto witness = acir_format::witness_buf_to_witness_data(this->witness); + + acir_format::AcirProgram program{ constraint_system, witness }; + auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + + Response response; + response.satisfied = builder.check_circuit(); + + return response; +} + +CircuitVerify::Response CircuitVerify::execute(const BBApiRequest& request) const +{ + auto vk = from_buffer>(verification_key); + + UltraVerifier verifier(vk); + bool verified = verifier.verify_proof(proof); + + Response response; + response.verified = verified; + + return response; +} + +ProofAsFields::Response ProofAsFields::execute(const BBApiRequest& request) const +{ + Response response; + + // Convert proof bytes to field elements + size_t num_fields = proof.size() / sizeof(bb::fr); + response.fields.reserve(num_fields); + + const auto* data = reinterpret_cast(proof.data()); + for (size_t i = 0; i < num_fields; ++i) { + response.fields.push_back(data[i]); + } + + return response; +} + +VkAsFields::Response VkAsFields::execute(const BBApiRequest& request) const +{ + Response response; + + if (is_mega_honk) { + auto vk = from_buffer>(verification_key); + response.fields = vk->to_field_elements(); + } else { + auto vk = from_buffer>(verification_key); + response.fields = vk->to_field_elements(); + } + + return response; +} + +CircuitWriteSolidityVerifier::Response CircuitWriteSolidityVerifier::execute(const BBApiRequest& request) const +{ + throw_or_abort("CircuitWriteSolidityVerifier not implemented yet"); +} + +CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiRequest& request) const +{ + // First prove + auto prove_result = CircuitProve{ circuit, witness, settings }.execute(request); + + // Then compute VK + auto vk_result = CircuitComputeVk{ CircuitInputNoVK{ circuit.name, circuit.bytecode }, settings }.execute(request); + + // Then verify + auto verify_result = + CircuitVerify{ vk_result.bytes, prove_result.public_inputs, prove_result.proof, settings }.execute(request); + + Response response; + response.verified = verify_result.verified; + response.proof = prove_result.proof; + response.public_inputs = prove_result.public_inputs; + + return response; +} + +CircuitWriteBytecode::Response CircuitWriteBytecode::execute(const BBApiRequest& request) const +{ + Response response; + response.bytecode = circuit.bytecode; + + if (format == "hex") { + response.formatted_output = bytes_to_hex(circuit.bytecode); + } else if (format == "base64") { + response.formatted_output = bytes_to_base64(circuit.bytecode); + } + + return response; +} + +CircuitValidate::Response CircuitValidate::execute(const BBApiRequest& request) const +{ + Response response; + response.is_valid = true; + response.validation_errors.clear(); + + try { + auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + // Basic validation passed if we can parse it + + if (check_recursive_structure) { + // TODO: Add recursive structure validation + } + } catch (const std::exception& e) { + response.is_valid = false; + response.validation_errors.push_back(e.what()); + } + + return response; +} + +CircuitBenchmark::Response CircuitBenchmark::execute(const BBApiRequest& request) const +{ + throw_or_abort("CircuitBenchmark not implemented yet"); +} + +} // namespace bb::bbapi \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp new file mode 100644 index 000000000000..bdbf179bb1b0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp @@ -0,0 +1,273 @@ +#pragma once +/** + * @file bbapi_ultra_honk.hpp + * @brief UltraHonk-specific command definitions for the Barretenberg RPC API. + * + * This file contains command structures for UltraHonk proof system operations + * including circuit proving, verification, VK computation, and utility functions. + */ +#include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/common/named_union.hpp" +#include "barretenberg/honk/proof_system/types/proof.hpp" +#include +#include + +namespace bb::bbapi { + +// CircuitInput, CircuitInputNoVK, and ProofSystemSettings are defined in bbapi_shared.hpp + +/** + * @struct CircuitProve + * @brief Represents a request to generate a proof. + * Currently, UltraHonk is the only proving system supported by BB (after plonk was deprecated and removed). + * This is used for one-shot proving, not our "IVC" scheme, ClientIVC-honk. For that, use the ClientIVC* commands. + * + * This structure is used to encapsulate all necessary parameters for generating a proof + * for a specific circuit, including the circuit bytecode, verification key, witness data, and options for the proving + * process. + */ +struct CircuitProve { + static constexpr const char* NAME = "CircuitProve"; + + /** + * @brief Contains proof and public inputs. + * Both are given as vectors of fields. To be used for verification. + * Example uses of this Response would be verification in native BB, WASM BB, solidity or recursively through Noir. + */ + struct Response { + static constexpr const char* NAME = "CircuitProveResponse"; + + PublicInputsVector public_inputs; + HonkProof proof; + }; + + CircuitInput circuit; + std::vector witness; + ProofSystemSettings settings; +}; + +struct CircuitComputeVk { + static constexpr const char* NAME = "CircuitComputeVk"; + + struct Response { + static constexpr const char* NAME = "CircuitComputeVkResponse"; + + std::vector bytes; // Serialized verification key + }; + + CircuitInputNoVK circuit; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** Compute verification key, Treat the previously loaded circuit as either a standalone circuit + * or a common final circuit used to verify all of IVC. */ +struct CircuitComputeIvcVk { + static constexpr const char* NAME = "CircuitComputeIvcVk"; + + struct Response { + static constexpr const char* NAME = "CircuitComputeIvcVkResponse"; + + std::vector bytes; // Serialized verification key + }; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @struct CircuitInfo + * @brief Consolidated command for retrieving circuit information. + * Combines gate count, circuit size, and other metadata into a single command. + */ +struct CircuitInfo { + static constexpr const char* NAME = "CircuitInfo"; + + struct Response { + static constexpr const char* NAME = "CircuitInfoResponse"; + + uint32_t total_gates; + uint32_t subgroup_size; + std::map gates_per_opcode; // Optional: gate counts per opcode + }; + + CircuitInput circuit; + bool include_gates_per_opcode = false; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @struct CircuitCheck + * @brief Verify that a witness satisfies a circuit's constraints. + * For debugging and validation purposes. + */ +struct CircuitCheck { + static constexpr const char* NAME = "CircuitCheck"; + + struct Response { + static constexpr const char* NAME = "CircuitCheckResponse"; + + bool satisfied; + }; + + CircuitInput circuit; + std::vector witness; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @struct CircuitVerify + * @brief Verify a proof against a verification key and public inputs. + */ +struct CircuitVerify { + static constexpr const char* NAME = "CircuitVerify"; + + struct Response { + static constexpr const char* NAME = "CircuitVerifyResponse"; + + bool verified; + }; + + std::vector verification_key; + PublicInputsVector public_inputs; + HonkProof proof; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @struct ProofAsFields + * @brief Convert a proof to field elements representation. + */ +struct ProofAsFields { + static constexpr const char* NAME = "ProofAsFields"; + + struct Response { + static constexpr const char* NAME = "ProofAsFieldsResponse"; + + std::vector fields; + }; + + HonkProof proof; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @struct VkAsFields + * @brief Convert a verification key to field elements representation. + */ +struct VkAsFields { + static constexpr const char* NAME = "VkAsFields"; + + struct Response { + static constexpr const char* NAME = "VkAsFieldsResponse"; + + std::vector fields; + }; + + std::vector verification_key; + bool is_mega_honk = false; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to generate Solidity verifier contract + */ +struct CircuitWriteSolidityVerifier { + static constexpr const char* NAME = "CircuitWriteSolidityVerifier"; + + struct Response { + static constexpr const char* NAME = "CircuitWriteSolidityVerifierResponse"; + + std::string solidity_code; + }; + + std::vector verification_key; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to prove and verify in one step + */ +struct CircuitProveAndVerify { + static constexpr const char* NAME = "CircuitProveAndVerify"; + + struct Response { + static constexpr const char* NAME = "CircuitProveAndVerifyResponse"; + + bool verified; + HonkProof proof; + PublicInputsVector public_inputs; + }; + + CircuitInput circuit; + std::vector witness; + ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to write circuit bytecode in various formats + */ +struct CircuitWriteBytecode { + static constexpr const char* NAME = "CircuitWriteBytecode"; + + struct Response { + static constexpr const char* NAME = "CircuitWriteBytecodeResponse"; + + std::vector bytecode; + std::string formatted_output; // For hex/base64 + }; + + CircuitInput circuit; + std::string format = "binary"; // binary, hex, base64 + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to validate circuit structure + */ +struct CircuitValidate { + static constexpr const char* NAME = "CircuitValidate"; + + struct Response { + static constexpr const char* NAME = "CircuitValidateResponse"; + + bool is_valid; + std::vector validation_errors; + }; + + CircuitInput circuit; + ProofSystemSettings settings; + bool check_recursive_structure = false; + Response execute(const BBApiRequest& request = {}) const; +}; + +/** + * @brief Command to benchmark circuit operations + */ +struct CircuitBenchmark { + static constexpr const char* NAME = "CircuitBenchmark"; + + struct Response { + static constexpr const char* NAME = "CircuitBenchmarkResponse"; + + double witness_generation_time_ms; + double proving_time_ms; + double verification_time_ms; + uint64_t peak_memory_bytes; + }; + + CircuitInput circuit; + std::vector witness; + ProofSystemSettings settings; + uint32_t num_iterations = 1; + bool benchmark_witness_generation = true; + bool benchmark_proving = true; + Response execute(const BBApiRequest& request = {}) const; +}; + +// OracleHashType enum and parse_oracle_hash_type are defined in bbapi_shared.hpp + +} // namespace bb::bbapi From f936e125e0a912bb1c7686c144d552da57fb5b12 Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 14:25:25 +0000 Subject: [PATCH 04/30] work on && refs --- .../src/barretenberg/api/bbapi_client_ivc.cpp | 26 +-- .../src/barretenberg/api/bbapi_client_ivc.hpp | 14 +- .../src/barretenberg/api/bbapi_execute.hpp | 26 +-- .../src/barretenberg/api/bbapi_ultra_honk.cpp | 205 +++++++++++++----- .../src/barretenberg/api/bbapi_ultra_honk.hpp | 25 ++- 5 files changed, 184 insertions(+), 112 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index af1cfba80fc2..210649d46f6d 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -10,21 +10,21 @@ namespace bb::bbapi { -ClientIvcStart::Response ClientIvcStart::execute(BBApiRequest& request) const +ClientIvcStart::Response ClientIvcStart::execute(BBApiRequest& request) && { request.ivc_in_progress = std::make_shared(request.trace_settings); request.ivc_stack_depth = 0; return Response{}; } -ClientIvcLoad::Response ClientIvcLoad::execute(BBApiRequest& request) const +ClientIvcLoad::Response ClientIvcLoad::execute(BBApiRequest& request) && { if (!request.ivc_in_progress) { throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); } request.last_circuit_name = circuit.name; - request.last_circuit_constraints = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + request.last_circuit_constraints = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); request.last_circuit_vk = circuit.verification_key; info("ClientIvcLoad - loaded circuit '", request.last_circuit_name, "'"); @@ -32,7 +32,7 @@ ClientIvcLoad::Response ClientIvcLoad::execute(BBApiRequest& request) const return Response{}; } -ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request) const +ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request) && { if (!request.ivc_in_progress) { throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); @@ -42,7 +42,7 @@ ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request throw_or_abort("No circuit loaded. Call ClientIvcLoad first."); } - acir_format::WitnessVector witness_data = acir_format::witness_buf_to_witness_data(witness); + acir_format::WitnessVector witness_data = acir_format::witness_buf_to_witness_data(std::move(witness)); acir_format::AcirProgram program{ std::move(request.last_circuit_constraints.value()), std::move(witness_data) }; const acir_format::ProgramMetadata metadata{ request.ivc_in_progress }; @@ -63,7 +63,7 @@ ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request return Response{}; } -ClientIvcProve::Response ClientIvcProve::execute(BBApiRequest& request) const +ClientIvcProve::Response ClientIvcProve::execute(BBApiRequest& request) && { if (!request.ivc_in_progress) { throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); @@ -123,11 +123,11 @@ static ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request return ivc.get_vk(); } -ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(const BBApiRequest& request) const +ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(const BBApiRequest& request) && { info("ClientIvcComputeStandaloneVk - deriving VK for circuit '", circuit.name, "'"); - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); @@ -142,11 +142,11 @@ ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(con return response; } -ClientIvcComputeIvcVk::Response ClientIvcComputeIvcVk::execute(const BBApiRequest& request) const +ClientIvcComputeIvcVk::Response ClientIvcComputeIvcVk::execute(const BBApiRequest& request) && { info("ClientIvcComputeIvcVk - deriving IVC VK for circuit '", circuit.name, "'"); - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); auto vk = compute_vk_for_ivc(request, constraint_system.public_inputs.size()); @@ -158,9 +158,9 @@ ClientIvcComputeIvcVk::Response ClientIvcComputeIvcVk::execute(const BBApiReques return response; } -ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const BBApiRequest& request) const +ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const BBApiRequest& request) && { - acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(circuit.bytecode), + acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)), /*witness=*/{} }; std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); @@ -183,4 +183,4 @@ ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const return response; } -} // namespace bb::bbapi \ No newline at end of file +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp index d71937991b99..a767bc9bd63a 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -25,7 +25,7 @@ struct ClientIvcStart { static constexpr const char* NAME = "ClientIvcStartResponse"; // Empty response - success indicated by no exception }; - Response execute(BBApiRequest& request) const; + Response execute(BBApiRequest& request) &&; }; struct ClientIvcLoad { @@ -37,7 +37,7 @@ struct ClientIvcLoad { }; CircuitInput circuit; - Response execute(BBApiRequest& request) const; + Response execute(BBApiRequest& request) &&; }; struct ClientIvcAccumulate { @@ -50,7 +50,7 @@ struct ClientIvcAccumulate { // Serialized witness for the last loaded circuit. std::vector witness; - Response execute(BBApiRequest& request) const; + Response execute(BBApiRequest& request) &&; }; struct ClientIvcProve { @@ -61,7 +61,7 @@ struct ClientIvcProve { ClientIVC::Proof proof; }; - Response execute(BBApiRequest& request) const; + Response execute(BBApiRequest& request) &&; }; /** Compute standalone verification key for a circuit */ @@ -76,7 +76,7 @@ struct ClientIvcComputeStandaloneVk { }; CircuitInputNoVK circuit; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** Compute IVC verification key */ @@ -90,7 +90,7 @@ struct ClientIvcComputeIvcVk { }; CircuitInputNoVK circuit; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -108,7 +108,7 @@ struct ClientIvcCheckPrecomputedVk { // Circuit with its precomputed VK CircuitInput circuit; std::string function_name; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; } // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index adad556b9cd5..7a3b6642e73b 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -6,17 +6,6 @@ namespace bb::bbapi { -/** - * @brief Convert a vector of field elements to JSON array format - */ -inline std::string field_elements_to_json(const std::vector& fields) -{ - if (fields.empty()) { - return "[]"; - } - return format("[", join(transform::map(fields, [](auto fr) { return format("\"", fr, "\""); })), "]"); -} - /** * @brief Executes a command by visiting a variant of all possible commands. * @@ -28,11 +17,7 @@ inline CommandResponse execute(BBApiRequest& request, Command&& command) { return std::move(command).visit([&request](auto&& cmd) -> CommandResponse { using CmdType = std::decay_t; - if constexpr (RequiresBBApiRequest) { - return cmd.execute(request); - } else { - return cmd.execute(request); - } + return std::forward(cmd).execute(request); }); } @@ -42,12 +27,7 @@ inline std::vector execute_request(BBApiRequest&& request, std: std::vector responses; responses.reserve(commands.size()); for (Command& command : commands) { - try { - responses.push_back(execute(request, std::move(command))); - } catch (const std::exception& e) { - // If there was an error, we stop processing further commands. - throw_or_abort(e.what()); - } + responses.push_back(execute(request, std::move(command))); } return responses; } @@ -67,4 +47,4 @@ template inline typename T::Response do_bbapi(bb { return command.execute(request); } -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp index 5b46f2cba33c..fb6f167291b6 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -1,15 +1,16 @@ #include "barretenberg/api/bbapi_ultra_honk.hpp" #include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" #include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" -#include "barretenberg/honk/proof_system/ultra_prover.hpp" -#include "barretenberg/honk/proof_system/ultra_verifier.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/ultra_honk/mega_composer.hpp" -#include "barretenberg/ultra_honk/ultra_composer.hpp" +#include "barretenberg/flavor/mega_flavor.hpp" +#include "barretenberg/honk/types/aggregation_object_type.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" +#include "barretenberg/ultra_honk/ultra_verifier.hpp" #include #include @@ -32,56 +33,127 @@ static std::string bytes_to_base64(const std::vector& bytes) throw_or_abort("Base64 encoding not implemented"); } -CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) const +CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); - auto witness = acir_format::witness_buf_to_witness_data(this->witness); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); + auto witness = acir_format::witness_buf_to_witness_data(std::move(this->witness)); acir_format::AcirProgram program{ constraint_system, witness }; - auto builder = acir_format::create_circuit(program, /*metadata=*/{}); - auto composer = UltraComposer(); - auto prover = composer.create_prover(builder); - auto proof = prover.construct_proof(); + // Determine honk recursion level based on settings + uint32_t honk_recursion = settings.honk_recursion; + if (honk_recursion == 0 && settings.recursive) { + honk_recursion = 1; // Default to UltraHonk recursion + } + + const acir_format::ProgramMetadata metadata{ + .honk_recursion = honk_recursion, + }; Response response; - response.proof = proof; - response.public_inputs = builder.get_public_inputs(); + + // Choose flavor based on settings + if (settings.ipa_accumulation || honk_recursion == 2) { + // UltraRollupFlavor for rollup circuits + using Flavor = UltraRollupFlavor; + auto builder = acir_format::create_circuit(program, metadata); + auto proving_key = std::make_shared>(builder, request.trace_settings); + + // Load or compute VK + std::shared_ptr vk; + if (!circuit.verification_key.empty()) { + vk = from_buffer>(circuit.verification_key); + } else { + vk = std::make_shared(proving_key->proving_key); + } + + UltraProver_ prover{ proving_key, vk }; + auto proof = prover.construct_proof(); + + response.proof = proof; + response.public_inputs = builder.get_public_inputs(); + } else { + // Regular UltraFlavor + using Flavor = UltraFlavor; + auto builder = acir_format::create_circuit(program, metadata); + auto proving_key = std::make_shared>(builder, request.trace_settings); + + // Load or compute VK + std::shared_ptr vk; + if (!circuit.verification_key.empty()) { + vk = from_buffer>(circuit.verification_key); + } else { + vk = std::make_shared(proving_key->proving_key); + } + + UltraProver_ prover{ proving_key, vk }; + auto proof = prover.construct_proof(); + + response.proof = proof; + response.public_inputs = builder.get_public_inputs(); + } return response; } -CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request) const +CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - auto builder = acir_format::create_circuit(program, /*metadata=*/{}); - auto composer = UltraComposer(); - auto proving_key = composer.compute_proving_key(builder); - auto verification_key = composer.compute_verification_key(proving_key); + // Determine honk recursion level based on settings + uint32_t honk_recursion = settings.honk_recursion; + if (honk_recursion == 0 && settings.recursive) { + honk_recursion = 1; // Default to UltraHonk recursion + } + + const acir_format::ProgramMetadata metadata{ + .honk_recursion = honk_recursion, + }; Response response; - response.bytes = to_buffer(*verification_key); + + // Choose flavor based on settings + if (settings.ipa_accumulation || honk_recursion == 2) { + // UltraRollupFlavor for rollup circuits + using Flavor = UltraRollupFlavor; + auto builder = acir_format::create_circuit(program, metadata); + auto proving_key = std::make_shared>(builder, request.trace_settings); + auto verification_key = std::make_shared(proving_key->proving_key); + + response.bytes = to_buffer(*verification_key); + } else { + // Regular UltraFlavor + using Flavor = UltraFlavor; + auto builder = acir_format::create_circuit(program, metadata); + auto proving_key = std::make_shared>(builder, request.trace_settings); + auto verification_key = std::make_shared(proving_key->proving_key); + + response.bytes = to_buffer(*verification_key); + } return response; } -CircuitComputeIvcVk::Response CircuitComputeIvcVk::execute(const BBApiRequest& request) const +CircuitComputeIvcVk::Response CircuitComputeIvcVk::execute(BB_UNUSED const BBApiRequest& request) && { throw_or_abort("CircuitComputeIvcVk not implemented yet"); } -CircuitInfo::Response CircuitInfo::execute(const BBApiRequest& request) const +CircuitInfo::Response CircuitInfo::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + const acir_format::ProgramMetadata metadata{ + .honk_recursion = settings.honk_recursion, + }; + + auto builder = acir_format::create_circuit(program, metadata); Response response; - response.total_gates = static_cast(builder.get_num_gates()); - response.subgroup_size = static_cast(builder.get_circuit_subgroup_size()); + response.total_gates = static_cast(builder.get_num_finalized_gates()); + response.subgroup_size = static_cast(builder.get_circuit_subgroup_size(response.total_gates)); if (include_gates_per_opcode) { // TODO: Implement gate counting per opcode @@ -91,34 +163,49 @@ CircuitInfo::Response CircuitInfo::execute(const BBApiRequest& request) const return response; } -CircuitCheck::Response CircuitCheck::execute(const BBApiRequest& request) const +CircuitCheck::Response CircuitCheck::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); - auto witness = acir_format::witness_buf_to_witness_data(this->witness); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); + auto witness = acir_format::witness_buf_to_witness_data(std::move(this->witness)); acir_format::AcirProgram program{ constraint_system, witness }; - auto builder = acir_format::create_circuit(program, /*metadata=*/{}); + + const acir_format::ProgramMetadata metadata{ + .honk_recursion = settings.honk_recursion, + }; + + auto builder = acir_format::create_circuit(program, metadata); Response response; - response.satisfied = builder.check_circuit(); + response.satisfied = CircuitChecker::check(builder); return response; } -CircuitVerify::Response CircuitVerify::execute(const BBApiRequest& request) const +CircuitVerify::Response CircuitVerify::execute(BB_UNUSED const BBApiRequest& request) && { - auto vk = from_buffer>(verification_key); - - UltraVerifier verifier(vk); - bool verified = verifier.verify_proof(proof); - Response response; - response.verified = verified; - return response; + // Try UltraFlavor first + try { + auto vk = from_buffer>(verification_key); + UltraVerifier_ verifier(vk); + response.verified = verifier.verify_proof(proof); + return response; + } catch (...) { + // If that fails, try UltraRollupFlavor + try { + auto vk = from_buffer>(verification_key); + UltraVerifier_ verifier(vk); + response.verified = verifier.verify_proof(proof); + return response; + } catch (...) { + throw_or_abort("Failed to deserialize verification key"); + } + } } -ProofAsFields::Response ProofAsFields::execute(const BBApiRequest& request) const +ProofAsFields::Response ProofAsFields::execute(BB_UNUSED const BBApiRequest& request) && { Response response; @@ -134,7 +221,7 @@ ProofAsFields::Response ProofAsFields::execute(const BBApiRequest& request) cons return response; } -VkAsFields::Response VkAsFields::execute(const BBApiRequest& request) const +VkAsFields::Response VkAsFields::execute(BB_UNUSED const BBApiRequest& request) && { Response response; @@ -142,19 +229,26 @@ VkAsFields::Response VkAsFields::execute(const BBApiRequest& request) const auto vk = from_buffer>(verification_key); response.fields = vk->to_field_elements(); } else { - auto vk = from_buffer>(verification_key); - response.fields = vk->to_field_elements(); + // Try UltraFlavor first + try { + auto vk = from_buffer>(verification_key); + response.fields = vk->to_field_elements(); + } catch (...) { + // If that fails, try UltraRollupFlavor + auto vk = from_buffer>(verification_key); + response.fields = vk->to_field_elements(); + } } return response; } -CircuitWriteSolidityVerifier::Response CircuitWriteSolidityVerifier::execute(const BBApiRequest& request) const +CircuitWriteSolidityVerifier::Response CircuitWriteSolidityVerifier::execute(BB_UNUSED const BBApiRequest& request) && { throw_or_abort("CircuitWriteSolidityVerifier not implemented yet"); } -CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiRequest& request) const +CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiRequest& request) && { // First prove auto prove_result = CircuitProve{ circuit, witness, settings }.execute(request); @@ -166,15 +260,12 @@ CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiReques auto verify_result = CircuitVerify{ vk_result.bytes, prove_result.public_inputs, prove_result.proof, settings }.execute(request); - Response response; - response.verified = verify_result.verified; - response.proof = prove_result.proof; - response.public_inputs = prove_result.public_inputs; - - return response; + return { .verified = verify_result.verified, + .proof = prove_result.proof, + .public_inputs = prove_result.public_inputs }; } -CircuitWriteBytecode::Response CircuitWriteBytecode::execute(const BBApiRequest& request) const +CircuitWriteBytecode::Response CircuitWriteBytecode::execute(BB_UNUSED const BBApiRequest& request) && { Response response; response.bytecode = circuit.bytecode; @@ -188,14 +279,14 @@ CircuitWriteBytecode::Response CircuitWriteBytecode::execute(const BBApiRequest& return response; } -CircuitValidate::Response CircuitValidate::execute(const BBApiRequest& request) const +CircuitValidate::Response CircuitValidate::execute(BB_UNUSED const BBApiRequest& request) && { Response response; response.is_valid = true; response.validation_errors.clear(); try { - auto constraint_system = acir_format::circuit_buf_to_acir_format(circuit.bytecode); + auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); // Basic validation passed if we can parse it if (check_recursive_structure) { @@ -209,9 +300,9 @@ CircuitValidate::Response CircuitValidate::execute(const BBApiRequest& request) return response; } -CircuitBenchmark::Response CircuitBenchmark::execute(const BBApiRequest& request) const +CircuitBenchmark::Response CircuitBenchmark::execute(BB_UNUSED const BBApiRequest& request) && { throw_or_abort("CircuitBenchmark not implemented yet"); } -} // namespace bb::bbapi \ No newline at end of file +} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp index bdbf179bb1b0..77d5ce439acc 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp @@ -44,6 +44,7 @@ struct CircuitProve { CircuitInput circuit; std::vector witness; ProofSystemSettings settings; + Response execute(const BBApiRequest& request = {}) &&; }; struct CircuitComputeVk { @@ -57,7 +58,7 @@ struct CircuitComputeVk { CircuitInputNoVK circuit; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** Compute verification key, Treat the previously loaded circuit as either a standalone circuit @@ -70,7 +71,7 @@ struct CircuitComputeIvcVk { std::vector bytes; // Serialized verification key }; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -92,7 +93,7 @@ struct CircuitInfo { CircuitInput circuit; bool include_gates_per_opcode = false; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -112,7 +113,7 @@ struct CircuitCheck { CircuitInput circuit; std::vector witness; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -132,7 +133,7 @@ struct CircuitVerify { PublicInputsVector public_inputs; HonkProof proof; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -149,7 +150,7 @@ struct ProofAsFields { }; HonkProof proof; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -167,7 +168,7 @@ struct VkAsFields { std::vector verification_key; bool is_mega_honk = false; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -184,7 +185,7 @@ struct CircuitWriteSolidityVerifier { std::vector verification_key; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -204,7 +205,7 @@ struct CircuitProveAndVerify { CircuitInput circuit; std::vector witness; ProofSystemSettings settings; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -222,7 +223,7 @@ struct CircuitWriteBytecode { CircuitInput circuit; std::string format = "binary"; // binary, hex, base64 - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -241,7 +242,7 @@ struct CircuitValidate { CircuitInput circuit; ProofSystemSettings settings; bool check_recursive_structure = false; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; /** @@ -265,7 +266,7 @@ struct CircuitBenchmark { uint32_t num_iterations = 1; bool benchmark_witness_generation = true; bool benchmark_proving = true; - Response execute(const BBApiRequest& request = {}) const; + Response execute(const BBApiRequest& request = {}) &&; }; // OracleHashType enum and parse_oracle_hash_type are defined in bbapi_shared.hpp From 1322c7acb4dcfe8af6ee89688e1ec18eec437908 Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 20:00:13 +0000 Subject: [PATCH 05/30] progress --- .../src/barretenberg/api/api_client_ivc.cpp | 12 ++--- .../cpp/src/barretenberg/api/bbapi.hpp | 49 +----------------- .../src/barretenberg/api/bbapi_execute.hpp | 50 ++++++++++++++++++- .../src/barretenberg/api/bbapi_ultra_honk.cpp | 30 ++++++++++- 4 files changed, 82 insertions(+), 59 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index e6ba8589f910..402451bd1d6c 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -1,6 +1,5 @@ #include "api_client_ivc.hpp" -#include "barretenberg/api/bbapi_commands.hpp" -#include "barretenberg/api/bbapi_execute.hpp" +#include "barretenberg/api/bbapi.hpp" #include "barretenberg/api/file_io.hpp" #include "barretenberg/api/log.hpp" #include "barretenberg/api/write_prover_output.hpp" @@ -63,12 +62,9 @@ void write_standalone_vk(const std::string& output_data_type, bbapi::BBApiRequest request; - auto response = bbapi::execute(bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }); - - if (!response.error_message.empty()) { - throw_or_abort("Failed to compute standalone VK: " + response.error_message); - } + auto response = bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } + }.execute(); if (output_format == "bytes") { write_file(output_path / "vk", response.vk_bytes); diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi.hpp index eb3d4df1b8f0..1d825e660fc3 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi.hpp @@ -7,54 +7,7 @@ * and provides unified Command and CommandResponse types for the API. */ #include "barretenberg/api/bbapi_client_ivc.hpp" +#include "barretenberg/api/bbapi_execute.hpp" #include "barretenberg/api/bbapi_shared.hpp" #include "barretenberg/api/bbapi_ultra_honk.hpp" #include "barretenberg/common/named_union.hpp" - -namespace bb::bbapi { -using Command = NamedUnion; - -using CommandResponse = NamedUnion; - -// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve -// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. -template -concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v; -} // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index 7a3b6642e73b..ca5d41982776 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -1,11 +1,59 @@ #pragma once -#include "barretenberg/api/bbapi.hpp" +#include "barretenberg/api/bbapi_client_ivc.hpp" +#include "barretenberg/api/bbapi_shared.hpp" +#include "barretenberg/api/bbapi_ultra_honk.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include namespace bb::bbapi { +using Command = NamedUnion; + +using CommandResponse = NamedUnion; + +// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve +// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. +template +concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + /** * @brief Executes a command by visiting a variant of all possible commands. * diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp index fb6f167291b6..8f11c39f3dd4 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -29,8 +29,34 @@ static std::string bytes_to_hex(const std::vector& bytes) static std::string bytes_to_base64(const std::vector& bytes) { - // TODO: Implement base64 encoding - throw_or_abort("Base64 encoding not implemented"); + // TODO replace this gpt-ese with a proper base64 library + static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string result; + size_t i = 0; + while (i < bytes.size()) { + uint32_t octet_a = i < bytes.size() ? bytes[i++] : 0; + uint32_t octet_b = i < bytes.size() ? bytes[i++] : 0; + uint32_t octet_c = i < bytes.size() ? bytes[i++] : 0; + + uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c; + + result.push_back(base64_chars[(triple >> 18) & 0x3F]); + result.push_back(base64_chars[(triple >> 12) & 0x3F]); + result.push_back(base64_chars[(triple >> 6) & 0x3F]); + result.push_back(base64_chars[triple & 0x3F]); + } + + // Add padding + size_t padding = bytes.size() % 3; + if (padding > 0) { + result.resize(result.size() - (3 - padding)); + for (size_t j = 0; j < (3 - padding); ++j) { + result.push_back('='); + } + } + + return result; } CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && From e2c4a79a6ee8b328d9b92a76e6b8cda851c4bf8d Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 20:36:32 +0000 Subject: [PATCH 06/30] progress --- .../src/barretenberg/api/api_client_ivc.cpp | 28 ++++++++++++------- .../barretenberg/api/api_client_ivc.test.cpp | 24 ++++++++-------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 402451bd1d6c..6eb13406d25c 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -14,6 +14,7 @@ #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/serialize/msgpack_check_eq.hpp" #include +#include #include namespace bb { @@ -38,14 +39,21 @@ acir_format::WitnessVector witness_map_to_witness_vector(std::map get_acir_program_decider_proving_key(acir_format::AcirProgram& program) +namespace { +std::string field_elements_to_json(const std::vector& fields) { - ClientIVC::ClientCircuit builder = acir_format::create_circuit(program); - - // Construct the verification key via the prover-constructed proving key with the proper trace settings - TraceSettings trace_settings{ AZTEC_TRACE_STRUCTURE }; - return std::make_shared(builder, trace_settings); + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < fields.size(); ++i) { + ss << '"' << fields[i] << '"'; + if (i < fields.size() - 1) { + ss << ","; + } + } + ss << "]"; + return ss.str(); } +} // namespace /** * @brief Compute and write to file a MegaHonk VK for a circuit to be accumulated in the IVC @@ -67,9 +75,9 @@ void write_standalone_vk(const std::string& output_data_type, }.execute(); if (output_format == "bytes") { - write_file(output_path / "vk", response.vk_bytes); + write_file(output_path / "vk", response.bytes); } else if (output_format == "fields") { - std::string json = bbapi::field_elements_to_json(response.vk_fields); + std::string json = field_elements_to_json(response.fields); write_file(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); } else { throw_or_abort("Unsupported output format for standalone vk: " + output_format); @@ -129,9 +137,9 @@ void write_vk_for_ivc(const std::string& output_data_type, const bool output_to_stdout = output_dir == "-"; if (output_to_stdout) { - write_bytes_to_stdout(response.vk_bytes); + write_bytes_to_stdout(response.bytes); } else { - write_file(output_dir / "vk", response.vk_bytes); + write_file(output_dir / "vk", response.bytes); } } diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp index 30213923d158..dd1c144a2337 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp @@ -1,5 +1,5 @@ #include "api_client_ivc.hpp" -#include "barretenberg/api/bbapi_commands.hpp" +#include "barretenberg/api/bbapi.hpp" #include "barretenberg/api/bbapi_execute.hpp" #include "barretenberg/api/file_io.hpp" #include "barretenberg/client_ivc/acir_bincode_mocks.hpp" @@ -46,20 +46,19 @@ void create_test_private_execution_steps(const std::filesystem::path& output_pat // Get the VK for the app circuit bbapi::BBApiRequest request; - auto app_vk = bbapi::execute(request, - bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }) - .vk_bytes; + auto app_vk_response = bbapi::execute( + request, bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }); + auto app_vk = app_vk_response.template get().bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Now create a kernel circuit that verifies the app circuit auto kernel_bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/true); auto kernel_witness_data = acir_bincode_mocks::create_kernel_witness(app_vk_fields); - auto kernel_vk = bbapi::execute(request, - bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode } }) - .vk_bytes; + auto kernel_vk_response = bbapi::execute( + request, + bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode } }); + auto kernel_vk = kernel_vk_response.template get().bytes; // Create PrivateExecutionStepRaw for the kernel std::vector raw_steps; @@ -102,10 +101,9 @@ ClientIVC::MegaVerificationKey get_ivc_vk(const std::filesystem::path& test_dir) { auto [app_bytecode, app_witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); bbapi::BBApiRequest request; - auto app_vk = bbapi::execute(request, - bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }) - .vk_bytes; + auto app_vk_response = bbapi::execute( + request, bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }); + auto app_vk = app_vk_response.template get().bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Use this to get the size of the vk. auto bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/false); From 75b174d501d6dba9a36688df7b49869df629ec53 Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 21:10:19 +0000 Subject: [PATCH 07/30] fix compilation --- .../src/barretenberg/api/api_client_ivc.cpp | 57 ++++++------------- .../barretenberg/api/api_client_ivc.test.cpp | 39 ++++++------- .../src/barretenberg/api/bbapi_client_ivc.cpp | 3 +- .../src/barretenberg/api/bbapi_client_ivc.hpp | 2 + 4 files changed, 39 insertions(+), 62 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 6eb13406d25c..5f8d404e32d7 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -68,8 +68,6 @@ void write_standalone_vk(const std::string& output_data_type, const std::string& output_path) { - bbapi::BBApiRequest request; - auto response = bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }.execute(); @@ -101,8 +99,10 @@ void write_vk_for_ivc(const std::string& output_format, ClientIVC ivc{ /*num_circuits=*/2, { AZTEC_TRACE_STRUCTURE } }; ClientIVCMockCircuitProducer circuit_producer; + // Since we need to specify the number of public inputs but ClientIvcComputeIvcVk derives it from bytecode, + // we need to create a mock circuit with the correct number of public inputs + // For now, we'll use the compute_vk_for_ivc function directly as it was designed for this purpose bbapi::BBApiRequest request; - auto vk = bbapi::compute_vk_for_ivc(request, num_public_inputs_in_final_circuit); const auto buf = to_buffer(vk); @@ -126,14 +126,9 @@ void write_vk_for_ivc(const std::string& output_data_type, auto bytecode = get_bytecode(bytecode_path); - bbapi::BBApiRequest request; - - auto response = bbapi::execute( - bbapi::ClientIvcComputeIvcVk{ .circuit = { .name = "final_circuit", .bytecode = std::move(bytecode) } }); - - if (!response.error_message.empty()) { - throw_or_abort("Failed to compute IVC VK: " + response.error_message); - } + auto response = bbapi::ClientIvcComputeIvcVk{ + .circuit = { .name = "final_circuit", .bytecode = std::move(bytecode) } + }.execute(); const bool output_to_stdout = output_dir == "-"; if (output_to_stdout) { @@ -150,31 +145,18 @@ void ClientIVCAPI::prove(const Flags& flags, bbapi::BBApiRequest request; - auto start_response = bbapi::execute(request, bbapi::ClientIvcStart{}); - if (!start_response.error_message.empty()) { - throw_or_abort("Failed to start ClientIVC: " + start_response.error_message); - } + bbapi::ClientIvcStart{}.execute(request); for (const auto& step : raw_steps) { - auto load_response = bbapi::execute( - request, - bbapi::ClientIvcLoad{ - .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } }); - if (!load_response.error_message.empty()) { - throw_or_abort("Failed to load circuit: " + load_response.error_message); - } + bbapi::ClientIvcLoad{ + .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } + }.execute(request); info("ClientIVC: accumulating " + step.function_name); - auto acc_response = bbapi::execute(request, bbapi::ClientIvcAccumulate{ .witness = step.witness }); - if (!acc_response.error_message.empty()) { - throw_or_abort("Failed to accumulate circuit: " + acc_response.error_message); - } + bbapi::ClientIvcAccumulate{ .witness = step.witness }.execute(request); } - auto prove_response = bbapi::execute(request, bbapi::ClientIvcProve{}); - if (!prove_response.error_message.empty()) { - throw_or_abort("Failed to prove: " + prove_response.error_message); - } + auto prove_response = bbapi::ClientIvcProve{}.execute(request); // We'd like to use the `write` function that UltraHonkAPI uses, but there are missing functions for creating // std::string representations of vks that don't feel worth implementing @@ -249,16 +231,13 @@ bool ClientIVCAPI::check_precomputed_vks(const std::filesystem::path& input_path return false; } - auto response = bbapi::execute( - request, - bbapi::ClientIvcCheckPrecomputedVk{ - .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk }, - .function_name = step.function_name }); + auto response = bbapi::ClientIvcCheckPrecomputedVk{ .circuit = { .name = step.function_name, + .bytecode = step.bytecode, + .verification_key = step.vk }, + .function_name = step.function_name } + .execute(); - if (!response.error_message.empty() || !response.valid) { - if (!response.error_message.empty()) { - info(response.error_message); - } + if (!response.valid) { return false; } } diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp index dd1c144a2337..12af7213f0be 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.test.cpp @@ -14,6 +14,7 @@ #include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" #include "barretenberg/flavor/mega_flavor.hpp" #include "barretenberg/serialize/msgpack.hpp" +#include "barretenberg/serialize/msgpack_check_eq.hpp" #include "barretenberg/srs/global_crs.hpp" #include #include @@ -46,19 +47,19 @@ void create_test_private_execution_steps(const std::filesystem::path& output_pat // Get the VK for the app circuit bbapi::BBApiRequest request; - auto app_vk_response = bbapi::execute( - request, bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }); - auto app_vk = app_vk_response.template get().bytes; + auto app_vk_response = + bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }.execute(); + auto app_vk = app_vk_response.bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Now create a kernel circuit that verifies the app circuit auto kernel_bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/true); auto kernel_witness_data = acir_bincode_mocks::create_kernel_witness(app_vk_fields); - auto kernel_vk_response = bbapi::execute( - request, - bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode } }); - auto kernel_vk = kernel_vk_response.template get().bytes; + auto kernel_vk_response = bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "kernel_circuit", .bytecode = kernel_bytecode } + }.execute(); + auto kernel_vk = kernel_vk_response.bytes; // Create PrivateExecutionStepRaw for the kernel std::vector raw_steps; @@ -101,9 +102,9 @@ ClientIVC::MegaVerificationKey get_ivc_vk(const std::filesystem::path& test_dir) { auto [app_bytecode, app_witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); bbapi::BBApiRequest request; - auto app_vk_response = bbapi::execute( - request, bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }); - auto app_vk = app_vk_response.template get().bytes; + auto app_vk_response = + bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "app_circuit", .bytecode = app_bytecode } }.execute(); + auto app_vk = app_vk_response.bytes; auto app_vk_fields = from_buffer(app_vk).to_field_elements(); // Use this to get the size of the vk. auto bytecode = acir_bincode_mocks::create_simple_kernel(app_vk_fields.size(), /*is_init_kernel=*/false); @@ -262,20 +263,16 @@ TEST_F(ClientIVCAPITests, CheckPrecomputedVksMismatch) auto [bytecode, witness_data] = acir_bincode_mocks::create_simple_circuit_bytecode(); bbapi::BBApiRequest request; - size_t vk_size = from_buffer( - bbapi::execute(request, - bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "simple_circuit", .bytecode = bytecode } }) - .vk_bytes) - .to_field_elements() - .size(); + auto vk_response = + bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "simple_circuit", .bytecode = bytecode } }.execute(); + size_t vk_size = from_buffer(vk_response.bytes).to_field_elements().size(); // Create a WRONG verification key (use a different circuit) auto different_bytecode = acir_bincode_mocks::create_simple_kernel(vk_size, /*is_init_kernel=*/true); - auto vk = bbapi::execute(request, - bbapi::ClientIvcComputeStandaloneVk{ - .circuit = { .name = "different_circuit", .bytecode = different_bytecode } }) - .vk_bytes; + auto vk_response2 = bbapi::ClientIvcComputeStandaloneVk{ + .circuit = { .name = "different_circuit", .bytecode = different_bytecode } + }.execute(); + auto vk = vk_response2.bytes; // Create PrivateExecutionStepRaw with wrong VK std::vector raw_steps; diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index 210649d46f6d..a5ce88ccaa0d 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -100,8 +100,7 @@ static std::shared_ptr get_acir_program_decider_pr return std::make_shared(builder, request.trace_settings); } -static ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, - size_t num_public_inputs_in_final_circuit) +ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit) { ClientIVC ivc{ request.trace_settings }; ClientIVCMockCircuitProducer circuit_producer; diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp index a767bc9bd63a..be9b1bb860a2 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -14,6 +14,8 @@ namespace bb::bbapi { +ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit); + /** * @brief * Note, only one IVC request can be made at a time for each batch_request. From b67136af01b3cfe0882c581df5900da119eeeb63 Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 21:27:56 +0000 Subject: [PATCH 08/30] fix api tests --- barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp | 1 - barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 5f8d404e32d7..46d00432787e 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -230,7 +230,6 @@ bool ClientIVCAPI::check_precomputed_vks(const std::filesystem::path& input_path info("FAIL: Expected precomputed vk for function ", step.function_name); return false; } - auto response = bbapi::ClientIvcCheckPrecomputedVk{ .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk }, diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index a5ce88ccaa0d..c178e7d4e4b1 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -172,13 +172,12 @@ ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const auto precomputed_vk = from_buffer>(circuit.verification_key); + Response response; + response.valid = true; std::string error_message = "Precomputed vk does not match computed vk for function " + function_name; if (!msgpack::msgpack_check_eq(*computed_vk, *precomputed_vk, error_message)) { - throw_or_abort(error_message); + response.valid = false; } - - Response response; - response.valid = true; return response; } From c5b822aa94eb0b52782cee1af898360be885989a Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 9 Jul 2025 22:11:54 +0000 Subject: [PATCH 09/30] simplify auto rebase --- .github/workflows/auto-rebase-pr.yml | 11 +- .../contracts/fees/fpc_contract/src/main.nr | 2 +- .../reset_output_validator_builder/mod.nr | 36 +-- .../note_hash_read_request_hints_builder.nr | 6 +- .../nullifier_read_request_hints_builder.nr | 6 +- ...t_split_sorted_transformed_value_arrays.nr | 4 +- scripts/auto_rebase_pr.sh | 287 +++--------------- 7 files changed, 74 insertions(+), 278 deletions(-) diff --git a/.github/workflows/auto-rebase-pr.yml b/.github/workflows/auto-rebase-pr.yml index 75e310e83150..96371148ea93 100644 --- a/.github/workflows/auto-rebase-pr.yml +++ b/.github/workflows/auto-rebase-pr.yml @@ -30,9 +30,18 @@ jobs: env: GH_TOKEN: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} run: | + set -x pr_head_ref=${{ github.event.pull_request.head.ref }} pr_base_ref=${{ github.event.pull_request.base.ref }} - ./scripts/auto_rebase_pr.sh "$pr_head_ref" "$pr_base_ref" + # ensure we have up to date head/base + git fetch origin "$pr_base_ref" "$pr_head_ref" + # Be sure to run the auto rebase script such that we don't write to it while it's being read. + cp ./scripts/auto_rebase_pr.sh .github/temp-script.sh + bash .github/temp-script.sh "$pr_head_ref" "$pr_base_ref" + rebase_sha=$(git rev-parse HEAD) + git switch --force-create "$pr_head_ref" "origin/$pr_base_ref" + git reset --hard "$rebase_sha" + git push origin "$pr_head_ref" --force-with-lease - name: Post failure comment if: failure() || steps.rebase.outcome == 'failure' diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index 8bdf54e7c0bf..08854e8e6077 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -159,7 +159,7 @@ pub contract FPC { Token::at(config.accepted_asset) .transfer_in_public(context.msg_sender(), context.this_address(), max_fee, authwit_nonce ) - .enqueue(&mut context); + .enqueue(&mut context); // docs:end:public_call context.set_as_fee_payer(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr index 723f90f681d8..5b2b98267225 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr @@ -63,25 +63,25 @@ impl ResetOutputValidatorBuilder { TRANSIENT_DATA_SQUASHING_HINTS_LEN ]; - ResetOutputValidatorBuilder { - output, - previous_kernel, - note_hash_read_request_hints_builder, - nullifier_read_request_hints_builder, - key_validation_hints, - transient_data_index_hints, - pending_note_hash_read_amount: 0, - settled_note_hash_read_amount: 0, - pending_nullifier_read_amount: 0, - settled_nullifier_read_amount: 0, - key_validation_amount: 0, - transient_data_squashing_amount: 0, - note_hash_siloing_amount: 0, - nullifier_siloing_amount: 0, - private_log_siloing_amount: 0, - padded_side_effects: PaddedSideEffects::empty(), + ResetOutputValidatorBuilder { + output, + previous_kernel, + note_hash_read_request_hints_builder, + nullifier_read_request_hints_builder, + key_validation_hints, + transient_data_index_hints, + pending_note_hash_read_amount: 0, + settled_note_hash_read_amount: 0, + pending_nullifier_read_amount: 0, + settled_nullifier_read_amount: 0, + key_validation_amount: 0, + transient_data_squashing_amount: 0, + note_hash_siloing_amount: 0, + nullifier_siloing_amount: 0, + private_log_siloing_amount: 0, + padded_side_effects: PaddedSideEffects::empty(), + } } - } pub fn get_validation_request_processor( self, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index a1382fe36133..1659379d9223 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NoteHashReadRequest NoteHashSettledReadHint::skip(MAX_NOTE_HASH_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), + 0, + ), + } } - } pub fn add_pending_read_hint(&mut self, read_request_index: u32, note_hash_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index 38e946f36d35..b337671abd12 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NullifierReadReques NullifierSettledReadHint::skip(MAX_NULLIFIER_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), + 0, + ), + } } - } pub fn add_pending_read_hint(&mut self, read_request_index: u32, nullifier_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 93106d54403e..5c5952252a1c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -267,9 +267,9 @@ mod tests { { original_index = i; } + } + self.hints.sorted_indexes[original_index] = new_index; } - self.hints.sorted_indexes[original_index] = new_index; - } pub fn execute(self) { if self.ascending { diff --git a/scripts/auto_rebase_pr.sh b/scripts/auto_rebase_pr.sh index 27bdab852fbc..f1e00490d029 100755 --- a/scripts/auto_rebase_pr.sh +++ b/scripts/auto_rebase_pr.sh @@ -1,263 +1,50 @@ #!/usr/bin/env bash set -euo pipefail -############################################################################### -# helpers -############################################################################### -function die { echo "❌ $*" >&2; exit 1; } -function is_merge { [[ $(git rev-list --parents -n1 "$1" | wc -w) -gt 2 ]]; } -function has_pr_suffix { [[ $(git show -s --format=%s "$1") =~ \(\#[0-9]+\)$ ]]; } -function is_empty_tree { git diff --quiet "$1"^ "$1"; } -function short_sha { - echo "${1:0:7}" -} +# args +pr_head_ref=${1:-} +pr_base_ref=${2:-} +[[ -z $pr_head_ref || -z $pr_base_ref ]] && { echo "usage: $0 " >&2; exit 1; } -############################################################################### -# args & fetch -############################################################################### -pr_head_ref=${1:-}; pr_base_ref=${2:-} -[[ -z $pr_head_ref || -z $pr_base_ref ]] && die "usage: $0 " - -git fetch origin "$pr_base_ref" "$pr_head_ref" merge_base=$(git merge-base "origin/$pr_base_ref" "origin/$pr_head_ref") -############################################################################### -# collect candidate commits -############################################################################### -commits=() -echo "📋 Collecting commits from $merge_base to origin/$pr_head_ref" >&2 -while read -r c; do - msg=$(git log -1 --format=%s "$c") - short=$(short_sha "$c") - if is_merge "$c"; then - echo " ⏭️ Skipping merge commit: $short - $msg" >&2 - continue - fi - if is_empty_tree "$c"; then - echo " ⏭️ Skipping empty commit: $short - $msg" >&2 - continue - fi - if has_pr_suffix "$c"; then - echo " ⏭️ Skipping PR commit: $short - $msg" >&2 - continue - fi - echo " ✅ Including commit: $short - $msg" >&2 - commits+=("$c") -done < <(git rev-list --reverse "$merge_base".."origin/$pr_head_ref") - -[[ ${#commits[@]} -eq 0 ]] && { echo "No commits to rebase" >&2; exit 0; } -total=${#commits[@]} -echo "📊 Total commits to rebase: $total" >&2 - -############################################################################### -# configure git based on most common author in candidate commits -############################################################################### -echo "🔧 Configuring git author from candidate commits" >&2 - -# Get the most common author from the candidate commits -author_info="" -if [[ ${#commits[@]} -gt 0 ]]; then - author_info=$( - for commit in "${commits[@]}"; do - git log -1 --format="%an|%ae" "$commit" - done | sort | uniq -c | sort -rn | head -1 | awk '{$1=""; print $0}' | xargs - ) +# collect commits, excluding empty commits, merge commits and previous squashed PR merges +commits=($( + git rev-list --reverse \ + --grep='\[empty\]' --grep='(#' \ + --no-merges \ + --invert-grep \ + "$merge_base..origin/$pr_head_ref" +)) + +if [ ${#commits[@]} -eq 0 ]; then + echo "No commits to rebase" >&2 fi -if [[ -n "$author_info" ]]; then - author_name=$(echo "$author_info" | cut -d'|' -f1) - author_email=$(echo "$author_info" | cut -d'|' -f2) - echo " Using most common author: $author_name <$author_email>" >&2 -else - # Fallback to aztec-bot - author_name="AztecBot" - author_email="tech@aztecprotocol.com" - echo " Using fallback author: $author_name <$author_email>" >&2 -fi - -git config user.name "$author_name" -git config user.email "$author_email" - -############################################################################### -# prepare working branch -############################################################################### -work_branch="auto-rebase-${pr_head_ref//\//-}" -git switch -c "$work_branch" "origin/$pr_base_ref" 2>/dev/null || { - git switch "$work_branch" - git reset --hard "origin/$pr_base_ref" -} - -############################################################################### -# helper functions -############################################################################### -# Try to apply a single commit using squash merge -function apply_single { - local sha="$1" before=$(git rev-parse --verify HEAD) - local short="$(short_sha "$sha")" - local msg=$(git log -1 --format=%s "$sha") - - echo "🔍 Trying single commit: $short - $msg" >&2 - - # Try to squash merge this single commit - if git merge --squash --no-commit "$sha" >/dev/null 2>&1; then - # Check if there are any changes - if git diff --cached --quiet; then - echo " ❌ No changes" >&2 - git reset --hard "$before" - return 1 - fi - - # Commit with the original commit's title - local original_msg=$(git log -1 --format=%s "$sha") - local original_body=$(git log -1 --format=%b "$sha") - if [[ -n "$original_body" ]]; then - git commit -m "$original_msg" -m "$original_body" >/dev/null - else - git commit -m "$original_msg" >/dev/null - fi - echo " ✅ Applied" >&2 - return 0 - else - echo " ❌ Conflict" >&2 - git merge --abort >/dev/null 2>&1 || true - git reset --hard "$before" - return 1 - fi -} - -# Create a squash commit for a range of commits -function create_squash_commit { - local start_idx=$1 end_idx=$2 - - # If it's just a single commit, preserve its original message - if [[ $start_idx -eq $end_idx ]]; then - local sha="${commits[$start_idx]}" - local original_msg=$(git log -1 --format=%s "$sha") - local original_body=$(git log -1 --format=%b "$sha") - if [[ -n "$original_body" ]]; then - git commit -m "$original_msg" -m "$original_body" >/dev/null - else - git commit -m "$original_msg" >/dev/null - fi - return - fi - - # Multiple commits - use squash format - links=() - commit_list="" - for ((k=start_idx; k<=end_idx; k++)); do - local sha="${commits[$k]}" - local short_sha="${sha:0:7}" - local msg=$(git log -1 --format=%s "$sha") - links+=("$short_sha") - commit_list="${commit_list}- ${short_sha} ${msg} (${short_sha})"$'\n' - done - - # Remove trailing newline - commit_list=${commit_list%$'\n'} - - # Commit with both comma-separated links and detailed list - git commit -m "squash: $(IFS=, ; echo "${links[*]}")" -m "$commit_list" >/dev/null -} - -# Try to find and apply the minimal batch that works -function find_minimal_batch { - local start_idx=$1 - local before=$(git rev-parse --verify HEAD) - - echo "🔄 Finding minimal batch starting from commit $start_idx..." >&2 - - # Try increasingly larger batches - for ((end_idx=start_idx; end_idx&2 - - # Reset to before state - git reset --hard "$before" >/dev/null 2>&1 - - # Try to cherry-pick all commits in this range - local all_applied=true - for ((k=start_idx; k<=end_idx; k++)); do - if ! git cherry-pick --no-commit "${commits[$k]}" >/dev/null 2>&1; then - all_applied=false - git cherry-pick --abort >/dev/null 2>&1 || true - break - fi - done - - if $all_applied && ! git diff --cached --quiet; then - # Success! Create the squash commit - echo " ✅ Batch [$start_idx..$end_idx] works!" >&2 - create_squash_commit "$start_idx" "$end_idx" - echo $((end_idx + 1)) # Output next index to process - return 0 - fi - - # Reset for next attempt - git reset --hard "$before" >/dev/null 2>&1 - done - - # If we get here, we couldn't find a working batch - return 1 -} - -############################################################################### -# main rebasing loop -############################################################################### -idx=0 -while (( idx < total )); do - # First, always try to apply as a single commit - if apply_single "${commits[$idx]}"; then - ((idx++)) || true - continue - fi - - # Single commit failed. Find the minimal batch that works - if new_idx=$(find_minimal_batch "$idx"); then - idx=$new_idx - else - # Can't find any working batch. Last resort: squash all remaining - echo "⚠️ Cannot find working batch. Squashing all remaining commits..." >&2 - - # Reset and try to squash merge all remaining commits at once - before=$(git rev-parse --verify HEAD) - - # Create a temp branch at the last commit - temp_branch="temp-squash-remaining-$$" - git branch "$temp_branch" "${commits[$((total-1))]}" >/dev/null 2>&1 - - if git merge --squash "$temp_branch" >/dev/null 2>&1 && ! git diff --cached --quiet; then - create_squash_commit "$idx" "$((total-1))" - git branch -D "$temp_branch" >/dev/null 2>&1 - break - else - git merge --abort >/dev/null 2>&1 || true - git branch -D "$temp_branch" >/dev/null 2>&1 || true - git reset --hard "$before" - - # Ultimate fallback: squash entire PR - echo "❌ Even remaining commits failed. Squashing entire PR..." >&2 - git reset --hard "origin/$pr_base_ref" - - if git merge --squash "origin/$pr_head_ref" >/dev/null 2>&1; then - create_squash_commit 0 "$((total-1))" - else - git merge --abort >/dev/null 2>&1 || true - die "rebase failed: unable to squash merge entire PR branch" - fi - fi - break +# create working branch +work_branch="auto-rebase-$pr_head_ref" +git switch --force-create "$work_branch" "origin/$pr_base_ref" + +# cherry-pick each commit +for commit in "${commits[@]}"; do + if ! git cherry-pick "$commit"; then + echo "Failed to cherry-pick $(git log -1 --format='%h %s' "$commit")" >&2 + git cherry-pick --abort 2>/dev/null || true + git switch - + git branch -D "$work_branch" + exit 1 fi done -############################################################################### -# fast-forward PR branch & optional push -############################################################################### -git branch -f "$pr_head_ref" HEAD -git switch "$pr_head_ref" -git branch -D "$work_branch" - -if [[ -n "${GH_TOKEN:-}" || -n "${GITHUB_TOKEN:-}" ]]; then +if [ "${PUSH:-0}" -eq 1 ]; then + # update PR branch + git switch --force-create "$pr_head_ref" "origin/$pr_base_ref" + git git reset --hard "$work_branch" git push origin "$pr_head_ref" --force-with-lease +else + echo "You are on a successful rebase branch. Use 'git log' to look around." + echo "To return, just do 'git checkout $pr_head_ref'." + echo "If you like what you see you can do:" + echo git reset --hard "$work_branch" + echo git push --force-with-lease fi - -echo "✅ Successfully rebased $pr_head_ref" >&2 From 8feca7a0905fc79f5717849344a734efb0643b12 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 16:08:09 +0000 Subject: [PATCH 10/30] fix instance override --- ci3/aws_request_instance | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci3/aws_request_instance b/ci3/aws_request_instance index 0765c2548c40..c0f1fb98b7f6 100755 --- a/ci3/aws_request_instance +++ b/ci3/aws_request_instance @@ -47,6 +47,10 @@ else exit 1 fi +if [ -n "${AWS_INSTANCE:-}" ]; then + instances=("$AWS_INSTANCE") +fi + set +e IFS=',' read -ra cpu_list <<< "$cpus" for cpu in "${cpu_list[@]}"; do From 1b064755d2b22ac2a235b7df53889ea75c7722cc Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 16:22:31 +0000 Subject: [PATCH 11/30] auto-rebase PR script update --- scripts/auto_rebase_pr.sh | 40 ++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/scripts/auto_rebase_pr.sh b/scripts/auto_rebase_pr.sh index f1e00490d029..e95e8ab1b54d 100755 --- a/scripts/auto_rebase_pr.sh +++ b/scripts/auto_rebase_pr.sh @@ -6,7 +6,7 @@ pr_head_ref=${1:-} pr_base_ref=${2:-} [[ -z $pr_head_ref || -z $pr_base_ref ]] && { echo "usage: $0 " >&2; exit 1; } -merge_base=$(git merge-base "origin/$pr_base_ref" "origin/$pr_head_ref") +merge_base=$(git merge-base "origin/$pr_base_ref" "$pr_head_ref") # collect commits, excluding empty commits, merge commits and previous squashed PR merges commits=($( @@ -14,7 +14,7 @@ commits=($( --grep='\[empty\]' --grep='(#' \ --no-merges \ --invert-grep \ - "$merge_base..origin/$pr_head_ref" + "$merge_base..$pr_head_ref" )) if [ ${#commits[@]} -eq 0 ]; then @@ -27,12 +27,38 @@ git switch --force-create "$work_branch" "origin/$pr_base_ref" # cherry-pick each commit for commit in "${commits[@]}"; do - if ! git cherry-pick "$commit"; then + echo "Cherry-picking $(git log -1 --format='%h %s' "$commit")" + if ! git cherry-pick -X theirs "$commit"; then echo "Failed to cherry-pick $(git log -1 --format='%h %s' "$commit")" >&2 - git cherry-pick --abort 2>/dev/null || true - git switch - - git branch -D "$work_branch" - exit 1 + + # Check if we're in an interactive terminal + if [ -t 0 ] && [ -t 1 ]; then + echo "" + echo "Cherry-pick conflict detected! Dropping into bash shell." + echo "You can:" + echo " - Fix conflicts and run: git cherry-pick --continue" + echo " - Skip this commit: git cherry-pick --skip" + echo " - Abort and exit: git cherry-pick --abort && exit" + echo " - Exit shell to abort the rebase" + echo "" + + # Drop into interactive bash + bash || true + + # Check if cherry-pick is still in progress + if git rev-parse --verify CHERRY_PICK_HEAD >/dev/null 2>&1; then + echo "Cherry-pick still in progress, aborting..." + git cherry-pick --abort 2>/dev/null || true + git switch - + git branch -D "$work_branch" + exit 1 + fi + else + git cherry-pick --abort 2>/dev/null || true + git switch - + git branch -D "$work_branch" + exit 1 + fi fi done From 0dc5a29e1dbf8989699216df241710453c8bd8f6 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 17:04:14 +0000 Subject: [PATCH 12/30] simplify --- .../cpp/src/barretenberg/api/bbapi_execute.hpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index ca5d41982776..0e2f3d133ebf 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -81,18 +81,3 @@ inline std::vector execute_request(BBApiRequest&& request, std: } } // namespace bb::bbapi - -namespace bb { -template -inline typename T::Response do_bbapi(T&& command) - requires(!bbapi::RequiresBBApiRequest) -{ - bbapi::BBApiRequest request; - return command.execute(request); -} - -template inline typename T::Response do_bbapi(bbapi::BBApiRequest& request, T&& command) -{ - return command.execute(request); -} -} // namespace bb From 9a701861de826cde9c0fe6a059980a79e169e37e Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 19:13:13 +0000 Subject: [PATCH 13/30] working tests --- .../src/barretenberg/api/api_client_ivc.cpp | 25 ++++++++----------- .../src/barretenberg/api/bbapi_client_ivc.cpp | 6 ++--- .../src/barretenberg/api/bbapi_ultra_honk.cpp | 8 +++--- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 46d00432787e..9d78a9aeb805 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -1,6 +1,7 @@ #include "api_client_ivc.hpp" #include "barretenberg/api/bbapi.hpp" #include "barretenberg/api/file_io.hpp" +#include "barretenberg/api/get_bytecode.hpp" #include "barretenberg/api/log.hpp" #include "barretenberg/api/write_prover_output.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" @@ -63,11 +64,11 @@ std::string field_elements_to_json(const std::vector& fields) * @param bytecode_path * @param witness_path */ -void write_standalone_vk(const std::string& output_data_type, - const std::string& bytecode_path, - const std::string& output_path) +void write_standalone_vk(const std::string& output_format, + const std::filesystem::path& bytecode_path, + const std::filesystem::path& output_path) { - + auto bytecode = get_bytecode(bytecode_path); auto response = bbapi::ClientIvcComputeStandaloneVk{ .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }.execute(); @@ -96,8 +97,6 @@ void write_vk_for_ivc(const std::string& output_format, if (output_format != "bytes") { throw_or_abort("Unsupported output format for ClientIVC vk: " + output_format); } - ClientIVC ivc{ /*num_circuits=*/2, { AZTEC_TRACE_STRUCTURE } }; - ClientIVCMockCircuitProducer circuit_producer; // Since we need to specify the number of public inputs but ClientIvcComputeIvcVk derives it from bytecode, // we need to create a mock circuit with the correct number of public inputs @@ -107,7 +106,6 @@ void write_vk_for_ivc(const std::string& output_format, const auto buf = to_buffer(vk); const bool output_to_stdout = output_dir == "-"; - const auto buf = to_buffer(ivc.get_vk()); if (output_to_stdout) { write_bytes_to_stdout(buf); @@ -146,17 +144,20 @@ void ClientIVCAPI::prove(const Flags& flags, bbapi::BBApiRequest request; bbapi::ClientIvcStart{}.execute(request); + std::vector raw_steps = PrivateExecutionStepRaw::load_and_decompress(input_path); + size_t last_circuit_public_inputs_size = 0; for (const auto& step : raw_steps) { bbapi::ClientIvcLoad{ .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } }.execute(request); + last_circuit_public_inputs_size = request.last_circuit_constraints->public_inputs.size(); info("ClientIVC: accumulating " + step.function_name); bbapi::ClientIvcAccumulate{ .witness = step.witness }.execute(request); } - auto prove_response = bbapi::ClientIvcProve{}.execute(request); + auto proof = bbapi::ClientIvcProve{}.execute(request).proof; // We'd like to use the `write` function that UltraHonkAPI uses, but there are missing functions for creating // std::string representations of vks that don't feel worth implementing @@ -177,8 +178,7 @@ void ClientIVCAPI::prove(const Flags& flags, if (flags.write_vk) { vinfo("writing ClientIVC vk in directory ", output_dir); - const size_t num_public_inputs_in_final_circuit = steps.folding_stack.back().constraints.public_inputs.size(); - write_vk_for_ivc("bytes", num_public_inputs_in_final_circuit, output_dir); + write_vk_for_ivc("bytes", last_circuit_public_inputs_size, output_dir); } } @@ -218,12 +218,9 @@ void ClientIVCAPI::write_solidity_verifier([[maybe_unused]] const Flags& flags, } bool ClientIVCAPI::check_precomputed_vks(const std::filesystem::path& input_path) - { - PrivateExecutionSteps steps; - steps.parse(PrivateExecutionStepRaw::load_and_decompress(input_path)); - bbapi::BBApiRequest request; + std::vector raw_steps = PrivateExecutionStepRaw::load_and_decompress(input_path); for (const auto& step : raw_steps) { if (step.vk.empty()) { diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index c178e7d4e4b1..8d215d987811 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -122,7 +122,7 @@ ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_ return ivc.get_vk(); } -ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(const BBApiRequest& request) && +ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(BB_UNUSED const BBApiRequest& request) && { info("ClientIvcComputeStandaloneVk - deriving VK for circuit '", circuit.name, "'"); @@ -130,7 +130,7 @@ ClientIvcComputeStandaloneVk::Response ClientIvcComputeStandaloneVk::execute(con acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); - auto verification_key = std::make_shared(proving_key->proving_key); + auto verification_key = std::make_shared(proving_key->get_precomputed()); Response response; response.bytes = to_buffer(*verification_key); @@ -163,7 +163,7 @@ ClientIvcCheckPrecomputedVk::Response ClientIvcCheckPrecomputedVk::execute(const /*witness=*/{} }; std::shared_ptr proving_key = get_acir_program_decider_proving_key(request, program); - auto computed_vk = std::make_shared(proving_key->proving_key); + auto computed_vk = std::make_shared(proving_key->get_precomputed()); if (circuit.verification_key.empty()) { info("FAIL: Expected precomputed vk for function ", function_name); diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp index 8f11c39f3dd4..346c35cc9d48 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -90,7 +90,7 @@ CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && if (!circuit.verification_key.empty()) { vk = from_buffer>(circuit.verification_key); } else { - vk = std::make_shared(proving_key->proving_key); + vk = std::make_shared(proving_key->get_precomputed()); } UltraProver_ prover{ proving_key, vk }; @@ -109,7 +109,7 @@ CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && if (!circuit.verification_key.empty()) { vk = from_buffer>(circuit.verification_key); } else { - vk = std::make_shared(proving_key->proving_key); + vk = std::make_shared(proving_key->get_precomputed()); } UltraProver_ prover{ proving_key, vk }; @@ -145,7 +145,7 @@ CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request using Flavor = UltraRollupFlavor; auto builder = acir_format::create_circuit(program, metadata); auto proving_key = std::make_shared>(builder, request.trace_settings); - auto verification_key = std::make_shared(proving_key->proving_key); + auto verification_key = std::make_shared(proving_key->get_precomputed()); response.bytes = to_buffer(*verification_key); } else { @@ -153,7 +153,7 @@ CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request using Flavor = UltraFlavor; auto builder = acir_format::create_circuit(program, metadata); auto proving_key = std::make_shared>(builder, request.trace_settings); - auto verification_key = std::make_shared(proving_key->proving_key); + auto verification_key = std::make_shared(proving_key->get_precomputed()); response.bytes = to_buffer(*verification_key); } From 5cb7fb50a07d6d4b5a549ad32cccb364064702f3 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 21:42:28 +0000 Subject: [PATCH 14/30] revert noir-projects --- .../src/state_vars/shared_mutable/test.nr | 32 ++++++++++------- .../src/test/helpers/test_environment.nr | 8 +++-- .../contracts/fees/fpc_contract/src/main.nr | 2 +- .../reset_output_validator_builder/mod.nr | 36 +++++++++---------- .../note_hash_read_request_hints_builder.nr | 6 ++-- .../nullifier_read_request_hints_builder.nr | 6 ++-- ...t_split_sorted_transformed_value_arrays.nr | 4 +-- 7 files changed, 52 insertions(+), 42 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index 6d8a2e7cada8..ef93edadcd77 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -79,7 +79,7 @@ unconstrained fn get_current_value_in_public_before_scheduled_change() { (original_value, timestamp_of_change) }); - env.set_next_block_timestamp(timestamp_of_change - 1); + env.advance_timestamp_to(timestamp_of_change - 1); env.public_context(|context| { let state_var = in_public(context); @@ -99,7 +99,7 @@ unconstrained fn get_current_value_in_public_at_scheduled_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change); + env.advance_timestamp_to(timestamp_of_change); env.public_context(|context| { let state_var = in_public(context); @@ -119,7 +119,7 @@ unconstrained fn get_current_value_in_public_after_scheduled_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change + 10); + env.advance_timestamp_to(timestamp_of_change + 10); env.public_context(|context| { let state_var = in_public(context); @@ -172,7 +172,7 @@ unconstrained fn get_current_delay_in_public_before_scheduled_change() { }); // The current delay still does not change right before the timestamp of change - env.set_next_block_timestamp(timestamp_of_change - 1); + env.advance_timestamp_to(timestamp_of_change - 1); env.public_context(|context| { let state_var = in_public(context); @@ -192,7 +192,7 @@ unconstrained fn get_current_delay_in_public_at_scheduled_change() { state_var.get_scheduled_delay() }); - env.set_next_block_timestamp(timestamp_of_change); + env.advance_timestamp_to(timestamp_of_change); env.public_context(|context| { let state_var = in_public(context); @@ -212,7 +212,7 @@ unconstrained fn get_current_delay_in_public_after_scheduled_change() { state_var.get_scheduled_delay() }); - env.set_next_block_timestamp(timestamp_of_change + 10); + env.advance_timestamp_to(timestamp_of_change + 10); env.public_context(|context| { let state_var = in_public(context); @@ -267,7 +267,8 @@ unconstrained fn get_current_value_in_private_immediately_before_change() { state_var.get_scheduled_value() }); - env.mine_block_at(timestamp_of_change - 1); + env.advance_timestamp_to(timestamp_of_change - 1); + cheatcodes::advance_blocks_by(1); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -294,7 +295,8 @@ unconstrained fn get_current_value_in_private_at_change() { state_var.get_scheduled_value() }); - env.mine_block_at(timestamp_of_change); + env.advance_timestamp_to(timestamp_of_change); + cheatcodes::advance_blocks_by(1); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -322,7 +324,8 @@ unconstrained fn get_current_value_in_private_after_change() { state_var.get_scheduled_value() }); - env.mine_block_at(timestamp_of_change + 10); + env.advance_timestamp_to(timestamp_of_change + 10); + cheatcodes::advance_blocks_by(1); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -353,7 +356,8 @@ unconstrained fn get_current_value_in_private_with_non_initial_delay() { }); let historical_timestamp = std::cmp::max(value_timestamp_of_change, delay_timestamp_of_change); - env.mine_block_at(historical_timestamp); + env.advance_timestamp_to(historical_timestamp); + cheatcodes::advance_blocks_by(1); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -387,7 +391,8 @@ unconstrained fn get_current_value_in_utility_before_scheduled_change() { state_var.get_scheduled_value() }); - env.mine_block_at(timestamp_of_change - 1); + env.advance_timestamp_to(timestamp_of_change - 1); + cheatcodes::advance_blocks_by(1); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp @@ -410,7 +415,8 @@ unconstrained fn get_current_value_in_utility_at_scheduled_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change); + state_var.get_scheduled_value() + }); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp @@ -433,7 +439,7 @@ unconstrained fn get_current_value_in_utility_after_scheduled_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change + 10); + env.advance_timestamp_to(timestamp_of_change + 10); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index bbde9ff5c298..a416fe801e10 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -135,8 +135,12 @@ impl TestEnvironment { ret_value } - /// Returns the number of the next block to be built. - pub unconstrained fn next_block_number(_self: Self) -> u32 { + /// Returns the block number of the block currently being built. Since sequencer is executing the public part + /// of transactions when building blocks, this block number is also returned by public_context.block_number(). + pub unconstrained fn pending_block_number(_self: Self) -> u32 { + // TODO: This oracle when used in PXE returns the latest synched block number by the node and not the pending + // block number! But TXE handles this in some messed up custom way so this might actually be kinda correct. + // Terrible. get_block_number() } diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index 08854e8e6077..8bdf54e7c0bf 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -159,7 +159,7 @@ pub contract FPC { Token::at(config.accepted_asset) .transfer_in_public(context.msg_sender(), context.this_address(), max_fee, authwit_nonce ) - .enqueue(&mut context); + .enqueue(&mut context); // docs:end:public_call context.set_as_fee_payer(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr index 5b2b98267225..723f90f681d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr @@ -63,25 +63,25 @@ impl ResetOutputValidatorBuilder { TRANSIENT_DATA_SQUASHING_HINTS_LEN ]; - ResetOutputValidatorBuilder { - output, - previous_kernel, - note_hash_read_request_hints_builder, - nullifier_read_request_hints_builder, - key_validation_hints, - transient_data_index_hints, - pending_note_hash_read_amount: 0, - settled_note_hash_read_amount: 0, - pending_nullifier_read_amount: 0, - settled_nullifier_read_amount: 0, - key_validation_amount: 0, - transient_data_squashing_amount: 0, - note_hash_siloing_amount: 0, - nullifier_siloing_amount: 0, - private_log_siloing_amount: 0, - padded_side_effects: PaddedSideEffects::empty(), - } + ResetOutputValidatorBuilder { + output, + previous_kernel, + note_hash_read_request_hints_builder, + nullifier_read_request_hints_builder, + key_validation_hints, + transient_data_index_hints, + pending_note_hash_read_amount: 0, + settled_note_hash_read_amount: 0, + pending_nullifier_read_amount: 0, + settled_nullifier_read_amount: 0, + key_validation_amount: 0, + transient_data_squashing_amount: 0, + note_hash_siloing_amount: 0, + nullifier_siloing_amount: 0, + private_log_siloing_amount: 0, + padded_side_effects: PaddedSideEffects::empty(), } + } pub fn get_validation_request_processor( self, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index 1659379d9223..a1382fe36133 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NoteHashReadRequest NoteHashSettledReadHint::skip(MAX_NOTE_HASH_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), - } + 0, + ), } + } pub fn add_pending_read_hint(&mut self, read_request_index: u32, note_hash_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index b337671abd12..38e946f36d35 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NullifierReadReques NullifierSettledReadHint::skip(MAX_NULLIFIER_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), - } + 0, + ), } + } pub fn add_pending_read_hint(&mut self, read_request_index: u32, nullifier_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 5c5952252a1c..93106d54403e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -267,9 +267,9 @@ mod tests { { original_index = i; } - } - self.hints.sorted_indexes[original_index] = new_index; } + self.hints.sorted_indexes[original_index] = new_index; + } pub fn execute(self) { if self.ascending { From 44a335f93b3125e467039527c3f2cb7b97adce95 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 21:57:07 +0000 Subject: [PATCH 15/30] remove unused --- .../src/barretenberg/api/api_client_ivc.cpp | 45 +------------------ .../src/barretenberg/api/api_client_ivc.hpp | 2 - .../barretenberg/api/write_prover_output.hpp | 14 ++++++ 3 files changed, 16 insertions(+), 45 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 9d78a9aeb805..e90d86d2cbb5 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -19,42 +19,7 @@ #include namespace bb { -namespace {} // anonymous namespace - -acir_format::WitnessVector witness_map_to_witness_vector(std::map const& witness_map) -{ - acir_format::WitnessVector wv; - size_t index = 0; - for (const auto& e : witness_map) { - uint64_t value = 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; -} - -namespace { -std::string field_elements_to_json(const std::vector& fields) -{ - std::stringstream ss; - ss << "["; - for (size_t i = 0; i < fields.size(); ++i) { - ss << '"' << fields[i] << '"'; - if (i < fields.size() - 1) { - ss << ","; - } - } - ss << "]"; - return ss.str(); -} -} // namespace +namespace { // anonymous namespace /** * @brief Compute and write to file a MegaHonk VK for a circuit to be accumulated in the IVC @@ -83,13 +48,6 @@ void write_standalone_vk(const std::string& output_format, } } -size_t get_num_public_inputs_in_circuit(const std::filesystem::path& bytecode_path) -{ - using namespace acir_format; - acir_format::AcirProgram program{ get_constraint_system(bytecode_path), /*witness=*/{} }; - return program.constraints.public_inputs.size(); -} - void write_vk_for_ivc(const std::string& output_format, size_t num_public_inputs_in_final_circuit, const std::filesystem::path& output_dir) @@ -135,6 +93,7 @@ void write_vk_for_ivc(const std::string& output_data_type, write_file(output_dir / "vk", response.bytes); } } +} // anonymous namespace void ClientIVCAPI::prove(const Flags& flags, const std::filesystem::path& input_path, diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.hpp index b9d74abb52b9..0e568ec0706e 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.hpp @@ -44,8 +44,6 @@ void gate_count_for_ivc(const std::string& bytecode_path, bool include_gates_per void write_arbitrary_valid_client_ivc_proof_and_vk_to_file(const std::filesystem::path& output_dir); -acir_format::WitnessVector witness_map_to_witness_vector(std::map const& witness_map); - std::vector decompress(const void* bytes, size_t size); } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/api/write_prover_output.hpp b/barretenberg/cpp/src/barretenberg/api/write_prover_output.hpp index cf9370b1a52d..436a9e50358a 100644 --- a/barretenberg/cpp/src/barretenberg/api/write_prover_output.hpp +++ b/barretenberg/cpp/src/barretenberg/api/write_prover_output.hpp @@ -10,6 +10,20 @@ namespace bb { +inline std::string field_elements_to_json(const std::vector& fields) +{ + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < fields.size(); ++i) { + ss << '"' << fields[i] << '"'; + if (i < fields.size() - 1) { + ss << ","; + } + } + ss << "]"; + return ss.str(); +} + template struct PubInputsProofAndKey { PublicInputsVector public_inputs; HonkProof proof; From 10ae9931d6b48632742eb17cb834a7cc451f758a Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 10 Jul 2025 22:33:53 +0000 Subject: [PATCH 16/30] comments --- .../src/barretenberg/api/bbapi_client_ivc.hpp | 84 ++++++++++++++++--- .../src/barretenberg/api/bbapi_execute.hpp | 2 - .../src/barretenberg/api/bbapi_ultra_honk.cpp | 62 -------------- .../src/barretenberg/api/bbapi_ultra_honk.hpp | 31 ------- 4 files changed, 74 insertions(+), 105 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp index be9b1bb860a2..36979b238dbc 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -14,15 +14,27 @@ namespace bb::bbapi { +/** + * @brief Helper function to compute verification key for IVC + * @param request The API request context + * @param num_public_inputs_in_final_circuit Number of public inputs in the final circuit + * @return The computed IVC verification key + */ ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit); /** - * @brief - * Note, only one IVC request can be made at a time for each batch_request. + * @struct ClientIvcStart + * @brief Initialize a new ClientIVC instance for incremental proof accumulation + * + * @note Only one IVC request can be made at a time for each batch_request. */ struct ClientIvcStart { static constexpr const char* NAME = "ClientIvcStart"; + /** + * @struct Response + * @brief Empty response indicating successful initialization + */ struct Response { static constexpr const char* NAME = "ClientIvcStartResponse"; // Empty response - success indicated by no exception @@ -30,85 +42,137 @@ struct ClientIvcStart { Response execute(BBApiRequest& request) &&; }; +/** + * @struct ClientIvcLoad + * @brief Load a circuit into the ClientIVC instance for accumulation + */ struct ClientIvcLoad { static constexpr const char* NAME = "ClientIvcLoad"; + /** + * @struct Response + * @brief Empty response indicating successful circuit loading + */ struct Response { static constexpr const char* NAME = "ClientIvcLoadResponse"; // Empty response - success indicated by no exception }; + /** @brief Circuit to be loaded with its bytecode and verification key */ CircuitInput circuit; Response execute(BBApiRequest& request) &&; }; +/** + * @struct ClientIvcAccumulate + * @brief Accumulate the previously loaded circuit into the IVC proof + */ struct ClientIvcAccumulate { static constexpr const char* NAME = "ClientIvcAccumulate"; + /** + * @struct Response + * @brief Empty response indicating successful circuit accumulation + */ struct Response { static constexpr const char* NAME = "ClientIvcAccumulateResponse"; // Empty response - success indicated by no exception }; - // Serialized witness for the last loaded circuit. + /** @brief Serialized witness data for the last loaded circuit */ std::vector witness; Response execute(BBApiRequest& request) &&; }; +/** + * @struct ClientIvcProve + * @brief Generate a proof for all accumulated circuits + */ struct ClientIvcProve { static constexpr const char* NAME = "ClientIvcProve"; + /** + * @struct Response + * @brief Contains the generated IVC proof + */ struct Response { static constexpr const char* NAME = "ClientIvcProveResponse"; + /** @brief Complete IVC proof for all accumulated circuits */ ClientIVC::Proof proof; }; Response execute(BBApiRequest& request) &&; }; -/** Compute standalone verification key for a circuit */ +/** + * @struct ClientIvcComputeStandaloneVk + * @brief Compute standalone verification key for a circuit + */ struct ClientIvcComputeStandaloneVk { static constexpr const char* NAME = "ClientIvcComputeStandaloneVk"; + /** + * @struct Response + * @brief Contains the computed verification key in multiple formats + */ struct Response { static constexpr const char* NAME = "ClientIvcComputeStandaloneVkResponse"; - std::vector bytes; // Serialized verification key - std::vector fields; // Verification key as field elements + /** @brief Serialized verification key in binary format */ + std::vector bytes; + /** @brief Verification key as array of field elements */ + std::vector fields; }; + /** @brief Circuit bytecode without precomputed VK */ CircuitInputNoVK circuit; Response execute(const BBApiRequest& request = {}) &&; }; -/** Compute IVC verification key */ +/** + * @struct ClientIvcComputeIvcVk + * @brief Compute IVC verification key for the complete proof + */ struct ClientIvcComputeIvcVk { static constexpr const char* NAME = "ClientIvcComputeIvcVk"; + /** + * @struct Response + * @brief Contains the computed IVC verification key + */ struct Response { static constexpr const char* NAME = "ClientIvcComputeIvcVkResponse"; - std::vector bytes; // Serialized IVC verification key + /** @brief Serialized IVC verification key in binary format */ + std::vector bytes; }; + /** @brief Final circuit bytecode for IVC VK computation */ CircuitInputNoVK circuit; Response execute(const BBApiRequest& request = {}) &&; }; /** - * @brief Command to check if a precomputed VK matches the circuit + * @struct ClientIvcCheckPrecomputedVk + * @brief Verify that a precomputed verification key matches the circuit */ struct ClientIvcCheckPrecomputedVk { static constexpr const char* NAME = "ClientIvcCheckPrecomputedVk"; + /** + * @struct Response + * @brief Contains the validation result + */ struct Response { static constexpr const char* NAME = "ClientIvcCheckPrecomputedVkResponse"; + /** @brief True if the precomputed VK matches the circuit */ bool valid; }; - // Circuit with its precomputed VK + /** @brief Circuit with its precomputed verification key */ CircuitInput circuit; + /** @brief Human-readable name for logging and error messages */ std::string function_name; Response execute(const BBApiRequest& request = {}) &&; }; diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index 0e2f3d133ebf..9c223fd3d734 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -23,7 +23,6 @@ using Command = NamedUnion; @@ -43,7 +42,6 @@ using CommandResponse = NamedUnion; diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp index 346c35cc9d48..2dfb65dc2c08 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -16,49 +16,6 @@ namespace bb::bbapi { -// Helper functions for format conversions -static std::string bytes_to_hex(const std::vector& bytes) -{ - std::stringstream ss; - ss << std::hex << std::setfill('0'); - for (uint8_t b : bytes) { - ss << std::setw(2) << static_cast(b); - } - return ss.str(); -} - -static std::string bytes_to_base64(const std::vector& bytes) -{ - // TODO replace this gpt-ese with a proper base64 library - static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - std::string result; - size_t i = 0; - while (i < bytes.size()) { - uint32_t octet_a = i < bytes.size() ? bytes[i++] : 0; - uint32_t octet_b = i < bytes.size() ? bytes[i++] : 0; - uint32_t octet_c = i < bytes.size() ? bytes[i++] : 0; - - uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c; - - result.push_back(base64_chars[(triple >> 18) & 0x3F]); - result.push_back(base64_chars[(triple >> 12) & 0x3F]); - result.push_back(base64_chars[(triple >> 6) & 0x3F]); - result.push_back(base64_chars[triple & 0x3F]); - } - - // Add padding - size_t padding = bytes.size() % 3; - if (padding > 0) { - result.resize(result.size() - (3 - padding)); - for (size_t j = 0; j < (3 - padding); ++j) { - result.push_back('='); - } - } - - return result; -} - CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && { auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); @@ -161,11 +118,6 @@ CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request return response; } -CircuitComputeIvcVk::Response CircuitComputeIvcVk::execute(BB_UNUSED const BBApiRequest& request) && -{ - throw_or_abort("CircuitComputeIvcVk not implemented yet"); -} - CircuitInfo::Response CircuitInfo::execute(BB_UNUSED const BBApiRequest& request) && { auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); @@ -291,20 +243,6 @@ CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiReques .public_inputs = prove_result.public_inputs }; } -CircuitWriteBytecode::Response CircuitWriteBytecode::execute(BB_UNUSED const BBApiRequest& request) && -{ - Response response; - response.bytecode = circuit.bytecode; - - if (format == "hex") { - response.formatted_output = bytes_to_hex(circuit.bytecode); - } else if (format == "base64") { - response.formatted_output = bytes_to_base64(circuit.bytecode); - } - - return response; -} - CircuitValidate::Response CircuitValidate::execute(BB_UNUSED const BBApiRequest& request) && { Response response; diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp index 77d5ce439acc..c919aa2bbaab 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp @@ -61,19 +61,6 @@ struct CircuitComputeVk { Response execute(const BBApiRequest& request = {}) &&; }; -/** Compute verification key, Treat the previously loaded circuit as either a standalone circuit - * or a common final circuit used to verify all of IVC. */ -struct CircuitComputeIvcVk { - static constexpr const char* NAME = "CircuitComputeIvcVk"; - - struct Response { - static constexpr const char* NAME = "CircuitComputeIvcVkResponse"; - - std::vector bytes; // Serialized verification key - }; - Response execute(const BBApiRequest& request = {}) &&; -}; - /** * @struct CircuitInfo * @brief Consolidated command for retrieving circuit information. @@ -208,24 +195,6 @@ struct CircuitProveAndVerify { Response execute(const BBApiRequest& request = {}) &&; }; -/** - * @brief Command to write circuit bytecode in various formats - */ -struct CircuitWriteBytecode { - static constexpr const char* NAME = "CircuitWriteBytecode"; - - struct Response { - static constexpr const char* NAME = "CircuitWriteBytecodeResponse"; - - std::vector bytecode; - std::string formatted_output; // For hex/base64 - }; - - CircuitInput circuit; - std::string format = "binary"; // binary, hex, base64 - Response execute(const BBApiRequest& request = {}) &&; -}; - /** * @brief Command to validate circuit structure */ From 2c41eb431587bb4dac25634f1a19ba9665110af6 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 17:13:21 +0000 Subject: [PATCH 17/30] revert --- .../src/state_vars/shared_mutable/test.nr | 27 +++++++++---------- .../src/test/helpers/test_environment.nr | 8 ++---- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index ef93edadcd77..c8d64b8450de 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -79,7 +79,7 @@ unconstrained fn get_current_value_in_public_before_scheduled_change() { (original_value, timestamp_of_change) }); - env.advance_timestamp_to(timestamp_of_change - 1); + env.set_next_block_timestamp(timestamp_of_change - 1); env.public_context(|context| { let state_var = in_public(context); @@ -99,7 +99,7 @@ unconstrained fn get_current_value_in_public_at_scheduled_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change); + env.set_next_block_timestamp(timestamp_of_change); env.public_context(|context| { let state_var = in_public(context); @@ -119,7 +119,7 @@ unconstrained fn get_current_value_in_public_after_scheduled_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change + 10); + env.set_next_block_timestamp(timestamp_of_change + 10); env.public_context(|context| { let state_var = in_public(context); @@ -172,7 +172,7 @@ unconstrained fn get_current_delay_in_public_before_scheduled_change() { }); // The current delay still does not change right before the timestamp of change - env.advance_timestamp_to(timestamp_of_change - 1); + env.set_next_block_timestamp(timestamp_of_change - 1); env.public_context(|context| { let state_var = in_public(context); @@ -192,7 +192,7 @@ unconstrained fn get_current_delay_in_public_at_scheduled_change() { state_var.get_scheduled_delay() }); - env.advance_timestamp_to(timestamp_of_change); + env.set_next_block_timestamp(timestamp_of_change); env.public_context(|context| { let state_var = in_public(context); @@ -212,7 +212,7 @@ unconstrained fn get_current_delay_in_public_after_scheduled_change() { state_var.get_scheduled_delay() }); - env.advance_timestamp_to(timestamp_of_change + 10); + env.set_next_block_timestamp(timestamp_of_change + 10); env.public_context(|context| { let state_var = in_public(context); @@ -267,7 +267,7 @@ unconstrained fn get_current_value_in_private_immediately_before_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change - 1); + env.set_next_block_timestamp(timestamp_of_change - 1); cheatcodes::advance_blocks_by(1); env.private_context(|context| { @@ -295,7 +295,7 @@ unconstrained fn get_current_value_in_private_at_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change); + env.set_next_block_timestamp(timestamp_of_change); cheatcodes::advance_blocks_by(1); env.private_context(|context| { @@ -324,7 +324,7 @@ unconstrained fn get_current_value_in_private_after_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change + 10); + env.set_next_block_timestamp(timestamp_of_change + 10); cheatcodes::advance_blocks_by(1); env.private_context(|context| { @@ -356,7 +356,7 @@ unconstrained fn get_current_value_in_private_with_non_initial_delay() { }); let historical_timestamp = std::cmp::max(value_timestamp_of_change, delay_timestamp_of_change); - env.advance_timestamp_to(historical_timestamp); + env.set_next_block_timestamp(historical_timestamp); cheatcodes::advance_blocks_by(1); env.private_context(|context| { @@ -391,7 +391,7 @@ unconstrained fn get_current_value_in_utility_before_scheduled_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change - 1); + env.set_next_block_timestamp(timestamp_of_change - 1); cheatcodes::advance_blocks_by(1); env.utility_context(|context| { @@ -415,8 +415,7 @@ unconstrained fn get_current_value_in_utility_at_scheduled_change() { state_var.get_scheduled_value() }); - state_var.get_scheduled_value() - }); + env.set_next_block_timestamp(timestamp_of_change); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp @@ -439,7 +438,7 @@ unconstrained fn get_current_value_in_utility_after_scheduled_change() { state_var.get_scheduled_value() }); - env.advance_timestamp_to(timestamp_of_change + 10); + env.set_next_block_timestamp(timestamp_of_change + 10); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index a416fe801e10..bbde9ff5c298 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -135,12 +135,8 @@ impl TestEnvironment { ret_value } - /// Returns the block number of the block currently being built. Since sequencer is executing the public part - /// of transactions when building blocks, this block number is also returned by public_context.block_number(). - pub unconstrained fn pending_block_number(_self: Self) -> u32 { - // TODO: This oracle when used in PXE returns the latest synched block number by the node and not the pending - // block number! But TXE handles this in some messed up custom way so this might actually be kinda correct. - // Terrible. + /// Returns the number of the next block to be built. + pub unconstrained fn next_block_number(_self: Self) -> u32 { get_block_number() } From 98941fca79f8eca887a9d8e8c9e086a25d41f2da Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 17:17:46 +0000 Subject: [PATCH 18/30] stub out UH --- .../src/barretenberg/api/api_client_ivc.cpp | 10 +- .../src/barretenberg/api/bbapi_client_ivc.cpp | 26 +- .../src/barretenberg/api/bbapi_client_ivc.hpp | 2 +- .../cpp/src/barretenberg/api/bbapi_shared.hpp | 6 +- .../src/barretenberg/api/bbapi_ultra_honk.cpp | 229 +----------------- .../src/barretenberg/api/bbapi_ultra_honk.hpp | 19 -- .../contracts/fees/fpc_contract/src/main.nr | 2 +- .../src/private_kernel_inner.nr | 36 +-- .../src/private_kernel_reset.nr | 14 +- .../reset_output_validator_builder/mod.nr | 36 +-- .../note_hash_read_request_hints_builder.nr | 6 +- .../nullifier_read_request_hints_builder.nr | 6 +- ...t_split_sorted_transformed_value_arrays.nr | 4 +- 13 files changed, 88 insertions(+), 308 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index e90d86d2cbb5..aa3bae2cfffa 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -58,9 +58,9 @@ void write_vk_for_ivc(const std::string& output_format, // Since we need to specify the number of public inputs but ClientIvcComputeIvcVk derives it from bytecode, // we need to create a mock circuit with the correct number of public inputs - // For now, we'll use the compute_vk_for_ivc function directly as it was designed for this purpose + // For now, we'll use the compute_civc_vk function directly as it was designed for this purpose bbapi::BBApiRequest request; - auto vk = bbapi::compute_vk_for_ivc(request, num_public_inputs_in_final_circuit); + auto vk = bbapi::compute_civc_vk(request, num_public_inputs_in_final_circuit); const auto buf = to_buffer(vk); const bool output_to_stdout = output_dir == "-"; @@ -105,13 +105,13 @@ void ClientIVCAPI::prove(const Flags& flags, bbapi::ClientIvcStart{}.execute(request); std::vector raw_steps = PrivateExecutionStepRaw::load_and_decompress(input_path); - size_t last_circuit_public_inputs_size = 0; + size_t loaded_circuit_public_inputs_size = 0; for (const auto& step : raw_steps) { bbapi::ClientIvcLoad{ .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } }.execute(request); - last_circuit_public_inputs_size = request.last_circuit_constraints->public_inputs.size(); + loaded_circuit_public_inputs_size = request.loaded_circuit_constraints->public_inputs.size(); info("ClientIVC: accumulating " + step.function_name); bbapi::ClientIvcAccumulate{ .witness = step.witness }.execute(request); } @@ -137,7 +137,7 @@ void ClientIVCAPI::prove(const Flags& flags, if (flags.write_vk) { vinfo("writing ClientIVC vk in directory ", output_dir); - write_vk_for_ivc("bytes", last_circuit_public_inputs_size, output_dir); + write_vk_for_ivc("bytes", loaded_circuit_public_inputs_size, output_dir); } } diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index 8d215d987811..881aafa5a62f 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -23,11 +23,11 @@ ClientIvcLoad::Response ClientIvcLoad::execute(BBApiRequest& request) && throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); } - request.last_circuit_name = circuit.name; - request.last_circuit_constraints = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - request.last_circuit_vk = circuit.verification_key; + request.loaded_circuit_name = circuit.name; + request.loaded_circuit_constraints = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); + request.loaded_circuit_vk = circuit.verification_key; - info("ClientIvcLoad - loaded circuit '", request.last_circuit_name, "'"); + info("ClientIvcLoad - loaded circuit '", request.loaded_circuit_name, "'"); return Response{}; } @@ -38,27 +38,27 @@ ClientIvcAccumulate::Response ClientIvcAccumulate::execute(BBApiRequest& request throw_or_abort("ClientIVC not started. Call ClientIvcStart first."); } - if (!request.last_circuit_constraints.has_value()) { + if (!request.loaded_circuit_constraints.has_value()) { throw_or_abort("No circuit loaded. Call ClientIvcLoad first."); } acir_format::WitnessVector witness_data = acir_format::witness_buf_to_witness_data(std::move(witness)); - acir_format::AcirProgram program{ std::move(request.last_circuit_constraints.value()), std::move(witness_data) }; + acir_format::AcirProgram program{ std::move(request.loaded_circuit_constraints.value()), std::move(witness_data) }; const acir_format::ProgramMetadata metadata{ request.ivc_in_progress }; auto circuit = acir_format::create_circuit(program, metadata); std::shared_ptr precomputed_vk; - if (!request.last_circuit_vk.empty()) { - precomputed_vk = from_buffer>(request.last_circuit_vk); + if (!request.loaded_circuit_vk.empty()) { + precomputed_vk = from_buffer>(request.loaded_circuit_vk); } - info("ClientIvcAccumulate - accumulating circuit '", request.last_circuit_name, "'"); + info("ClientIvcAccumulate - accumulating circuit '", request.loaded_circuit_name, "'"); request.ivc_in_progress->accumulate(circuit, precomputed_vk); request.ivc_stack_depth++; - request.last_circuit_constraints.reset(); - request.last_circuit_vk.clear(); + request.loaded_circuit_constraints.reset(); + request.loaded_circuit_vk.clear(); return Response{}; } @@ -100,7 +100,7 @@ static std::shared_ptr get_acir_program_decider_pr return std::make_shared(builder, request.trace_settings); } -ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit) +ClientIVC::VerificationKey compute_civc_vk(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit) { ClientIVC ivc{ request.trace_settings }; ClientIVCMockCircuitProducer circuit_producer; @@ -147,7 +147,7 @@ ClientIvcComputeIvcVk::Response ClientIvcComputeIvcVk::execute(const BBApiReques auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - auto vk = compute_vk_for_ivc(request, constraint_system.public_inputs.size()); + auto vk = compute_civc_vk(request, constraint_system.public_inputs.size()); Response response; response.bytes = to_buffer(vk); diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp index 36979b238dbc..ccddfe4a64be 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -20,7 +20,7 @@ namespace bb::bbapi { * @param num_public_inputs_in_final_circuit Number of public inputs in the final circuit * @return The computed IVC verification key */ -ClientIVC::VerificationKey compute_vk_for_ivc(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit); +ClientIVC::VerificationKey compute_civc_vk(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit); /** * @struct ClientIvcStart diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp index ca4c50528717..a2158c5f5fdf 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_shared.hpp @@ -121,11 +121,11 @@ struct BBApiRequest { uint32_t ivc_stack_depth = 0; std::shared_ptr ivc_in_progress; // Name of the last loaded circuit - std::string last_circuit_name; + std::string loaded_circuit_name; // Store the parsed constraint system to get ahead of parsing before accumulate - std::optional last_circuit_constraints; + std::optional loaded_circuit_constraints; // Store the verification key passed with the circuit - std::vector last_circuit_vk; + std::vector loaded_circuit_vk; }; } // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp index 2dfb65dc2c08..280c26f2dbd0 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.cpp @@ -16,257 +16,54 @@ namespace bb::bbapi { -CircuitProve::Response CircuitProve::execute(const BBApiRequest& request) && +CircuitProve::Response CircuitProve::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - auto witness = acir_format::witness_buf_to_witness_data(std::move(this->witness)); - - acir_format::AcirProgram program{ constraint_system, witness }; - - // Determine honk recursion level based on settings - uint32_t honk_recursion = settings.honk_recursion; - if (honk_recursion == 0 && settings.recursive) { - honk_recursion = 1; // Default to UltraHonk recursion - } - - const acir_format::ProgramMetadata metadata{ - .honk_recursion = honk_recursion, - }; - - Response response; - - // Choose flavor based on settings - if (settings.ipa_accumulation || honk_recursion == 2) { - // UltraRollupFlavor for rollup circuits - using Flavor = UltraRollupFlavor; - auto builder = acir_format::create_circuit(program, metadata); - auto proving_key = std::make_shared>(builder, request.trace_settings); - - // Load or compute VK - std::shared_ptr vk; - if (!circuit.verification_key.empty()) { - vk = from_buffer>(circuit.verification_key); - } else { - vk = std::make_shared(proving_key->get_precomputed()); - } - - UltraProver_ prover{ proving_key, vk }; - auto proof = prover.construct_proof(); - - response.proof = proof; - response.public_inputs = builder.get_public_inputs(); - } else { - // Regular UltraFlavor - using Flavor = UltraFlavor; - auto builder = acir_format::create_circuit(program, metadata); - auto proving_key = std::make_shared>(builder, request.trace_settings); - - // Load or compute VK - std::shared_ptr vk; - if (!circuit.verification_key.empty()) { - vk = from_buffer>(circuit.verification_key); - } else { - vk = std::make_shared(proving_key->get_precomputed()); - } - - UltraProver_ prover{ proving_key, vk }; - auto proof = prover.construct_proof(); - - response.proof = proof; - response.public_inputs = builder.get_public_inputs(); - } - - return response; + throw_or_abort("not implemented yet!"); } -CircuitComputeVk::Response CircuitComputeVk::execute(const BBApiRequest& request) && +CircuitComputeVk::Response CircuitComputeVk::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - - // Determine honk recursion level based on settings - uint32_t honk_recursion = settings.honk_recursion; - if (honk_recursion == 0 && settings.recursive) { - honk_recursion = 1; // Default to UltraHonk recursion - } - - const acir_format::ProgramMetadata metadata{ - .honk_recursion = honk_recursion, - }; - - Response response; - - // Choose flavor based on settings - if (settings.ipa_accumulation || honk_recursion == 2) { - // UltraRollupFlavor for rollup circuits - using Flavor = UltraRollupFlavor; - auto builder = acir_format::create_circuit(program, metadata); - auto proving_key = std::make_shared>(builder, request.trace_settings); - auto verification_key = std::make_shared(proving_key->get_precomputed()); - - response.bytes = to_buffer(*verification_key); - } else { - // Regular UltraFlavor - using Flavor = UltraFlavor; - auto builder = acir_format::create_circuit(program, metadata); - auto proving_key = std::make_shared>(builder, request.trace_settings); - auto verification_key = std::make_shared(proving_key->get_precomputed()); - - response.bytes = to_buffer(*verification_key); - } - - return response; + throw_or_abort("not implemented yet!"); } CircuitInfo::Response CircuitInfo::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - acir_format::AcirProgram program{ constraint_system, /*witness=*/{} }; - - const acir_format::ProgramMetadata metadata{ - .honk_recursion = settings.honk_recursion, - }; - - auto builder = acir_format::create_circuit(program, metadata); - - Response response; - response.total_gates = static_cast(builder.get_num_finalized_gates()); - response.subgroup_size = static_cast(builder.get_circuit_subgroup_size(response.total_gates)); - - if (include_gates_per_opcode) { - // TODO: Implement gate counting per opcode - response.gates_per_opcode = {}; - } - - return response; + throw_or_abort("not implemented yet!"); } CircuitCheck::Response CircuitCheck::execute(BB_UNUSED const BBApiRequest& request) && { - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - auto witness = acir_format::witness_buf_to_witness_data(std::move(this->witness)); - - acir_format::AcirProgram program{ constraint_system, witness }; - - const acir_format::ProgramMetadata metadata{ - .honk_recursion = settings.honk_recursion, - }; - - auto builder = acir_format::create_circuit(program, metadata); - - Response response; - response.satisfied = CircuitChecker::check(builder); - - return response; + throw_or_abort("not implemented yet!"); } CircuitVerify::Response CircuitVerify::execute(BB_UNUSED const BBApiRequest& request) && { - Response response; - - // Try UltraFlavor first - try { - auto vk = from_buffer>(verification_key); - UltraVerifier_ verifier(vk); - response.verified = verifier.verify_proof(proof); - return response; - } catch (...) { - // If that fails, try UltraRollupFlavor - try { - auto vk = from_buffer>(verification_key); - UltraVerifier_ verifier(vk); - response.verified = verifier.verify_proof(proof); - return response; - } catch (...) { - throw_or_abort("Failed to deserialize verification key"); - } - } + throw_or_abort("not implemented yet!"); } ProofAsFields::Response ProofAsFields::execute(BB_UNUSED const BBApiRequest& request) && { - Response response; - - // Convert proof bytes to field elements - size_t num_fields = proof.size() / sizeof(bb::fr); - response.fields.reserve(num_fields); - - const auto* data = reinterpret_cast(proof.data()); - for (size_t i = 0; i < num_fields; ++i) { - response.fields.push_back(data[i]); - } - - return response; + throw_or_abort("not implemented yet!"); } VkAsFields::Response VkAsFields::execute(BB_UNUSED const BBApiRequest& request) && { - Response response; - - if (is_mega_honk) { - auto vk = from_buffer>(verification_key); - response.fields = vk->to_field_elements(); - } else { - // Try UltraFlavor first - try { - auto vk = from_buffer>(verification_key); - response.fields = vk->to_field_elements(); - } catch (...) { - // If that fails, try UltraRollupFlavor - auto vk = from_buffer>(verification_key); - response.fields = vk->to_field_elements(); - } - } - - return response; + throw_or_abort("not implemented yet!"); } CircuitWriteSolidityVerifier::Response CircuitWriteSolidityVerifier::execute(BB_UNUSED const BBApiRequest& request) && { - throw_or_abort("CircuitWriteSolidityVerifier not implemented yet"); + throw_or_abort("not implemented yet"); } -CircuitProveAndVerify::Response CircuitProveAndVerify::execute(const BBApiRequest& request) && +CircuitProveAndVerify::Response CircuitProveAndVerify::execute(BB_UNUSED const BBApiRequest& request) && { - // First prove - auto prove_result = CircuitProve{ circuit, witness, settings }.execute(request); - - // Then compute VK - auto vk_result = CircuitComputeVk{ CircuitInputNoVK{ circuit.name, circuit.bytecode }, settings }.execute(request); - - // Then verify - auto verify_result = - CircuitVerify{ vk_result.bytes, prove_result.public_inputs, prove_result.proof, settings }.execute(request); - - return { .verified = verify_result.verified, - .proof = prove_result.proof, - .public_inputs = prove_result.public_inputs }; -} - -CircuitValidate::Response CircuitValidate::execute(BB_UNUSED const BBApiRequest& request) && -{ - Response response; - response.is_valid = true; - response.validation_errors.clear(); - - try { - auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode)); - // Basic validation passed if we can parse it - - if (check_recursive_structure) { - // TODO: Add recursive structure validation - } - } catch (const std::exception& e) { - response.is_valid = false; - response.validation_errors.push_back(e.what()); - } - - return response; + throw_or_abort("not implemented yet!"); } CircuitBenchmark::Response CircuitBenchmark::execute(BB_UNUSED const BBApiRequest& request) && { - throw_or_abort("CircuitBenchmark not implemented yet"); + throw_or_abort("not implemented yet!"); } } // namespace bb::bbapi diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp index c919aa2bbaab..c218ba6746dc 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_ultra_honk.hpp @@ -195,25 +195,6 @@ struct CircuitProveAndVerify { Response execute(const BBApiRequest& request = {}) &&; }; -/** - * @brief Command to validate circuit structure - */ -struct CircuitValidate { - static constexpr const char* NAME = "CircuitValidate"; - - struct Response { - static constexpr const char* NAME = "CircuitValidateResponse"; - - bool is_valid; - std::vector validation_errors; - }; - - CircuitInput circuit; - ProofSystemSettings settings; - bool check_recursive_structure = false; - Response execute(const BBApiRequest& request = {}) &&; -}; - /** * @brief Command to benchmark circuit operations */ diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index 8bdf54e7c0bf..08854e8e6077 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -159,7 +159,7 @@ pub contract FPC { Token::at(config.accepted_asset) .transfer_in_public(context.msg_sender(), context.this_address(), max_fee, authwit_nonce ) - .enqueue(&mut context); + .enqueue(&mut context); // docs:end:public_call context.set_as_fee_payer(); 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 69e67f91afdd..65aa11caa4e6 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 @@ -60,26 +60,28 @@ impl PrivateKernelInnerCircuitPrivateInputs { start_private_call_stack_length - 1]; - private_call_data_validator.verify_proof(false /* is_first_app */); - private_call_data_validator.validate_common( - self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, - ); - private_call_data_validator.validate_against_call_request(call_request); - private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); - - // Generate output. - // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. - let output = unsafe { self.generate_output() }; - - // Validate output. - if dep::types::validate::should_validate_output() { - PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + private_call_data_validator.verify_proof(false /* is_first_app */); + private_call_data_validator.validate_common( + self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, + ); + private_call_data_validator.validate_against_call_request(call_request); + private_call_data_validator.validate_against_previous_kernel( self.previous_kernel.public_inputs, - self.private_call, ); + + // Generate output. + // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. + let output = unsafe { self.generate_output() }; + + // Validate output. + if dep::types::validate::should_validate_output() { + PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + self.previous_kernel.public_inputs, + self.private_call, + ); + } + output } - output -} } mod tests { 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 bcdc01dc5a5b..8a11dfe0f00a 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 @@ -226,14 +226,14 @@ mod tests { TransientDataIndexHint::nada(MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASHES_PER_TX); TRANSIENT_DATA_SQUASHING_HINTS_LEN ], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(), - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(), - key_validation_hints: BoundedVec::new(), - validation_requests_split_counter: 0, - dimensions, - padded_side_effects: PaddedSideEffects::empty(), + note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(), + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(), + key_validation_hints: BoundedVec::new(), + validation_requests_split_counter: 0, + dimensions, + padded_side_effects: PaddedSideEffects::empty(), + } } - } pub fn with_siloing(&mut self) -> Self { self.dimensions.NOTE_HASH_SILOING_AMOUNT = NOTE_HASH_SILOING_AMOUNT; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr index 723f90f681d8..5b2b98267225 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr @@ -63,25 +63,25 @@ impl ResetOutputValidatorBuilder { TRANSIENT_DATA_SQUASHING_HINTS_LEN ]; - ResetOutputValidatorBuilder { - output, - previous_kernel, - note_hash_read_request_hints_builder, - nullifier_read_request_hints_builder, - key_validation_hints, - transient_data_index_hints, - pending_note_hash_read_amount: 0, - settled_note_hash_read_amount: 0, - pending_nullifier_read_amount: 0, - settled_nullifier_read_amount: 0, - key_validation_amount: 0, - transient_data_squashing_amount: 0, - note_hash_siloing_amount: 0, - nullifier_siloing_amount: 0, - private_log_siloing_amount: 0, - padded_side_effects: PaddedSideEffects::empty(), + ResetOutputValidatorBuilder { + output, + previous_kernel, + note_hash_read_request_hints_builder, + nullifier_read_request_hints_builder, + key_validation_hints, + transient_data_index_hints, + pending_note_hash_read_amount: 0, + settled_note_hash_read_amount: 0, + pending_nullifier_read_amount: 0, + settled_nullifier_read_amount: 0, + key_validation_amount: 0, + transient_data_squashing_amount: 0, + note_hash_siloing_amount: 0, + nullifier_siloing_amount: 0, + private_log_siloing_amount: 0, + padded_side_effects: PaddedSideEffects::empty(), + } } - } pub fn get_validation_request_processor( self, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index a1382fe36133..1659379d9223 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NoteHashReadRequest NoteHashSettledReadHint::skip(MAX_NOTE_HASH_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), + 0, + ), + } } - } pub fn add_pending_read_hint(&mut self, read_request_index: u32, note_hash_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index 38e946f36d35..b337671abd12 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NullifierReadReques NullifierSettledReadHint::skip(MAX_NULLIFIER_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), + 0, + ), + } } - } pub fn add_pending_read_hint(&mut self, read_request_index: u32, nullifier_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 93106d54403e..5c5952252a1c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -267,9 +267,9 @@ mod tests { { original_index = i; } + } + self.hints.sorted_indexes[original_index] = new_index; } - self.hints.sorted_indexes[original_index] = new_index; - } pub fn execute(self) { if self.ascending { From 2b1e846c0003dadf95201a274b7f6c99c623387b Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 17:40:05 +0000 Subject: [PATCH 19/30] sync --- barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index 9c223fd3d734..6f103657bb74 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -23,7 +23,6 @@ using Command = NamedUnion; @@ -42,7 +41,6 @@ using CommandResponse = NamedUnion; From 168b8be72ba5e937fde31a70725d5402510eb853 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 18:23:12 +0000 Subject: [PATCH 20/30] fmt --- .../contracts/fees/fpc_contract/src/main.nr | 2 +- .../src/private_kernel_inner.nr | 36 +++++++++---------- .../src/private_kernel_reset.nr | 14 ++++---- .../reset_output_validator_builder/mod.nr | 36 +++++++++---------- .../note_hash_read_request_hints_builder.nr | 6 ++-- .../nullifier_read_request_hints_builder.nr | 6 ++-- ...t_split_sorted_transformed_value_arrays.nr | 4 +-- 7 files changed, 51 insertions(+), 53 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index 08854e8e6077..8bdf54e7c0bf 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -159,7 +159,7 @@ pub contract FPC { Token::at(config.accepted_asset) .transfer_in_public(context.msg_sender(), context.this_address(), max_fee, authwit_nonce ) - .enqueue(&mut context); + .enqueue(&mut context); // docs:end:public_call context.set_as_fee_payer(); 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 65aa11caa4e6..69e67f91afdd 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 @@ -60,28 +60,26 @@ impl PrivateKernelInnerCircuitPrivateInputs { start_private_call_stack_length - 1]; - private_call_data_validator.verify_proof(false /* is_first_app */); - private_call_data_validator.validate_common( - self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, - ); - private_call_data_validator.validate_against_call_request(call_request); - private_call_data_validator.validate_against_previous_kernel( + private_call_data_validator.verify_proof(false /* is_first_app */); + private_call_data_validator.validate_common( + self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, + ); + private_call_data_validator.validate_against_call_request(call_request); + private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); + + // Generate output. + // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. + let output = unsafe { self.generate_output() }; + + // Validate output. + if dep::types::validate::should_validate_output() { + PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( self.previous_kernel.public_inputs, + self.private_call, ); - - // Generate output. - // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. - let output = unsafe { self.generate_output() }; - - // Validate output. - if dep::types::validate::should_validate_output() { - PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( - self.previous_kernel.public_inputs, - self.private_call, - ); - } - output } + output +} } mod tests { 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 8a11dfe0f00a..bcdc01dc5a5b 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 @@ -226,14 +226,14 @@ mod tests { TransientDataIndexHint::nada(MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASHES_PER_TX); TRANSIENT_DATA_SQUASHING_HINTS_LEN ], - note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(), - nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(), - key_validation_hints: BoundedVec::new(), - validation_requests_split_counter: 0, - dimensions, - padded_side_effects: PaddedSideEffects::empty(), - } + note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(), + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(), + key_validation_hints: BoundedVec::new(), + validation_requests_split_counter: 0, + dimensions, + padded_side_effects: PaddedSideEffects::empty(), } + } pub fn with_siloing(&mut self) -> Self { self.dimensions.NOTE_HASH_SILOING_AMOUNT = NOTE_HASH_SILOING_AMOUNT; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr index 5b2b98267225..723f90f681d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr @@ -63,25 +63,25 @@ impl ResetOutputValidatorBuilder { TRANSIENT_DATA_SQUASHING_HINTS_LEN ]; - ResetOutputValidatorBuilder { - output, - previous_kernel, - note_hash_read_request_hints_builder, - nullifier_read_request_hints_builder, - key_validation_hints, - transient_data_index_hints, - pending_note_hash_read_amount: 0, - settled_note_hash_read_amount: 0, - pending_nullifier_read_amount: 0, - settled_nullifier_read_amount: 0, - key_validation_amount: 0, - transient_data_squashing_amount: 0, - note_hash_siloing_amount: 0, - nullifier_siloing_amount: 0, - private_log_siloing_amount: 0, - padded_side_effects: PaddedSideEffects::empty(), - } + ResetOutputValidatorBuilder { + output, + previous_kernel, + note_hash_read_request_hints_builder, + nullifier_read_request_hints_builder, + key_validation_hints, + transient_data_index_hints, + pending_note_hash_read_amount: 0, + settled_note_hash_read_amount: 0, + pending_nullifier_read_amount: 0, + settled_nullifier_read_amount: 0, + key_validation_amount: 0, + transient_data_squashing_amount: 0, + note_hash_siloing_amount: 0, + nullifier_siloing_amount: 0, + private_log_siloing_amount: 0, + padded_side_effects: PaddedSideEffects::empty(), } + } pub fn get_validation_request_processor( self, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index 1659379d9223..a1382fe36133 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NoteHashReadRequest NoteHashSettledReadHint::skip(MAX_NOTE_HASH_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), - } + 0, + ), } + } pub fn add_pending_read_hint(&mut self, read_request_index: u32, note_hash_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index b337671abd12..38e946f36d35 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -23,10 +23,10 @@ impl NullifierReadReques NullifierSettledReadHint::skip(MAX_NULLIFIER_READ_REQUESTS_PER_TX); SETTLED_HINTS_LEN ], - 0, - ), - } + 0, + ), } + } pub fn add_pending_read_hint(&mut self, read_request_index: u32, nullifier_index: u32) { let hint_index = self.pending_read_hints.len(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 5c5952252a1c..93106d54403e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -267,9 +267,9 @@ mod tests { { original_index = i; } - } - self.hints.sorted_indexes[original_index] = new_index; } + self.hints.sorted_indexes[original_index] = new_index; + } pub fn execute(self) { if self.ascending { From 28f722df223c333dc7996bc9309b9bfdedecb678 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 18:38:12 +0000 Subject: [PATCH 21/30] BOOTSTRAP_TO, BOOTSTRAP_AFTER --- bootstrap.sh | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 7a81f5798ce4..81f36ba7c813 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -240,8 +240,28 @@ function build { aztec-up/bootstrap.sh ) + local start_building=false for project in "${serial_projects[@]}"; do - $project/bootstrap.sh ${1:-} + # BOOTSTRAP_AFTER and BOOTSTRAP_TO are used to control the order of building. + # If BOOTSTRAP_AFTER is set, it should be one of our serial projects and we will only build projects after it. + # If BOOTSTRAP_TO is set, it should be one of our serial projects and we will only build projects up to it. We will skip parallel_cmds. + + # Start building after we've seen BOOTSTRAP_AFTER, skipping BOOTSTRAP_AFTER itself. + if [ "$project" == "${BOOTSTRAP_AFTER:-}" ]; then + start_building=true + continue + fi + + # Build the project if we should be building + if [[ -z "${BOOTSTRAP_AFTER:-}" || "$start_building" = true ]]; then + $project/bootstrap.sh ${1:-} + fi + + # Stop the build if we've reached BOOTSTRAP_TO + # We therefore don't run parallel commands if BOOTSTRAP_TO is set. + if [ "$project" = "${BOOTSTRAP_TO:-}" ]; then + return + fi done parallel --line-buffer --tag --halt now,fail=1 "denoise '{}'" ::: ${parallel_cmds[@]} From 86fe4121261fd770da9386e6a1ea0b11d38a0bf3 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 19:13:25 +0000 Subject: [PATCH 22/30] support for bytes_and_fields --- barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index aa3bae2cfffa..7e84d9a65a2e 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -38,9 +38,9 @@ void write_standalone_vk(const std::string& output_format, .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }.execute(); - if (output_format == "bytes") { + if (output_format == "bytes" || output_format == "bytes_and_fields") { write_file(output_path / "vk", response.bytes); - } else if (output_format == "fields") { + } else if (output_format == "fields" || output_format == "bytes_and_fields") { std::string json = field_elements_to_json(response.fields); write_file(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); } else { From 7e4fd7339abe07afedf6a9ec5575099bd30d397c Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 19:25:19 +0000 Subject: [PATCH 23/30] fix parsing --- barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 7e84d9a65a2e..73c0112eb4ea 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -38,12 +38,17 @@ void write_standalone_vk(const std::string& output_format, .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) } }.execute(); + bool wrote_file = false; if (output_format == "bytes" || output_format == "bytes_and_fields") { write_file(output_path / "vk", response.bytes); - } else if (output_format == "fields" || output_format == "bytes_and_fields") { + wrote_file = true; + } + if (output_format == "fields" || output_format == "bytes_and_fields") { std::string json = field_elements_to_json(response.fields); write_file(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); - } else { + wrote_file = true; + } + if (!wrote_file) { throw_or_abort("Unsupported output format for standalone vk: " + output_format); } } From 03aaf0a7cfef52a988616fd1f0413e4608797bc3 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 20:47:17 +0000 Subject: [PATCH 24/30] fixes for cli --- .../src/barretenberg/api/api_client_ivc.cpp | 31 +++++++++++++------ barretenberg/cpp/src/barretenberg/bb/cli.cpp | 2 +- noir-projects/scripts/generate_vk_json.js | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 73c0112eb4ea..c02313c32945 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -39,13 +39,24 @@ void write_standalone_vk(const std::string& output_format, }.execute(); bool wrote_file = false; + bool is_stdout = output_path == "-"; + auto write_fn = [&](const std::filesystem::path& path, const auto& data) { + if (is_stdout) { + write_bytes_to_stdout(data); + } else { + write_file(path, data); + } + }; + if (output_format == "bytes_and_fields" && is_stdout) { + throw_or_abort("Cannot write to stdout in bytes_and_fields format."); + } if (output_format == "bytes" || output_format == "bytes_and_fields") { - write_file(output_path / "vk", response.bytes); + write_fn(output_path / "vk", response.bytes); wrote_file = true; } if (output_format == "fields" || output_format == "bytes_and_fields") { std::string json = field_elements_to_json(response.fields); - write_file(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); + write_fn(output_path / "vk_fields.json", std::vector(json.begin(), json.end())); wrote_file = true; } if (!wrote_file) { @@ -53,9 +64,9 @@ void write_standalone_vk(const std::string& output_format, } } -void write_vk_for_ivc(const std::string& output_format, - size_t num_public_inputs_in_final_circuit, - const std::filesystem::path& output_dir) +void write_civc_vk(const std::string& output_format, + size_t num_public_inputs_in_final_circuit, + const std::filesystem::path& output_dir) { if (output_format != "bytes") { throw_or_abort("Unsupported output format for ClientIVC vk: " + output_format); @@ -77,9 +88,9 @@ void write_vk_for_ivc(const std::string& output_format, } } -void write_vk_for_ivc(const std::string& output_data_type, - const std::string& bytecode_path, - const std::filesystem::path& output_dir) +void write_civc_vk(const std::string& output_data_type, + const std::string& bytecode_path, + const std::filesystem::path& output_dir) { if (output_data_type != "bytes") { throw_or_abort("Unsupported output format for ClientIVC vk: " + output_data_type); @@ -142,7 +153,7 @@ void ClientIVCAPI::prove(const Flags& flags, if (flags.write_vk) { vinfo("writing ClientIVC vk in directory ", output_dir); - write_vk_for_ivc("bytes", loaded_circuit_public_inputs_size, output_dir); + write_civc_vk("bytes", loaded_circuit_public_inputs_size, output_dir); } } @@ -210,7 +221,7 @@ void ClientIVCAPI::write_vk(const Flags& flags, { if (flags.verifier_type == "ivc") { - write_vk_for_ivc(flags.output_format, bytecode_path, output_path); + write_civc_vk(flags.output_format, bytecode_path, output_path); } else if (flags.verifier_type == "standalone") { write_standalone_vk(flags.output_format, bytecode_path, output_path); } else { diff --git a/barretenberg/cpp/src/barretenberg/bb/cli.cpp b/barretenberg/cpp/src/barretenberg/bb/cli.cpp index ec0e4708fef4..ac7d74bf2617 100644 --- a/barretenberg/cpp/src/barretenberg/bb/cli.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/cli.cpp @@ -578,7 +578,7 @@ int parse_and_run_cli_command(int argc, char* argv[]) // Immediately after parsing, we can init the global CRS factory. Note this does not yet read or download any // points; that is done on-demand. srs::init_net_crs_factory(flags.crs_path); - if (prove->parsed() || write_vk->parsed()) { + if ((prove->parsed() || write_vk->parsed()) && output_path != "-") { // If writing to an output folder, make sure it exists. std::filesystem::create_directories(output_path); } diff --git a/noir-projects/scripts/generate_vk_json.js b/noir-projects/scripts/generate_vk_json.js index 3fb3575ca42f..d2ec5627d282 100644 --- a/noir-projects/scripts/generate_vk_json.js +++ b/noir-projects/scripts/generate_vk_json.js @@ -144,7 +144,7 @@ async function generateVKData( const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); if (circuitType == CircuitType.ClientIVCCircuit) { - write_vk_flow = "write_vk_for_ivc"; + write_vk_flow = "write_civc_vk"; vk_as_fields_flow = "vk_as_fields_mega_honk"; honk_recursion = 0; } else if (circuitType == CircuitType.RollupHonkCircuit) { From 2cdab8e85983161b62f986153404e11de7c7f684 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 14 Jul 2025 20:48:34 +0000 Subject: [PATCH 25/30] drop unused file --- noir-projects/scripts/generate_vk_json.js | 211 ---------------------- 1 file changed, 211 deletions(-) delete mode 100644 noir-projects/scripts/generate_vk_json.js diff --git a/noir-projects/scripts/generate_vk_json.js b/noir-projects/scripts/generate_vk_json.js deleted file mode 100644 index d2ec5627d282..000000000000 --- a/noir-projects/scripts/generate_vk_json.js +++ /dev/null @@ -1,211 +0,0 @@ -const path = require("path"); -const fs = require("fs/promises"); -const child_process = require("child_process"); -const crypto = require("crypto"); - -const clientIvcPatterns = require("../client_ivc_circuits.json"); -const rollupHonkPatterns = require("../rollup_honk_circuits.json"); - -const CircuitType = { - ClientIVCCircuit: 0, - RollupHonkCircuit: 1, - HonkCircuit: 2, -}; - -const { - readVKFromS3, - writeVKToS3, - getBarretenbergHash, - generateArtifactHash, - BB_BIN_PATH, -} = require("./verification_keys"); - -function vkBinaryFileNameForArtifactName(outputFolder, artifactName) { - return path.join(outputFolder, `${artifactName}.vk`); -} - -function vkJsonFileNameForArtifactName(outputFolder, artifactName) { - return path.join(outputFolder, `${artifactName}.vk.json`); -} - -function vkDataFileNameForArtifactName(outputFolder, artifactName) { - return path.join(outputFolder, `${artifactName}.vk.data.json`); -} - -async function getBytecodeHash(artifactPath) { - const { bytecode } = JSON.parse(await fs.readFile(artifactPath)); - if (!bytecode) { - throw new Error("No bytecode found in artifact: " + artifactPath); - } - return crypto.createHash("md5").update(bytecode).digest("hex"); -} - -async function getArtifactHash(artifactPath, circuitType, isRecursive) { - const bytecodeHash = await getBytecodeHash(artifactPath); - const barretenbergHash = await getBarretenbergHash(); - return generateArtifactHash( - barretenbergHash, - bytecodeHash, - circuitType, - isRecursive - ); -} - -async function hasArtifactHashChanged(artifactHash, vkDataPath) { - try { - const { artifactHash: previousArtifactHash } = JSON.parse( - await fs.readFile(vkDataPath, "utf8") - ); - if (previousArtifactHash === artifactHash) { - return false; - } else { - console.log( - `Circuit ${artifactName} has changed, old hash ${previousArtifactHash}, new hash ${artifactHash}` - ); - } - } catch (ignored) { - console.log(`No on disk vk found in: ${vkDataPath}`); - } - return true; -} - -function typeOfCircuit(artifactName) { - if ( - clientIvcPatterns.some((pattern) => artifactName.match(new RegExp(pattern))) - ) { - return CircuitType.ClientIVCCircuit; - } else if ( - rollupHonkPatterns.some((pattern) => - artifactName.match(new RegExp(pattern)) - ) - ) { - return CircuitType.RollupHonkCircuit; - } else { - return CircuitType.HonkCircuit; - } -} - -async function processArtifact(artifactPath, artifactName, outputFolder) { - const circuitType = typeOfCircuit(artifactName); - const isRecursive = true; - - const artifactHash = await getArtifactHash( - artifactPath, - circuitType, - isRecursive - ); - - const vkDataPath = vkDataFileNameForArtifactName(outputFolder, artifactName); - - const hasChanged = await hasArtifactHashChanged(artifactHash, vkDataPath); - if (!hasChanged) { - console.log(`Reusing on disk vk: ${vkDataPath}`); - return; - } - - let vkData = await readVKFromS3(artifactName, artifactHash); - if (!vkData) { - vkData = await generateVKData( - artifactName, - outputFolder, - artifactPath, - artifactHash, - circuitType, - isRecursive - ); - await writeVKToS3(artifactName, artifactHash, JSON.stringify(vkData)); - } else { - console.log("Using VK from remote cache for", artifactName); - } - - await fs.writeFile(vkDataPath, JSON.stringify(vkData, null, 2)); -} - -async function generateVKData( - artifactName, - outputFolder, - artifactPath, - artifactHash, - circuitType, - isRecursive -) { - if (circuitType == CircuitType.ClientIVCCircuit) { - console.log("Generating new client ivc vk for", artifactName); - } else if (circuitType == CircuitType.RollupHonkCircuit) { - console.log("Generating new rollup honk vk for", artifactName); - } else { - console.log("Generating new honk vk for", artifactName); - } - - const binaryVkPath = vkBinaryFileNameForArtifactName( - outputFolder, - artifactName - ); - const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - - if (circuitType == CircuitType.ClientIVCCircuit) { - write_vk_flow = "write_civc_vk"; - vk_as_fields_flow = "vk_as_fields_mega_honk"; - honk_recursion = 0; - } else if (circuitType == CircuitType.RollupHonkCircuit) { - write_vk_flow = "write_vk_ultra_rollup_honk"; - vk_as_fields_flow = "vk_as_fields_ultra_rollup_honk"; - honk_recursion = 2; - } else { - write_vk_flow = "write_vk --scheme ultra_honk"; - vk_as_fields_flow = "vk_as_fields_ultra_honk"; - honk_recursion = 1; - } - - const writeVkCommand = `${BB_BIN_PATH} ${write_vk_flow} -h ${honk_recursion} -b "${artifactPath}" -o "${binaryVkPath}"`; - - console.log("WRITE VK CMD: ", writeVkCommand); - - const vkAsFieldsCommand = `${BB_BIN_PATH} ${vk_as_fields_flow} -k "${binaryVkPath}" -o "${jsonVkPath}"`; - - console.log("VK AS FIELDS CMD: ", vkAsFieldsCommand); - - await new Promise((resolve, reject) => { - child_process.exec(`${writeVkCommand} && ${vkAsFieldsCommand}`, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - const binaryVk = await fs.readFile(binaryVkPath); - const jsonVk = JSON.parse(await fs.readFile(jsonVkPath, "utf8")); - await fs.unlink(jsonVkPath); - await fs.unlink(binaryVkPath); - - const vkData = { - keyAsBytes: binaryVk.toString("hex"), - keyAsFields: jsonVk, - artifactHash, - }; - console.log("Generated vk for", artifactName); - - return vkData; -} - -async function main() { - let [artifactPath, outputFolder] = process.argv.slice(2); - if (!artifactPath || !outputFolder) { - console.log( - "Usage: node generate_vk_json.js " - ); - return; - } - - await processArtifact( - artifactPath, - path.basename(artifactPath, ".json"), - outputFolder - ); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}); From cfa50faff16d9b8c11caa4dca8e14aa2f6c5cb5f Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 15 Jul 2025 15:05:44 +0000 Subject: [PATCH 26/30] not needed --- barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp index 6f103657bb74..1e31053ceaeb 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_execute.hpp @@ -44,12 +44,6 @@ using CommandResponse = NamedUnion; -// Specifically check for ClientIvcStart, ClientIvcLoad, ClientIvcAccumulate, and ClientIvcProve -// Helps type-check C++ code, but we don't use this distinction for RPC commands or WASM. -template -concept RequiresBBApiRequest = std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v; - /** * @brief Executes a command by visiting a variant of all possible commands. * From 9fe7a46e17275c81f8e963909a18d59bf217a470 Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 15 Jul 2025 12:27:32 -0400 Subject: [PATCH 27/30] build fixes --- barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp | 4 ++-- barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp | 2 ++ .../cpp/src/barretenberg/polynomials/backing_memory.hpp | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp index 881aafa5a62f..863d32fb0697 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.cpp @@ -12,7 +12,7 @@ namespace bb::bbapi { ClientIvcStart::Response ClientIvcStart::execute(BBApiRequest& request) && { - request.ivc_in_progress = std::make_shared(request.trace_settings); + request.ivc_in_progress = std::make_shared(num_circuits, request.trace_settings); request.ivc_stack_depth = 0; return Response{}; } @@ -102,7 +102,7 @@ static std::shared_ptr get_acir_program_decider_pr ClientIVC::VerificationKey compute_civc_vk(const BBApiRequest& request, size_t num_public_inputs_in_final_circuit) { - ClientIVC ivc{ request.trace_settings }; + ClientIVC ivc{ /* num_circuits */ 2, request.trace_settings }; ClientIVCMockCircuitProducer circuit_producer; // Initialize the IVC with an arbitrary circuit diff --git a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp index ccddfe4a64be..9f1500eec6f5 100644 --- a/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/api/bbapi_client_ivc.hpp @@ -39,6 +39,8 @@ struct ClientIvcStart { static constexpr const char* NAME = "ClientIvcStartResponse"; // Empty response - success indicated by no exception }; + // Number of circuits to be accumulated. + size_t num_circuits; Response execute(BBApiRequest& request) &&; }; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/backing_memory.hpp b/barretenberg/cpp/src/barretenberg/polynomials/backing_memory.hpp index 679ee92cde59..57663c48db74 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/backing_memory.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/backing_memory.hpp @@ -8,6 +8,7 @@ #include "barretenberg/common/slab_allocator.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "unistd.h" #include #include #include From 9c6769f610550c9d2054f2c6b0ffd9cd0cc4f7d3 Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 15 Jul 2025 12:48:50 -0400 Subject: [PATCH 28/30] noir revert --- .../aztec/src/state_vars/shared_mutable/test.nr | 15 +++++---------- noir-projects/noir-contracts/bootstrap.sh | 2 +- noir-projects/noir-protocol-circuits/bootstrap.sh | 3 ++- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index c8d64b8450de..6d8a2e7cada8 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -267,8 +267,7 @@ unconstrained fn get_current_value_in_private_immediately_before_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change - 1); - cheatcodes::advance_blocks_by(1); + env.mine_block_at(timestamp_of_change - 1); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -295,8 +294,7 @@ unconstrained fn get_current_value_in_private_at_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change); - cheatcodes::advance_blocks_by(1); + env.mine_block_at(timestamp_of_change); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -324,8 +322,7 @@ unconstrained fn get_current_value_in_private_after_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change + 10); - cheatcodes::advance_blocks_by(1); + env.mine_block_at(timestamp_of_change + 10); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -356,8 +353,7 @@ unconstrained fn get_current_value_in_private_with_non_initial_delay() { }); let historical_timestamp = std::cmp::max(value_timestamp_of_change, delay_timestamp_of_change); - env.set_next_block_timestamp(historical_timestamp); - cheatcodes::advance_blocks_by(1); + env.mine_block_at(historical_timestamp); env.private_context(|context| { // Make sure we're at a block with the expected timestamp @@ -391,8 +387,7 @@ unconstrained fn get_current_value_in_utility_before_scheduled_change() { state_var.get_scheduled_value() }); - env.set_next_block_timestamp(timestamp_of_change - 1); - cheatcodes::advance_blocks_by(1); + env.mine_block_at(timestamp_of_change - 1); env.utility_context(|context| { // Make sure we're at a block with the expected timestamp diff --git a/noir-projects/noir-contracts/bootstrap.sh b/noir-projects/noir-contracts/bootstrap.sh index fc2c6422d425..d801763978b5 100755 --- a/noir-projects/noir-contracts/bootstrap.sh +++ b/noir-projects/noir-contracts/bootstrap.sh @@ -26,7 +26,7 @@ export PLATFORM_TAG=any export BB=${BB:-../../barretenberg/cpp/build/bin/bb} export NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} export TRANSPILER=${TRANSPILER:-../../avm-transpiler/target/release/avm-transpiler} -export BB_HASH=$(cache_content_hash ../../barretenberg/cpp/.rebuild_patterns) +export BB_HASH=$(../../barretenberg/cpp/bootstrap.sh hash) export NOIR_HASH=${NOIR_HASH:-$(../../noir/bootstrap.sh hash)} export tmp_dir=./target/tmp diff --git a/noir-projects/noir-protocol-circuits/bootstrap.sh b/noir-projects/noir-protocol-circuits/bootstrap.sh index 8af4041bed3a..65b469b2a750 100755 --- a/noir-projects/noir-protocol-circuits/bootstrap.sh +++ b/noir-projects/noir-protocol-circuits/bootstrap.sh @@ -9,7 +9,7 @@ export HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-16} export PLATFORM_TAG=any export BB=${BB:-../../barretenberg/cpp/build/bin/bb} export NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} -export BB_HASH=$(cache_content_hash ../../barretenberg/cpp/.rebuild_patterns) +export BB_HASH=$(../../barretenberg/cpp/bootstrap.sh hash) export NOIR_HASH=${NOIR_HASH:-$(../../noir/bootstrap.sh hash)} export key_dir=./target/keys @@ -65,6 +65,7 @@ function compile { echo "Error: $json_path bytecode size of $bytecode_size exceeds 850MB" exit 1 fi + cache_upload circuit-$hash.tar.gz $json_path &> /dev/null fi From 116a8e2307ddf0a79ad83e30d0809ad8f03139fa Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 15 Jul 2025 17:15:29 +0000 Subject: [PATCH 29/30] num circuits fix --- barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index c02313c32945..4f5c9580a13e 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -117,10 +117,10 @@ void ClientIVCAPI::prove(const Flags& flags, { bbapi::BBApiRequest request; - - bbapi::ClientIvcStart{}.execute(request); std::vector raw_steps = PrivateExecutionStepRaw::load_and_decompress(input_path); + bbapi::ClientIvcStart{ .num_circuits = raw_steps.size() }.execute(request); + size_t loaded_circuit_public_inputs_size = 0; for (const auto& step : raw_steps) { bbapi::ClientIvcLoad{ From 1f9695afc5f3878d5a5fcf55979129ab1e058b2c Mon Sep 17 00:00:00 2001 From: ludamad Date: Tue, 15 Jul 2025 18:16:00 +0000 Subject: [PATCH 30/30] fixes --- barretenberg/cpp/bootstrap.sh | 6 ++---- barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/bootstrap.sh b/barretenberg/cpp/bootstrap.sh index dd48173c92f2..9fb2842b64dc 100755 --- a/barretenberg/cpp/bootstrap.sh +++ b/barretenberg/cpp/bootstrap.sh @@ -308,11 +308,9 @@ case "$cmd" in # Download cached flow inputs from the specified commit export AZTEC_CACHE_COMMIT=$commit_hash + # TODO currently does nothing! to reinstate in cache_download export FORCE_CACHE_DOWNLOAD=${FORCE_CACHE_DOWNLOAD:-1} - echo "Running with FORCE_CACHE_DOWNLOAD=1. This should work, but as a workaround you can set FORCE_CACHE_DOWNLOAD=0 before the bench_ivc call to build some parts." - ../../noir/bootstrap.sh - USE_CIRCUITS_CACHE=1 ../../noir-projects/noir-protocol-circuits/bootstrap.sh - yarn --cwd ../../yarn-project/bb-prover generate + USE_CIRCUITS_CACHE=1 BOOTSTRAP_AFTER=barretenberg BOOSTRAP_TO=yarn-project ../../bootstrap.sh rm -rf bench-out diff --git a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp index 4f5c9580a13e..5b4add39168d 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_client_ivc.cpp @@ -127,6 +127,7 @@ void ClientIVCAPI::prove(const Flags& flags, .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk } }.execute(request); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access): we know the optional has been set here. loaded_circuit_public_inputs_size = request.loaded_circuit_constraints->public_inputs.size(); info("ClientIVC: accumulating " + step.function_name); bbapi::ClientIvcAccumulate{ .witness = step.witness }.execute(request);