diff --git a/aztec-nargo/compile_then_postprocess.sh b/aztec-nargo/compile_then_postprocess.sh index 3f1c252bbf0..60f2cc6d869 100755 --- a/aztec-nargo/compile_then_postprocess.sh +++ b/aztec-nargo/compile_then_postprocess.sh @@ -39,7 +39,7 @@ for artifact in $artifacts_to_process; do echo "Generating verification key for function $fn_name" # BB outputs the verification key to stdout as raw bytes, however, we need to base64 encode it before storing it in the artifact - verification_key=$($BB write_vk_for_ivc -h -b ${fn_artifact_path} -o - | base64) + verification_key=$($BB write_vk_for_ivc -b ${fn_artifact_path} -o - | base64) rm $fn_artifact_path jq ".functions[$fn_index].verification_key = \"$verification_key\"" $artifact > $artifact.tmp mv $artifact.tmp $artifact diff --git a/barretenberg/acir_tests/bootstrap.sh b/barretenberg/acir_tests/bootstrap.sh index 41c0f0dd26c..b5504e5d825 100755 --- a/barretenberg/acir_tests/bootstrap.sh +++ b/barretenberg/acir_tests/bootstrap.sh @@ -69,9 +69,9 @@ function test { } local plonk_tests=$(find ./acir_tests -maxdepth 1 -mindepth 1 -type d | \ - grep -vE 'verify_honk_proof|double_verify_honk_proof') + grep -vE 'verify_honk_proof|double_verify_honk_proof|verify_rollup_honk_proof') local honk_tests=$(find ./acir_tests -maxdepth 1 -mindepth 1 -type d | \ - grep -vE 'single_verify_proof|double_verify_proof|double_verify_nested_proof') + grep -vE 'single_verify_proof|double_verify_proof|double_verify_nested_proof|verify_rollup_honk_proof') # barretenberg-acir-tests-sol: run FLOW=sol ./run_test.sh assert_statement @@ -119,6 +119,8 @@ function test { run SYS=ultra_honk FLOW=prove_then_verify RECURSIVE=true ./run_test.sh assert_statement run SYS=ultra_honk FLOW=prove_then_verify RECURSIVE=true ./run_test.sh double_verify_honk_proof run SYS=ultra_honk FLOW=prove_and_verify_program ./run_test.sh merkle_insert + run SYS=ultra_rollup_honk FLOW=prove_and_verify ./run_test.sh verify_rollup_honk_proof + # barretenberg-acir-tests-bb-client-ivc: run FLOW=prove_then_verify_client_ivc ./run_test.sh 6_array diff --git a/barretenberg/acir_tests/regenerate_verify_honk_proof_inputs.sh b/barretenberg/acir_tests/regenerate_verify_honk_proof_inputs.sh index da1d1b43496..03a46ad70cc 100755 --- a/barretenberg/acir_tests/regenerate_verify_honk_proof_inputs.sh +++ b/barretenberg/acir_tests/regenerate_verify_honk_proof_inputs.sh @@ -8,30 +8,44 @@ CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:+-v} -if [ -f $BIN ]; then - BIN=$(realpath $BIN) +if [ -f "$BIN" ]; then + BIN=$(realpath "$BIN") else - BIN=$(realpath $(which $BIN)) + BIN=$(realpath "$(which "$BIN")") fi export BRANCH -# the program for which a proof will be recursively verified +# The program for which a proof will be recursively verified PROGRAM=assert_statement -# the program containing the recursive verifier -RECURSIVE_PROGRAM=verify_honk_proof +# The programs containing the recursive verifier +RECURSIVE_PROGRAMS=(verify_honk_proof verify_rollup_honk_proof) -./reset_acir_tests.sh --programs "$PROGRAM" +./reset_acir_tests.sh --no-rebuild-nargo --programs "$PROGRAM" cd "acir_tests/$PROGRAM" -TOML_DIR=../../../../noir/noir-repo/test_programs/execution_success/"$RECURSIVE_PROGRAM" -if [ ! -d "$TOML_DIR" ]; then - echo "Error: Directory $TOML_DIR does not exist." - exit 1 -fi +# Base directory for TOML outputs +BASE_TOML_DIR=../../../../noir/noir-repo/test_programs/execution_success + +for RECURSIVE_PROGRAM in "${RECURSIVE_PROGRAMS[@]}"; do + TOML_DIR="$BASE_TOML_DIR/$RECURSIVE_PROGRAM" + + if [ ! -d "$TOML_DIR" ]; then + echo "Error: Directory $TOML_DIR does not exist." + exit 1 + fi + + echo "Generating recursion inputs for $RECURSIVE_PROGRAM and writing to directory $TOML_DIR" + + # Decide the command based on the recursive program + if [[ "$RECURSIVE_PROGRAM" == "verify_rollup_honk_proof" ]]; then + COMMAND="write_recursion_inputs_rollup_honk" + else + COMMAND="write_recursion_inputs_honk" + fi -echo "Generating recursion inputs and writing to directory $TOML_DIR" -$BIN write_recursion_inputs_honk --recursive $VERBOSE -c $CRS_PATH -b ./target/program.json -o "$TOML_DIR" + $BIN "$COMMAND" --recursive $VERBOSE -c "$CRS_PATH" -b ./target/program.json -o "$TOML_DIR" +done cd ../.. -./reset_acir_tests.sh --programs "$RECURSIVE_PROGRAM" \ No newline at end of file +./reset_acir_tests.sh --no-rebuild-nargo --programs "${RECURSIVE_PROGRAMS[@]}" diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index b411f0136ef..21eb4f5c214 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -66,12 +66,12 @@ SKIP_ARRAY+=(regression_5045) # if HONK is false, we should skip verify_honk_proof if [ "$HONK" = false ]; then # Don't run programs with Honk recursive verifier - SKIP_ARRAY+=(verify_honk_proof double_verify_honk_proof) + SKIP_ARRAY+=(verify_honk_proof double_verify_honk_proof verify_rollup_honk_proof) fi if [ "$HONK" = true ]; then # Don't run programs with Plonk recursive verifier(s) - SKIP_ARRAY+=(single_verify_proof double_verify_proof double_verify_nested_proof) + SKIP_ARRAY+=(single_verify_proof double_verify_proof double_verify_nested_proof verify_rollup_honk_proof) fi if [ "$CLIENT_IVC_SKIPS" = true ]; then diff --git a/barretenberg/cpp/src/barretenberg/bb/acir_format_getters.hpp b/barretenberg/cpp/src/barretenberg/bb/acir_format_getters.hpp index 9e1023c3722..feec425c9c2 100644 --- a/barretenberg/cpp/src/barretenberg/bb/acir_format_getters.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/acir_format_getters.hpp @@ -13,7 +13,7 @@ acir_format::WitnessVector get_witness(std::string const& witness_path) return acir_format::witness_buf_to_witness_data(witness_data); } -acir_format::AcirFormat get_constraint_system(std::string const& bytecode_path, bool honk_recursion) +acir_format::AcirFormat get_constraint_system(std::string const& bytecode_path, uint32_t honk_recursion) { auto bytecode = get_bytecode(bytecode_path); return acir_format::circuit_buf_to_acir_format(bytecode, honk_recursion); @@ -25,7 +25,7 @@ acir_format::WitnessVectorStack get_witness_stack(std::string const& witness_pat return acir_format::witness_buf_to_witness_stack(witness_data); } -std::vector get_constraint_systems(std::string const& bytecode_path, bool honk_recursion) +std::vector get_constraint_systems(std::string const& bytecode_path, uint32_t honk_recursion) { auto bytecode = get_bytecode(bytecode_path); return acir_format::program_buf_to_acir_format(bytecode, honk_recursion); diff --git a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp index cbdfae92198..8a228b5f051 100644 --- a/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/api_client_ivc.hpp @@ -93,8 +93,7 @@ class ClientIVCAPI : public API { // TODO(https://github.com/AztecProtocol/barretenberg/issues/1162): Efficiently unify ACIR stack parsing if (input_type == "compiletime_stack") { - auto program_stack = - acir_format::get_acir_program_stack(bytecode_path, witness_path, /*honk_recursion=*/false); + auto program_stack = acir_format::get_acir_program_stack(bytecode_path, witness_path, /*honk_recursion=*/0); // Accumulate the entire program stack into the IVC while (!program_stack.empty()) { auto stack_item = program_stack.back(); @@ -116,7 +115,7 @@ class ClientIVCAPI : public API { std::vector witness_buf = decompress(reinterpret_cast(wit.data()), wit.size()); // NOLINT - AcirFormat constraints = circuit_buf_to_acir_format(constraint_buf, /*honk_recursion=*/false); + AcirFormat constraints = circuit_buf_to_acir_format(constraint_buf, /*honk_recursion=*/0); WitnessVector witness = witness_buf_to_witness_data(witness_buf); folding_stack.push_back(AcirProgram{ constraints, witness }); diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 571f9aa23bf..8661657438d 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -13,6 +13,7 @@ #include "barretenberg/dsl/acir_format/proof_surgeon.hpp" #include "barretenberg/dsl/acir_proofs/acir_composer.hpp" #include "barretenberg/dsl/acir_proofs/honk_contract.hpp" +#include "barretenberg/flavor/flavor.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" @@ -22,7 +23,9 @@ #include "barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp" #include "barretenberg/vm/avm/trace/public_inputs.hpp" +#include #ifndef DISABLE_AZTEC_VM #include "barretenberg/vm/avm/generated/flavor.hpp" @@ -81,7 +84,7 @@ std::string honk_vk_to_json(std::vector& data) */ bool proveAndVerify(const std::string& bytecodePath, const bool recursive, const std::string& witnessPath) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/0); auto witness = get_witness(witnessPath); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; @@ -143,7 +146,12 @@ bool proveAndVerifyHonkAcirFormat(acir_format::AcirProgram program, acir_format: template bool proveAndVerifyHonk(const std::string& bytecodePath, const bool recursive, const std::string& witnessPath) { - constexpr bool honk_recursion = IsAnyOf; + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + } const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = honk_recursion }; // Populate the acir constraint system and witness from gzipped data @@ -165,7 +173,12 @@ bool proveAndVerifyHonk(const std::string& bytecodePath, const bool recursive, c template bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const bool recursive, const std::string& witnessPath) { - constexpr bool honk_recursion = IsAnyOf; + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + } const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = honk_recursion }; auto program_stack = acir_format::get_acir_program_stack(bytecodePath, witnessPath, metadata.honk_recursion); @@ -234,13 +247,12 @@ void prove_tube(const std::string& output_path) builder->add_pairing_point_accumulator(current_aggregation_object); // The tube only calls an IPA recursive verifier once, so we can just add this IPA claim and proof - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1154): We shouldn't add these to the public inputs for - // now since we don't handle them correctly. Uncomment when we start using UltraRollupHonk in the rollup. - // builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices()); - // builder->ipa_proof = convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data); + builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices()); + builder->ipa_proof = convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data); + ASSERT(builder->ipa_proof.size() && "IPA proof should not be empty"); - using Prover = UltraProver_; - using Verifier = UltraVerifier_; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; Prover tube_prover{ *builder }; auto tube_proof = tube_prover.construct_proof(); std::string tubeProofPath = output_path + "/proof"; @@ -252,7 +264,7 @@ void prove_tube(const std::string& output_path) std::string tubeVkPath = output_path + "/vk"; auto tube_verification_key = - std::make_shared(tube_prover.proving_key->proving_key); + std::make_shared(tube_prover.proving_key->proving_key); write_file(tubeVkPath, to_buffer(tube_verification_key)); std::string tubeAsFieldsVkPath = output_path + "/vk_fields.json"; @@ -264,7 +276,18 @@ void prove_tube(const std::string& output_path) info("Native verification of the tube_proof"); auto ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); Verifier tube_verifier(tube_verification_key, ipa_verification_key); - bool verified = tube_verifier.verify_proof(tube_proof, builder->ipa_proof); + + // Break up the tube proof into the honk portion and the ipa portion + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor + const size_t HONK_PROOF_LENGTH = 469; + // The extra calculation is for the IPA proof length. + ASSERT(tube_proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2 + num_public_inputs); + // split out the ipa proof + const std::ptrdiff_t honk_proof_with_pub_inputs_length = + static_cast(HONK_PROOF_LENGTH + num_public_inputs); + auto ipa_proof = HonkProof(tube_proof.begin() + honk_proof_with_pub_inputs_length, tube_proof.end()); + auto tube_honk_proof = HonkProof(tube_proof.begin(), tube_proof.end() + honk_proof_with_pub_inputs_length); + bool verified = tube_verifier.verify_proof(tube_honk_proof, ipa_proof); info("Tube proof verification: ", verified); } @@ -285,7 +308,7 @@ void prove(const std::string& bytecodePath, const std::string& outputPath, const bool recursive) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/0); auto witness = get_witness(witnessPath); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; @@ -314,8 +337,11 @@ void prove(const std::string& bytecodePath, * @param bytecodePath Path to the file containing the serialized circuit */ template -void gateCount(const std::string& bytecodePath, bool recursive, bool honk_recursion) +void gateCount(const std::string& bytecodePath, bool recursive, uint32_t honk_recursion) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1180): Try to only do this when necessary. + init_grumpkin_crs(1 << CONST_ECCVM_LOG_N); + // All circuit reports will be built into the string below std::string functions_string = "{\"functions\": [\n "; auto constraint_systems = get_constraint_systems(bytecodePath, honk_recursion); @@ -376,7 +402,8 @@ void gate_count_for_ivc(const std::string& bytecodePath) { // All circuit reports will be built into the string below std::string functions_string = "{\"functions\": [\n "; - auto constraint_systems = get_constraint_systems(bytecodePath, /*honk_recursion=*/false); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1181): Use enum for honk_recursion. + auto constraint_systems = get_constraint_systems(bytecodePath, /*honk_recursion=*/0); // Initialize an SRS to make the ClientIVC constructor happy init_bn254_crs(1 << 20); @@ -492,7 +519,7 @@ void write_vk(const std::string& bytecodePath, const std::string& outputPath, co void write_pk(const std::string& bytecodePath, const std::string& outputPath, const bool recursive) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/0); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; acir_composer.create_finalized_circuit(constraint_system, recursive); acir_composer.finalize_circuit(); @@ -776,17 +803,28 @@ UltraProver_ compute_valid_prover(const std::string& bytecodePath, using Builder = Flavor::CircuitBuilder; using Prover = UltraProver_; - constexpr bool honk_recursion = IsAnyOf; + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + } const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = honk_recursion }; acir_format::AcirProgram program{ get_constraint_system(bytecodePath, metadata.honk_recursion) }; if (!witnessPath.empty()) { program.witness = get_witness(witnessPath); } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1180): Don't init grumpkin crs when unnecessary. + init_grumpkin_crs(1 << CONST_ECCVM_LOG_N); auto builder = acir_format::create_circuit(program, metadata); auto prover = Prover{ builder }; init_bn254_crs(prover.proving_key->proving_key.circuit_size); + + // output the vk + typename Flavor::VerificationKey vk(prover.proving_key->proving_key); + debug(vk.to_field_elements()); return std::move(prover); } @@ -847,18 +885,34 @@ template bool verify_honk(const std::string& proof_path, auto vk = std::make_shared(from_buffer(read_file(vk_path))); vk->pcs_verification_key = std::make_shared>(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1154): Remove this and pass in the IPA proof to the - // verifier. std::shared_ptr> ipa_verification_key = nullptr; if constexpr (HasIPAAccumulator) { - init_grumpkin_crs(1 << 16); - vk->contains_ipa_claim = false; + init_grumpkin_crs(1 << CONST_ECCVM_LOG_N); ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); } Verifier verifier{ vk, ipa_verification_key }; - bool verified = verifier.verify_proof(proof); - + bool verified; + if constexpr (HasIPAAccumulator) { + // Break up the tube proof into the honk portion and the ipa portion + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor + const size_t HONK_PROOF_LENGTH = 469; + const size_t num_public_inputs = + static_cast(proof[1]) - PAIRING_POINT_ACCUMULATOR_SIZE - IPA_CLAIM_SIZE; + // The extra calculation is for the IPA proof length. + debug("proof size: ", proof.size()); + debug("num public inputs: ", num_public_inputs); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1182): Move to ProofSurgeon. + ASSERT(proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2 + num_public_inputs); + // split out the ipa proof + const std::ptrdiff_t honk_proof_with_pub_inputs_length = + static_cast(HONK_PROOF_LENGTH + num_public_inputs); + auto ipa_proof = HonkProof(proof.begin() + honk_proof_with_pub_inputs_length, proof.end()); + auto tube_honk_proof = HonkProof(proof.begin(), proof.end() + honk_proof_with_pub_inputs_length); + verified = verifier.verify_proof(proof, ipa_proof); + } else { + verified = verifier.verify_proof(proof); + } vinfo("verified: ", verified); return verified; } @@ -914,7 +968,7 @@ void write_vk_for_ivc(const std::string& bytecodePath, const std::string& output init_bn254_crs(1 << 20); init_grumpkin_crs(1 << 15); - Program program{ get_constraint_system(bytecodePath, /*honk_recursion=*/false), /*witness=*/{} }; + Program program{ get_constraint_system(bytecodePath, /*honk_recursion=*/0), /*witness=*/{} }; auto& ivc_constraints = program.constraints.ivc_recursion_constraints; TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; @@ -965,7 +1019,16 @@ void write_recursion_inputs_honk(const std::string& bytecodePath, using VerificationKey = Flavor::VerificationKey; using FF = Flavor::FF; - const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = true }; + ASSERT(recursive); + + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + init_grumpkin_crs(1 << CONST_ECCVM_LOG_N); + } + const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = honk_recursion }; acir_format::AcirProgram program; program.constraints = get_constraint_system(bytecodePath, metadata.honk_recursion); @@ -979,7 +1042,8 @@ void write_recursion_inputs_honk(const std::string& bytecodePath, VerificationKey verification_key(prover.proving_key->proving_key); // Construct a string with the content of the toml file (vk hash, proof, public inputs, vk) - std::string toml_content = acir_format::ProofSurgeon::construct_recursion_inputs_toml_data(proof, verification_key); + std::string toml_content = + acir_format::ProofSurgeon::construct_recursion_inputs_toml_data(proof, verification_key); // Write all components to the TOML file std::string toml_path = outputPath + "/Prover.toml"; @@ -1056,7 +1120,7 @@ void prove_output_all(const std::string& bytecodePath, const std::string& outputPath, const bool recursive) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/0); auto witness = get_witness(witnessPath); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; @@ -1118,12 +1182,21 @@ void prove_honk_output_all(const std::string& bytecodePath, using Prover = UltraProver_; using VerificationKey = Flavor::VerificationKey; - constexpr bool honk_recursion = IsAnyOf; + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + } + const acir_format::ProgramMetadata metadata{ .recursive = recursive, .honk_recursion = honk_recursion }; acir_format::AcirProgram program{ get_constraint_system(bytecodePath, metadata.honk_recursion), get_witness(witnessPath) }; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1180): Don't init grumpkin crs when unnecessary. + init_grumpkin_crs(1 << CONST_ECCVM_LOG_N); + auto builder = acir_format::create_circuit(program, metadata); // Construct Honk proof @@ -1146,6 +1219,7 @@ void prove_honk_output_all(const std::string& bytecodePath, vinfo("binary proof written to: ", proofPath); // Write the proof as fields + info("proof: ", proof); std::string proofJson = to_json(proof); write_file(proofFieldsPath, { proofJson.begin(), proofJson.end() }); vinfo("proof as fields written to: ", proofFieldsPath); @@ -1157,6 +1231,7 @@ void prove_honk_output_all(const std::string& bytecodePath, // Write the vk as fields std::vector vk_data = vk.to_field_elements(); + debug("vk: ", vk_data); auto vk_json = honk_vk_to_json(vk_data); write_file(vkFieldsOutputPath, { vk_json.begin(), vk_json.end() }); vinfo("vk as fields written to: ", vkFieldsOutputPath); @@ -1198,7 +1273,8 @@ int main(int argc, char* argv[]) const std::string vk_path = get_option(args, "-k", "./target/vk"); const std::string pk_path = get_option(args, "-r", "./target/pk"); - const bool honk_recursion = flag_present(args, "-h"); + const uint32_t honk_recursion = static_cast(stoi(get_option(args, "-h", "0"))); + debug("honk recursion is: ", honk_recursion); const bool recursive = flag_present(args, "--recursive"); CRS_PATH = get_option(args, "-c", CRS_PATH); @@ -1274,7 +1350,7 @@ int main(int argc, char* argv[]) std::string output_path = get_option(args, "-o", "./target"); auto tube_proof_path = output_path + "/proof"; auto tube_vk_path = output_path + "/vk"; - return verify_honk(tube_proof_path, tube_vk_path) ? 0 : 1; + return verify_honk(tube_proof_path, tube_vk_path) ? 0 : 1; } else if (command == "gates") { gateCount(bytecode_path, recursive, honk_recursion); } else if (command == "gates_mega_honk") { @@ -1301,9 +1377,12 @@ int main(int argc, char* argv[]) } else if (command == "vk_as_fields") { std::string output_path = get_option(args, "-o", vk_path + "_fields.json"); vk_as_fields(vk_path, output_path); - } else if (command == "write_recursion_inputs_honk") { + } else if (command == "write_recursion_inputs_ultra_honk") { std::string output_path = get_option(args, "-o", "./target"); write_recursion_inputs_honk(bytecode_path, witness_path, output_path, recursive); + } else if (command == "write_recursion_inputs_rollup_honk") { + std::string output_path = get_option(args, "-o", "./target"); + write_recursion_inputs_honk(bytecode_path, witness_path, output_path, recursive); #ifndef DISABLE_AZTEC_VM } else if (command == "avm_prove") { std::filesystem::path avm_public_inputs_path = @@ -1330,6 +1409,8 @@ int main(int argc, char* argv[]) return verify_honk(proof_path, vk_path) ? 0 : 1; } else if (command == "verify_ultra_keccak_honk") { return verify_honk(proof_path, vk_path) ? 0 : 1; + } else if (command == "verify_ultra_rollup_honk") { + return verify_honk(proof_path, vk_path) ? 0 : 1; } else if (command == "write_vk_ultra_honk") { std::string output_path = get_option(args, "-o", "./target/vk"); write_vk_honk(bytecode_path, output_path, recursive); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 2322375fba3..68d5958a2b8 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -529,7 +529,6 @@ template class IPA { GroupElement ipa_relation = GroupElement::batch_mul(msm_elements, msm_scalars); ipa_relation.assert_equal(-opening_claim.commitment); - ASSERT(ipa_relation.get_value() == -opening_claim.commitment.get_value() && "IPA relation failed."); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1144): Add proper constraints for taking the log of a field_t. Fr stdlib_log_poly_length(static_cast(log_poly_length)); return {stdlib_log_poly_length, round_challenges_inv, G_zero}; @@ -622,7 +621,7 @@ template class IPA { // TODO(https://github.com/AztecProtocol/barretenberg/issues/1144): need checks here on poly_length. const auto poly_length = static_cast(poly_length_var.get_value()); - info("poly_length = ", poly_length); + debug("poly_length = ", poly_length); // Step 2. // Receive generator challenge u and compute auxiliary generator const Fr generator_challenge = transcript->template get_challenge("IPA:generator_challenge"); @@ -726,7 +725,6 @@ template class IPA { GroupElement ipa_relation = GroupElement::batch_mul(msm_elements, msm_scalars); ipa_relation.assert_equal(-opening_claim.commitment); - ASSERT(ipa_relation.get_value() == -opening_claim.commitment.get_value() && "IPA relation failed."); return (ipa_relation.get_value() == -opening_claim.commitment.get_value()); } @@ -946,12 +944,9 @@ template class IPA { ASSERT(challenge_poly.evaluate(opening_pair.challenge) == opening_pair.evaluation && "Opening claim does not hold for challenge polynomial."); IPA::compute_opening_proof(ck, { challenge_poly, opening_pair }, prover_transcript); + ASSERT(challenge_poly.evaluate(fq(output_claim.opening_pair.challenge.get_value())) == fq(output_claim.opening_pair.evaluation.get_value())); - // Since we know this circuit will not have any more IPA claims to accumulate, add IPA Claim to public inputs of circuit and add the proof to the builder. - Builder* builder = r.get_context(); - builder->add_ipa_claim(output_claim.get_witness_indices()); - builder->ipa_proof = prover_transcript->proof_data; - + output_claim.opening_pair.evaluation.self_reduce(); return {output_claim, prover_transcript->proof_data}; } }; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/ipa_recursive.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/ipa_recursive.test.cpp index 940978c37d1..9479dff856a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/ipa_recursive.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/ipa_recursive.test.cpp @@ -160,6 +160,8 @@ class IPARecursiveTests : public CommitmentTest { // polynomial. auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2); + builder.add_ipa_claim(output_claim.get_witness_indices()); + builder.ipa_proof = ipa_proof; builder.finalize_circuit(/*ensure_nonzero=*/false); info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ", builder.get_num_finalized_gates()); @@ -264,6 +266,8 @@ TEST_F(IPARecursiveTests, AccumulationAndFullRecursiveVerifier) // Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h // polynomial. auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2); + builder.add_ipa_claim(output_claim.get_witness_indices()); + builder.ipa_proof = ipa_proof; builder.finalize_circuit(/*ensure_nonzero=*/false); info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ", builder.get_num_finalized_gates()); @@ -310,6 +314,8 @@ TEST_F(IPARecursiveTests, AccumulationWithDifferentSizes) // Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h // polynomial. auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2); + builder.add_ipa_claim(output_claim.get_witness_indices()); + builder.ipa_proof = ipa_proof; builder.finalize_circuit(/*ensure_nonzero=*/false); info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ", builder.get_num_finalized_gates()); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 16307f2a43e..fbbd3f0a58a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -2,6 +2,7 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp" +#include "barretenberg/flavor/flavor.hpp" #include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" #include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" #include "barretenberg/stdlib/primitives/field/field_conversion.hpp" @@ -18,6 +19,12 @@ using namespace bb; template class DSLBigInts; template class DSLBigInts; +template struct HonkRecursionConstraintsOutput { + PairingPointAccumulatorIndices agg_obj_indices; + OpeningClaim> ipa_claim; + HonkProof ipa_proof; +}; + template void build_constraints(Builder& builder, AcirProgram& program, const ProgramMetadata& metadata) { @@ -239,8 +246,14 @@ void build_constraints(Builder& builder, AcirProgram& program, const ProgramMeta process_plonk_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter); PairingPointAccumulatorIndices current_aggregation_object = stdlib::recursion::init_default_agg_obj_indices(builder); - current_aggregation_object = process_honk_recursion_constraints( - builder, constraint_system, has_valid_witness_assignments, gate_counter, current_aggregation_object); + HonkRecursionConstraintsOutput output = + process_honk_recursion_constraints(builder, + constraint_system, + has_valid_witness_assignments, + gate_counter, + current_aggregation_object, + metadata.honk_recursion); + current_aggregation_object = output.agg_obj_indices; #ifndef DISABLE_AZTEC_VM current_aggregation_object = process_avm_recursion_constraints( @@ -250,13 +263,20 @@ void build_constraints(Builder& builder, AcirProgram& program, const ProgramMeta // default one if the circuit is recursive and honk_recursion is true. if (!constraint_system.honk_recursion_constraints.empty() || !constraint_system.avm_recursion_constraints.empty()) { - ASSERT(metadata.honk_recursion); + ASSERT(metadata.honk_recursion != 0); builder.add_pairing_point_accumulator(current_aggregation_object); - } else if (metadata.honk_recursion && builder.is_recursive_circuit) { + } else if (metadata.honk_recursion != 0 && builder.is_recursive_circuit) { // Make sure the verification key records the public input indices of the // final recursion output. builder.add_pairing_point_accumulator(current_aggregation_object); } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1183): This assertion should be true, except for + // the root rollup as of now since the root rollup will not output a ipa proof. + // ASSERT((metadata.honk_recursion == 2) == (output.ipa_proof.size() > 0)); + if (metadata.honk_recursion == 2) { + builder.add_ipa_claim(output.ipa_claim.get_witness_indices()); + builder.ipa_proof = output.ipa_proof; + } } } @@ -346,13 +366,15 @@ void process_plonk_recursion_constraints(Builder& builder, } } -PairingPointAccumulatorIndices process_honk_recursion_constraints( +HonkRecursionConstraintsOutput process_honk_recursion_constraints( Builder& builder, AcirFormat& constraint_system, bool has_valid_witness_assignments, GateCounter& gate_counter, - PairingPointAccumulatorIndices current_aggregation_object) + PairingPointAccumulatorIndices current_aggregation_object, + uint32_t honk_recursion) { + HonkRecursionConstraintsOutput output; // Add recursion constraints size_t idx = 0; std::vector>> nested_ipa_claims; @@ -385,15 +407,47 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( auto ipa_transcript_1 = std::make_shared(nested_ipa_proofs[0]); auto ipa_transcript_2 = std::make_shared(nested_ipa_proofs[1]); - IPA>::accumulate( + auto [ipa_claim, ipa_proof] = IPA>::accumulate( commitment_key, ipa_transcript_1, nested_ipa_claims[0], ipa_transcript_2, nested_ipa_claims[1]); + output.ipa_claim = ipa_claim; + output.ipa_proof = ipa_proof; } else if (nested_ipa_claims.size() == 1) { - builder.add_ipa_claim(nested_ipa_claims[0].get_witness_indices()); + output.ipa_claim = nested_ipa_claims[0]; // This conversion looks suspicious but there's no need to make this an output of the circuit since its a proof // that will be checked anyway. - builder.ipa_proof = convert_stdlib_proof_to_native(nested_ipa_proofs[0]); + output.ipa_proof = convert_stdlib_proof_to_native(nested_ipa_proofs[0]); + } else if (nested_ipa_claims.size() > 2) { + throw_or_abort("Too many nested IPA claims to accumulate"); + } else { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1184): Move to IPA class. + if (honk_recursion == 2) { + info("Proving with UltraRollupHonk but no IPA claims exist."); + // just create some fake IPA claim and proof + using NativeCurve = curve::Grumpkin; + using Curve = stdlib::grumpkin; + auto ipa_transcript = std::make_shared(); + auto ipa_commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + size_t n = 4; + auto poly = Polynomial(n); + for (size_t i = 0; i < n; i++) { + poly.at(i) = fq::random_element(); + } + fq x = fq::random_element(); + fq eval = poly.evaluate(x); + auto commitment = ipa_commitment_key->commit(poly); + const OpeningPair opening_pair = { x, eval }; + IPA::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript); + + auto stdlib_comm = Curve::Group::from_witness(&builder, commitment); + auto stdlib_x = Curve::ScalarField::from_witness(&builder, x); + auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval); + OpeningClaim stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm }; + output.ipa_claim = stdlib_opening_claim; + output.ipa_proof = ipa_transcript->export_proof(); + } } - return current_aggregation_object; + output.agg_obj_indices = current_aggregation_object; + return output; } void process_ivc_recursion_constraints(MegaCircuitBuilder& builder, @@ -532,7 +586,7 @@ UltraCircuitBuilder create_circuit(AcirFormat& constraint_system, bool recursive, const size_t size_hint, const WitnessVector& witness, - bool honk_recursion, + uint32_t honk_recursion, [[maybe_unused]] std::shared_ptr, bool collect_gates_per_opcode) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 9bcd7bbd7db..2990764939b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -203,9 +203,12 @@ struct ProgramMetadata { // inside of another SNARK. For example, a recursive friendly proof may use Blake3Pedersen // for hashing in its transcript, while we still want a prove that uses Keccak for its // transcript in order to be able to verify SNARKs on Ethereum. - bool honk_recursion = false; // honk_recursion means we will honk to recursively verify this + uint32_t honk_recursion = 0; // honk_recursion means we will honk to recursively verify this // circuit. This distinction is needed to not add the default // aggregation object when we're not using the honk RV. + // 0 means we are not proving with honk + // 1 means we are using the UltraHonk flavor + // 2 means we are using the UltraRollupHonk flavor bool collect_gates_per_opcode = false; size_t size_hint = 0; }; @@ -225,7 +228,7 @@ Builder create_circuit(AcirFormat& constraint_system, bool recursive, const size_t size_hint = 0, const WitnessVector& witness = {}, - bool honk_recursion = false, + uint32_t honk_recursion = 0, std::shared_ptr op_queue = std::make_shared(), bool collect_gates_per_opcode = false); @@ -274,7 +277,8 @@ void process_plonk_recursion_constraints(Builder& builder, void process_honk_recursion_constraints(Builder& builder, AcirFormat& constraint_system, bool has_valid_witness_assignments, - GateCounter& gate_counter); + GateCounter& gate_counter, + uint32_t honk_recursion); void process_ivc_recursion_constraints(MegaCircuitBuilder& builder, AcirFormat& constraints, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 4a5097a4dd4..49ec32e7418 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -36,7 +36,7 @@ class AcirIntegrationTest : public ::testing::Test { } acir_format::AcirProgramStack get_program_stack_data_from_test_file(const std::string& test_program_name, - bool honk_recursion = false) + uint32_t honk_recursion = 0) { std::string base_path = "../../acir_tests/acir_tests/" + test_program_name + "/target"; std::string bytecode_path = base_path + "/program.json"; @@ -46,7 +46,7 @@ class AcirIntegrationTest : public ::testing::Test { } acir_format::AcirProgram get_program_data_from_test_file(const std::string& test_program_name, - bool honk_recursion = false) + uint32_t honk_recursion = 0) { auto program_stack = get_program_stack_data_from_test_file(test_program_name, honk_recursion); ASSERT(program_stack.size() == 1); // Otherwise this method will not return full stack data @@ -150,8 +150,8 @@ TEST_P(AcirIntegrationSingleTest, DISABLED_ProveAndVerifyProgram) info("Test: ", test_name); acir_format::AcirProgram acir_program = get_program_data_from_test_file( test_name, - /*honk_recursion=*/ - false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): Assumes Flavor is not UltraHonk + /*honk_recursion=*/0); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): + // Assumes Flavor is not UltraHonk // Construct a bberg circuit from the acir representation Builder builder = acir_format::create_circuit(acir_program); @@ -372,8 +372,8 @@ TEST_P(AcirIntegrationFoldingTest, DISABLED_ProveAndVerifyProgramStack) info("Test: ", test_name); auto program_stack = get_program_stack_data_from_test_file( - test_name, /*honk_recursion=*/false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): - // Assumes Flavor is not UltraHonk + test_name, /*honk_recursion=*/0); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): + // Assumes Flavor is not UltraHonk while (!program_stack.empty()) { auto program = program_stack.back(); @@ -480,8 +480,8 @@ TEST_F(AcirIntegrationTest, DISABLED_UpdateAcirCircuit) std::string test_name = "6_array"; // arbitrary program with RAM gates auto acir_program = get_program_data_from_test_file( - test_name, /*honk_recursion=*/false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): - // Assumes Flavor is not UltraHonk + test_name, /*honk_recursion=*/0); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): + // Assumes Flavor is not UltraHonk // Construct a bberg circuit from the acir representation Builder circuit = acir_format::create_circuit(acir_program); @@ -515,12 +515,11 @@ TEST_F(AcirIntegrationTest, DISABLED_HonkRecursion) using Builder = Flavor::CircuitBuilder; std::string test_name = "verify_honk_proof"; // arbitrary program with RAM gates - // Note: honk_recursion set to false here because the selection of the honk recursive verifier is indicated by the - // proof_type field of the constraint generated from noir. + // Note: honk_recursion set to 1 here we are using the UltraFlavor. // The honk_recursion flag determines whether a noir program will be recursively verified via Honk in a Noir // program. auto acir_program = get_program_data_from_test_file(test_name, - /*honk_recursion=*/false); + /*honk_recursion=*/1); // Construct a bberg circuit from the acir representation Builder circuit = acir_format::create_circuit(acir_program); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index 251ca8236e7..f22bf954b85 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -465,7 +465,7 @@ WitnessOrConstant parse_input(Program::FunctionInput input) void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af, - bool honk_recursion, + uint32_t honk_recursion, size_t opcode_index) { std::visit( @@ -634,9 +634,13 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1074): Eventually arg.proof_type will // be the only means for setting the proof type. use of honk_recursion flag in this context can go // away once all noir programs (e.g. protocol circuits) are updated to use the new pattern. - if (honk_recursion && proof_type_in != HONK && proof_type_in != AVM && proof_type_in != ROLLUP_HONK && + if (proof_type_in != HONK && proof_type_in != AVM && proof_type_in != ROLLUP_HONK && proof_type_in != ROLLUP_ROOT_HONK) { - proof_type_in = HONK; + if (honk_recursion == 1) { + proof_type_in = HONK; + } else if (honk_recursion == 2) { + proof_type_in = ROLLUP_HONK; + } } auto c = RecursionConstraint{ @@ -791,7 +795,7 @@ void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& block.trace.push_back(acir_mem_op); } -AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit, bool honk_recursion) +AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit, uint32_t honk_recursion) { AcirFormat af; // `varnum` is the true number of variables, thus we add one to the index which starts at zero @@ -837,7 +841,7 @@ AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit, bool ho return af; } -AcirFormat circuit_buf_to_acir_format(std::vector const& buf, bool honk_recursion) +AcirFormat circuit_buf_to_acir_format(std::vector const& buf, uint32_t honk_recursion) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/927): Move to using just // `program_buf_to_acir_format` once Honk fully supports all ACIR test flows For now the backend still expects @@ -892,7 +896,7 @@ WitnessVector witness_buf_to_witness_data(std::vector const& buf) return witness_map_to_witness_vector(w); } -std::vector program_buf_to_acir_format(std::vector const& buf, bool honk_recursion) +std::vector program_buf_to_acir_format(std::vector const& buf, uint32_t honk_recursion) { auto program = Program::Program::bincodeDeserialize(buf); @@ -920,7 +924,7 @@ WitnessVectorStack witness_buf_to_witness_stack(std::vector const& buf) #ifndef __wasm__ AcirProgramStack get_acir_program_stack(std::string const& bytecode_path, std::string const& witness_path, - bool honk_recursion) + uint32_t honk_recursion) { std::vector bytecode = get_bytecode(bytecode_path); std::vector constraint_systems = diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index adfd8a75806..4560c824544 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -4,7 +4,7 @@ namespace acir_format { -AcirFormat circuit_buf_to_acir_format(std::vector const& buf, bool honk_recursion); +AcirFormat circuit_buf_to_acir_format(std::vector const& buf, uint32_t honk_recursion); /** * @brief Converts from the ACIR-native `WitnessMap` format to Barretenberg's internal `WitnessVector` format. @@ -16,13 +16,13 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf, bool honk */ WitnessVector witness_buf_to_witness_data(std::vector const& buf); -std::vector program_buf_to_acir_format(std::vector const& buf, bool honk_recursion); +std::vector program_buf_to_acir_format(std::vector const& buf, uint32_t honk_recursion); WitnessVectorStack witness_buf_to_witness_stack(std::vector const& buf); #ifndef __wasm__ AcirProgramStack get_acir_program_stack(std::string const& bytecode_path, std::string const& witness_path, - bool honk_recursion); + uint32_t honk_recursion); #endif } // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp index 46e9a0f06b0..473ea82cce6 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp @@ -122,7 +122,7 @@ class AcirAvmRecursionConstraint : public ::testing::Test { mock_opcode_indices(constraint_system); auto outer_circuit = - create_circuit(constraint_system, /*recursive*/ false, /*size_hint*/ 0, witness, /*honk_recursion=*/true); + create_circuit(constraint_system, /*recursive*/ false, /*size_hint*/ 0, witness, /*honk_recursion=*/1); return outer_circuit; } }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index 4e34694eb2d..38849d2554b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -1,4 +1,5 @@ #include "honk_recursion_constraint.hpp" +#include "barretenberg/constants.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" #include "barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp" @@ -10,6 +11,8 @@ #include "proof_surgeon.hpp" #include "recursion_constraint.hpp" +#include + namespace acir_format { using namespace bb; @@ -36,8 +39,7 @@ void create_dummy_vkey_and_proof(Builder& builder, size_t proof_size, size_t public_inputs_size, const std::vector& key_fields, - const std::vector& proof_fields, - bool is_rollup_honk_recursion_constraint) + const std::vector& proof_fields) { // Set vkey->circuit_size correctly based on the proof size size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); @@ -62,7 +64,7 @@ void create_dummy_vkey_and_proof(Builder& builder, builder.assert_equal(builder.add_variable(1), key_fields[3].witness_index); uint32_t offset = 4; size_t num_inner_public_inputs = public_inputs_size - bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if (is_rollup_honk_recursion_constraint) { + if constexpr (HasIPAAccumulator) { num_inner_public_inputs -= bb::IPA_CLAIM_SIZE; } @@ -72,12 +74,13 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } - if (is_rollup_honk_recursion_constraint) { + if constexpr (HasIPAAccumulator) { // Key field is the whether the proof contains an aggregation object. builder.assert_equal(builder.add_variable(1), key_fields[offset++].witness_index); // We are making the assumption that the IPA claim is behind the inner public inputs and pairing point object for (size_t i = 0; i < bb::IPA_CLAIM_SIZE; i++) { - builder.assert_equal(builder.add_variable(num_inner_public_inputs + i), key_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(num_inner_public_inputs + PAIRING_POINT_ACCUMULATOR_SIZE + i), + key_fields[offset].witness_index); offset++; } } @@ -110,10 +113,10 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } - if (is_rollup_honk_recursion_constraint) { - IPAClaimIndices ipa_claim; // WORKTODO: initialize this to something? - for (auto idx : ipa_claim) { - builder.assert_equal(idx, proof_fields[offset].witness_index); + // IPA claim + if constexpr (HasIPAAccumulator) { + for (size_t i = 0; i < bb::IPA_CLAIM_SIZE; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); offset++; } } @@ -169,6 +172,35 @@ void create_dummy_vkey_and_proof(Builder& builder, builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); offset += 4; } + // IPA Proof + if constexpr (HasIPAAccumulator) { + // Poly length + builder.assert_equal(builder.add_variable(1), proof_fields[offset].witness_index); + offset++; + + // Ls and Rs + for (size_t i = 0; i < static_cast(2) * CONST_ECCVM_LOG_N; i++) { + auto comm = curve::Grumpkin::AffineElement::one() * fq::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + offset += 2; + } + + // G_zero + auto G_zero = curve::Grumpkin::AffineElement::one() * fq::random_element(); + auto G_zero_frs = field_conversion::convert_to_bn254_frs(G_zero); + builder.assert_equal(builder.add_variable(G_zero_frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(G_zero_frs[1]), proof_fields[offset + 1].witness_index); + offset += 2; + + // a_zero + auto a_zero = fq::random_element(); + auto a_zero_frs = field_conversion::convert_to_bn254_frs(a_zero); + builder.assert_equal(builder.add_variable(a_zero_frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(a_zero_frs[1]), proof_fields[offset + 1].witness_index); + offset += 2; + } ASSERT(offset == proof_size + public_inputs_size); } } // namespace @@ -196,9 +228,8 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; - bool is_rollup_honk_recursion_constraint = - (input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); - ASSERT(input.proof_type == HONK || is_rollup_honk_recursion_constraint); + ASSERT(input.proof_type == HONK || HasIPAAccumulator); + ASSERT((input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK) == HasIPAAccumulator); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. @@ -226,19 +257,15 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( // In the constraint, the agg object public inputs are still contained in the proof. To get the 'raw' size of // the proof and public_inputs we subtract and add the corresponding amount from the respective sizes. size_t size_of_proof_with_no_pub_inputs = input.proof.size() - bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if (is_rollup_honk_recursion_constraint) { + if constexpr (HasIPAAccumulator) { size_of_proof_with_no_pub_inputs -= bb::IPA_CLAIM_SIZE; } size_t total_num_public_inputs = input.public_inputs.size() + bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if (is_rollup_honk_recursion_constraint) { + if constexpr (HasIPAAccumulator) { total_num_public_inputs += bb::IPA_CLAIM_SIZE; } - create_dummy_vkey_and_proof(builder, - size_of_proof_with_no_pub_inputs, - total_num_public_inputs, - key_fields, - proof_fields, - is_rollup_honk_recursion_constraint); + create_dummy_vkey_and_proof( + builder, size_of_proof_with_no_pub_inputs, total_num_public_inputs, key_fields, proof_fields); } // Recursively verify the proof @@ -246,29 +273,16 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( RecursiveVerifier verifier(&builder, vkey); aggregation_state_ct input_agg_obj = bb::stdlib::recursion::convert_witness_indices_to_agg_obj( builder, input_aggregation_object_indices); - std::vector honk_proof = proof_fields; HonkRecursionConstraintOutput output; - if (is_rollup_honk_recursion_constraint) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor - const size_t HONK_PROOF_LENGTH = 469; - // The extra calculation is for the IPA proof length. - ASSERT(input.proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2); - ASSERT(proof_fields.size() == HONK_PROOF_LENGTH + 65 + input.public_inputs.size()); - // split out the ipa proof - const std::ptrdiff_t honk_proof_with_pub_inputs_length = - static_cast(HONK_PROOF_LENGTH + input.public_inputs.size()); - output.ipa_proof = - StdlibProof(honk_proof.begin() + honk_proof_with_pub_inputs_length, honk_proof.end()); - honk_proof = StdlibProof(honk_proof.begin(), honk_proof.end() + honk_proof_with_pub_inputs_length); - } - UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(honk_proof, input_agg_obj); + UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(proof_fields, input_agg_obj); // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public inputs // is important, like what the plonk recursion constraint does. output.agg_obj_indices = verifier_output.agg_obj.get_witness_indices(); - if (is_rollup_honk_recursion_constraint) { + if constexpr (HasIPAAccumulator) { ASSERT(HasIPAAccumulator); output.ipa_claim = verifier_output.ipa_opening_claim; + output.ipa_proof = verifier_output.ipa_proof; } return output; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index 7f1dbd8f6cb..bec5fb78019 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -125,31 +125,14 @@ template class AcirHonkRecursionConstraint : public ::testing: WitnessVector witness{ 5, 10, 15, 5, inverse_of_five, 1, }; - auto builder = - create_circuit(constraint_system, /*recursive*/ true, /*size_hint*/ 0, witness, /*honk recursion*/ true); - if constexpr (HasIPAAccumulator) { - using NativeCurve = curve::Grumpkin; - using Curve = stdlib::grumpkin; - auto ipa_transcript = std::make_shared(); - auto ipa_commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); - size_t n = 4; - auto poly = Polynomial(n); - for (size_t i = 0; i < n; i++) { - poly.at(i) = fq::random_element(); - } - fq x = fq::random_element(); - fq eval = poly.evaluate(x); - auto commitment = ipa_commitment_key->commit(poly); - const OpeningPair opening_pair = { x, eval }; - IPA::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript); - - auto stdlib_comm = Curve::Group::from_witness(&builder, commitment); - auto stdlib_x = Curve::ScalarField::from_witness(&builder, x); - auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval); - OpeningClaim stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm }; - builder.add_ipa_claim(stdlib_opening_claim.get_witness_indices()); - builder.ipa_proof = ipa_transcript->export_proof(); + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; } + auto builder = create_circuit( + constraint_system, /*recursive*/ true, /*size_hint*/ 0, witness, /*honk recursion*/ honk_recursion); return builder; } @@ -203,8 +186,14 @@ template class AcirHonkRecursionConstraint : public ::testing: constraint_system.original_opcode_indices = create_empty_original_opcode_indices(); mock_opcode_indices(constraint_system); - auto outer_circuit = - create_circuit(constraint_system, /*recursive*/ true, /*size_hint*/ 0, witness, /*honk recursion*/ true); + uint32_t honk_recursion = 0; + if constexpr (IsAnyOf) { + honk_recursion = 1; + } else if constexpr (IsAnyOf) { + honk_recursion = 2; + } + auto outer_circuit = create_circuit( + constraint_system, /*recursive*/ true, /*size_hint*/ 0, witness, /*honk recursion*/ honk_recursion); return outer_circuit; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp index 40bbedb02a3..f7edc905446 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/map.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/flavor/flavor.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" #include "barretenberg/serialize/msgpack.hpp" @@ -27,14 +28,19 @@ class ProofSurgeon { * @param verification_key * @param toml_path */ + template static std::string construct_recursion_inputs_toml_data(std::vector& proof, const auto& verification_key) { // Convert verification key to fields std::vector vkey_fields = verification_key.to_field_elements(); // Get public inputs by cutting them out of the proof - const size_t num_public_inputs_to_extract = - verification_key.num_public_inputs - bb::PAIRING_POINT_ACCUMULATOR_SIZE; + size_t num_public_inputs_to_extract = verification_key.num_public_inputs - bb::PAIRING_POINT_ACCUMULATOR_SIZE; + if constexpr (bb::HasIPAAccumulator) { + num_public_inputs_to_extract -= bb::IPA_CLAIM_SIZE; + } + debug("proof size: ", proof.size()); + debug("number of public inputs to extract: ", num_public_inputs_to_extract); std::vector public_inputs = acir_format::ProofSurgeon::cut_public_inputs_from_proof(proof, num_public_inputs_to_extract); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index a645a39649f..a3e037af23f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -42,7 +42,7 @@ WASM_EXPORT void acir_init_proving_key(in_ptr acir_composer_ptr, uint8_t const* { auto acir_composer = reinterpret_cast(*acir_composer_ptr); auto constraint_system = - acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/false); + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/0); acir_composer->create_finalized_circuit(constraint_system, *recursive); acir_composer->init_proving_key(); @@ -53,7 +53,7 @@ WASM_EXPORT void acir_create_proof( { auto acir_composer = reinterpret_cast(*acir_composer_ptr); auto constraint_system = - acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/false); + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/0); auto witness = acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)); acir_composer->create_finalized_circuit(constraint_system, *recursive, witness); @@ -68,7 +68,7 @@ WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result) { - const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = true }; + const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 }; acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), metadata.honk_recursion), acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)) @@ -91,7 +91,7 @@ WASM_EXPORT void acir_prove_and_verify_mega_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result) { - const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = false }; + const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 0 }; acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), metadata.honk_recursion), @@ -137,7 +137,7 @@ WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, { auto acir_composer = reinterpret_cast(*acir_composer_ptr); auto constraint_system = - acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/false); + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/0); acir_composer->create_finalized_circuit(constraint_system, *recursive); auto pk = acir_composer->init_proving_key(); // We flatten to a vector first, as that's how we treat it on the calling side. @@ -196,8 +196,7 @@ WASM_EXPORT void acir_prove_and_verify_aztec_client(uint8_t const* acir_stack, for (auto [bincode, wit] : zip_view(acirs, witnesses)) { acir_format::WitnessVector witness = acir_format::witness_buf_to_witness_data(wit); - acir_format::AcirFormat constraints = - acir_format::circuit_buf_to_acir_format(bincode, /*honk_recursion=*/false); + acir_format::AcirFormat constraints = acir_format::circuit_buf_to_acir_format(bincode, /*honk_recursion=*/0); folding_stack.push_back(Program{ constraints, witness }); } // TODO(#7371) dedupe this with the rest of the similar code @@ -254,8 +253,7 @@ WASM_EXPORT void acir_prove_aztec_client(uint8_t const* acir_stack, for (auto [bincode, wit] : zip_view(acirs, witnesses)) { acir_format::WitnessVector witness = acir_format::witness_buf_to_witness_data(wit); - acir_format::AcirFormat constraints = - acir_format::circuit_buf_to_acir_format(bincode, /*honk_recursion=*/false); + acir_format::AcirFormat constraints = acir_format::circuit_buf_to_acir_format(bincode, /*honk_recursion=*/0); folding_stack.push_back(Program{ constraints, witness }); } TraceSettings trace_settings{ E2E_FULL_TEST_STRUCTURE }; @@ -318,7 +316,7 @@ WASM_EXPORT void acir_prove_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, uint8_t** out) { - const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = true }; + const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 }; acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), metadata.honk_recursion), @@ -338,11 +336,11 @@ WASM_EXPORT void acir_prove_ultra_keccak_honk(uint8_t const* acir_vec, uint8_t** out) { auto constraint_system = - acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/true); + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/1); auto witness = acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)); auto builder = acir_format::create_circuit( - constraint_system, *recursive, 0, witness, /*honk_recursion=*/true); + constraint_system, *recursive, 0, witness, /*honk_recursion=*/1); UltraKeccakProver prover{ builder }; auto proof = prover.construct_proof(); @@ -384,7 +382,7 @@ WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, bool const* r using DeciderProvingKey = DeciderProvingKey_; using VerificationKey = UltraFlavor::VerificationKey; - const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = true }; + const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 }; acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format( from_buffer>(acir_vec), metadata.honk_recursion) }; @@ -400,7 +398,7 @@ WASM_EXPORT void acir_write_vk_ultra_keccak_honk(uint8_t const* acir_vec, bool c using DeciderProvingKey = DeciderProvingKey_; using VerificationKey = UltraKeccakFlavor::VerificationKey; - const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = true }; + const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 }; acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format( from_buffer>(acir_vec), metadata.honk_recursion) }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index c8170f4373c..3caa326d5dc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -46,7 +46,25 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ using VerifierCommitments = typename Flavor::VerifierCommitments; using Transcript = typename Flavor::Transcript; - transcript = std::make_shared(proof); + Output output; + StdlibProof honk_proof; + if constexpr (HasIPAAccumulator) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor + const size_t HONK_PROOF_LENGTH = 469; + const size_t num_public_inputs = static_cast(proof[1].get_value()); + // The extra calculation is for the IPA proof length. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1182): Handle in ProofSurgeon. + ASSERT(proof.size() == HONK_PROOF_LENGTH + (1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2) + num_public_inputs - + (PAIRING_POINT_ACCUMULATOR_SIZE + IPA_CLAIM_SIZE)); + // split out the ipa proof + const std::ptrdiff_t honk_proof_with_pub_inputs_length = static_cast( + HONK_PROOF_LENGTH + num_public_inputs - (PAIRING_POINT_ACCUMULATOR_SIZE + IPA_CLAIM_SIZE)); + output.ipa_proof = StdlibProof(proof.begin() + honk_proof_with_pub_inputs_length, proof.end()); + honk_proof = StdlibProof(proof.begin(), proof.end() + honk_proof_with_pub_inputs_length); + } else { + honk_proof = proof; + } + transcript = std::make_shared(honk_proof); auto verification_key = std::make_shared(builder, key); OinkVerifier oink_verifier{ builder, verification_key, transcript }; oink_verifier.verify(); @@ -127,7 +145,6 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ pairing_points[1] = pairing_points[1].normalize(); // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): generate recursion separator challenge properly. agg_obj.aggregate(pairing_points, recursion_separator); - Output output; output.agg_obj = std::move(agg_obj); // Extract the IPA claim from the public inputs @@ -135,6 +152,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ if constexpr (HasIPAAccumulator) { const auto recover_fq_from_public_inputs = [](std::array& limbs) { for (size_t k = 0; k < Curve::BaseField::NUM_LIMBS; k++) { + info("limbs " + std::to_string(k) + ": ", limbs[k]); limbs[k].create_range_constraint(Curve::BaseField::NUM_LIMB_BITS, "limb_" + std::to_string(k)); } return Curve::BaseField::unsafe_construct_from_limbs(limbs[0], limbs[1], limbs[2], limbs[3], false); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp index 7a8006e6431..852455581d3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp @@ -16,6 +16,7 @@ template struct UltraRecursiveVerifierOutput { using Builder = typename Flavor::CircuitBuilder; AggregationObject agg_obj; OpeningClaim> ipa_opening_claim; + StdlibProof ipa_proof; }; template class UltraRecursiveVerifier_ { public: diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp index 86ab9028de1..2280ddbac5f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp @@ -1,7 +1,10 @@ #include "barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/commitment_schemes/ipa/ipa.hpp" #include "barretenberg/common/test.hpp" +#include "barretenberg/flavor/flavor.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -30,7 +33,10 @@ template class RecursiveVerifierTest : public testing // Defines types for the outer circuit, i.e. the circuit of the recursive verifier using OuterBuilder = typename RecursiveFlavor::CircuitBuilder; - using OuterFlavor = std::conditional_t, MegaFlavor, UltraFlavor>; + using OuterFlavor = + std::conditional_t, + MegaFlavor, + std::conditional_t, UltraRollupFlavor, UltraFlavor>>; using OuterProver = UltraProver_; using OuterVerifier = UltraVerifier_; using OuterDeciderProvingKey = DeciderProvingKey_; @@ -68,11 +74,42 @@ template class RecursiveVerifierTest : public testing } PairingPointAccumulatorIndices agg_obj_indices = stdlib::recursion::init_default_agg_obj_indices(builder); builder.add_pairing_point_accumulator(agg_obj_indices); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1184): Move to IPA class. + if constexpr (HasIPAAccumulator) { + using NativeCurve = curve::Grumpkin; + using Curve = stdlib::grumpkin; + auto ipa_transcript = std::make_shared(); + auto ipa_commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + size_t n = 4; + auto poly = Polynomial(n); + for (size_t i = 0; i < n; i++) { + poly.at(i) = fq::random_element(); + } + fq x = fq::random_element(); + fq eval = poly.evaluate(x); + auto commitment = ipa_commitment_key->commit(poly); + const OpeningPair opening_pair = { x, eval }; + IPA::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript); + + auto stdlib_comm = Curve::Group::from_witness(&builder, commitment); + auto stdlib_x = Curve::ScalarField::from_witness(&builder, x); + auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval); + OpeningClaim stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm }; + builder.add_ipa_claim(stdlib_opening_claim.get_witness_indices()); + builder.ipa_proof = ipa_transcript->export_proof(); + } return builder; }; public: - static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } + static void SetUpTestSuite() + { + bb::srs::init_crs_factory("../srs_db/ignition"); + if constexpr (HasIPAAccumulator) { + bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } + } /** * @brief Create inner circuit and call check_circuit on it @@ -139,9 +176,15 @@ template class RecursiveVerifierTest : public testing // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; RecursiveVerifier verifier{ &outer_circuit, verification_key }; - [[maybe_unused]] auto pairing_points = verifier.verify_proof( + HonkProof honk_proof; + + typename RecursiveVerifier::Output verifier_output = verifier.verify_proof( inner_proof, init_default_aggregation_state(outer_circuit)); + if constexpr (HasIPAAccumulator) { + outer_circuit.add_ipa_claim(verifier_output.ipa_opening_claim.get_witness_indices()); + outer_circuit.ipa_proof = convert_stdlib_proof_to_native(verifier_output.ipa_proof); + } auto outer_proving_key = std::make_shared(outer_circuit); auto outer_verification_key = @@ -214,6 +257,10 @@ template class RecursiveVerifierTest : public testing bb::stdlib::recursion::honk::UltraRecursiveVerifierOutput output = verifier.verify_proof(inner_proof, agg_obj); aggregation_state pairing_points = output.agg_obj; + if constexpr (HasIPAAccumulator) { + outer_circuit.add_ipa_claim(output.ipa_opening_claim.get_witness_indices()); + outer_circuit.ipa_proof = convert_stdlib_proof_to_native(output.ipa_proof); + } info("Recursive Verifier: num gates = ", outer_circuit.get_estimated_num_finalized_gates()); // Check for a failure flag in the recursive verifier circuit @@ -221,10 +268,16 @@ template class RecursiveVerifierTest : public testing // Check 1: Perform native verification then perform the pairing on the outputs of the recursive // verifier and check that the result agrees. + bool native_result; InnerVerifier native_verifier(verification_key); - auto native_result = native_verifier.verify_proof(inner_proof); - using VerifierCommitmentKey = typename InnerFlavor::VerifierCommitmentKey; - auto pcs_verification_key = std::make_shared(); + if constexpr (HasIPAAccumulator) { + native_verifier.ipa_verification_key = + std::make_shared>(1 << CONST_ECCVM_LOG_N); + native_result = native_verifier.verify_proof(inner_proof, convert_stdlib_proof_to_native(output.ipa_proof)); + } else { + native_result = native_verifier.verify_proof(inner_proof); + } + auto pcs_verification_key = std::make_shared(); bool result = pcs_verification_key->pairing_check(pairing_points.P0.get_value(), pairing_points.P1.get_value()); info("input pairing points result: ", result); auto recursive_result = native_verifier.verification_key->verification_key->pcs_verification_key->pairing_check( @@ -244,11 +297,16 @@ template class RecursiveVerifierTest : public testing auto proving_key = std::make_shared(outer_circuit); OuterProver prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); - OuterVerifier verifier(verification_key); auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - - ASSERT(verified); + if constexpr (HasIPAAccumulator) { + auto ipa_verification_key = + std::make_shared>(1 << CONST_ECCVM_LOG_N); + OuterVerifier verifier(verification_key, ipa_verification_key); + ASSERT(verifier.verify_proof(proof, proving_key->proving_key.ipa_proof)); + } else { + OuterVerifier verifier(verification_key); + ASSERT(verifier.verify_proof(proof)); + } } } @@ -293,6 +351,7 @@ using Flavors = testing::Types, MegaRecursiveFlavor_, UltraRecursiveFlavor_, UltraRecursiveFlavor_, + UltraRollupRecursiveFlavor_, UltraRecursiveFlavor_, MegaRecursiveFlavor_, MegaZKRecursiveFlavor_, @@ -317,7 +376,9 @@ HEAVY_TYPED_TEST(RecursiveVerifierTest, SingleRecursiveVerification) HEAVY_TYPED_TEST(RecursiveVerifierTest, IndependentVKHash) { - if constexpr (std::same_as>) { + if constexpr (IsAnyOf, + UltraRollupRecursiveFlavor_>) { TestFixture::test_independent_vk_hash(); } else { GTEST_SKIP() << "Not built for this parameter"; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp index 440d1051834..ff3d495236b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp @@ -24,6 +24,7 @@ class UltraRollupFlavor : public bb::UltraFlavor { */ class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: + virtual ~VerificationKey() = default; bool contains_ipa_claim; IPAClaimPubInputIndices ipa_claim_public_input_indices; @@ -84,6 +85,7 @@ class UltraRollupFlavor : public bb::UltraFlavor { commitment = proving_key.commitment_key->commit(polynomial); } } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate // up. VerificationKey(const uint64_t circuit_size, diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index fdddf701b5a..765546c6c08 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -191,6 +191,7 @@ library Constants { uint256 internal constant PRIVATE_CONTEXT_INPUTS_LENGTH = 40; uint256 internal constant FEE_RECIPIENT_LENGTH = 2; uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; + uint256 internal constant IPA_CLAIM_LENGTH = 10; uint256 internal constant SCOPED_READ_REQUEST_LEN = 3; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 3; uint256 internal constant PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; @@ -222,8 +223,12 @@ library Constants { uint256 internal constant NUM_BASE_PARITY_PER_ROOT_PARITY = 4; uint256 internal constant RECURSIVE_PROOF_LENGTH = 459; uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 459; - uint256 internal constant TUBE_PROOF_LENGTH = 459; + uint256 internal constant IPA_PROOF_LENGTH = 65; + uint256 internal constant RECURSIVE_ROLLUP_HONK_PROOF_LENGTH = 534; + uint256 internal constant NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH = 534; + uint256 internal constant TUBE_PROOF_LENGTH = 534; uint256 internal constant HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 128; + uint256 internal constant ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 139; uint256 internal constant CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 143; uint256 internal constant MAX_PUBLIC_BYTECODE_SIZE_IN_BYTES = 96000; uint256 internal constant MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS = 21; @@ -294,4 +299,6 @@ library Constants { uint256 internal constant PROOF_TYPE_OINK = 2; uint256 internal constant PROOF_TYPE_PG = 3; uint256 internal constant PROOF_TYPE_AVM = 4; + uint256 internal constant PROOF_TYPE_ROLLUP_HONK = 5; + uint256 internal constant PROOF_TYPE_ROOT_ROLLUP_HONK = 6; } diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index 79f0b445a74..c62b2a57583 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -6,6 +6,7 @@ set -eu # representing a list of circuit reports for a program. # The ACIR tests in barretenberg also expect every target bytecode to have the name `acir.gz` while this script expects the same name of the package MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' client_ivc_circuits.json) +ROLLUP_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' rollup_honk_circuits.json) cd noir-protocol-circuits PROTOCOL_CIRCUITS_DIR=$PWD @@ -31,11 +32,21 @@ for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do fi done + IS_ROLLUP_HONK_CIRCUIT="false" + for pattern in $ROLLUP_HONK_CIRCUIT_PATTERNS; do + if echo "$ARTIFACT_NAME" | grep -qE "$pattern"; then + IS_ROLLUP_HONK_CIRCUIT="true" + break + fi + done + # If it's mega honk, we need to use the gates_for_ivc command if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then - GATES_INFO=$($BB_BIN gates_for_ivc -h -b "$pathname") + GATES_INFO=$($BB_BIN gates_for_ivc -h 0 -b "$pathname") + elif [ "$IS_ROLLUP_HONK_CIRCUIT" = "true" ]; then + GATES_INFO=$($BB_BIN gates -h 2 -b "$pathname") else - GATES_INFO=$($BB_BIN gates -h -b "$pathname") + GATES_INFO=$($BB_BIN gates -h 1 -b "$pathname") fi MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r ".functions[0] | {package_name: "\"$ARTIFACT_NAME\"", functions: [{name: \"main\", opcodes: .acir_opcodes, circuit_size}]}") diff --git a/noir-projects/noir-contracts/bootstrap.sh b/noir-projects/noir-contracts/bootstrap.sh index a441ec1c978..f2482f75e96 100755 --- a/noir-projects/noir-contracts/bootstrap.sh +++ b/noir-projects/noir-contracts/bootstrap.sh @@ -72,7 +72,7 @@ function process_function() { if ! cache_download vk-$hash.tar.gz &> /dev/null; then # It's not in the cache. Generate the vk file and upload it to the cache. echo_stderr "Generating vk for function: $name..." - echo "$bytecode_b64" | base64 -d | gunzip | $BB write_vk_for_ivc -h -b - -o $tmp_dir/$hash 2>/dev/null + echo "$bytecode_b64" | base64 -d | gunzip | $BB write_vk_for_ivc -b - -o $tmp_dir/$hash 2>/dev/null cache_upload vk-$hash.tar.gz $tmp_dir/$hash &> /dev/null fi diff --git a/noir-projects/noir-protocol-circuits/bootstrap.sh b/noir-projects/noir-protocol-circuits/bootstrap.sh index bbdba711507..84f930f4b16 100755 --- a/noir-projects/noir-protocol-circuits/bootstrap.sh +++ b/noir-projects/noir-protocol-circuits/bootstrap.sh @@ -26,7 +26,18 @@ ivc_patterns=( "app_creator" "app_reader" ) + +rollup_honk_patterns=( + "empty_nested.*" + "private_kernel_empty.*" + "rollup_base.*" + "rollup_block.*" + "rollup_merge" +) + + ivc_regex=$(IFS="|"; echo "${ivc_patterns[*]}") +rollup_honk_regex=$(IFS="|"; echo "${rollup_honk_patterns[*]}") function on_exit() { rm -rf $tmp_dir @@ -40,7 +51,7 @@ mkdir -p $tmp_dir mkdir -p $key_dir # Export vars needed inside compile. -export tmp_dir key_dir ci3 ivc_regex +export tmp_dir key_dir ci3 ivc_regex rollup_honk_regex function compile { set -euo pipefail @@ -65,15 +76,21 @@ function compile { cache_upload circuit-$hash.tar.gz $json_path &> /dev/null fi + echo "$name" if echo "$name" | grep -qE "${ivc_regex}"; then local proto="client_ivc" local write_vk_cmd="write_vk_for_ivc" local vk_as_fields_cmd="vk_as_fields_mega_honk" + elif echo "$name" | grep -qE "${rollup_honk_regex}"; then + local proto="ultra_rollup_honk" + local write_vk_cmd="write_vk_ultra_rollup_honk -h 2" + local vk_as_fields_cmd="vk_as_fields_ultra_rollup_honk" else local proto="ultra_honk" - local write_vk_cmd="write_vk_ultra_honk" + local write_vk_cmd="write_vk_ultra_honk -h 1" local vk_as_fields_cmd="vk_as_fields_ultra_honk" fi + echo "$proto$" # No vks needed for simulated circuits. [[ "$name" == *"simulated"* ]] && return @@ -86,7 +103,7 @@ function compile { local key_path="$key_dir/$name.vk.data.json" echo_stderr "Generating vk for function: $name..." SECONDS=0 - local vk_cmd="jq -r '.bytecode' $json_path | base64 -d | gunzip | $BB $write_vk_cmd -h -b - -o - --recursive | xxd -p -c 0" + local vk_cmd="jq -r '.bytecode' $json_path | base64 -d | gunzip | $BB $write_vk_cmd -b - -o - --recursive | xxd -p -c 0" echo_stderr $vk_cmd vk=$(dump_fail "$vk_cmd") local vkf_cmd="echo '$vk' | xxd -r -p | $BB $vk_as_fields_cmd -k - -o -" diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr index 2d0ce595218..20b4f7b831b 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr @@ -1,6 +1,6 @@ use crate::parity_public_inputs::ParityPublicInputs; use dep::types::{ - constants::{BASE_PARITY_INDEX, VK_TREE_HEIGHT}, + constants::{BASE_PARITY_INDEX, PROOF_TYPE_HONK, VK_TREE_HEIGHT}, merkle_tree::membership::assert_check_membership, proof::{ recursive_proof::RecursiveProof, @@ -31,11 +31,12 @@ impl Empty for RootParityInput { impl Verifiable for RootParityInput { fn verify(self) { let inputs = ParityPublicInputs::serialize(self.public_inputs); - std::verify_proof( + std::verify_proof_with_type( self.verification_key.key, self.proof.fields, inputs, self.verification_key.hash, + PROOF_TYPE_HONK, ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr index b70561863b8..b2ab3e23789 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr @@ -1,6 +1,6 @@ use crate::parity_public_inputs::ParityPublicInputs; use dep::types::{ - constants::{ROOT_PARITY_INDEX, VK_TREE_HEIGHT}, + constants::{PROOF_TYPE_HONK, ROOT_PARITY_INDEX, VK_TREE_HEIGHT}, merkle_tree::membership::assert_check_membership, proof::{ recursive_proof::NestedRecursiveProof, @@ -31,11 +31,12 @@ impl Empty for RootRollupParityInput { impl Verifiable for RootRollupParityInput { fn verify(self) { let inputs = ParityPublicInputs::serialize(self.public_inputs); - std::verify_proof( + std::verify_proof_with_type( self.verification_key.key, self.proof.fields, inputs, self.verification_key.hash, + PROOF_TYPE_HONK, ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr index fa8a054d0e6..818f77cb6f3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr @@ -2,16 +2,16 @@ use dep::types::{ block_header::BlockHeader, KernelCircuitPublicInputs, proof::{ - recursive_proof::RecursiveProof, + rollup_recursive_proof::RecursiveProof, traits::Verifiable, - verification_key::{HonkVerificationKey, VerificationKey}, + verification_key::{RollupHonkVerificationKey, VerificationKey}, }, traits::Empty, }; pub struct EmptyNestedCircuitPublicInputs { proof: RecursiveProof, - vk: HonkVerificationKey, + vk: RollupHonkVerificationKey, } impl Verifiable for EmptyNestedCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr index 224c0d9258a..3a81f8e3923 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr @@ -1,11 +1,11 @@ use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; use dep::types::{ - constants::VK_TREE_HEIGHT, + constants::{PROOF_TYPE_ROLLUP_HONK, VK_TREE_HEIGHT}, merkle_tree::{membership::assert_check_membership, MembershipWitness}, proof::{ - recursive_proof::NestedRecursiveProof, + rollup_recursive_proof::NestedRecursiveProof, traits::Verifiable, - verification_key::{HonkVerificationKey, VerificationKey}, + verification_key::{RollupHonkVerificationKey, VerificationKey}, }, traits::Empty, utils::arrays::find_index_hint, @@ -14,7 +14,7 @@ use dep::types::{ pub struct PreviousRollupBlockData { pub block_root_or_block_merge_public_inputs: BlockRootOrBlockMergePublicInputs, pub proof: NestedRecursiveProof, - pub vk: HonkVerificationKey, + pub vk: RollupHonkVerificationKey, pub vk_witness: MembershipWitness, } @@ -23,7 +23,13 @@ impl Verifiable for PreviousRollupBlockData { let inputs = BlockRootOrBlockMergePublicInputs::serialize( self.block_root_or_block_merge_public_inputs, ); - std::verify_proof(self.vk.key, self.proof.fields, inputs, self.vk.hash); + std::verify_proof_with_type( + self.vk.key, + self.proof.fields, + inputs, + self.vk.hash, + PROOF_TYPE_ROLLUP_HONK, + ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index b4248fc2946..29601458b52 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -1,11 +1,11 @@ use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; use dep::types::{ - constants::VK_TREE_HEIGHT, + constants::{PROOF_TYPE_ROLLUP_HONK, VK_TREE_HEIGHT}, merkle_tree::{membership::assert_check_membership, MembershipWitness}, proof::{ - recursive_proof::NestedRecursiveProof, + rollup_recursive_proof::NestedRecursiveProof, traits::Verifiable, - verification_key::{HonkVerificationKey, VerificationKey}, + verification_key::{RollupHonkVerificationKey, VerificationKey}, }, traits::Empty, utils::arrays::find_index_hint, @@ -14,7 +14,7 @@ use dep::types::{ pub struct PreviousRollupData { pub base_or_merge_rollup_public_inputs: BaseOrMergeRollupPublicInputs, pub proof: NestedRecursiveProof, - pub vk: HonkVerificationKey, + pub vk: RollupHonkVerificationKey, pub vk_witness: MembershipWitness, } @@ -22,7 +22,13 @@ impl Verifiable for PreviousRollupData { fn verify(self) { let inputs = BaseOrMergeRollupPublicInputs::serialize(self.base_or_merge_rollup_public_inputs); - std::verify_proof(self.vk.key, self.proof.fields, inputs, self.vk.hash); + std::verify_proof_with_type( + self.vk.key, + self.proof.fields, + inputs, + self.vk.hash, + PROOF_TYPE_ROLLUP_HONK, + ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr index a6ae7338fbe..d753043a639 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr @@ -178,7 +178,7 @@ mod tests { let vk_tree: MerkleTree = comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = BLOCK_ROOT_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(BLOCK_ROOT_ROLLUP_INDEX); @@ -191,7 +191,7 @@ mod tests { let vk_tree: MerkleTree = comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = BLOCK_MERGE_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(BLOCK_MERGE_ROLLUP_INDEX); @@ -204,7 +204,7 @@ mod tests { let vk_tree: MerkleTree = comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(ROOT_PARITY_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index 72cb2d7bfbe..adf7abccbd2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -208,7 +208,7 @@ mod tests { comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = PRIVATE_BASE_ROLLUP_VK_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = @@ -225,7 +225,7 @@ mod tests { comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(MERGE_ROLLUP_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(MERGE_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = MERGE_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(MERGE_ROLLUP_INDEX); @@ -239,7 +239,7 @@ mod tests { let vk_tree: MerkleTree = comptime { fixtures::vk_tree::get_vk_merkle_tree() }; inputs.previous_rollup_data[0].vk = - fixtures::vk_tree::generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX); + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(ROOT_PARITY_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr index 714c410eef9..45a1cb067fc 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr @@ -17,8 +17,10 @@ pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { previous_rollup_data[0].block_root_or_block_merge_public_inputs.vk_tree_root = vk_tree_root; previous_rollup_data[1].block_root_or_block_merge_public_inputs.vk_tree_root = vk_tree_root; - previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); - previous_rollup_data[1].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); + previous_rollup_data[0].vk = + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(vk_index); + previous_rollup_data[1].vk = + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(vk_index); previous_rollup_data[0].vk_witness = MembershipWitness { leaf_index: vk_index as Field, sibling_path: vk_path }; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index 98eb969713e..932ea8d4122 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -21,8 +21,10 @@ pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.vk_tree_root = vk_tree_root; - previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); - previous_rollup_data[1].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); + previous_rollup_data[0].vk = + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(vk_index); + previous_rollup_data[1].vk = + fixtures::vk_tree::generate_fake_rollup_honk_vk_for_index(vk_index); previous_rollup_data[0].vk_witness = MembershipWitness { leaf_index: vk_index as Field, sibling_path: vk_path }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr index f2ceedee9bc..a7541275ae0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr @@ -2,24 +2,25 @@ use crate::{ abis::kernel_circuit_public_inputs::{ KernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, }, - constants::HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + constants::{PROOF_TYPE_ROLLUP_HONK, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS}, proof::{traits::Verifiable, tube_proof::TubeProof, vk_data::VkData}, }; pub struct PublicTubeData { pub public_inputs: PrivateToPublicKernelCircuitPublicInputs, pub proof: TubeProof, - pub vk_data: VkData, + pub vk_data: VkData, } impl Verifiable for PublicTubeData { fn verify(self) { let inputs = PrivateToPublicKernelCircuitPublicInputs::serialize(self.public_inputs); - std::verify_proof( + std::verify_proof_with_type( self.vk_data.vk.key, self.proof.fields, inputs, self.vk_data.vk.hash, + PROOF_TYPE_ROLLUP_HONK, ); } } @@ -27,17 +28,18 @@ impl Verifiable for PublicTubeData { pub struct PrivateTubeData { pub public_inputs: KernelCircuitPublicInputs, pub proof: TubeProof, - pub vk_data: VkData, + pub vk_data: VkData, } impl Verifiable for PrivateTubeData { fn verify(self) { let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); - std::verify_proof( + std::verify_proof_with_type( self.vk_data.vk.key, self.proof.fields, inputs, self.vk_data.vk.hash, + PROOF_TYPE_ROLLUP_HONK, ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 88d51b89f60..a8a6480fc23 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -324,6 +324,7 @@ pub global PRIVATE_CONTEXT_INPUTS_LENGTH: u32 = pub global FEE_RECIPIENT_LENGTH: u32 = 2; pub global AGGREGATION_OBJECT_LENGTH: u32 = 16; +pub global IPA_CLAIM_LENGTH: u32 = 10; pub global SCOPED_READ_REQUEST_LEN: u32 = READ_REQUEST_LENGTH + 1; pub global PUBLIC_DATA_READ_LENGTH: u32 = 3; @@ -461,10 +462,16 @@ pub global NUM_BASE_PARITY_PER_ROOT_PARITY: u32 = 4; // Lengths of the different types of proofs in fields pub global RECURSIVE_PROOF_LENGTH: u32 = 459; -pub global NESTED_RECURSIVE_PROOF_LENGTH: u32 = 459; -pub global TUBE_PROOF_LENGTH: u32 = RECURSIVE_PROOF_LENGTH; // in the future these can differ +pub global NESTED_RECURSIVE_PROOF_LENGTH: u32 = RECURSIVE_PROOF_LENGTH; +pub global IPA_PROOF_LENGTH: u32 = 65; +pub global RECURSIVE_ROLLUP_HONK_PROOF_LENGTH: u32 = + RECURSIVE_PROOF_LENGTH + IPA_CLAIM_LENGTH + IPA_PROOF_LENGTH; +pub global NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH: u32 = RECURSIVE_ROLLUP_HONK_PROOF_LENGTH; +pub global TUBE_PROOF_LENGTH: u32 = RECURSIVE_ROLLUP_HONK_PROOF_LENGTH; // in the future these can differ pub global HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 128; // size of an Ultra verification key +pub global ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = + HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS + IPA_CLAIM_LENGTH + 1; // size of an Ultra verification key pub global CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 143; // size of a Mega verification key // VK is composed of @@ -762,3 +769,5 @@ pub global PROOF_TYPE_HONK: u32 = 1; pub global PROOF_TYPE_OINK: u32 = 2; pub global PROOF_TYPE_PG: u32 = 3; pub global PROOF_TYPE_AVM: u32 = 4; +pub global PROOF_TYPE_ROLLUP_HONK: u32 = 5; +pub global PROOF_TYPE_ROOT_ROLLUP_HONK: u32 = 6; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr index dd8befa8834..ee669f00314 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/mod.nr @@ -1,5 +1,6 @@ pub mod avm_proof; pub mod recursive_proof; +pub mod rollup_recursive_proof; pub mod traits; pub mod tube_proof; pub mod verification_key; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/rollup_recursive_proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/rollup_recursive_proof.nr new file mode 100644 index 00000000000..9969022bb8d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/rollup_recursive_proof.nr @@ -0,0 +1,76 @@ +use crate::{ + constants::{NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_ROLLUP_HONK_PROOF_LENGTH}, + traits::{Deserialize, Empty, Serialize}, +}; + +pub struct RecursiveProof { + pub fields: [Field; RECURSIVE_ROLLUP_HONK_PROOF_LENGTH], +} + +impl Serialize for RecursiveProof { + fn serialize(self) -> [Field; RECURSIVE_ROLLUP_HONK_PROOF_LENGTH] { + self.fields + } +} + +impl Deserialize for RecursiveProof { + fn deserialize(fields: [Field; RECURSIVE_ROLLUP_HONK_PROOF_LENGTH]) -> Self { + RecursiveProof { fields } + } +} + +impl Empty for RecursiveProof { + fn empty() -> Self { + RecursiveProof { fields: [0; RECURSIVE_ROLLUP_HONK_PROOF_LENGTH] } + } +} + +pub struct NestedRecursiveProof { + pub fields: [Field; NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH], +} + +impl Serialize for NestedRecursiveProof { + fn serialize(self) -> [Field; NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH] { + self.fields + } +} + +impl Deserialize for NestedRecursiveProof { + fn deserialize(fields: [Field; NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH]) -> Self { + NestedRecursiveProof { fields } + } +} + +impl Empty for NestedRecursiveProof { + fn empty() -> Self { + NestedRecursiveProof { fields: [0; NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH] } + } +} + +impl Eq for RecursiveProof { + fn eq(self, other: Self) -> bool { + (self.fields == other.fields) + } +} + +impl Eq for NestedRecursiveProof { + fn eq(self, other: Self) -> bool { + (self.fields == other.fields) + } +} + +#[test] +fn serialization_of_empty_recursive() { + let item = RecursiveProof::empty(); + let serialized = item.serialize(); + let deserialized = RecursiveProof::deserialize(serialized); + assert(item.eq(deserialized)); +} + +#[test] +fn serialization_of_empty_nested() { + let item = NestedRecursiveProof::empty(); + let serialized = item.serialize(); + let deserialized = NestedRecursiveProof::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr index 46572b1e69b..bad539bd738 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr @@ -1,7 +1,7 @@ use crate::{ constants::{ AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, - HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, }, traits::{Deserialize, Empty, Serialize}, }; @@ -51,6 +51,7 @@ impl Eq for VerificationKey { } } +pub type RollupHonkVerificationKey = VerificationKey; pub type HonkVerificationKey = VerificationKey; pub type ClientIVCVerificationKey = VerificationKey; pub type AvmVerificationKey = VerificationKey; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr index db6d9d9d9b8..a4a0078d074 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr @@ -4,8 +4,8 @@ use crate::constants::{ HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, MERGE_ROLLUP_INDEX, PRIVATE_BASE_ROLLUP_VK_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - PUBLIC_BASE_ROLLUP_VK_INDEX, ROOT_PARITY_INDEX, ROOT_ROLLUP_INDEX, TUBE_VK_INDEX, - VK_TREE_HEIGHT, + PUBLIC_BASE_ROLLUP_VK_INDEX, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, ROOT_PARITY_INDEX, + ROOT_ROLLUP_INDEX, TUBE_VK_INDEX, VK_TREE_HEIGHT, }; use crate::hash::verification_key_hash; use crate::merkle_tree::merkle_tree::MerkleTree; @@ -26,6 +26,13 @@ pub fn generate_fake_honk_vk_for_index( VerificationKey { key, hash: verification_key_hash(key) } } +pub fn generate_fake_rollup_honk_vk_for_index( + index: u32, +) -> VerificationKey { + let key = generate_fake_vk_for_index(index); + VerificationKey { key, hash: verification_key_hash(key) } +} + pub fn generate_fake_client_ivc_vk_for_index( index: u32, ) -> VerificationKey { @@ -51,21 +58,22 @@ pub fn get_vk_merkle_tree() -> MerkleTree { leaves[EMPTY_NESTED_INDEX] = generate_fake_honk_vk_for_index(EMPTY_NESTED_INDEX).hash; leaves[PRIVATE_KERNEL_EMPTY_INDEX] = generate_fake_honk_vk_for_index(PRIVATE_KERNEL_EMPTY_INDEX).hash; - leaves[TUBE_VK_INDEX] = generate_fake_honk_vk_for_index(TUBE_VK_INDEX).hash; + leaves[TUBE_VK_INDEX] = generate_fake_rollup_honk_vk_for_index(TUBE_VK_INDEX).hash; leaves[AVM_VK_INDEX] = generate_fake_honk_vk_for_index(AVM_VK_INDEX).hash; leaves[PRIVATE_BASE_ROLLUP_VK_INDEX] = - generate_fake_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX).hash; + generate_fake_rollup_honk_vk_for_index(PRIVATE_BASE_ROLLUP_VK_INDEX).hash; leaves[PUBLIC_BASE_ROLLUP_VK_INDEX] = - generate_fake_honk_vk_for_index(PUBLIC_BASE_ROLLUP_VK_INDEX).hash; + generate_fake_rollup_honk_vk_for_index(PUBLIC_BASE_ROLLUP_VK_INDEX).hash; leaves[BASE_PARITY_INDEX] = generate_fake_honk_vk_for_index(BASE_PARITY_INDEX).hash; leaves[ROOT_PARITY_INDEX] = generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX).hash; - leaves[MERGE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(MERGE_ROLLUP_INDEX).hash; - leaves[BLOCK_ROOT_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX).hash; + leaves[MERGE_ROLLUP_INDEX] = generate_fake_rollup_honk_vk_for_index(MERGE_ROLLUP_INDEX).hash; + leaves[BLOCK_ROOT_ROLLUP_INDEX] = + generate_fake_rollup_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX).hash; leaves[BLOCK_MERGE_ROLLUP_INDEX] = - generate_fake_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX).hash; + generate_fake_rollup_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX).hash; leaves[ROOT_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(ROOT_ROLLUP_INDEX).hash; leaves[BLOCK_ROOT_ROLLUP_EMPTY_INDEX] = - generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_EMPTY_INDEX).hash; + generate_fake_rollup_honk_vk_for_index(BLOCK_ROOT_ROLLUP_EMPTY_INDEX).hash; MerkleTree::new(leaves) } diff --git a/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh index 4e38ee52e3c..459e799cc2a 100755 --- a/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh +++ b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh @@ -124,6 +124,7 @@ DEST="$SCRIPT_DIR/../dest" mkdir -p $DEST MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' "$SCRIPT_DIR/../../client_ivc_circuits.json") +ROLLUP_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' "$SCRIPT_DIR/../../rollup_honk_circuits.json") # Process each CIRCUIT_NAME. for CIRCUIT_NAME in "${CIRCUIT_NAMES[@]}"; do @@ -148,11 +149,21 @@ for CIRCUIT_NAME in "${CIRCUIT_NAMES[@]}"; do fi done + IS_ROLLUP_HONK_CIRCUIT="false" + for pattern in $ROLLUP_HONK_CIRCUIT_PATTERNS; do + if echo "$ARTIFACT_FILE_NAME" | grep -qE "$pattern"; then + IS_ROLLUP_HONK_CIRCUIT="true" + break + fi + done + # Generate the flamegraph. if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then - $PROFILER gates --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --output-filename "$CIRCUIT_NAME" --backend-gates-command "gates_for_ivc" -- -h + $PROFILER gates --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --output-filename "$CIRCUIT_NAME" --backend-gates-command "gates_for_ivc" -- -h 0 + elif [ "$IS_ROLLUP_HONK_CIRCUIT" = "true" ]; then + $PROFILER gates --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --output-filename "$CIRCUIT_NAME" -- -h 2 else - $PROFILER gates --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --output-filename "$CIRCUIT_NAME" -- -h + $PROFILER gates --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --output-filename "$CIRCUIT_NAME" -- -h 1 fi echo "Flamegraph generated for circuit: $CIRCUIT_NAME" diff --git a/noir-projects/rollup_honk_circuits.json b/noir-projects/rollup_honk_circuits.json new file mode 100644 index 00000000000..43e5bdb3463 --- /dev/null +++ b/noir-projects/rollup_honk_circuits.json @@ -0,0 +1,7 @@ +[ + "empty_nested.*", + "private_kernel_empty.*", + "rollup_base.*", + "rollup_block.*", + "rollup_merge" +] \ No newline at end of file diff --git a/noir-projects/scripts/generate_vk_json.js b/noir-projects/scripts/generate_vk_json.js index 3bbe390ff9d..3b390581163 100644 --- a/noir-projects/scripts/generate_vk_json.js +++ b/noir-projects/scripts/generate_vk_json.js @@ -4,6 +4,14 @@ 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, @@ -32,13 +40,13 @@ async function getBytecodeHash(artifactPath) { return crypto.createHash("md5").update(bytecode).digest("hex"); } -async function getArtifactHash(artifactPath, isClientIvc, isRecursive) { +async function getArtifactHash(artifactPath, circuitType, isRecursive) { const bytecodeHash = await getBytecodeHash(artifactPath); const barretenbergHash = await getBarretenbergHash(); return generateArtifactHash( barretenbergHash, bytecodeHash, - isClientIvc, + circuitType, isRecursive ); } @@ -61,19 +69,29 @@ async function hasArtifactHashChanged(artifactHash, vkDataPath) { return true; } -function isClientIvcCircuit(artifactName) { - return clientIvcPatterns.some((pattern) => - artifactName.match(new RegExp(pattern)) - ); +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 isClientIvc = isClientIvcCircuit(artifactName); + const circuitType = typeOfCircuit(artifactName); const isRecursive = true; const artifactHash = await getArtifactHash( artifactPath, - isClientIvc, + circuitType, isRecursive ); @@ -92,7 +110,7 @@ async function processArtifact(artifactPath, artifactName, outputFolder) { outputFolder, artifactPath, artifactHash, - isClientIvc, + circuitType, isRecursive ); await writeVKToS3(artifactName, artifactHash, JSON.stringify(vkData)); @@ -108,13 +126,15 @@ async function generateVKData( outputFolder, artifactPath, artifactHash, - isClientIvc, + circuitType, isRecursive ) { - if (isClientIvc) { + 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 vk for", artifactName); + console.log("Generating new honk vk for", artifactName); } const binaryVkPath = vkBinaryFileNameForArtifactName( @@ -123,20 +143,29 @@ async function generateVKData( ); const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - function getVkCommand() { - if (isClientIvc) return "write_vk_for_ivc"; - return "write_vk_ultra_honk"; + if (circuitType == CircuitType.ClientIVCCircuit) { + write_vk_flow = "write_vk_for_ivc"; + 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_ultra_honk"; + vk_as_fields_flow = "vk_as_fields_ultra_honk"; + honk_recursion = 1; } - const writeVkCommand = `${BB_BIN_PATH} ${getVkCommand()} -h -b "${artifactPath}" -o "${binaryVkPath}" ${ + const writeVkCommand = `${BB_BIN_PATH} ${write_vk_flow} -h ${honk_recursion} -b "${artifactPath}" -o "${binaryVkPath}" ${ isRecursive ? "--recursive" : "" }`; console.log("WRITE VK CMD: ", writeVkCommand); - const vkAsFieldsCommand = `${BB_BIN_PATH} ${ - isClientIvc ? "vk_as_fields_mega_honk" : "vk_as_fields_ultra_honk" - } -k "${binaryVkPath}" -o "${jsonVkPath}"`; + 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) => { diff --git a/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Nargo.toml new file mode 100644 index 00000000000..6a391f9fa87 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "verify_rollup_honk_proof" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Prover.toml new file mode 100644 index 00000000000..4c4591c2f4d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +proof = ["0x0000000000000000000000000000000000000000000000000000000000001000", "0x000000000000000000000000000000000000000000000000000000000000001b", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x00000000000000000000000000000000000000000000000198351784bcb51220", "0x0000000000000000000000000000000000000000000000010d0f8f1f7113655e", "0x000000000000000000000000000000000000000000000004112bf58ccdc9d1a6", "0x0000000000000000000000000000000000000000000000000002a60f71be5fae", "0x00000000000000000000000000000000000000000000000c277ca8f3f566b58e", "0x00000000000000000000000000000000000000000000000eb132e7fdc58ac690", "0x000000000000000000000000000000000000000000000009f620b17904c216fc", "0x0000000000000000000000000000000000000000000000000000418193e46832", "0x16cf7cc6f21f642a8118cfa0dc61f2537a91ecacc5f3668eabd665cc680e03fb", "0x18158b8584791bfbe5ee10a85fdd34c00d56a8a5d88129ffe078746088491b46", "0x000000000000000000000000000000f31a9f28cd3a9e1f6075aaf9ec8727208c", "0x00000000000000000000000000000000001233f898e5172cd4bc911b998709fe", "0x000000000000000000000000000000ca718983bbd788cb6bb027395398bb2eb4", "0x000000000000000000000000000000000005b1206cd018c3ccdef2d56d001872", "0x00000000000000000000000000000078e6f7d3378f422821fb4d4c068b216657", "0x000000000000000000000000000000000003b440ded66529bee75ef104f807dc", "0x000000000000000000000000000000803d9477bd05cdc528ae79ac9ac3063b59", "0x00000000000000000000000000000000001fbc07b498117324c534a1959454de", "0x000000000000000000000000000000186d9a95a47ff0ad2b0140d0d4617c19a2", "0x00000000000000000000000000000000001ae8fbb60548a48b872fc55c81ae2a", "0x0000000000000000000000000000003b01e2f9a4875516f4efaa4e8927193d77", "0x00000000000000000000000000000000001e49d5f5e233972d0ce5bd6affcbd2", "0x0000000000000000000000000000002a171861b26b214d20a7cb4d428a270b19", "0x000000000000000000000000000000000006d220e2a01128ecd1358cfd02bb10", "0x000000000000000000000000000000e45bf2a5a87cf3f64798f8279a77be8f0b", "0x00000000000000000000000000000000001fc24780eee3fa3aedc08349ec0a49", "0x0000000000000000000000000000002a171861b26b214d20a7cb4d428a270b19", "0x000000000000000000000000000000000006d220e2a01128ecd1358cfd02bb10", "0x000000000000000000000000000000e45bf2a5a87cf3f64798f8279a77be8f0b", "0x00000000000000000000000000000000001fc24780eee3fa3aedc08349ec0a49", "0x0000000000000000000000000000001d37b931273e72178e88ce50335e2dc83e", "0x00000000000000000000000000000000000511d63534ad2ccafc77415b1a29b0", "0x000000000000000000000000000000e7d019c73ebbc6451c01ac52f156ecf865", "0x0000000000000000000000000000000000268c3d97d581e919b815696da25cc3", "0x0000000000000000000000000000000d9599859b3bdcdb478812ee25d2f0eeee", "0x000000000000000000000000000000000026c9e7abbb73875fddb1ac55cdf1e2", "0x00000000000000000000000000000033c989fdb71acf8d4184c7a0d321e08d73", "0x00000000000000000000000000000000001c175d26699767e4c519b04251b5ee", "0x0000000000000000000000000000000f92946b5ba26bb09b66d65834d2f4cf5b", "0x000000000000000000000000000000000012b63a80baf4d982c5122a471bc42a", "0x0000000000000000000000000000006fa3c86e91550801f284938bfa104ca096", "0x00000000000000000000000000000000002c51726c2563a7b5d9dc69ea0263fc", "0x306287f56c48effd2f9699a46db9267c91263b6de06d7b7be9cfa4662dab37dd", "0x0001c67d74e8b02c88b9ac1213c831e0970dacda994bf5155a12512dc254c824", "0x1925a443b3d49b3a0d80d8ca41c6f32687b5dfaaa8f21a65517bc5db6bd1e47b", "0x251a4faf274456bbe0c7f69fa8f67e5a1c079622d6233f636500dfbcf9b621cb", "0x0e6a61c9e1bafd7067d9830443de3c05afc3dd79f45a195de5a90732a0868f45", "0x0a7245508b1615f792270dba05f387ada642988a9584ffb4030c4a90c7efcf12", "0x15863f2959c9d468cf756679c24ad8d8aeca54121684681e546e5e40a0b6ceb0", "0x0404eef3cb7467c0065e2ed7525a88d3d9b8d62fe0c441ed5fc2439722641f02", "0x08f4ec100b001fba3c773208d57cc0b6416ca1341e02129e717d93fc2e3e40c2", "0x0a49765410098eb75f5e725f163dbfa492e91b739f0cbcd6ac8a84898d0c4b55", "0x191eec3f8f395fb4c4fea8cd5e726d5a01b8f7de6d73b92af658a9826982effa", "0x27dadf71f0d9b4b09eb744718d20bed1185bf6fe9074c0e38a3574a9fef10468", "0x000daf66f8c35c1d3b887a3f974bde18e804ac7768fea8257518ae1303d441d8", "0x1622a82d0d30d00a9a5df5e5448ce64e575385413872f601a5d3f507eb07004a", "0x2d6191ae1a2657e766345dd4e60c43db5043bbda7b159b768dffa0371055901a", "0x2544bbdd4ce4b098eb4feddcaa7aa95a69f418f205d3e6716cf20d6d607b31fc", "0x27539990c10c0e5d05e07efa3c268354576cb00e2e50d27ae72204baa46a04f2", "0x1bf39a47211a4b4224dc726a437ea853097dfc7ada0f3e2d4e3f4d3a7edd1bc4", "0x15759bd32285dc0c51e46a0eeea80f755bfa77e18a65c62e241a2c7fbb8370b8", "0x2616a41128e14a226c459a93a19b13de581caa4f75c6368dbf7257a323fc84b9", "0x1bc5b5a9238571c7efeb9e992e4b410e2affdf015518126bc6b23ca2986d02c6", "0x08a03b8831139f22a329f22ab8a87eed1c9313db7d993718c6b1c0735e66a719", "0x2e3e957d6c4b250f0cdbdd00ada94bb53dc70104196176e9abe473647aa86a09", "0x1b6c77870100cd99fa8a85db4bdcab5da5c3505704cfbb2bda11463d25b6eea6", "0x00e1e81ba9dfbd1b7cd9192d5f0218c2eff9bf6f4dd859e07bdb163633ebf310", "0x2e7d519ecb078293b55adc1f9078e01f375a97dc2374725c9b178bb1df019aea", "0x0af9c92343c56476189c42b4c578a170c85111555b3fddaa74666a0f7f860ec1", "0x213b21f0891215c865fa84e0c1744765e3c0a36b5062c39e46b95704f478f746", "0x22f71989fdc01723d4e1cc854cbd9b482af30ad642f3a5dad765e016264bfd95", "0x0de2e531eab5853f2d7759b3e258fc0d5860d10678331b00d2612c4f794538e9", "0x26d4d98c23dccd50cb40b89ea899fcc23cd06e141582932d0acf1915c85a1c6c", "0x27094a91f28e55036e178acd6adeec53adb0a4b93e8365a57f237ca9d2e94405", "0x019662c5cbf555a9b96b65742647426a33c97b595e8516c433e742b49e22cabb", "0x2d32a500f4e75b3377432fb7febb00bf1fa6306a621f8801306ab293b12b370a", "0x2984ccbc3fa69b375e758005d2e668619e71c84e007fc9361305d17c046c18b6", "0x15a8c7880db4f1e48ba2f406d514eaa76df3c8e3db2964808f38e59ab63268e0", "0x014f53ec2db52091b3a6a2d445e4bd93ac9f5ed122ba701c5682c26c1f5bc4cb", "0x1cd8668cba6d841aaad54684e3613db68dfd0a57258f5e6d7207ca5aa91f8f7c", "0x2c198f396bd3785539b5d9b8ec33da835fae84caac528b587dbfa5d380378d28", "0x1912c183ff1b57a17d1cf630346d4547566384ab3ca09602bf98d83ead40ef52", "0x23b691d4c3445720248facd6dc688d2afa13277ed408405e833a053b7543bea3", "0x275b0dfd8d39f50c6d672e02e10a775102c54674ae0eeda61acca7bd339fe3d7", "0x1ec7eaa32c32988df48890320c31e49a6d8e1db47fe19aa936433045a6b20d3e", "0x07be4532de3a24a63bee613d6b42cbd294bcf8b0fa401d9bf838f7c5a6fd7a11", "0x030d7505ece9e71c5e2fc1717cdf463c41f2be0e368bb39e8d9337652e4848c9", "0x13759dca280cbe036507810ef0baf9d02389ce0772200ceba30957c4280504fb", "0x155b5775cf065eca5d4791b76503cf6864b1f089e09658f8d73bce95aad8b63d", "0x03408af42e89123440902eee1b218ac54893a05c499e544ab152f2dc4d2a7406", "0x0f095b86ec10064e8538959a22d69f1842d0cb92a8bfc9f63e9af82d9f518aa8", "0x2ecff3efe9ca5247b99ee0ff636cb7c667ca0752ca3bd7e019750c6a0824c05e", "0x15a1eb4c9f778792e854b14a65f461491346eb3b5afbc0f47a04f37df950c0c7", "0x1c45fe9bd5a8a577e734667d5d2f75aaf042288faadd45840c15fda952d683e6", "0x0b1916e811028364d7ab4726ce9ee4158df2f3d7ec6b6de78b5dc5eb0ca33271", "0x26198efbc197e8b8995c6663dc22091aa79a66b43551576aed3bfac59a9a633c", "0x1c600b24660c474a5e7d065773c8bf46861b86bfd35263b7dedb6844cee0c2e0", "0x0f70705ffbc0c80c20feffa4040d88bda32bce28c68cae7f09f1298fa4e918b3", "0x26a5e8599e18ca537978b64c6e36d14aaaf77b1e73969ecc89d74f72c5141a91", "0x0d6d63868e3e7095a8c26da8ecd37e232f9fc59096db96f17ed3934ecba34478", "0x2193d7b12212843e643dbbdcf3cedb55fa67bac5e65a2ce8583ea507c04cce6c", "0x2141f72eb19fa0b2490400bf9b436c73f14c60e77a16138ae4b0d39629f8ed7b", "0x2e25c471d729c4742747fe52fbaf000d3b958480ea93141abbc6bb389ad854c7", "0x0b2299402112e0205f74bb313786994ca83c7bd204cca59e6dfa3b147c21203b", "0x159c2236da8acc75769bb8138dce9c6ea319651e9abed3c12ddd8f554e292486", "0x03b25006c2280965d306ba2a24c81a09d72d2b0c5f7f214221c76f6501efc911", "0x241850ae454b281ca5be4b064855da6481ce150485770e9b273de8a29a64fbd4", "0x2d1b2592def2035dacc6a50dd657994d98b669c13c8c4fa7a5de32bb1ff2afee", "0x18d3529fbe8fb1864ea8f336dc7c3088c229cfa3221d97b86b7399e3580f25be", "0x0cbc1780a299eed3dec9a3fc932606e76a56a9e6007e4818eefb3acc0c97eff1", "0x2b7951293695c48e3a040fd16efd03e6d2805a2e7d14863b12d44e2f0be6e548", "0x2e7279731396111d824de2d6fd4daf6bde38241f466774c888cab684af0310c9", "0x02787750cc8668538916ed23c77ef9f29a69904a5160910786c5e150c842fc7d", "0x0eecf3012294c565cea1737dcdaa677702e519c37394587bfb67f648712da35d", "0x04390e489dd2324235647de594b8fa12b9265f02a085e7ef528b0cde68b0c785", "0x12c1b72615ed431b56834d7427e04977c1ef53a7a8e5c8bb709f6930faa43ac9", "0x0ff305bdb025415d21cf771039088b787ea6b4f673fb88baf0bac451fd1e4b92", "0x045142ff5fe9c320cad25dc9a3cafa4668636c80228abecb46eb54c820eb2e5e", "0x2a0d0e0bcbaf05661431062ae2d2bd21fae75caa81fe7731051b64e6fbbce173", "0x23c761d849f4fabddd42918bdb9acd36381667f3ea3610c7a1599ba6096ca70d", "0x24091599cb2e211ed9d108b9197a3827507232941dc23113dbcee7e3459ccbd9", "0x0302343a788ded8936bb590a8eefd4aec4d704c2c6c24d70a60e4870c75196a1", "0x291b653f0b3b851572d7c0db159f88659326d61d1bd265bb08556e0e2156b753", "0x2e6683095e6a8ecff419b9c1bda2fca70f2686d7458230fcdb0b061469f91dea", "0x0856b8f721b54e425fe9aa589ba710f2845e72fc351793738df49c40967d716f", "0x12ae3e5184a7fed794ac452f94d51221ba134cf35f35179b66349bc4f426f33f", "0x23c35f99e0892be80095db2623042be2742c2b138b1df1efe03bd899dd35937d", "0x036bd6bd2b5b631e928f002e91ca13c55c24ad1b915839582709d0aabb1a3082", "0x1fb1cfc6f64e0b2e0a1d9bafc1702a468197f4a2fe41b233e04203dd699131fb", "0x1cfa0be2485c7cc8baee2f61c8059b887b581e4eab15c23941d226e3c2c849e1", "0x1fb8e18786782eb1842c6f1f4eb4cf22e1b8c5f310a6346db75735387f80013d", "0x20921175a4d50b6f672caffce2f12040e6e3bc792c4f38cb51b477fa19f12364", "0x15b7206684270facba2d70bf47ffa4f7d449f65cff70f8021b6a06598d60f4ea", "0x06932a178b45439cdc4e2c0313aaa31c29f561dea1e200d2347e82e1dcb2985d", "0x1486c1622fec7d6e0f7f08b4185daa992d0515e1e7ff782944cda22ff0df6065", "0x15ef8cf4627592aabc6efc812e210d4dfc4da02e41e53320b61364bd21deceed", "0x0a7974b21e7412c8ebe6c76217e74810a2b81eeda730a263ac64fb3bba2ec025", "0x046f771fc1399865a01e60419d2c969279fe1675aa0eeeb6a439e23a46813c89", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x166c19d70d8289a27c0eb973c525449ff7c70f23b32c38664848d4e4f14c955e", "0x22a2a920418bc6b0e16bd4b1696403b50d767a2339f788c62d3501dfd6d49554", "0x1c98c74062a05e52635b8cd160f7a76ec9045086de6fd29a2fdb2d51263bcc79", "0x1a3fc6e17e3a842c75bec9c41eeeb86751d10593ac2f69e6613c6608ce1e81f5", "0x21b27032c51038cf5487c60cf185d961fdec079677d267de3584d0b10c725240", "0x2de258ec1715ebc899390c9b05df9d65bd4757b569e5089afe6fc5c82c644b6b", "0x17061178ce0a7677558f33c2d6e4df02abb874f0ce7c22ad6a4a970161e0067f", "0x0169fa33066295974bb138801aacb5394816f5e05f242777d01b61b26e9eb2a7", "0x083eb97ea0e9791b11e64d920061cdff4622e9667a1760a80daa0dccfcafa042", "0x14b2070214354b2a8d7bd85efd042b2694677e41f5eb086f661df62be9d2409b", "0x2ea8ff97b1f59d4140c261964679111a963887587083e2443fa501f5e04245a1", "0x0ea3f4b3a74a29e3b5915426dff09eecf626ccd235f440a0adb67dbee38b8a18", "0x0898eaf4c2a5b4fd444e4f6260ad50e8df5ee1122cfb24c92dc606e4c617e076", "0x2e999b837edd61563dd94622763ba78468dab492c60829b55ad0b7095657826b", "0x180b65b148ae698c1018f24bfb49d4a700f67c47743e00efd34664e55ef632bc", "0x1eb2e1145982710a3ec233db72a0e4503883915b5e40ca5176b690af47c9ad87", "0x0c02c12a4089148c7a6e04277d9fea54915a88bc9f8d82cf4d58678a134e0124", "0x1715e74ad1c0bb740556e1e0227ce90e02310f5b033d5432559413a654f66fc2", "0x2de1d99911bcca2220e64331bc24481772f6ce35eebb082d63b3eab29a9b757b", "0x29327816bcf7c5c7ab28e339320f894dde297645c27d0aa0cee46a5c40471d0b", "0x07de8fabb98b1082d45824659e4b0ea62df3b7b76f26edfd9d67105a04ad75f8", "0x2e5bea4efb41fc22121db6fe400d91132968c5d898c14a0568610578fb7d9d57", "0x2f12a17b5d6bc006672bf388fd786fe2a0b3a15c380147fa4b7bd2b695c8101f", "0x26f724ff2a50863698db3dcfff0886edd8983d0c79fb5c1e5f591c5da66b302e", "0x1d1c4729b0d36cbcd59d69128fe6107a5d2280cd4ac31cfabad0262b51f00fe3", "0x14b18cd70319121bbc9cad9171e55d538864f9101cdd171e44b4058519cef3f9", "0x079a0b9d12cdf0cfb34a3708a4850a998cbd9b5ec62ce3f1103adac2fdd8a820", "0x12304d32e34962cf30b9955972c350e359d6bf62d0de9c98c72d9f0ab51131bd", "0x1b6ff02390ab39e40e65e045040f6e777ebfdea61902709dff743594eaf89509", "0x0e6e12ee6f19e11a543e63c4402419d0f07b424aec46eb4b909e090e57a6e6ea", "0x0e586c602754d885e91f077f9f219c1935a25c1ff5656fe5b445bff7efbef1a0", "0x116eb62fe75014d073f3526bbd97269f41064cdec2fefaab38a0acb333dd01bd", "0x1282bd7d7cbf0b806f729e331c1a7ac0c2598e2d75d1d2e0d62f3177df456b65", "0x0a85412e6b0eec538dd5038b532fb9e8e78476f1c4c677ba4e1ab310bbe40881", "0x0a85412e6b0eec538dd5038b532fb9e8e78476f1c4c677ba4e1ab310bbe40881", "0x2ffadaf1e9bf16dacff62d3ffb2d0f531da05737784be3a2d8eb61cafeed5560", "0x2002a5977ca93eb87d175fe3becb116997eac4993bbb73ec86d9326e1870bf2d", "0x1b418c821f6658d3c049194500604a449a1f7dc0d4aba87ad2bf554beefcfca5", "0x26407c0e8e64c2d127867b79cd0eef3edd6331ff3ed73d690eb748d94e08a9da", "0x2d4d4d75b30f50f2c562a046416637321909ec5bbc8c42eeb821b9326f89082a", "0x0000000000000000000000000000004f3b54655d2514081bf5b44620a2321680", "0x0000000000000000000000000000000000115472529ac9d0d7f94b6e15c6577b", "0x0000000000000000000000000000008ab9aa27023aa3fc58f408ab70b61a95b4", "0x00000000000000000000000000000000001118c892f3db5267f7d6d914edc04b", "0x0000000000000000000000000000001e8e1a870c828d9f8dddb0bdd8717a1150", "0x00000000000000000000000000000000001543c08c73ce441069251bee8a7ccf", "0x0000000000000000000000000000008215f11fa2188558ff721f8375825fb83c", "0x00000000000000000000000000000000000e31ae1d3a8332ed8cd38a8b209732", "0x000000000000000000000000000000d3ec44f7b83edc73d68c8892508d1592bd", "0x000000000000000000000000000000000006c1040c255d7b7688c31b4510f23b", "0x000000000000000000000000000000ec0d8427da7f35dedc93a42151b733feda", "0x0000000000000000000000000000000000296be1164397e24a3a95191d8f6acc", "0x0000000000000000000000000000006ef8210a3d90676f69caa1fe5d8353c226", "0x000000000000000000000000000000000024da7d17ed96fd2936e4bf381c460b", "0x000000000000000000000000000000d77f23fcadf7a6c19b7abef79268be9d30", "0x000000000000000000000000000000000007633ab01f5031fce5f16dba2b8e85", "0x0000000000000000000000000000005373fa1bb2baf156400ff4e60e6d9e84a3", "0x0000000000000000000000000000000000027e546ad562d24dae1063cbdbc5b4", "0x000000000000000000000000000000215aace588221c522bbc3d37eeb6f5273a", "0x0000000000000000000000000000000000063836cba05de3aa7813f54ed551b0", "0x000000000000000000000000000000050ae581123a9f65c92e35fd8fa9701dbc", "0x00000000000000000000000000000000002410871be237d666ed18fbaa0d4b53", "0x000000000000000000000000000000cd56ffd0cd263e30b90a521fd5b596fafe", "0x000000000000000000000000000000000002c79b34816830ec1e23bb1c131378", "0x000000000000000000000000000000150243fc42bde77914c155525f502b52cc", "0x000000000000000000000000000000000018bb64e2202e775ba805ed061abbdd", "0x000000000000000000000000000000d6b80a8a854fca134bb93030711f047275", "0x00000000000000000000000000000000000a87725eff75afc2d27f36b70ce951", "0x0000000000000000000000000000008af1e797628750941961d1ef9244b50f60", "0x000000000000000000000000000000000028b2290830a86f3bcd9db3a086251a", "0x00000000000000000000000000000007c3e0411ed5f2f276d2a658a9771a18a2", "0x00000000000000000000000000000000000974acd5f5847e300968d89b5a9ca9", "0x000000000000000000000000000000cb629eb69673c03619a88d48ca9ae68970", "0x00000000000000000000000000000000001d114437273293fd65b36e8321e274", "0x000000000000000000000000000000ecb2df851d702c95bd599346fb56d68e3e", "0x00000000000000000000000000000000002653d2cd543961e9e83a93387e9b96", "0x000000000000000000000000000000ead451fa7ba7e312c96a74107c27ad9736", "0x000000000000000000000000000000000011b952a737bcee1489197a273fb677", "0x0000000000000000000000000000006829212925ff54efee074c43911a3bca56", "0x00000000000000000000000000000000001fcd76b6a7065773fff04246a0dde7", "0x0000000000000000000000000000009585201bb8a8aaca49f72e3ef81fd0182b", "0x00000000000000000000000000000000002e3e3c6039ddf04d350f64019bb10e", "0x000000000000000000000000000000e4b332d5cc93d838948795e32bce4f9048", "0x00000000000000000000000000000000000bbbc875dc13137229856beeaa8f3e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x22206fcc5c3b0898156852484d5f37f85d35d8b8aeb565697dd199d09e7a5cec", "0x19d3624ed1ab8eb7cb2c0c611f105cac54fd99cb83d3e1a3118aaded389a1962", "0x195139b81a6b92e865e582abbd4bfffb20a58dabe86663c2970374b4c332a08b", "0x217c7b444d49a26539a8f4fa6986dfd99e6c54123b3176a328f982d53c93f780", "0x2aea9a445c7855ada0acd0217ae4ae246ce32e7d3184876be8facd5d6ad7cf21", "0x229635ed1530b6d4c1bcaab18683ee77de072256ff66e89ce73f0871e8629b6f", "0x0d2e7c3d34ec80dbf267d86a682f348de3efef15097b4800c0a3920b5ac828bf", "0x25bf71d3459cb3b36e082388eb0bcbed1c47aac10167983a8d746a9ae4eced96", "0x1ccaaea883ccd7ac517f8d79afcddb652e0ef1895649b1f3468390a80731e1b7", "0x0be5724df9d80b16038ec9bbea91bab1dd7b4c87653a86a9e9ad386406659a1f", "0x2b78eea73d09a89dc9d114e9b3f26af9ddebb6dd36abd2efbc39abfe905d1aa1", "0x17edf16afacd239c408db23dce3db2ca0bfc154217a345cbadc130994fe53ed1", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000807a729ac756815393e47d04c6246b8348", "0x000000000000000000000000000000000019f305937c8c47b7dacf5fab1aa8b4", "0x000000000000000000000000000000c0ed4e98aa74ce610873cabc4b95a00134", "0x00000000000000000000000000000000000d516bc6b3a02be3f087b76c12be88", "0x000000000000000000000000000000e45af0c8ba661e75785fd2471326778e10", "0x00000000000000000000000000000000001589091efbdf11f8afa9c2d54dad86", "0x000000000000000000000000000000ffe3819b65cb309abdc6119ee873a7046a", "0x00000000000000000000000000000000000f2d67fc9070b0b7363747463c12a6", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x1259539942eec51d5c53a19e6a6509d0bb10652a0ae852c7a4d48691a07c2d04", "0x21327da46c2c2f5183a7bb7a555d692582cb43319d028003ae3314427b2e2cee", "0x11ae288d0ebed5c93eb043e8e9e0a5a8da2e73c9564c013f6f77e2c75d9b6afb", "0x149ea3efa38041e1c2a490c28743de7ef70ed1ceac3290a147dbdb7427a1e5f7", "0x0ff8f2dcfa13ab248c35e38b827eb564140acca19094bd3f6b43480c24b1179b", "0x1d362e1726dce5a89a0b1028b5ae19c553cc33de9ad99ffb4a6f4df311a4c861", "0x03d28762bf78921834d18558fc20481a6921d4a863426a993d36ba0d9147bb58", "0x2fc693fe8b1c2bf894dc0ea77917c0e114b69ae0fe5e4aec86d813f485c9cfe1", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c", "0x025f07864b94d3ac018dc7e250aa8cd4cf266e8a258bc88bfd0f06eb19638b9f", "0x2f16d6396da879ee6c9d00000ceb26718cb7f696535e7700c57a49ead54acb67", "0x000000000000000000000000000000e7d4d22c7924866dbd40a7d07c78f3d221", "0x000000000000000000000000000000000011d8a95d17e954a17361390291aa74"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000001000", "0x000000000000000000000000000000000000000000000000000000000000001b", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000012", "0x0000000000000000000000000000000000000000000000000000000000000013", "0x0000000000000000000000000000000000000000000000000000000000000014", "0x0000000000000000000000000000000000000000000000000000000000000015", "0x0000000000000000000000000000000000000000000000000000000000000016", "0x0000000000000000000000000000000000000000000000000000000000000017", "0x0000000000000000000000000000000000000000000000000000000000000018", "0x0000000000000000000000000000000000000000000000000000000000000019", "0x000000000000000000000000000000000000000000000000000000000000001a", "0x0000000000000000000000000000001f218b9483ed0942db15a28f417b248c6a", "0x0000000000000000000000000000000000120f46fb150fa5544f70413659ac49", "0x000000000000000000000000000000054bf69002abed9f9354db858292ee051b", "0x000000000000000000000000000000000003bd06a2c7606596f9eebda30dc708", "0x0000000000000000000000000000006c892b6234def66f6577959d064de4f749", "0x0000000000000000000000000000000000275343f0c8be74b6adaaf08488d71d", "0x000000000000000000000000000000826318e94744b1f7ff6776deffacebe17b", "0x00000000000000000000000000000000000f57fa00c8a7dafecb9ebaa52c523e", "0x000000000000000000000000000000032d7ef2b49315f1f09e67af355aebe815", "0x00000000000000000000000000000000000058cf4aba931d69238a327636e771", "0x00000000000000000000000000000091a26171db51087d9773ee271fe440fe4e", "0x0000000000000000000000000000000000014772ce2168f21ce8e217ac82596e", "0x000000000000000000000000000000d8197c7f95b3d7b116cb23b2be067742eb", "0x00000000000000000000000000000000001fb1a5cc1a1c33fa4699ade4a992f4", "0x000000000000000000000000000000ea89f3283423819ba34d92f1af1b60cf2a", "0x0000000000000000000000000000000000054f8cf376bda1948450747ce44405", "0x000000000000000000000000000000ac09001ff01875c762a7d467f333c9f0fa", "0x0000000000000000000000000000000000159abc799405ce9b72e9b8f0a58907", "0x000000000000000000000000000000870a9353bab217f6617fcea8b66efe55f5", "0x000000000000000000000000000000000016a23b3c4e2a9a54a68d8e187b4acd", "0x0000000000000000000000000000004e42c7133c8b802e7073cbdc76a95f54bc", "0x0000000000000000000000000000000000116d2ee2d6d93084d2f5576a9eff91", "0x0000000000000000000000000000000a9c29dd5c7e6b6bed485755ab7867129f", "0x0000000000000000000000000000000000182bf61f320d66dc49746f3f767b8a", "0x000000000000000000000000000000d9ad8b5943ead2741efdeb311b8305c9db", "0x000000000000000000000000000000000025043141e7a515687c6d80d0853b76", "0x0000000000000000000000000000003447e05ab4400999c9704862944ef03bb3", "0x00000000000000000000000000000000000d8d5f85133d06d56249c6463ac023", "0x000000000000000000000000000000a81a33be27f85f6030c2d794fc5ea7a0ec", "0x000000000000000000000000000000000025580b84ad2a823052effa19d61d88", "0x000000000000000000000000000000d398efe5afb73ff0ff0d5b4d919ebfeae4", "0x00000000000000000000000000000000000ce6de4173c77b111df4ae25bcf751", "0x000000000000000000000000000000d693725e4d29c3c1856f58d3657e4f8afd", "0x000000000000000000000000000000000000e860bbb23a26836fab3733b1a5d2", "0x00000000000000000000000000000004d908124a014f6dd4217600bbe017179a", "0x0000000000000000000000000000000000009639107ef0d7660211c3cb26fd83", "0x0000000000000000000000000000002c120d25144b16975f344bb8e0911f50aa", "0x0000000000000000000000000000000000025c989a5fbbc39a745dfa0c526d1b", "0x00000000000000000000000000000029c1683a4f2321682c17677f325c27de6a", "0x000000000000000000000000000000000017dcb48f840e14a56297e5e157ab5d", "0x0000000000000000000000000000006f8e97f2719363e73a919b60136cdf6fa7", "0x00000000000000000000000000000000001cc7ed8398842814b8d8b0a47fbff9", "0x00000000000000000000000000000074ba3ad568a253626720f6cf84a8048147", "0x000000000000000000000000000000000015a62e81e4d73a4bc690880130b274", "0x000000000000000000000000000000db0e9ab080d6e0b016d94b483c68a22b06", "0x00000000000000000000000000000000000530f0adac9e85a13bbe967daae7d1", "0x0000000000000000000000000000000a14cc5e4f5bd6610a377407c783d936d0", "0x00000000000000000000000000000000000550cdda8250517265285faa5a7517", "0x00000000000000000000000000000039d6a99d59ce1d827d7a6ae4ba48e2070a", "0x000000000000000000000000000000000027e18e542338c47beb02405dec6795", "0x000000000000000000000000000000e119c0de9378fef5e737a3e6c30e399742", "0x00000000000000000000000000000000002128ad7838a6a53762477930fd162b", "0x000000000000000000000000000000053d0020faf1ab4ecf00d41c2a01f4c504", "0x0000000000000000000000000000000000067729164ec966f4d8dec2642bfcca", "0x0000000000000000000000000000004e45ee83f5be6f212f96d9f88f62bc459a", "0x000000000000000000000000000000000020065b860db7e7f600ab625cda79c2", "0x00000000000000000000000000000093200fd4a93240ee6fff2d25065692e138", "0x0000000000000000000000000000000000244c194c60da2b4d787d5f98c136d1", "0x0000000000000000000000000000009354951db4088a11f00a3f56f9f54f0d7c", "0x000000000000000000000000000000000022dba94f08aaa5e6113bd537d354c3", "0x00000000000000000000000000000051931edd7fc2b2ff98d701d3072a909b41", "0x00000000000000000000000000000000001a026a2f8c1a2eb52a4d73daf3ab70", "0x000000000000000000000000000000a14701bcefa7c0c8d498abd548d689bc10", "0x00000000000000000000000000000000002da7bcb43520678e91f1c1422ee3fc", "0x000000000000000000000000000000deb2deb6c321a235675612f31bfd349dac", "0x000000000000000000000000000000000021315fa1cc6bb01b68f70de8e42f65", "0x00000000000000000000000000000013c727a1f60952056815260454d067900a", "0x000000000000000000000000000000000016d6e8d1ef7ebe3a30f3c8b0920807", "0x00000000000000000000000000000039d2e1e0191154f0059ed5412fc9c1cb1e", "0x000000000000000000000000000000000010435db71d51c501515cf705eb8277", "0x00000000000000000000000000000038222e1253633affb05f15fc206a5cbe07", "0x000000000000000000000000000000000003816781c9f9a9cca72015ee3348f4", "0x000000000000000000000000000000137f14764aed7a2559351dca3212a626ac", "0x00000000000000000000000000000000002d207af6743643d96947c9b1a259a6", "0x00000000000000000000000000000056089fbf1dc6b4af91ff8121303d83319d", "0x0000000000000000000000000000000000211ee2c4cf62fe3e7a9ce95faeb23e", "0x000000000000000000000000000000bbd960e0fdbaa3f47270679afd6bfcd349", "0x0000000000000000000000000000000000075069f76e6438da345431e1b2c58e", "0x000000000000000000000000000000ce72715195cd6f174603a8a614eb077e47", "0x00000000000000000000000000000000002724dd7694b7e169e5a264a6e02f9e", "0x000000000000000000000000000000a53ef0e9fc8df74a32e08c53a230c36836", "0x0000000000000000000000000000000000153ce938348613707a18a83d7511fe", "0x0000000000000000000000000000007234f68ff4ed021c91a2786b9b6cd75d1c", "0x000000000000000000000000000000000024a8faba9f2405c6660f1750c5cdcb", "0x0000000000000000000000000000002b80d6b55199d55c762fbaec636a525f3e", "0x0000000000000000000000000000000000217f0ffe90bea51c49a1b331adae9c", "0x0000000000000000000000000000000ed2d8303f6f9c83d86d5c13f3fb4e99dd", "0x000000000000000000000000000000000009c45c61155d314160b50b20e35c94", "0x0000000000000000000000000000009cf5a0abb80a3b2fe13b28fe8f315409b7", "0x0000000000000000000000000000000000188a2ffed7f8cbe84c7a0f1b018cd0", "0x00000000000000000000000000000085656153a6120eebdf3a488dccad95d00d", "0x000000000000000000000000000000000023cd626f5dde3ce81de0e7d4f74dc2", "0x000000000000000000000000000000d078687b7ffc17ed454fba23b4ecae0ec4", "0x00000000000000000000000000000000002501de6f063c457fccf291f449fe04", "0x0000000000000000000000000000009a4a3363201808e24813118bbaf3bd079b", "0x00000000000000000000000000000000002da4af07c13c8064fb9c44ff43a9cd", "0x000000000000000000000000000000cf91f0cb73295831bc93869fc19cdbad99", "0x00000000000000000000000000000000001ee5d0cdde02f62e468b034f988c56", "0x000000000000000000000000000000183a142ac675e313630847be47fe912b91", "0x00000000000000000000000000000000001558e16ed49142b74e4a2085b22287", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000c47f6850760801197f1d78c8b522e3e8ce", "0x00000000000000000000000000000000001c16df0851ab44fc5fc86fc32d901a", "0x0000000000000000000000000000003a206d1590ecddff13695a16efa7c66055", "0x000000000000000000000000000000000011d6dc438ccc1de6046419780f726b"] diff --git a/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/src/main.nr new file mode 100644 index 00000000000..71c4760a422 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/verify_rollup_honk_proof/src/main.nr @@ -0,0 +1,21 @@ +// This circuit aggregates a single Honk proof from `assert_statement`. +global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 469 + 65; +global ROLLUP_HONK_IDENTIFIER: u32 = 5; +fn main( + verification_key: [Field; 139], + // This is the proof without public inputs attached. + // This means: the size of this does not change with the number of public inputs. + proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], + public_inputs: pub [Field; 1], + // This is currently not public. It is fine given that the vk is a part of the circuit definition. + // I believe we want to eventually make it public too though. + key_hash: Field, +) { + std::verify_proof_with_type( + verification_key, + proof, + public_inputs, + key_hash, + ROLLUP_HONK_IDENTIFIER, + ); +} diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 40698aa6bfb..48a68983126 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -670,7 +670,7 @@ async function verifyProofInternal( pathToBB: string, proofFullPath: string, verificationKeyPath: string, - command: 'verify_ultra_honk' | 'verify_ultra_keccak_honk' | 'avm_verify', + command: 'verify_ultra_honk' | 'verify_ultra_rollup_honk' | 'verify_ultra_keccak_honk' | 'avm_verify', log: LogFn, ): Promise { const binaryPresent = await fs diff --git a/yarn-project/bb-prover/src/honk.ts b/yarn-project/bb-prover/src/honk.ts index eb9e13236f2..8c4b013176c 100644 --- a/yarn-project/bb-prover/src/honk.ts +++ b/yarn-project/bb-prover/src/honk.ts @@ -1,16 +1,33 @@ import { type ProtocolArtifact } from '@aztec/noir-protocol-circuits-types'; -export type UltraHonkFlavor = 'ultra_honk' | 'ultra_keccak_honk'; +export type UltraHonkFlavor = 'ultra_honk' | 'ultra_keccak_honk' | 'ultra_rollup_honk'; const UltraKeccakHonkCircuits = ['RootRollupArtifact'] as const satisfies ProtocolArtifact[]; +const UltraHonkCircuits = [ + // 'EmptyNestedArtifact', + // 'PrivateKernelEmptyArtifact', + 'BaseParityArtifact', + 'RootParityArtifact', +] as const satisfies ProtocolArtifact[]; + export type UltraKeccakHonkProtocolArtifact = (typeof UltraKeccakHonkCircuits)[number]; -export type UltraHonkProtocolArtifact = Exclude; +export type UltraHonkProtocolArtifact = (typeof UltraHonkCircuits)[number]; +export type UltraRollupHonkProtocolArtifact = Exclude< + Exclude, + UltraHonkProtocolArtifact +>; export function getUltraHonkFlavorForCircuit(artifact: UltraKeccakHonkProtocolArtifact): 'ultra_keccak_honk'; export function getUltraHonkFlavorForCircuit(artifact: UltraHonkProtocolArtifact): 'ultra_honk'; +export function getUltraHonkFlavorForCircuit(artifact: UltraRollupHonkProtocolArtifact): 'ultra_rollup_honk'; export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor; export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor { - return isUltraKeccakHonkCircuit(artifact) ? 'ultra_keccak_honk' : 'ultra_honk'; + if (isUltraKeccakHonkCircuit(artifact)) { + return 'ultra_keccak_honk'; + } else if (UltraHonkCircuits.includes(artifact as UltraHonkProtocolArtifact)) { + return 'ultra_honk'; + } + return 'ultra_rollup_honk'; } function isUltraKeccakHonkCircuit(artifact: ProtocolArtifact): artifact is UltraKeccakHonkProtocolArtifact { diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 7c5378cf677..9eb66ac7576 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -16,13 +16,16 @@ import { EmptyNestedCircuitInputs, EmptyNestedData, Fr, + IPA_CLAIM_LENGTH, type KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type ParityPublicInputs, type PrivateKernelEmptyInputData, PrivateKernelEmptyInputs, Proof, RECURSIVE_PROOF_LENGTH, + RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RecursiveProof, type RootParityInputs, TUBE_PROOF_LENGTH, @@ -77,6 +80,7 @@ import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-cl import { abiEncode } from '@noir-lang/noirc_abi'; import { type Abi, type WitnessMap } from '@noir-lang/types'; +import { assert } from 'console'; import crypto from 'crypto'; import { promises as fs } from 'fs'; import * as path from 'path'; @@ -118,7 +122,7 @@ export interface BBProverConfig extends BBConfig, ACVMConfig { */ export class BBNativeRollupProver implements ServerCircuitProver { private verificationKeys = new Map< - `ultra${'_keccak_' | '_'}honk_${ServerProtocolArtifact}`, + `ultra${'_keccak_' | '_' | '_rollup_'}honk_${ServerProtocolArtifact}`, Promise >(); @@ -212,13 +216,15 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getPrivateBaseRollupProof( inputs: PrivateBaseRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const artifactName = 'PrivateBaseRollupArtifact'; const { circuitOutput, proof } = await this.createRecursiveProof( inputs, artifactName, - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertPrivateBaseRollupInputsToWitnessMap, convertPrivateBaseRollupOutputsFromWitnessMap, ); @@ -237,13 +243,15 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getPublicBaseRollupProof( inputs: PublicBaseRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const artifactName = 'PublicBaseRollupArtifact'; const { circuitOutput, proof } = await this.createRecursiveProof( inputs, artifactName, - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertPublicBaseRollupInputsToWitnessMap, convertPublicBaseRollupOutputsFromWitnessMap, ); @@ -262,11 +270,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getMergeRollupProof( input: MergeRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const { circuitOutput, proof } = await this.createRecursiveProof( input, 'MergeRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, ); @@ -285,11 +295,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getBlockRootRollupProof( input: BlockRootRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const { circuitOutput, proof } = await this.createRecursiveProof( input, 'BlockRootRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertBlockRootRollupInputsToWitnessMap, convertBlockRootRollupOutputsFromWitnessMap, ); @@ -308,11 +320,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getEmptyBlockRootRollupProof( input: EmptyBlockRootRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const { circuitOutput, proof } = await this.createRecursiveProof( input, 'EmptyBlockRootRollupArtifact', - RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertEmptyBlockRootRollupInputsToWitnessMap, convertEmptyBlockRootRollupOutputsFromWitnessMap, ); @@ -331,11 +345,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async getBlockMergeRollupProof( input: BlockMergeRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const { circuitOutput, proof } = await this.createRecursiveProof( input, 'BlockMergeRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertBlockMergeRollupInputsToWitnessMap, convertBlockMergeRollupOutputsFromWitnessMap, ); @@ -373,7 +389,9 @@ export class BBNativeRollupProver implements ServerCircuitProver { public async getEmptyPrivateKernelProof( inputs: PrivateKernelEmptyInputData, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const emptyNested = await this.getEmptyNestedProof(); const emptyPrivateKernelProof = await this.getEmptyPrivateKernelProofFromEmptyNested( PrivateKernelEmptyInputs.from({ @@ -390,7 +408,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { const { proof } = await this.createRecursiveProof( inputs, 'EmptyNestedArtifact', - RECURSIVE_PROOF_LENGTH, + RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, (nothing: any) => abiEncode(ServerCircuitArtifacts.EmptyNestedArtifact.abi as Abi, { _inputs: nothing as any }), () => new EmptyNestedCircuitInputs(), ); @@ -407,11 +425,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { private async getEmptyPrivateKernelProofFromEmptyNested( inputs: PrivateKernelEmptyInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const { circuitOutput, proof } = await this.createRecursiveProof( inputs, 'PrivateKernelEmptyArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertPrivateKernelEmptyInputsToWitnessMap, convertPrivateKernelEmptyOutputsFromWitnessMap, ); @@ -618,7 +638,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { this.instrumentation.recordSize('circuitSize', 'tubeCircuit', tubeVK.circuitSize); // Sanity check the tube proof (can be removed later) - await this.verifyWithKey('ultra_honk', tubeVK, tubeProof.binaryProof); + await this.verifyWithKey('ultra_rollup_honk', tubeVK, tubeProof.binaryProof); logger.info( `Generated proof for tubeCircuit in ${Math.ceil(provingResult.durationMs)} ms, size: ${ @@ -753,7 +773,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @returns - The valid proof */ public async ensureValidProof( - proof: RecursiveProof, + proof: RecursiveProof, // WORKTODO circuit: ServerProtocolArtifact, vk: VerificationKeyData, ) { @@ -764,7 +784,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { } const operation = async (bbWorkingDirectory: string) => { - const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH - IPA_CLAIM_LENGTH; const proofFullFilename = path.join(bbWorkingDirectory, PROOF_FILENAME); const vkFullFilename = path.join(bbWorkingDirectory, VK_FILENAME); @@ -804,7 +824,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { fields, new Proof(proof.binaryProof.buffer, vk.numPublicInputs), true, - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_PROOF_LENGTH, // WORKTODO ); }; return await this.runInDirectory(operation); @@ -876,7 +896,12 @@ export class BBNativeRollupProver implements ServerCircuitProver { const json = JSON.parse(proofString); - const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + let numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + if (proofLength == NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) { + numPublicInputs -= IPA_CLAIM_LENGTH; + } + + assert(json.length - numPublicInputs == proofLength, 'Proof length mismatch'); const fieldsWithoutPublicInputs = json .slice(0, 3) diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index e8aff2e43cc..70257ec280b 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -13,6 +13,7 @@ import { EmptyNestedData, type KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type ParityPublicInputs, type PrivateKernelEmptyInputData, PrivateKernelEmptyInputs, @@ -96,9 +97,11 @@ export class TestCircuitProver implements ServerCircuitProver { public async getEmptyPrivateKernelProof( inputs: PrivateKernelEmptyInputData, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { const emptyNested = new EmptyNestedData( - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), ProtocolCircuitVks['EmptyNestedArtifact'].keyAsFields, ); const kernelInputs = new PrivateKernelEmptyInputs( @@ -113,7 +116,7 @@ export class TestCircuitProver implements ServerCircuitProver { return await this.simulate( kernelInputs, 'PrivateKernelEmptyArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertPrivateKernelEmptyInputsToWitnessMap, convertSimulatedPrivateKernelEmptyOutputsFromWitnessMap, ); @@ -157,17 +160,22 @@ export class TestCircuitProver implements ServerCircuitProver { public async getTubeProof(_tubeInput: TubeInputs): Promise> { await this.delay(); - return makeProofAndVerificationKey(makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()); + return makeProofAndVerificationKey( + makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), + ); } @trackSpan('TestCircuitProver.getPrivateBaseRollupProof') public async getPrivateBaseRollupProof( inputs: PrivateBaseRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( inputs, 'PrivateBaseRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertSimulatedPrivateBaseRollupInputsToWitnessMap, convertSimulatedPrivateBaseRollupOutputsFromWitnessMap, ); @@ -176,11 +184,13 @@ export class TestCircuitProver implements ServerCircuitProver { @trackSpan('TestCircuitProver.getPublicBaseRollupProof') public async getPublicBaseRollupProof( inputs: PublicBaseRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( inputs, 'PublicBaseRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertSimulatedPublicBaseRollupInputsToWitnessMap, convertSimulatedPublicBaseRollupOutputsFromWitnessMap, ); @@ -194,11 +204,13 @@ export class TestCircuitProver implements ServerCircuitProver { @trackSpan('TestCircuitProver.getMergeRollupProof') public async getMergeRollupProof( input: MergeRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( input, 'MergeRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, ); @@ -212,11 +224,13 @@ export class TestCircuitProver implements ServerCircuitProver { @trackSpan('TestCircuitProver.getBlockRootRollupProof') public async getBlockRootRollupProof( input: BlockRootRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( input, 'BlockRootRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertSimulatedBlockRootRollupInputsToWitnessMap, convertSimulatedBlockRootRollupOutputsFromWitnessMap, ); @@ -230,11 +244,13 @@ export class TestCircuitProver implements ServerCircuitProver { @trackSpan('TestCircuitProver.getEmptyBlockRootRollupProof') public async getEmptyBlockRootRollupProof( input: EmptyBlockRootRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( input, 'EmptyBlockRootRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertEmptyBlockRootRollupInputsToWitnessMap, convertEmptyBlockRootRollupOutputsFromWitnessMap, ); @@ -248,11 +264,13 @@ export class TestCircuitProver implements ServerCircuitProver { @trackSpan('TestCircuitProver.getBlockMergeRollupProof') public async getBlockMergeRollupProof( input: BlockMergeRollupInputs, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return await this.simulate( input, 'BlockMergeRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, convertBlockMergeRollupInputsToWitnessMap, convertBlockMergeRollupOutputsFromWitnessMap, ); diff --git a/yarn-project/circuit-types/src/interfaces/proving-job-source.test.ts b/yarn-project/circuit-types/src/interfaces/proving-job-source.test.ts index f27fe8fb85e..af6da9b1b11 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job-source.test.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job-source.test.ts @@ -1,4 +1,4 @@ -import { NESTED_RECURSIVE_PROOF_LENGTH, VerificationKeyData, makeRecursiveProof } from '@aztec/circuits.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, VerificationKeyData, makeRecursiveProof } from '@aztec/circuits.js'; import { BaseOrMergeRollupPublicInputs } from '@aztec/circuits.js/rollup'; import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundation/json-rpc/test'; @@ -47,10 +47,13 @@ describe('ProvingJobSourceSchema', () => { it('resolveProvingJob', async () => { await context.client.resolveProvingJob('a-job-id', { type: ProvingRequestType.PRIVATE_BASE_ROLLUP, - result: makePublicInputsAndRecursiveProof( + result: makePublicInputsAndRecursiveProof< + BaseOrMergeRollupPublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >( BaseOrMergeRollupPublicInputs.empty(), - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFake(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), }); }); diff --git a/yarn-project/circuit-types/src/interfaces/proving-job.ts b/yarn-project/circuit-types/src/interfaces/proving-job.ts index 618016bfc7e..331f914224f 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job.ts @@ -4,6 +4,7 @@ import { BaseParityInputs, KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, ParityPublicInputs, PrivateKernelEmptyInputData, RECURSIVE_PROOF_LENGTH, @@ -58,15 +59,15 @@ export type PublicInputsAndRecursiveProof( +function schemaForPublicInputsAndRecursiveProof( inputs: ZodFor, - proofSize = NESTED_RECURSIVE_PROOF_LENGTH, -): ZodFor> { + proofSize: N, +): ZodFor> { return z.object({ inputs, proof: RecursiveProof.schemaFor(proofSize), verificationKey: VerificationKeyData.schema, - }) as ZodFor>; + }) as ZodFor>; } export function makePublicInputsAndRecursiveProof( @@ -166,7 +167,10 @@ export type ProvingJobInputsMap = { export const ProvingJobResult = z.discriminatedUnion('type', [ z.object({ type: z.literal(ProvingRequestType.PRIVATE_KERNEL_EMPTY), - result: schemaForPublicInputsAndRecursiveProof(KernelCircuitPublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + KernelCircuitPublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.PUBLIC_VM), @@ -174,31 +178,49 @@ export const ProvingJobResult = z.discriminatedUnion('type', [ }), z.object({ type: z.literal(ProvingRequestType.PRIVATE_BASE_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BaseOrMergeRollupPublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BaseOrMergeRollupPublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.PUBLIC_BASE_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BaseOrMergeRollupPublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BaseOrMergeRollupPublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.MERGE_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BaseOrMergeRollupPublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BaseOrMergeRollupPublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BlockRootOrBlockMergePublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BlockRootOrBlockMergePublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.BLOCK_ROOT_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BlockRootOrBlockMergePublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BlockRootOrBlockMergePublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.BLOCK_MERGE_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(BlockRootOrBlockMergePublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof( + BlockRootOrBlockMergePublicInputs.schema, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + ), }), z.object({ type: z.literal(ProvingRequestType.ROOT_ROLLUP), - result: schemaForPublicInputsAndRecursiveProof(RootRollupPublicInputs.schema), + result: schemaForPublicInputsAndRecursiveProof(RootRollupPublicInputs.schema, NESTED_RECURSIVE_PROOF_LENGTH), }), z.object({ type: z.literal(ProvingRequestType.BASE_PARITY), @@ -215,14 +237,35 @@ export const ProvingJobResult = z.discriminatedUnion('type', [ ]); export type ProvingJobResult = z.infer; export type ProvingJobResultsMap = { - [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: PublicInputsAndRecursiveProof; + [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: PublicInputsAndRecursiveProof< + KernelCircuitPublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; [ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey; - [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.PUBLIC_BASE_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.MERGE_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof; - [ProvingRequestType.BLOCK_MERGE_ROLLUP]: PublicInputsAndRecursiveProof; + [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PublicInputsAndRecursiveProof< + BaseOrMergeRollupPublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; + [ProvingRequestType.PUBLIC_BASE_ROLLUP]: PublicInputsAndRecursiveProof< + BaseOrMergeRollupPublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; + [ProvingRequestType.MERGE_ROLLUP]: PublicInputsAndRecursiveProof< + BaseOrMergeRollupPublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; + [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof< + BlockRootOrBlockMergePublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; + [ProvingRequestType.BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof< + BlockRootOrBlockMergePublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; + [ProvingRequestType.BLOCK_MERGE_ROLLUP]: PublicInputsAndRecursiveProof< + BlockRootOrBlockMergePublicInputs, + typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH + >; [ProvingRequestType.ROOT_ROLLUP]: PublicInputsAndRecursiveProof; [ProvingRequestType.BASE_PARITY]: PublicInputsAndRecursiveProof; [ProvingRequestType.ROOT_PARITY]: PublicInputsAndRecursiveProof< diff --git a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts index e9a63893f3e..5143bd42708 100644 --- a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts @@ -4,6 +4,7 @@ import { type BaseParityInputs, type KernelCircuitPublicInputs, type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type ParityPublicInputs, type PrivateKernelEmptyInputData, type RECURSIVE_PROOF_LENGTH, @@ -59,13 +60,17 @@ export interface ServerCircuitProver { baseRollupInput: PrivateBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; getPublicBaseRollupProof( inputs: PublicBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Get a recursively verified client IVC proof (making it a compatible honk proof for the rest of the rollup). @@ -85,7 +90,9 @@ export interface ServerCircuitProver { input: MergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Creates a proof for the given input. @@ -95,7 +102,9 @@ export interface ServerCircuitProver { input: BlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Creates a proof for the given input. @@ -105,7 +114,9 @@ export interface ServerCircuitProver { input: EmptyBlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Creates a proof for the given input. @@ -115,7 +126,9 @@ export interface ServerCircuitProver { input: BlockMergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Creates a proof for the given input. @@ -125,13 +138,15 @@ export interface ServerCircuitProver { input: RootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise>; getEmptyPrivateKernelProof( inputs: PrivateKernelEmptyInputData, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise< + PublicInputsAndRecursiveProof + >; /** * Create a proof for the AVM circuit. diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 4139dd7aab5..00cc1a9beac 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -169,6 +169,7 @@ export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 867; export const PRIVATE_CONTEXT_INPUTS_LENGTH = 40; export const FEE_RECIPIENT_LENGTH = 2; export const AGGREGATION_OBJECT_LENGTH = 16; +export const IPA_CLAIM_LENGTH = 10; export const SCOPED_READ_REQUEST_LEN = 3; export const PUBLIC_DATA_READ_LENGTH = 3; export const PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; @@ -202,8 +203,12 @@ export const NUM_MSGS_PER_BASE_PARITY = 4; export const NUM_BASE_PARITY_PER_ROOT_PARITY = 4; export const RECURSIVE_PROOF_LENGTH = 459; export const NESTED_RECURSIVE_PROOF_LENGTH = 459; -export const TUBE_PROOF_LENGTH = 459; +export const IPA_PROOF_LENGTH = 65; +export const RECURSIVE_ROLLUP_HONK_PROOF_LENGTH = 534; +export const NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH = 534; +export const TUBE_PROOF_LENGTH = 534; export const HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 128; +export const ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 139; export const CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 143; export const AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 86; export const MAX_PUBLIC_BYTECODE_SIZE_IN_BYTES = 96000; @@ -339,6 +344,8 @@ export const PROOF_TYPE_HONK = 1; export const PROOF_TYPE_OINK = 2; export const PROOF_TYPE_PG = 3; export const PROOF_TYPE_AVM = 4; +export const PROOF_TYPE_ROLLUP_HONK = 5; +export const PROOF_TYPE_ROOT_ROLLUP_HONK = 6; export enum GeneratorIndex { NOTE_HASH = 1, NOTE_HASH_NONCE = 2, diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.test.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.test.ts index 1eb9eb51fb9..c08dacee0fb 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.test.ts @@ -1,6 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; -import { NESTED_RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH } from '../../constants.gen.js'; import { makeHeader } from '../../tests/factories.js'; import { makeRecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; @@ -20,7 +20,10 @@ describe('PrivateKernelEmptyInputData', () => { describe('PrivateKernelEmptyInputs', () => { it('serializes and deserializes', () => { const obj = new PrivateKernelEmptyInputs( - new EmptyNestedData(makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), VerificationKeyAsFields.makeFakeHonk()), + new EmptyNestedData( + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyAsFields.makeFakeRollupHonk(), + ), makeHeader(), Fr.random(), Fr.random(), @@ -35,8 +38,8 @@ describe('PrivateKernelEmptyInputs', () => { describe('EmptyNestedData', () => { it('serializes and deserializes', () => { const obj = new EmptyNestedData( - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - VerificationKeyAsFields.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyAsFields.makeFakeRollupHonk(), ); expect(EmptyNestedData.fromBuffer(obj.toBuffer())).toEqual(obj); }); diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts index ad8e7157259..f5a1075fd15 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts @@ -4,7 +4,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; -import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { RECURSIVE_ROLLUP_HONK_PROOF_LENGTH } from '../../constants.gen.js'; import { BlockHeader } from '../block_header.js'; import { RecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; @@ -115,7 +115,7 @@ export class EmptyNestedCircuitInputs { export class EmptyNestedData { constructor( - public readonly proof: RecursiveProof, + public readonly proof: RecursiveProof, public readonly vk: VerificationKeyAsFields, ) {} @@ -127,14 +127,14 @@ export class EmptyNestedData { const reader = BufferReader.asReader(buf); const recursiveProof = reader.readObject(RecursiveProof); - if (recursiveProof.proof.length !== RECURSIVE_PROOF_LENGTH) { + if (recursiveProof.proof.length !== RECURSIVE_ROLLUP_HONK_PROOF_LENGTH) { throw new TypeError( - `Invalid proof length. Expected: ${RECURSIVE_PROOF_LENGTH} got: ${recursiveProof.proof.length}`, + `Invalid proof length. Expected: ${RECURSIVE_ROLLUP_HONK_PROOF_LENGTH} got: ${recursiveProof.proof.length}`, ); } return new EmptyNestedData( - recursiveProof as RecursiveProof, + recursiveProof as RecursiveProof, reader.readObject(VerificationKeyAsFields), ); } diff --git a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_block_data.ts b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_block_data.ts index 2d203aa8ffd..a679a1cea19 100644 --- a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_block_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_block_data.ts @@ -1,6 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; import { MembershipWitness } from '../membership_witness.js'; import { RecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; @@ -18,7 +18,7 @@ export class PreviousRollupBlockData { /** * The proof of the block merge or block root rollup circuit. */ - public proof: RecursiveProof, + public proof: RecursiveProof, /** * The verification key of the block merge or block root rollup circuit. */ @@ -46,7 +46,7 @@ export class PreviousRollupBlockData { const reader = BufferReader.asReader(buffer); return new PreviousRollupBlockData( reader.readObject(BlockRootOrBlockMergePublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), MembershipWitness.fromBuffer(reader, VK_TREE_HEIGHT), ); diff --git a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts index 85d495186be..5f4f0f7e874 100644 --- a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts @@ -1,6 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; import { MembershipWitness } from '../membership_witness.js'; import { RecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; @@ -18,7 +18,7 @@ export class PreviousRollupData { /** * The proof of the base or merge rollup circuit. */ - public proof: RecursiveProof, + public proof: RecursiveProof, /** * The verification key of the base or merge rollup circuit. */ @@ -46,7 +46,7 @@ export class PreviousRollupData { const reader = BufferReader.asReader(buffer); return new PreviousRollupData( reader.readObject(BaseOrMergeRollupPublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), MembershipWitness.fromBuffer(reader, VK_TREE_HEIGHT), ); diff --git a/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts b/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts index 7fc0c3bc917..342b5b388a9 100644 --- a/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/private_tube_data.ts @@ -1,6 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH } from '../../constants.gen.js'; import { KernelCircuitPublicInputs } from '../kernel/kernel_circuit_public_inputs.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { VkWitnessData } from '../vk_witness_data.js'; @@ -8,14 +8,14 @@ import { VkWitnessData } from '../vk_witness_data.js'; export class PrivateTubeData { constructor( public publicInputs: KernelCircuitPublicInputs, - public proof: RecursiveProof, + public proof: RecursiveProof, public vkData: VkWitnessData, ) {} static empty() { return new PrivateTubeData( KernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), + makeEmptyRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), VkWitnessData.empty(), ); } @@ -24,7 +24,7 @@ export class PrivateTubeData { const reader = BufferReader.asReader(buffer); return new PrivateTubeData( reader.readObject(KernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), reader.readObject(VkWitnessData), ); } diff --git a/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts index 7ca444204a7..18075b5a92c 100644 --- a/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts @@ -1,6 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; +import { NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH } from '../../constants.gen.js'; import { PrivateToPublicKernelCircuitPublicInputs } from '../kernel/private_to_public_kernel_circuit_public_inputs.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { VkWitnessData } from '../vk_witness_data.js'; @@ -8,14 +8,14 @@ import { VkWitnessData } from '../vk_witness_data.js'; export class PublicTubeData { constructor( public publicInputs: PrivateToPublicKernelCircuitPublicInputs, - public proof: RecursiveProof, + public proof: RecursiveProof, public vkData: VkWitnessData, ) {} static empty() { return new PublicTubeData( PrivateToPublicKernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), + makeEmptyRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), VkWitnessData.empty(), ); } @@ -24,7 +24,7 @@ export class PublicTubeData { const reader = BufferReader.asReader(buffer); return new PublicTubeData( reader.readObject(PrivateToPublicKernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), reader.readObject(VkWitnessData), ); } diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index f3fc4a27610..04ca57d1d82 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -5,7 +5,10 @@ import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; -import { HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS } from '../constants.gen.js'; +import { + HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, +} from '../constants.gen.js'; import { CircuitType } from './shared.js'; /** @@ -142,6 +145,13 @@ export class VerificationKeyAsFields { return new VerificationKeyAsFields(makeTuple(HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, Fr.random, seed), Fr.random()); } + static makeFakeRollupHonk(seed = 1): VerificationKeyAsFields { + return new VerificationKeyAsFields( + makeTuple(ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, Fr.random, seed), + Fr.random(), + ); + } + /** * Builds an 'empty' verification key * @returns An 'empty' verification key @@ -210,6 +220,21 @@ export class VerificationKey { ); } + /** + * Builds a fake Rollup Honk verification key that should be accepted by circuits. + * @returns A fake verification key. + */ + static makeRollupFake(): VerificationKey { + return new VerificationKey( + CircuitType.ULTRA, // This is entirely arbitrary + 2048, + 116, + {}, // Empty set of commitments + false, + times(16, i => i), + ); + } + /** * Builds a fake verification key that should be accepted by circuits. * @returns A fake verification key. @@ -249,7 +274,14 @@ export class VerificationKeyData { return new VerificationKeyData(VerificationKeyAsFields.makeFakeHonk(), VerificationKey.makeFake().toBuffer()); } - static makeFake(len = HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS): VerificationKeyData { + static makeFakeRollupHonk(): VerificationKeyData { + return new VerificationKeyData( + VerificationKeyAsFields.makeFakeRollupHonk(), + VerificationKey.makeRollupFake().toBuffer(), + ); + } + + static makeFake(len = ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS): VerificationKeyData { return new VerificationKeyData(VerificationKeyAsFields.makeFake(len), VerificationKey.makeFake().toBuffer()); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index d5e83e22c9a..2cbedd38627 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -61,6 +61,7 @@ import { MaxBlockNumber, MembershipWitness, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, @@ -762,7 +763,10 @@ export function makePreviousRollupData( ): PreviousRollupData { return new PreviousRollupData( makeBaseOrMergeRollupPublicInputs(seed, globalVariables), - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH, seed + 0x50), + makeRecursiveProof( + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + seed + 0x50, + ), VerificationKeyAsFields.makeFakeHonk(), makeMembershipWitness(VK_TREE_HEIGHT, seed + 0x120), ); @@ -780,7 +784,10 @@ export function makePreviousRollupBlockData( ): PreviousRollupBlockData { return new PreviousRollupBlockData( makeBlockRootOrBlockMergeRollupPublicInputs(seed, globalVariables), - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH, seed + 0x50), + makeRecursiveProof( + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, + seed + 0x50, + ), VerificationKeyAsFields.makeFakeHonk(), makeMembershipWitness(VK_TREE_HEIGHT, seed + 0x120), ); diff --git a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts index e052b1cd044..5f3a6f9a660 100644 --- a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts +++ b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts @@ -24,6 +24,7 @@ import { type PrivateToPublicKernelCircuitPublicInputs, type PublicDataHint, type RECURSIVE_PROOF_LENGTH, + ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, type RecursiveProof, RevertCode, RollupValidationRequests, @@ -638,7 +639,7 @@ export function mapPreviousRollupDataToNoir(previousRollupData: PreviousRollupDa previousRollupData.baseOrMergeRollupPublicInputs, ), proof: mapRecursiveProofToNoir(previousRollupData.proof), - vk: mapVerificationKeyToNoir(previousRollupData.vk, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + vk: mapVerificationKeyToNoir(previousRollupData.vk, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), vk_witness: { leaf_index: mapFieldToNoir(new Fr(previousRollupData.vkWitness.leafIndex)), sibling_path: mapTuple(previousRollupData.vkWitness.siblingPath, mapFieldToNoir), @@ -659,7 +660,7 @@ export function mapPreviousRollupBlockDataToNoir( previousRollupData.blockRootOrBlockMergePublicInputs, ), proof: mapRecursiveProofToNoir(previousRollupData.proof), - vk: mapVerificationKeyToNoir(previousRollupData.vk, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + vk: mapVerificationKeyToNoir(previousRollupData.vk, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), vk_witness: { leaf_index: mapFieldToNoir(new Fr(previousRollupData.vkWitness.leafIndex)), sibling_path: mapTuple(previousRollupData.vkWitness.siblingPath, mapFieldToNoir), @@ -832,7 +833,7 @@ function mapPrivateTubeDataToNoir(data: PrivateTubeData): PrivateTubeDataNoir { return { public_inputs: mapKernelCircuitPublicInputsToNoir(data.publicInputs), proof: mapRecursiveProofToNoir(data.proof), - vk_data: mapVkWitnessDataToNoir(data.vkData, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + vk_data: mapVkWitnessDataToNoir(data.vkData, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), }; } @@ -866,7 +867,7 @@ function mapPublicTubeDataToNoir(data: PublicTubeData): PublicTubeDataNoir { return { public_inputs: mapPrivateToPublicKernelCircuitPublicInputsToNoir(data.publicInputs), proof: mapRecursiveProofToNoir(data.proof), - vk_data: mapVkWitnessDataToNoir(data.vkData, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + vk_data: mapVkWitnessDataToNoir(data.vkData, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), }; } @@ -905,7 +906,7 @@ export function mapEmptyKernelInputsToNoir(inputs: PrivateKernelEmptyInputs): Pr function mapEmptyNestedDataToNoir(inputs: EmptyNestedData): EmptyNestedDataNoir { return { proof: mapRecursiveProofToNoir(inputs.proof), - vk: mapVerificationKeyToNoir(inputs.vk, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), + vk: mapVerificationKeyToNoir(inputs.vk, ROLLUP_HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), }; } diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_hashes.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_hashes.ts index 47f65312f17..847b71a557f 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_hashes.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_hashes.ts @@ -15,7 +15,7 @@ function resolveRelativePath(relativePath: string) { const main = async () => { // TODO(#7410) tube VK should have been generated in noir-projects, but since we don't have a limited set of tubes // we fake it here. - const tubeVK = VerificationKeyData.makeFakeHonk(); + const tubeVK = VerificationKeyData.makeFakeRollupHonk(); const tubeVKPath = resolveRelativePath('../../artifacts/keys/tube.vk.data.json'); await fs.writeFile( tubeVKPath, diff --git a/yarn-project/prover-client/src/block_builder/light.test.ts b/yarn-project/prover-client/src/block_builder/light.test.ts index 26a5cfee69b..95180821db1 100644 --- a/yarn-project/prover-client/src/block_builder/light.test.ts +++ b/yarn-project/prover-client/src/block_builder/light.test.ts @@ -19,6 +19,7 @@ import { L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, MembershipWitness, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY, type ParityPublicInputs, @@ -84,12 +85,14 @@ describe('LightBlockBuilder', () => { let builder: LightweightBlockBuilder; let emptyProof: RecursiveProof; + let emptyRollupProof: RecursiveProof; beforeAll(async () => { logger = createLogger('prover-client:test:block-builder'); simulator = new TestCircuitProver(new NoopTelemetryClient()); vkTreeRoot = getVKTreeRoot(); emptyProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); + emptyRollupProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH); db = await NativeWorldStateService.tmp(); }); @@ -277,7 +280,7 @@ describe('LightBlockBuilder', () => { const vkIndex = TUBE_VK_INDEX; const vkPath = getVKSiblingPath(vkIndex); const vkData = new VkWitnessData(TubeVk, vkIndex, vkPath); - const tubeData = new PrivateTubeData(tx.data.toKernelCircuitPublicInputs(), emptyProof, vkData); + const tubeData = new PrivateTubeData(tx.data.toKernelCircuitPublicInputs(), emptyRollupProof, vkData); const hints = await buildBaseRollupHints(tx, globalVariables, expectsFork, spongeBlobState); const inputs = new PrivateBaseRollupInputs(tubeData, hints as PrivateBaseRollupHints); const result = await simulator.getPrivateBaseRollupProof(inputs); @@ -289,8 +292,8 @@ describe('LightBlockBuilder', () => { const getMergeOutput = async (left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) => { const baseRollupVk = ProtocolCircuitVks['PrivateBaseRollupArtifact'].keyAsFields; const baseRollupVkWitness = getVkMembershipWitness(baseRollupVk); - const leftInput = new PreviousRollupData(left, emptyProof, baseRollupVk, baseRollupVkWitness); - const rightInput = new PreviousRollupData(right, emptyProof, baseRollupVk, baseRollupVkWitness); + const leftInput = new PreviousRollupData(left, emptyRollupProof, baseRollupVk, baseRollupVkWitness); + const rightInput = new PreviousRollupData(right, emptyRollupProof, baseRollupVk, baseRollupVkWitness); const inputs = new MergeRollupInputs([leftInput, rightInput]); const result = await simulator.getMergeRollupProof(inputs); return result.inputs; @@ -329,8 +332,8 @@ describe('LightBlockBuilder', () => { const mergeRollupVk = ProtocolCircuitVks['MergeRollupArtifact'].keyAsFields; const mergeRollupVkWitness = getVkMembershipWitness(mergeRollupVk); - const rollupLeft = new PreviousRollupData(left, emptyProof, mergeRollupVk, mergeRollupVkWitness); - const rollupRight = new PreviousRollupData(right, emptyProof, mergeRollupVk, mergeRollupVkWitness); + const rollupLeft = new PreviousRollupData(left, emptyRollupProof, mergeRollupVk, mergeRollupVkWitness); + const rollupRight = new PreviousRollupData(right, emptyRollupProof, mergeRollupVk, mergeRollupVkWitness); const startArchiveSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, expectsFork); const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, expectsFork); const previousBlockHashLeafIndex = BigInt(startArchiveSnapshot.nextAvailableLeafIndex - 1); diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index c8a0cc9f34f..31b25d55e73 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -18,7 +18,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MerkleTreeCalculator, - type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, @@ -275,8 +275,16 @@ async function getPublicDataHint(db: MerkleTreeWriteOperations, leafSlot: bigint } export function createMergeRollupInputs( - left: [BaseOrMergeRollupPublicInputs, RecursiveProof, VerificationKeyAsFields], - right: [BaseOrMergeRollupPublicInputs, RecursiveProof, VerificationKeyAsFields], + left: [ + BaseOrMergeRollupPublicInputs, + RecursiveProof, + VerificationKeyAsFields, + ], + right: [ + BaseOrMergeRollupPublicInputs, + RecursiveProof, + VerificationKeyAsFields, + ], ) { const mergeInputs = new MergeRollupInputs([ getPreviousRollupDataFromPublicInputs(left[0], left[1], left[2]), @@ -288,12 +296,12 @@ export function createMergeRollupInputs( export function createBlockMergeRollupInputs( left: [ BlockRootOrBlockMergePublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], right: [ BlockRootOrBlockMergePublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], ) { @@ -429,10 +437,10 @@ export async function getRootTreeSiblingPath(treeId: T // Builds the inputs for the final root rollup circuit, without making any changes to trees export function getRootRollupInput( rollupOutputLeft: BlockRootOrBlockMergePublicInputs, - rollupProofLeft: RecursiveProof, + rollupProofLeft: RecursiveProof, verificationKeyLeft: VerificationKeyAsFields, rollupOutputRight: BlockRootOrBlockMergePublicInputs, - rollupProofRight: RecursiveProof, + rollupProofRight: RecursiveProof, verificationKeyRight: VerificationKeyAsFields, proverId: Fr, ) { @@ -449,7 +457,7 @@ export function getRootRollupInput( export function getPreviousRollupDataFromPublicInputs( rollupOutput: BaseOrMergeRollupPublicInputs, - rollupProof: RecursiveProof, + rollupProof: RecursiveProof, vk: VerificationKeyAsFields, ) { const leafIndex = getVKIndex(vk); @@ -464,7 +472,7 @@ export function getPreviousRollupDataFromPublicInputs( export function getPreviousRollupBlockDataFromPublicInputs( rollupOutput: BlockRootOrBlockMergePublicInputs, - rollupProof: RecursiveProof, + rollupProof: RecursiveProof, vk: VerificationKeyAsFields, ) { const leafIndex = getVKIndex(vk); diff --git a/yarn-project/prover-client/src/orchestrator/block-proving-state.ts b/yarn-project/prover-client/src/orchestrator/block-proving-state.ts index 6bc5efecacb..55f0431a302 100644 --- a/yarn-project/prover-client/src/orchestrator/block-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/block-proving-state.ts @@ -6,6 +6,7 @@ import { type GlobalVariables, type L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY, type Proof, @@ -24,8 +25,8 @@ import { type TxProvingState } from './tx-proving-state.js'; export type MergeRollupInputData = { inputs: [BaseOrMergeRollupPublicInputs | undefined, BaseOrMergeRollupPublicInputs | undefined]; proofs: [ - RecursiveProof | undefined, - RecursiveProof | undefined, + RecursiveProof | undefined, + RecursiveProof | undefined, ]; verificationKeys: [VerificationKeyAsFields | undefined, VerificationKeyAsFields | undefined]; }; @@ -159,7 +160,7 @@ export class BlockProvingState { public storeMergeInputs( mergeInputs: [ BaseOrMergeRollupPublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], indexWithinMerge: number, diff --git a/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts b/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts index 3ea4db2228c..55d8cd0d8b8 100644 --- a/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts @@ -5,7 +5,7 @@ import { Fr, type GlobalVariables, type L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, - type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, type Proof, type RecursiveProof, @@ -29,8 +29,8 @@ enum PROVING_STATE_LIFECYCLE { export type BlockMergeRollupInputData = { inputs: [BlockRootOrBlockMergePublicInputs | undefined, BlockRootOrBlockMergePublicInputs | undefined]; proofs: [ - RecursiveProof | undefined, - RecursiveProof | undefined, + RecursiveProof | undefined, + RecursiveProof | undefined, ]; verificationKeys: [VerificationKeyAsFields | undefined, VerificationKeyAsFields | undefined]; }; @@ -148,7 +148,7 @@ export class EpochProvingState { public storeMergeInputs( mergeInputs: [ BlockRootOrBlockMergePublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], indexWithinMerge: number, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 4095deeaac1..d3a2f725ec2 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -25,7 +25,7 @@ import { type GlobalVariables, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, - type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY, PrivateKernelEmptyInputData, @@ -104,7 +104,7 @@ const logger = createLogger('prover-client:orchestrator'); export class ProvingOrchestrator implements EpochProver { private provingState: EpochProvingState | undefined = undefined; private pendingProvingJobs: AbortController[] = []; - private paddingTxProof?: ProofAndVerificationKey; + private paddingTxProof?: ProofAndVerificationKey; private provingPromise: Promise | undefined = undefined; private metrics: ProvingOrchestratorMetrics; @@ -525,7 +525,7 @@ export class ProvingOrchestrator implements EpochProver { private provePaddingTransactions( txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }>, paddingTx: ProcessedTx, - proofAndVk: ProofAndVerificationKey, + proofAndVk: ProofAndVerificationKey, provingState: BlockProvingState, ) { // The padding tx contains the proof and vk, generated separately from the base inputs @@ -1147,7 +1147,7 @@ export class ProvingOrchestrator implements EpochProver { currentIndex: bigint, mergeInputData: [ BaseOrMergeRollupPublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], ) { @@ -1185,7 +1185,7 @@ export class ProvingOrchestrator implements EpochProver { currentIndex: bigint, mergeInputData: [ BlockRootOrBlockMergePublicInputs, - RecursiveProof, + RecursiveProof, VerificationKeyAsFields, ], ) { diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index 863a702d1d3..f4a3fb8433a 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -14,10 +14,12 @@ import type { BaseParityInputs, KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, ParityPublicInputs, PrivateKernelEmptyInputData, RECURSIVE_PROOF_LENGTH, RootParityInputs, + TUBE_PROOF_LENGTH, } from '@aztec/circuits.js'; import { type BaseOrMergeRollupPublicInputs, @@ -273,7 +275,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: PrivateKernelEmptyInputData, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs, signal, epochNumber); } @@ -281,7 +285,7 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: TubeInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise> { return this.enqueue(ProvingRequestType.TUBE_PROOF, inputs, signal, epochNumber); } @@ -313,7 +317,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: PrivateBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.PRIVATE_BASE_ROLLUP, inputs, signal, epochNumber); } @@ -321,7 +327,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: PublicBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.PUBLIC_BASE_ROLLUP, inputs, signal, epochNumber); } @@ -333,7 +341,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: MergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.MERGE_ROLLUP, inputs, signal, epochNumber); } @@ -345,7 +355,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: BlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.BLOCK_ROOT_ROLLUP, inputs, signal, epochNumber); } @@ -353,7 +365,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: EmptyBlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP, inputs, signal, epochNumber); } @@ -365,7 +379,9 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource inputs: BlockMergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueue(ProvingRequestType.BLOCK_MERGE_ROLLUP, inputs, signal, epochNumber); } diff --git a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts index 6dc3db0a933..a5a0a4a7b86 100644 --- a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts +++ b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts @@ -14,6 +14,7 @@ import { type BaseParityInputs, type KernelCircuitPublicInputs, type NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type ParityPublicInputs, type PrivateKernelEmptyInputData, type RECURSIVE_PROOF_LENGTH, @@ -149,7 +150,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { input: BlockMergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.BLOCK_MERGE_ROLLUP, input, epochNumber), ProvingRequestType.BLOCK_MERGE_ROLLUP, @@ -163,7 +166,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { input: BlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.BLOCK_ROOT_ROLLUP, input, epochNumber), ProvingRequestType.BLOCK_ROOT_ROLLUP, @@ -177,7 +182,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { input: EmptyBlockRootRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP, input, epochNumber), ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP, @@ -191,7 +198,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { inputs: PrivateKernelEmptyInputData, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs, epochNumber), ProvingRequestType.PRIVATE_KERNEL_EMPTY, @@ -205,7 +214,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { input: MergeRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.MERGE_ROLLUP, input, epochNumber), ProvingRequestType.MERGE_ROLLUP, @@ -218,7 +229,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { baseRollupInput: PrivateBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.PRIVATE_BASE_ROLLUP, baseRollupInput, epochNumber), ProvingRequestType.PRIVATE_BASE_ROLLUP, @@ -232,7 +245,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { inputs: PublicBaseRollupInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return this.enqueueAndWaitForJob( this.generateId(ProvingRequestType.PUBLIC_BASE_ROLLUP, inputs, epochNumber), ProvingRequestType.PUBLIC_BASE_ROLLUP, diff --git a/yarn-project/prover-client/src/test/mock_prover.ts b/yarn-project/prover-client/src/test/mock_prover.ts index f67b3147830..ea791dec259 100644 --- a/yarn-project/prover-client/src/test/mock_prover.ts +++ b/yarn-project/prover-client/src/test/mock_prover.ts @@ -17,6 +17,7 @@ import { type BaseParityInputs, type KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, type PrivateKernelEmptyInputData, RECURSIVE_PROOF_LENGTH, type RootParityInputs, @@ -132,12 +133,14 @@ export class MockProver implements ServerCircuitProver { _baseRollupInput: PrivateBaseRollupInputs, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBaseOrMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -146,12 +149,14 @@ export class MockProver implements ServerCircuitProver { _inputs: PublicBaseRollupInputs, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBaseOrMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -160,12 +165,14 @@ export class MockProver implements ServerCircuitProver { _input: MergeRollupInputs, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBaseOrMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -174,8 +181,8 @@ export class MockProver implements ServerCircuitProver { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBlockRootOrBlockMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -184,12 +191,14 @@ export class MockProver implements ServerCircuitProver { _input: EmptyBlockRootRollupInputs, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBlockRootOrBlockMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -198,12 +207,14 @@ export class MockProver implements ServerCircuitProver { _input: BlockRootRollupInputs, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeBlockRootOrBlockMergeRollupPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), + VerificationKeyData.makeFakeRollupHonk(), ), ); } @@ -212,11 +223,13 @@ export class MockProver implements ServerCircuitProver { _inputs: PrivateKernelEmptyInputData, _signal?: AbortSignal, _epochNumber?: number, - ): Promise> { + ): Promise< + PublicInputsAndRecursiveProof + > { return Promise.resolve( makePublicInputsAndRecursiveProof( makeKernelCircuitPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + makeRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH), VerificationKeyData.makeFakeHonk(), ), ); @@ -238,7 +251,7 @@ export class MockProver implements ServerCircuitProver { getTubeProof(): Promise> { return Promise.resolve( - makeProofAndVerificationKey(makeRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFake()), + makeProofAndVerificationKey(makeRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFakeRollupHonk()), ); } }