From 69ed94391e64a53a23a86c663960f67020c30d75 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 27 Aug 2025 13:38:17 +0000 Subject: [PATCH 01/35] works --- .vscode/settings.json | 2 +- avm-transpiler/Cargo.lock | 32 +- ...test_civc_standalone_vks_havent_changed.sh | 2 +- .../translator_circuit_checker.cpp | 80 +- .../op_queue/ecc_op_queue.test.cpp | 2 +- .../barretenberg/op_queue/ecc_ops_table.hpp | 2 +- .../translator_decomposition_relation.hpp | 8 +- ...translator_decomposition_relation_impl.hpp | 1204 +++++++++-------- .../translator_extra_relations.hpp | 13 +- .../translator_extra_relations_impl.hpp | 51 + .../translator_non_native_field_relation.hpp | 6 +- ...nslator_non_native_field_relation_impl.hpp | 6 +- .../mega_circuit_builder.cpp | 4 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 2 +- .../relation_correctness.test.cpp | 6 +- .../translator_vm/translator.test.cpp | 16 +- .../translator_circuit_builder.cpp | 37 +- .../translator_circuit_builder.test.cpp | 14 +- .../translator_vm/translator_proving_key.hpp | 1 + .../translator_vm/translator_verifier.cpp | 1 + proving-systems.code-workspace | 280 ++-- 21 files changed, 977 insertions(+), 792 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0964715c3fdf..1165a9ce066c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -167,7 +167,7 @@ // C++/Circuits settings /////////////////////////////////////// "[cpp]": { - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd", + "editor.defaultFormatter": "xaver.clang-format", "editor.formatOnSave": true }, // diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index e39bb5b5271f..bf28cdd42245 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "acir" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir_field", "base64 0.22.1", @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "ark-bn254", "ark-ff", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir", "acvm_blackbox_solver", @@ -54,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir", "blake2", @@ -467,7 +467,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir", "acvm_blackbox_solver", @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "brillig" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir_field", "serde", @@ -499,7 +499,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acir", "acvm_blackbox_solver", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "fm" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "codespan-reporting", "iter-extended", @@ -1122,7 +1122,7 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "iter-extended" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" [[package]] name = "itertools" @@ -1224,7 +1224,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "noir_protobuf" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "color-eyre", "prost", @@ -1232,7 +1232,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acvm", "iter-extended", @@ -1247,11 +1247,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" [[package]] name = "noirc_errors" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acvm", "base64 0.22.1", @@ -1268,7 +1268,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1326,7 +1326,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "1.0.0-beta.11" +version = "1.0.0-beta.10" dependencies = [ "acvm", "iter-extended", diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 2fcea8f575c0..45f14325ef23 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -11,7 +11,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="251cc432" +pinned_short_hash="5de0bc05" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index 9c16cb0c33d4..0d22f23f92bd 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -92,6 +92,69 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) { // Get the values of P.x Fr op_code = circuit.get_variable(op_wire[i]); + Fr op_code_next = circuit.get_variable(op_wire[i + 1]); + if (op_code != op_code_next) { + return report_fail("Mismatch of opcodes for the same UltraOp = ", i); + } + + // Current accumulator (updated value) + const std::vector current_accumulator_binary_limbs = { + circuit.get_variable(accumulators_binary_limbs_0_wire[i]), + circuit.get_variable(accumulators_binary_limbs_1_wire[i]), + circuit.get_variable(accumulators_binary_limbs_2_wire[i]), + circuit.get_variable(accumulators_binary_limbs_3_wire[i]), + }; + + // Previous accumulator + const std::vector previous_accumulator_binary_limbs = { + circuit.get_variable(accumulators_binary_limbs_0_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_1_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_2_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_3_wire[i + 1]), + }; + + if (op_code == 0) { + for (auto [curent_limb, previous_limb] : + zip_view(current_accumulator_binary_limbs, previous_accumulator_binary_limbs)) { + if (curent_limb != previous_limb) { + return report_fail("No-op should not change the accumulator = ", i); + } + } + // WORKTODO: check everything else is set to 0 + + size_t odd_gate_index = i + 1; + const std::vector current_accumulator_binary_limbs_copy = { + circuit.get_variable(accumulators_binary_limbs_0_wire[odd_gate_index]), + circuit.get_variable(accumulators_binary_limbs_1_wire[odd_gate_index]), + circuit.get_variable(accumulators_binary_limbs_2_wire[odd_gate_index]), + circuit.get_variable(accumulators_binary_limbs_3_wire[odd_gate_index]), + }; + if (odd_gate_index < circuit.num_gates - 1) { + size_t next_even_gate_index = i + 2; + const std::vector current_accumulator_binary_limbs = { + circuit.get_variable(accumulators_binary_limbs_0_wire[next_even_gate_index]), + circuit.get_variable(accumulators_binary_limbs_1_wire[next_even_gate_index]), + circuit.get_variable(accumulators_binary_limbs_2_wire[next_even_gate_index]), + circuit.get_variable(accumulators_binary_limbs_3_wire[next_even_gate_index]), + }; + + for (size_t j = 0; j < current_accumulator_binary_limbs.size(); j++) { + if (current_accumulator_binary_limbs_copy[j] != current_accumulator_binary_limbs[j]) { + return report_fail("accumulator copy failed at row = ", odd_gate_index); + } + } + } else { + // Check accumulator starts at zero + for (const auto& limb : current_accumulator_binary_limbs_copy) { + if (limb != Fr(0)) { + return report_fail("accumulator doesn't start with 0 = ", odd_gate_index); + } + } + } + + continue; + } + Fr p_x_lo = circuit.get_variable(x_lo_y_hi_wire[i]); Fr p_x_hi = circuit.get_variable(x_hi_z_1_wire[i]); Fr p_x_0 = circuit.get_variable(p_x_0_p_x_1_wire[i]); @@ -123,22 +186,6 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) Fr low_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i]); Fr high_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i + 1]); - // Current accumulator (updated value) - const std::vector current_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[i]), - circuit.get_variable(accumulators_binary_limbs_1_wire[i]), - circuit.get_variable(accumulators_binary_limbs_2_wire[i]), - circuit.get_variable(accumulators_binary_limbs_3_wire[i]), - }; - - // Previous accumulator - const std::vector previous_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_1_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_2_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_3_wire[i + 1]), - }; - // Quotient const std::vector quotient_binary_limbs = { circuit.get_variable(quotient_low_binary_limbs[i]), @@ -437,7 +484,6 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) } { size_t odd_gate_index = i + 1; - // Check the accumulator is copied correctly const std::vector current_accumulator_binary_limbs_copy = { circuit.get_variable(accumulators_binary_limbs_0_wire[odd_gate_index]), circuit.get_variable(accumulators_binary_limbs_1_wire[odd_gate_index]), diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp index a5cfd0e77cde..47d8c9c49b7b 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp @@ -77,7 +77,7 @@ class ECCOpQueueTest { for (size_t i = 0; i < eccvm_table.size(); ++i) { EXPECT_EQ(ultra_opcode_values[2 * i], eccvm_table[i].op_code.value()); - EXPECT_EQ(ultra_opcode_values[2 * i + 1], Fr(0)); + EXPECT_EQ(ultra_opcode_values[2 * i + 1], eccvm_table[i].op_code.value()); } }; }; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index ed0288c2eb6c..6d742f7bdc82 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -302,7 +302,7 @@ class UltraEccOpsTable { column_polynomials[2].at(i) = op.x_hi; column_polynomials[3].at(i) = op.y_lo; i++; - column_polynomials[0].at(i) = !op.op_code.is_random_op ? 0 : op.op_code.random_value_2; + column_polynomials[0].at(i) = !op.op_code.is_random_op ? op.op_code.value() : op.op_code.random_value_2; // only the first 'op' field is utilized column_polynomials[1].at(i) = op.y_hi; column_polynomials[2].at(i) = op.z_1; diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp index 6fba92a17fa6..175706f7d947 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp @@ -18,10 +18,10 @@ template class TranslatorDecompositionRelationImpl { static constexpr size_t RELATION_LENGTH = 3; // degree(lagrange_even_in_minicircuit_in_minicircuit(a - a_0 - a_1*2¹⁴ ... - a_l⋅2¹⁴ˡ )) = 2 static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, // decomposition of P.x limb 0 into microlimbs subrelation - 3, // decomposition of P.x limb 1 into microlimbs subrelation - 3, // decomposition of P.x limb 2 into microlimbs subrelation - 3, // decomposition of P.x limb 3 into microlimbs subrelation + 4, // decomposition of P.x limb 0 into microlimbs subrelation + 4, // decomposition of P.x limb 1 into microlimbs subrelation + 4, // decomposition of P.x limb 2 into microlimbs subrelation + 4, // decomposition of P.x limb 3 into microlimbs subrelation 3, // decomposition of P.y limb 0 into microlimbs subrelation 3, // decomposition of P.y limb 1 into microlimbs subrelation 3, // decomposition of P.y limb 2 into microlimbs subrelation diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp index 52a8d47b717d..8e04b27453e4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp @@ -37,588 +37,626 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio static constexpr size_t NUM_LIMB_BITS = 68; // Number of bits in a standard limb used for bigfield operations static constexpr size_t NUM_MICRO_LIMB_BITS = 14; // Number of bits in a standard limb used for bigfield operations - // Value to multiply an element by to perform an appropriate shift - static auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); - - // Values to multiply an element by to perform an appropriate shift - static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); - static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; - - // Shifts used to constrain ranges further - static auto SHIFT_12_TO_14 = - FF(4); // Shift used to range constrain the last microlimb of 68-bit limbs (standard limbs) - static auto SHIFT_10_TO_14 = - FF(16); // Shift used to range constrain the last microlimb of 52-bit limb (top quotient limb) - static auto SHIFT_8_TO_14 = FF(64); // Shift used to range constrain the last microlimb of 50-bit - // limbs (top limb of standard 254-bit value) - static auto SHIFT_4_TO_14 = - FF(1024); // Shift used to range constrain the last mircrolimb of 60-bit limbs from z scalars - - using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - - auto p_x_low_limbs = View(in.p_x_low_limbs); - auto p_x_low_limbs_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); - auto p_x_low_limbs_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); - auto p_x_low_limbs_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); - auto p_x_low_limbs_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); - auto p_x_low_limbs_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); - auto p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); - auto p_x_low_limbs_range_constraint_0_shift = View(in.p_x_low_limbs_range_constraint_0_shift); - auto p_x_low_limbs_range_constraint_1_shift = View(in.p_x_low_limbs_range_constraint_1_shift); - auto p_x_low_limbs_range_constraint_2_shift = View(in.p_x_low_limbs_range_constraint_2_shift); - auto p_x_low_limbs_range_constraint_3_shift = View(in.p_x_low_limbs_range_constraint_3_shift); - auto p_x_low_limbs_range_constraint_4_shift = View(in.p_x_low_limbs_range_constraint_4_shift); - auto p_x_high_limbs = View(in.p_x_high_limbs); - auto p_x_high_limbs_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); - auto p_x_high_limbs_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); - auto p_x_high_limbs_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); - auto p_x_high_limbs_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); - auto p_x_high_limbs_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); - auto p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); - auto p_x_high_limbs_range_constraint_0_shift = View(in.p_x_high_limbs_range_constraint_0_shift); - auto p_x_high_limbs_range_constraint_1_shift = View(in.p_x_high_limbs_range_constraint_1_shift); - auto p_x_high_limbs_range_constraint_2_shift = View(in.p_x_high_limbs_range_constraint_2_shift); - auto p_x_high_limbs_range_constraint_3_shift = View(in.p_x_high_limbs_range_constraint_3_shift); - auto p_y_low_limbs = View(in.p_y_low_limbs); - auto p_y_low_limbs_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); - auto p_y_low_limbs_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); - auto p_y_low_limbs_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); - auto p_y_low_limbs_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); - auto p_y_low_limbs_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); - auto p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); - auto p_y_low_limbs_range_constraint_0_shift = View(in.p_y_low_limbs_range_constraint_0_shift); - auto p_y_low_limbs_range_constraint_1_shift = View(in.p_y_low_limbs_range_constraint_1_shift); - auto p_y_low_limbs_range_constraint_2_shift = View(in.p_y_low_limbs_range_constraint_2_shift); - auto p_y_low_limbs_range_constraint_3_shift = View(in.p_y_low_limbs_range_constraint_3_shift); - auto p_y_low_limbs_range_constraint_4_shift = View(in.p_y_low_limbs_range_constraint_4_shift); - auto p_y_high_limbs = View(in.p_y_high_limbs); - auto p_y_high_limbs_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); - auto p_y_high_limbs_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); - auto p_y_high_limbs_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); - auto p_y_high_limbs_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); - auto p_y_high_limbs_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); - auto p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); - auto p_y_high_limbs_range_constraint_0_shift = View(in.p_y_high_limbs_range_constraint_0_shift); - auto p_y_high_limbs_range_constraint_1_shift = View(in.p_y_high_limbs_range_constraint_1_shift); - auto p_y_high_limbs_range_constraint_2_shift = View(in.p_y_high_limbs_range_constraint_2_shift); - auto p_y_high_limbs_range_constraint_3_shift = View(in.p_y_high_limbs_range_constraint_3_shift); - auto z_low_limbs = View(in.z_low_limbs); - auto z_low_limbs_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); - auto z_low_limbs_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); - auto z_low_limbs_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); - auto z_low_limbs_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); - auto z_low_limbs_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); - auto z_low_limbs_shift = View(in.z_low_limbs_shift); - auto z_low_limbs_range_constraint_0_shift = View(in.z_low_limbs_range_constraint_0_shift); - auto z_low_limbs_range_constraint_1_shift = View(in.z_low_limbs_range_constraint_1_shift); - auto z_low_limbs_range_constraint_2_shift = View(in.z_low_limbs_range_constraint_2_shift); - auto z_low_limbs_range_constraint_3_shift = View(in.z_low_limbs_range_constraint_3_shift); - auto z_low_limbs_range_constraint_4_shift = View(in.z_low_limbs_range_constraint_4_shift); - auto z_high_limbs = View(in.z_high_limbs); - auto z_high_limbs_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); - auto z_high_limbs_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); - auto z_high_limbs_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); - auto z_high_limbs_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); - auto z_high_limbs_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); - auto z_high_limbs_shift = View(in.z_high_limbs_shift); - auto z_high_limbs_range_constraint_0_shift = View(in.z_high_limbs_range_constraint_0_shift); - auto z_high_limbs_range_constraint_1_shift = View(in.z_high_limbs_range_constraint_1_shift); - auto z_high_limbs_range_constraint_2_shift = View(in.z_high_limbs_range_constraint_2_shift); - auto z_high_limbs_range_constraint_3_shift = View(in.z_high_limbs_range_constraint_3_shift); - auto z_high_limbs_range_constraint_4_shift = View(in.z_high_limbs_range_constraint_4_shift); - auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); - auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); - auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); - auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - auto accumulator_low_limbs_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); - auto accumulator_low_limbs_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); - auto accumulator_low_limbs_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); - auto accumulator_low_limbs_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); - auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); - auto accumulator_low_limbs_range_constraint_0_shift = View(in.accumulator_low_limbs_range_constraint_0_shift); - auto accumulator_low_limbs_range_constraint_1_shift = View(in.accumulator_low_limbs_range_constraint_1_shift); - auto accumulator_low_limbs_range_constraint_2_shift = View(in.accumulator_low_limbs_range_constraint_2_shift); - auto accumulator_low_limbs_range_constraint_3_shift = View(in.accumulator_low_limbs_range_constraint_3_shift); - auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); - auto accumulator_high_limbs_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); - auto accumulator_high_limbs_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); - auto accumulator_high_limbs_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); - auto accumulator_high_limbs_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); - auto accumulator_high_limbs_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); - auto accumulator_high_limbs_range_constraint_0_shift = View(in.accumulator_high_limbs_range_constraint_0_shift); - auto accumulator_high_limbs_range_constraint_1_shift = View(in.accumulator_high_limbs_range_constraint_1_shift); - auto accumulator_high_limbs_range_constraint_2_shift = View(in.accumulator_high_limbs_range_constraint_2_shift); - auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); - auto quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); - auto quotient_low_limbs_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); - auto quotient_low_limbs_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); - auto quotient_low_limbs_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); - auto quotient_low_limbs_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); - auto quotient_low_limbs_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); - auto quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); - auto quotient_low_limbs_range_constraint_0_shift = View(in.quotient_low_limbs_range_constraint_0_shift); - auto quotient_low_limbs_range_constraint_1_shift = View(in.quotient_low_limbs_range_constraint_1_shift); - auto quotient_low_limbs_range_constraint_2_shift = View(in.quotient_low_limbs_range_constraint_2_shift); - auto quotient_low_limbs_range_constraint_3_shift = View(in.quotient_low_limbs_range_constraint_3_shift); - auto quotient_low_limbs_range_constraint_4_shift = View(in.quotient_low_limbs_range_constraint_4_shift); - auto quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); - auto quotient_high_limbs_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); - auto quotient_high_limbs_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); - auto quotient_high_limbs_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); - auto quotient_high_limbs_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); - auto quotient_high_limbs_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); - auto quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); - auto quotient_high_limbs_range_constraint_0_shift = View(in.quotient_high_limbs_range_constraint_0_shift); - auto quotient_high_limbs_range_constraint_1_shift = View(in.quotient_high_limbs_range_constraint_1_shift); - auto quotient_high_limbs_range_constraint_2_shift = View(in.quotient_high_limbs_range_constraint_2_shift); - auto quotient_high_limbs_range_constraint_3_shift = View(in.quotient_high_limbs_range_constraint_3_shift); - auto relation_wide_limbs = View(in.relation_wide_limbs); - auto relation_wide_limbs_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); - auto relation_wide_limbs_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); - auto relation_wide_limbs_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); - auto relation_wide_limbs_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); - auto p_x_high_limbs_range_constraint_tail_shift = View(in.p_x_high_limbs_range_constraint_tail_shift); - auto accumulator_high_limbs_range_constraint_tail_shift = - View(in.accumulator_high_limbs_range_constraint_tail_shift); - auto relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); - auto relation_wide_limbs_range_constraint_0_shift = View(in.relation_wide_limbs_range_constraint_0_shift); - auto relation_wide_limbs_range_constraint_1_shift = View(in.relation_wide_limbs_range_constraint_1_shift); - auto relation_wide_limbs_range_constraint_2_shift = View(in.relation_wide_limbs_range_constraint_2_shift); - auto relation_wide_limbs_range_constraint_3_shift = View(in.relation_wide_limbs_range_constraint_3_shift); - auto p_y_high_limbs_range_constraint_tail_shift = View(in.p_y_high_limbs_range_constraint_tail_shift); - auto quotient_high_limbs_range_constraint_tail_shift = View(in.quotient_high_limbs_range_constraint_tail_shift); - auto p_x_low_limbs_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); - auto p_x_low_limbs_range_constraint_tail_shift = View(in.p_x_low_limbs_range_constraint_tail_shift); - auto p_x_high_limbs_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); - auto p_x_high_limbs_range_constraint_4_shift = View(in.p_x_high_limbs_range_constraint_4_shift); - auto p_y_low_limbs_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); - auto p_y_low_limbs_range_constraint_tail_shift = View(in.p_y_low_limbs_range_constraint_tail_shift); - auto p_y_high_limbs_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); - auto p_y_high_limbs_range_constraint_4_shift = View(in.p_y_high_limbs_range_constraint_4_shift); - auto z_low_limbs_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); - auto z_low_limbs_range_constraint_tail_shift = View(in.z_low_limbs_range_constraint_tail_shift); - auto z_high_limbs_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); - auto z_high_limbs_range_constraint_tail_shift = View(in.z_high_limbs_range_constraint_tail_shift); - auto accumulator_low_limbs_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); - auto accumulator_low_limbs_range_constraint_tail_shift = View(in.accumulator_low_limbs_range_constraint_tail_shift); - auto accumulator_high_limbs_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); - auto accumulator_high_limbs_range_constraint_4_shift = View(in.accumulator_high_limbs_range_constraint_4_shift); - auto quotient_low_limbs_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); - auto quotient_low_limbs_range_constraint_tail_shift = View(in.quotient_low_limbs_range_constraint_tail_shift); - auto quotient_high_limbs_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); - auto quotient_high_limbs_range_constraint_4_shift = View(in.quotient_high_limbs_range_constraint_4_shift); - auto x_lo_y_hi = View(in.x_lo_y_hi); - auto x_hi_z_1 = View(in.x_hi_z_1); - auto y_lo_z_2 = View(in.y_lo_z_2); - auto x_lo_y_hi_shift = View(in.x_lo_y_hi_shift); - auto x_hi_z_1_shift = View(in.x_hi_z_1_shift); - auto y_lo_z_2_shift = View(in.y_lo_z_2_shift); - auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - - // Contributions that decompose 50, 52, 68 or 84 bit limbs used for computation into range-constrained chunks - // Contribution 1 , P_x lowest limb decomposition - auto tmp_1 = ((p_x_low_limbs_range_constraint_0 + p_x_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_low_limbs); - tmp_1 *= lagrange_even_in_minicircuit; - tmp_1 *= scaling_factor; - std::get<0>(accumulators) += tmp_1; - - // Contribution 2 , P_x second lowest limb decomposition - auto tmp_2 = ((p_x_low_limbs_range_constraint_0_shift + p_x_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_x_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_x_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_x_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - p_x_low_limbs_shift); - tmp_2 *= lagrange_even_in_minicircuit; - tmp_2 *= scaling_factor; - std::get<1>(accumulators) += tmp_2; - - // Contribution 3 , P_x third limb decomposition - auto tmp_3 = ((p_x_high_limbs_range_constraint_0 + p_x_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_high_limbs); - tmp_3 *= lagrange_even_in_minicircuit; - tmp_3 *= scaling_factor; - std::get<2>(accumulators) += tmp_3; - - // Contribution 4 , P_x highest limb decomposition - auto tmp_4 = - ((p_x_high_limbs_range_constraint_0_shift + p_x_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_x_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_x_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - p_x_high_limbs_shift); - tmp_4 *= lagrange_even_in_minicircuit; - tmp_4 *= scaling_factor; - std::get<3>(accumulators) += tmp_4; - - // Contribution 5 , P_y lowest limb decomposition - auto tmp_5 = ((p_y_low_limbs_range_constraint_0 + p_y_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_low_limbs); - tmp_5 *= lagrange_even_in_minicircuit; - tmp_5 *= scaling_factor; - std::get<4>(accumulators) += tmp_5; - - // Contribution 6 , P_y second lowest limb decomposition - auto tmp_6 = ((p_y_low_limbs_range_constraint_0_shift + p_y_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_y_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_y_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_y_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - p_y_low_limbs_shift); - tmp_6 *= lagrange_even_in_minicircuit; - tmp_6 *= scaling_factor; - std::get<5>(accumulators) += tmp_6; - - // Contribution 7 , P_y third limb decomposition - auto tmp_7 = ((p_y_high_limbs_range_constraint_0 + p_y_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_high_limbs); - tmp_7 *= lagrange_even_in_minicircuit; - tmp_7 *= scaling_factor; - std::get<6>(accumulators) += tmp_7; - - // Contribution 8 , P_y highest limb decomposition - auto tmp_8 = - ((p_y_high_limbs_range_constraint_0_shift + p_y_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_y_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_y_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - p_y_high_limbs_shift); - tmp_8 *= lagrange_even_in_minicircuit; - tmp_8 *= scaling_factor; - std::get<7>(accumulators) += tmp_8; - - // Contribution 9 , z_1 low limb decomposition - auto tmp_9 = - ((z_low_limbs_range_constraint_0 + z_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - z_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + z_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_low_limbs); - tmp_9 *= lagrange_even_in_minicircuit; - tmp_9 *= scaling_factor; - std::get<8>(accumulators) += tmp_9; - - // Contribution 10 , z_2 low limb decomposition - auto tmp_10 = ((z_low_limbs_range_constraint_0_shift + z_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - z_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - z_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - z_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - z_low_limbs_shift); - tmp_10 *= lagrange_even_in_minicircuit; - tmp_10 *= scaling_factor; - std::get<9>(accumulators) += tmp_10; - - // Contribution 11 , z_1 high limb decomposition - auto tmp_11 = - ((z_high_limbs_range_constraint_0 + z_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - z_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + z_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_high_limbs); - tmp_11 *= lagrange_even_in_minicircuit; - tmp_11 *= scaling_factor; - std::get<10>(accumulators) += tmp_11; - - // Contribution 12 , z_2 high limb decomposition - auto tmp_12 = ((z_high_limbs_range_constraint_0_shift + z_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - z_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - z_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - z_high_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - z_high_limbs_shift); - tmp_12 *= lagrange_even_in_minicircuit; - tmp_12 *= scaling_factor; - std::get<11>(accumulators) += tmp_12; - - // Contribution 13 , accumulator lowest limb decomposition - auto tmp_13 = - ((accumulator_low_limbs_range_constraint_0 + accumulator_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - accumulators_binary_limbs_0); - tmp_13 *= lagrange_even_in_minicircuit; - tmp_13 *= scaling_factor; - std::get<12>(accumulators) += tmp_13; - // Contribution 14 , accumulator second limb decomposition - auto tmp_14 = ((accumulator_low_limbs_range_constraint_0_shift + - accumulator_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - accumulator_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - accumulator_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - accumulator_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - accumulators_binary_limbs_1); - tmp_14 *= lagrange_even_in_minicircuit; - tmp_14 *= scaling_factor; - std::get<13>(accumulators) += tmp_14; - - // Contribution 15 , accumulator second highest limb decomposition - auto tmp_15 = - ((accumulator_high_limbs_range_constraint_0 + accumulator_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - accumulators_binary_limbs_2); - tmp_15 *= lagrange_even_in_minicircuit; - tmp_15 *= scaling_factor; - std::get<14>(accumulators) += tmp_15; - // Contribution 16 , accumulator highest limb decomposition - auto tmp_16 = ((accumulator_high_limbs_range_constraint_0_shift + - accumulator_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - accumulator_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - accumulators_binary_limbs_3); - tmp_16 *= lagrange_even_in_minicircuit; - tmp_16 *= scaling_factor; - std::get<15>(accumulators) += tmp_16; - - // Contribution 15 , quotient lowest limb decomposition - auto tmp_17 = ((quotient_low_limbs_range_constraint_0 + quotient_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_low_binary_limbs); - tmp_17 *= lagrange_even_in_minicircuit; - tmp_17 *= scaling_factor; - std::get<16>(accumulators) += tmp_17; - // Contribution 16 , quotient second lowest limb decomposition - auto tmp_18 = - ((quotient_low_limbs_range_constraint_0_shift + quotient_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - quotient_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - quotient_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - quotient_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - quotient_low_binary_limbs_shift); - tmp_18 *= lagrange_even_in_minicircuit; - tmp_18 *= scaling_factor; - std::get<17>(accumulators) += tmp_18; - - // Contribution 19 , quotient second highest limb decomposition - auto tmp_19 = ((quotient_high_limbs_range_constraint_0 + quotient_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_high_binary_limbs); - tmp_19 *= lagrange_even_in_minicircuit; - tmp_19 *= scaling_factor; - std::get<18>(accumulators) += tmp_19; - // Contribution 20 , quotient highest limb decomposition - auto tmp_20 = ((quotient_high_limbs_range_constraint_0_shift + - quotient_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - quotient_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - quotient_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - quotient_high_binary_limbs_shift); - tmp_20 *= lagrange_even_in_minicircuit; - tmp_20 *= scaling_factor; - std::get<19>(accumulators) += tmp_20; - - // Contribution 21 , decomposition of the low wide relation limb used for the bigfield relation. - // N.B. top microlimbs of relation wide limbs are stored in microlimbs for range constraints of P_x, P_y, - // accumulator and quotient. This is to save space and because these microlimbs are not used by their namesakes, - // since top limbs in 254/6-bit values use one less microlimb for the top 50/52-bit limb - auto tmp_21 = ((relation_wide_limbs_range_constraint_0 + relation_wide_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - relation_wide_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + - accumulator_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs); - tmp_21 *= lagrange_even_in_minicircuit; - tmp_21 *= scaling_factor; - std::get<20>(accumulators) += tmp_21; - - // Contribution 22 , decomposition of high relation limb - auto tmp_22 = ((relation_wide_limbs_range_constraint_0_shift + - relation_wide_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - relation_wide_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_y_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + - quotient_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs_shift); - tmp_22 *= lagrange_even_in_minicircuit; - tmp_22 *= scaling_factor; - std::get<21>(accumulators) += tmp_22; - - // Contributions enfocing a reduced range constraint on high limbs (these relation force the last microlimb in - // each limb to be more severely range constrained) - - // Contribution 23, range constrain the highest microlimb of lowest P.x limb to be 12 bits (68 % 14 = 12) - auto tmp_23 = p_x_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail; - tmp_23 *= lagrange_even_in_minicircuit; - tmp_23 *= scaling_factor; - std::get<22>(accumulators) += tmp_23; - - // Contribution 24, range constrain the highest microlimb of second lowest P.x limb to be 12 bits - auto tmp_24 = p_x_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail_shift; - tmp_24 *= lagrange_even_in_minicircuit; - tmp_24 *= scaling_factor; - std::get<23>(accumulators) += tmp_24; - - // Contribution 25, range constrain the highest microlimb of second highest P.x limb to be 12 bits - auto tmp_25 = p_x_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_high_limbs_range_constraint_tail; - tmp_25 *= lagrange_even_in_minicircuit; - tmp_25 *= scaling_factor; - std::get<24>(accumulators) += tmp_25; - - // Contribution 26, range constrain the highest microilmb of highest P.x limb to be 8 bits (50 % 14 = 8) - auto tmp_26 = (p_x_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_x_high_limbs_range_constraint_4_shift); - - tmp_26 *= lagrange_even_in_minicircuit; - tmp_26 *= scaling_factor; - std::get<25>(accumulators) += tmp_26; - - // Contribution 27, range constrain the highest microlimb of lowest P.y limb to be 12 bits (68 % 14 = 12) - auto tmp_27 = p_y_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail; - tmp_27 *= lagrange_even_in_minicircuit; - tmp_27 *= scaling_factor; - std::get<26>(accumulators) += tmp_27; - - // Contribution 28, range constrain the highest microlimb of second lowest P.y limb to be 12 bits (68 % 14 = 12) - auto tmp_28 = p_y_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail_shift; - tmp_28 *= lagrange_even_in_minicircuit; - tmp_28 *= scaling_factor; - std::get<27>(accumulators) += tmp_28; - - // Contribution 29, range constrain the highest microlimb of second highest P.y limb to be 12 bits (68 % 14 = - // 12) - auto tmp_29 = p_y_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_high_limbs_range_constraint_tail; - tmp_29 *= lagrange_even_in_minicircuit; - tmp_29 *= scaling_factor; - std::get<28>(accumulators) += tmp_29; - - // Contribution 30, range constrain the highest microlimb of highest P.y limb to be 8 bits (50 % 14 = 8) - auto tmp_30 = (p_y_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_y_high_limbs_range_constraint_4_shift); - - tmp_30 *= lagrange_even_in_minicircuit; - tmp_30 *= scaling_factor; - std::get<29>(accumulators) += tmp_30; - - // Contribution 31, range constrain the highest microlimb of low z1 limb to be 12 bits (68 % 14 = 12) - auto tmp_31 = (z_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail); - tmp_31 *= lagrange_even_in_minicircuit; - tmp_31 *= scaling_factor; - std::get<30>(accumulators) += tmp_31; - - // Contribution 32, range constrain the highest microlimb of low z2 limb to be 12 bits (68 % 14 = 12) - auto tmp_32 = (z_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail_shift); - tmp_32 *= lagrange_even_in_minicircuit; - tmp_32 *= scaling_factor; - std::get<31>(accumulators) += tmp_32; - - // Contribution 33, range constrain the highest microlimb of high z1 limb to be 4 bits (60 % 14 = 12) - auto tmp_33 = (z_high_limbs_range_constraint_4 * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail); - tmp_33 *= lagrange_even_in_minicircuit; - tmp_33 *= scaling_factor; - std::get<32>(accumulators) += tmp_33; - - // Contribution 34, range constrain the highest microlimb of high z2 limb to be 4 bits (60 % 14 = 12) - auto tmp_34 = (z_high_limbs_range_constraint_4_shift * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail_shift); - tmp_34 *= lagrange_even_in_minicircuit; - tmp_34 *= scaling_factor; - std::get<33>(accumulators) += tmp_34; - - // Contribution 35, range constrain the highest microlimb of lowest current accumulator limb to be 12 bits (68 % - // 14 = 12) - auto tmp_35 = - (accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_low_limbs_range_constraint_tail); - tmp_35 *= lagrange_even_in_minicircuit; - tmp_35 *= scaling_factor; - std::get<34>(accumulators) += tmp_35; - - // Contribution 36, range constrain the highest microlimb of second lowest current accumulator limb to be 12 - // bits (68 % 14 = 12) - auto tmp_36 = (accumulator_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - - accumulator_low_limbs_range_constraint_tail_shift); - tmp_36 *= lagrange_even_in_minicircuit; - tmp_36 *= scaling_factor; - std::get<35>(accumulators) += tmp_36; - - // Contribution 37, range constrain the highest microlimb of second highest current accumulator limb to be 12 - // bits (68 % 14 = 12) - auto tmp_37 = - (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_high_limbs_range_constraint_tail); - tmp_37 *= lagrange_even_in_minicircuit; - tmp_37 *= scaling_factor; - std::get<36>(accumulators) += tmp_37; - - // Contribution 38, range constrain the highest microlimb of highest current accumulator limb to be 8 bits (50 % - // 14 = 12) - auto tmp_38 = (accumulator_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - - accumulator_high_limbs_range_constraint_4_shift); - tmp_38 *= lagrange_even_in_minicircuit; - tmp_38 *= scaling_factor; - std::get<37>(accumulators) += tmp_38; - - // Contribution 39, range constrain the highest microlimb of lowest quotient limb to be 12 bits (68 % 14 = 12) - auto tmp_39 = (quotient_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_low_limbs_range_constraint_tail); - tmp_39 *= lagrange_even_in_minicircuit; - tmp_39 *= scaling_factor; - std::get<38>(accumulators) += tmp_39; - - // Contribution 40, range constrain the highest microlimb of second lowest quotient limb to be 12 bits (68 % 14 - // = 12) - auto tmp_40 = - (quotient_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - quotient_low_limbs_range_constraint_tail_shift); - tmp_40 *= lagrange_even_in_minicircuit; - tmp_40 *= scaling_factor; - std::get<39>(accumulators) += tmp_40; - - // Contribution 41, range constrain the highest microlimb of second highest quotient limb to be 12 bits (68 % 14 - // = 12) - auto tmp_41 = (quotient_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_high_limbs_range_constraint_tail); - tmp_41 *= lagrange_even_in_minicircuit; - tmp_41 *= scaling_factor; - std::get<40>(accumulators) += tmp_41; - - // Contribution 42, range constrain the highest microlimb of highest quotient limb to be 10 bits (52 % 14 = 12) - auto tmp_42 = - (quotient_high_limbs_range_constraint_3_shift * SHIFT_10_TO_14 - quotient_high_limbs_range_constraint_4_shift); - tmp_42 *= lagrange_even_in_minicircuit; - tmp_42 *= scaling_factor; - std::get<41>(accumulators) += tmp_42; - - // Contributions where we decompose initial EccOpQueue values into 68-bit limbs - - // Contribution 43, decompose x_lo - auto tmp_43 = (p_x_low_limbs + p_x_low_limbs_shift * LIMB_SHIFT) - x_lo_y_hi; - tmp_43 *= lagrange_even_in_minicircuit; - tmp_43 *= scaling_factor; - std::get<42>(accumulators) += tmp_43; - - // Contribution 44, decompose x_hi - auto tmp_44 = (p_x_high_limbs + p_x_high_limbs_shift * LIMB_SHIFT) - x_hi_z_1; - tmp_44 *= lagrange_even_in_minicircuit; - tmp_44 *= scaling_factor; - std::get<43>(accumulators) += tmp_44; - // Contribution 45, decompose y_lo - auto tmp_45 = (p_y_low_limbs + p_y_low_limbs_shift * LIMB_SHIFT) - y_lo_z_2; - tmp_45 *= lagrange_even_in_minicircuit; - tmp_45 *= scaling_factor; - std::get<44>(accumulators) += tmp_45; - - // Contribution 46, decompose y_hi - auto tmp_46 = (p_y_high_limbs + p_y_high_limbs_shift * LIMB_SHIFT) - x_lo_y_hi_shift; - tmp_46 *= lagrange_even_in_minicircuit; - tmp_46 *= scaling_factor; - std::get<45>(accumulators) += tmp_46; - - // Contribution 47, decompose z1 - auto tmp_47 = (z_low_limbs + z_high_limbs * LIMB_SHIFT) - x_hi_z_1_shift; - tmp_47 *= lagrange_even_in_minicircuit; - tmp_47 *= scaling_factor; - std::get<46>(accumulators) += tmp_47; - - // Contribution 48, decompose z2 - auto tmp_48 = (z_low_limbs_shift + z_high_limbs_shift * LIMB_SHIFT) - y_lo_z_2_shift; - tmp_48 *= lagrange_even_in_minicircuit; - tmp_48 *= scaling_factor; - std::get<47>(accumulators) += tmp_48; + // Contribution 13, accumulator lowest limb decomposition + [&]() { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + // Values to multiply an element by to perform an appropriate shift + static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + + auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); + auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); + auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); + auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); + auto accumulator_low_limbs_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); + auto accumulator_low_limbs_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); + auto accumulator_low_limbs_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); + auto accumulator_low_limbs_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); + auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); + auto accumulator_low_limbs_range_constraint_0_shift = View(in.accumulator_low_limbs_range_constraint_0_shift); + auto accumulator_low_limbs_range_constraint_1_shift = View(in.accumulator_low_limbs_range_constraint_1_shift); + auto accumulator_low_limbs_range_constraint_2_shift = View(in.accumulator_low_limbs_range_constraint_2_shift); + auto accumulator_low_limbs_range_constraint_3_shift = View(in.accumulator_low_limbs_range_constraint_3_shift); + auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); + auto accumulator_high_limbs_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); + auto accumulator_high_limbs_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); + auto accumulator_high_limbs_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); + auto accumulator_high_limbs_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); + auto accumulator_high_limbs_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); + auto accumulator_high_limbs_range_constraint_0_shift = View(in.accumulator_high_limbs_range_constraint_0_shift); + auto accumulator_high_limbs_range_constraint_1_shift = View(in.accumulator_high_limbs_range_constraint_1_shift); + auto accumulator_high_limbs_range_constraint_2_shift = View(in.accumulator_high_limbs_range_constraint_2_shift); + auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); + auto op = View(in.op); + auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); + + // Contribution 13, accumulator lowest limb decomposition + auto tmp_1 = + ((accumulator_low_limbs_range_constraint_0 + accumulator_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + accumulators_binary_limbs_0); + tmp_1 *= lagrange_even_in_minicircuit * op; + tmp_1 *= scaling_factor; + std::get<0>(accumulators) += tmp_1; + + // Contribution 14, accumulator second limb decomposition + auto tmp_2 = ((accumulator_low_limbs_range_constraint_0_shift + + accumulator_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + accumulator_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + accumulator_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + accumulator_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + accumulators_binary_limbs_1); + tmp_2 *= lagrange_even_in_minicircuit * op; + tmp_2 *= scaling_factor; + std::get<1>(accumulators) += tmp_2; + + // Contribution 15, accumulator second highest limb decomposition + auto tmp_3 = + ((accumulator_high_limbs_range_constraint_0 + accumulator_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + accumulators_binary_limbs_2); + tmp_3 *= lagrange_even_in_minicircuit * op; + tmp_3 *= scaling_factor; + std::get<2>(accumulators) += tmp_3; + + // Contribution 16, accumulator highest limb decomposition + auto tmp_4 = ((accumulator_high_limbs_range_constraint_0_shift + + accumulator_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + accumulator_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + accumulators_binary_limbs_3); + tmp_4 *= lagrange_even_in_minicircuit * op; + tmp_4 *= scaling_factor; + std::get<3>(accumulators) += tmp_4; + }(); + + [&]() { + using Accumulator = std::tuple_element_t<4, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + // Value to multiply an element by to perform an appropriate shift + static auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); + + // Values to multiply an element by to perform an appropriate shift + static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; + + auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); + auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); + auto accumulator_high_limbs_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); + + // Shifts used to constrain ranges further + static auto SHIFT_12_TO_14 = + FF(4); // Shift used to range constrain the last microlimb of 68-bit limbs (standard limbs) + static auto SHIFT_10_TO_14 = + FF(16); // Shift used to range constrain the last microlimb of 52-bit limb (top quotient limb) + static auto SHIFT_8_TO_14 = FF(64); // Shift used to range constrain the last microlimb of 50-bit + // limbs (top limb of standard 254-bit value) + static auto SHIFT_4_TO_14 = + FF(1024); // Shift used to range constrain the last mircrolimb of 60-bit limbs from z scalars + + auto p_x_low_limbs = View(in.p_x_low_limbs); + auto p_x_low_limbs_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); + auto p_x_low_limbs_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); + auto p_x_low_limbs_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); + auto p_x_low_limbs_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); + auto p_x_low_limbs_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); + auto p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); + auto p_x_low_limbs_range_constraint_0_shift = View(in.p_x_low_limbs_range_constraint_0_shift); + auto p_x_low_limbs_range_constraint_1_shift = View(in.p_x_low_limbs_range_constraint_1_shift); + auto p_x_low_limbs_range_constraint_2_shift = View(in.p_x_low_limbs_range_constraint_2_shift); + auto p_x_low_limbs_range_constraint_3_shift = View(in.p_x_low_limbs_range_constraint_3_shift); + auto p_x_low_limbs_range_constraint_4_shift = View(in.p_x_low_limbs_range_constraint_4_shift); + auto p_x_high_limbs = View(in.p_x_high_limbs); + auto p_x_high_limbs_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); + auto p_x_high_limbs_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); + auto p_x_high_limbs_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); + auto p_x_high_limbs_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); + auto p_x_high_limbs_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); + auto p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); + auto p_x_high_limbs_range_constraint_0_shift = View(in.p_x_high_limbs_range_constraint_0_shift); + auto p_x_high_limbs_range_constraint_1_shift = View(in.p_x_high_limbs_range_constraint_1_shift); + auto p_x_high_limbs_range_constraint_2_shift = View(in.p_x_high_limbs_range_constraint_2_shift); + auto p_x_high_limbs_range_constraint_3_shift = View(in.p_x_high_limbs_range_constraint_3_shift); + auto p_y_low_limbs = View(in.p_y_low_limbs); + auto p_y_low_limbs_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); + auto p_y_low_limbs_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); + auto p_y_low_limbs_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); + auto p_y_low_limbs_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); + auto p_y_low_limbs_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); + auto p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); + auto p_y_low_limbs_range_constraint_0_shift = View(in.p_y_low_limbs_range_constraint_0_shift); + auto p_y_low_limbs_range_constraint_1_shift = View(in.p_y_low_limbs_range_constraint_1_shift); + auto p_y_low_limbs_range_constraint_2_shift = View(in.p_y_low_limbs_range_constraint_2_shift); + auto p_y_low_limbs_range_constraint_3_shift = View(in.p_y_low_limbs_range_constraint_3_shift); + auto p_y_low_limbs_range_constraint_4_shift = View(in.p_y_low_limbs_range_constraint_4_shift); + auto p_y_high_limbs = View(in.p_y_high_limbs); + auto p_y_high_limbs_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); + auto p_y_high_limbs_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); + auto p_y_high_limbs_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); + auto p_y_high_limbs_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); + auto p_y_high_limbs_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); + auto p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); + auto p_y_high_limbs_range_constraint_0_shift = View(in.p_y_high_limbs_range_constraint_0_shift); + auto p_y_high_limbs_range_constraint_1_shift = View(in.p_y_high_limbs_range_constraint_1_shift); + auto p_y_high_limbs_range_constraint_2_shift = View(in.p_y_high_limbs_range_constraint_2_shift); + auto p_y_high_limbs_range_constraint_3_shift = View(in.p_y_high_limbs_range_constraint_3_shift); + auto z_low_limbs = View(in.z_low_limbs); + auto z_low_limbs_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); + auto z_low_limbs_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); + auto z_low_limbs_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); + auto z_low_limbs_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); + auto z_low_limbs_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); + auto z_low_limbs_shift = View(in.z_low_limbs_shift); + auto z_low_limbs_range_constraint_0_shift = View(in.z_low_limbs_range_constraint_0_shift); + auto z_low_limbs_range_constraint_1_shift = View(in.z_low_limbs_range_constraint_1_shift); + auto z_low_limbs_range_constraint_2_shift = View(in.z_low_limbs_range_constraint_2_shift); + auto z_low_limbs_range_constraint_3_shift = View(in.z_low_limbs_range_constraint_3_shift); + auto z_low_limbs_range_constraint_4_shift = View(in.z_low_limbs_range_constraint_4_shift); + auto z_high_limbs = View(in.z_high_limbs); + auto z_high_limbs_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); + auto z_high_limbs_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); + auto z_high_limbs_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); + auto z_high_limbs_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); + auto z_high_limbs_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); + auto z_high_limbs_shift = View(in.z_high_limbs_shift); + auto z_high_limbs_range_constraint_0_shift = View(in.z_high_limbs_range_constraint_0_shift); + auto z_high_limbs_range_constraint_1_shift = View(in.z_high_limbs_range_constraint_1_shift); + auto z_high_limbs_range_constraint_2_shift = View(in.z_high_limbs_range_constraint_2_shift); + auto z_high_limbs_range_constraint_3_shift = View(in.z_high_limbs_range_constraint_3_shift); + auto z_high_limbs_range_constraint_4_shift = View(in.z_high_limbs_range_constraint_4_shift); + auto quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); + auto quotient_low_limbs_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); + auto quotient_low_limbs_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); + auto quotient_low_limbs_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); + auto quotient_low_limbs_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); + auto quotient_low_limbs_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); + auto quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); + auto quotient_low_limbs_range_constraint_0_shift = View(in.quotient_low_limbs_range_constraint_0_shift); + auto quotient_low_limbs_range_constraint_1_shift = View(in.quotient_low_limbs_range_constraint_1_shift); + auto quotient_low_limbs_range_constraint_2_shift = View(in.quotient_low_limbs_range_constraint_2_shift); + auto quotient_low_limbs_range_constraint_3_shift = View(in.quotient_low_limbs_range_constraint_3_shift); + auto quotient_low_limbs_range_constraint_4_shift = View(in.quotient_low_limbs_range_constraint_4_shift); + auto quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); + auto quotient_high_limbs_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); + auto quotient_high_limbs_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); + auto quotient_high_limbs_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); + auto quotient_high_limbs_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); + auto quotient_high_limbs_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); + auto quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); + auto quotient_high_limbs_range_constraint_0_shift = View(in.quotient_high_limbs_range_constraint_0_shift); + auto quotient_high_limbs_range_constraint_1_shift = View(in.quotient_high_limbs_range_constraint_1_shift); + auto quotient_high_limbs_range_constraint_2_shift = View(in.quotient_high_limbs_range_constraint_2_shift); + auto quotient_high_limbs_range_constraint_3_shift = View(in.quotient_high_limbs_range_constraint_3_shift); + auto relation_wide_limbs = View(in.relation_wide_limbs); + auto relation_wide_limbs_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); + auto relation_wide_limbs_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); + auto relation_wide_limbs_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); + auto relation_wide_limbs_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); + auto p_x_high_limbs_range_constraint_tail_shift = View(in.p_x_high_limbs_range_constraint_tail_shift); + auto accumulator_high_limbs_range_constraint_tail_shift = + View(in.accumulator_high_limbs_range_constraint_tail_shift); + auto relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); + auto relation_wide_limbs_range_constraint_0_shift = View(in.relation_wide_limbs_range_constraint_0_shift); + auto relation_wide_limbs_range_constraint_1_shift = View(in.relation_wide_limbs_range_constraint_1_shift); + auto relation_wide_limbs_range_constraint_2_shift = View(in.relation_wide_limbs_range_constraint_2_shift); + auto relation_wide_limbs_range_constraint_3_shift = View(in.relation_wide_limbs_range_constraint_3_shift); + auto p_y_high_limbs_range_constraint_tail_shift = View(in.p_y_high_limbs_range_constraint_tail_shift); + auto quotient_high_limbs_range_constraint_tail_shift = View(in.quotient_high_limbs_range_constraint_tail_shift); + auto p_x_low_limbs_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); + auto p_x_low_limbs_range_constraint_tail_shift = View(in.p_x_low_limbs_range_constraint_tail_shift); + auto p_x_high_limbs_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); + auto p_x_high_limbs_range_constraint_4_shift = View(in.p_x_high_limbs_range_constraint_4_shift); + auto p_y_low_limbs_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); + auto p_y_low_limbs_range_constraint_tail_shift = View(in.p_y_low_limbs_range_constraint_tail_shift); + auto p_y_high_limbs_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); + auto p_y_high_limbs_range_constraint_4_shift = View(in.p_y_high_limbs_range_constraint_4_shift); + auto z_low_limbs_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); + auto z_low_limbs_range_constraint_tail_shift = View(in.z_low_limbs_range_constraint_tail_shift); + auto z_high_limbs_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); + auto z_high_limbs_range_constraint_tail_shift = View(in.z_high_limbs_range_constraint_tail_shift); + auto accumulator_low_limbs_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); + auto accumulator_low_limbs_range_constraint_tail_shift = + View(in.accumulator_low_limbs_range_constraint_tail_shift); + auto accumulator_high_limbs_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); + auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); + auto accumulator_high_limbs_range_constraint_4_shift = View(in.accumulator_high_limbs_range_constraint_4_shift); + auto quotient_low_limbs_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); + auto quotient_low_limbs_range_constraint_tail_shift = View(in.quotient_low_limbs_range_constraint_tail_shift); + auto quotient_high_limbs_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); + auto quotient_high_limbs_range_constraint_4_shift = View(in.quotient_high_limbs_range_constraint_4_shift); + auto x_lo_y_hi = View(in.x_lo_y_hi); + auto x_hi_z_1 = View(in.x_hi_z_1); + auto y_lo_z_2 = View(in.y_lo_z_2); + auto x_lo_y_hi_shift = View(in.x_lo_y_hi_shift); + auto x_hi_z_1_shift = View(in.x_hi_z_1_shift); + auto y_lo_z_2_shift = View(in.y_lo_z_2_shift); + auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); + + // Contribution 5 , P_y lowest limb decomposition + auto tmp_5 = ((p_y_low_limbs_range_constraint_0 + p_y_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_low_limbs); + tmp_5 *= lagrange_even_in_minicircuit; + tmp_5 *= scaling_factor; + std::get<4>(accumulators) += tmp_5; + + // Contribution 6 , P_y second lowest limb decomposition + auto tmp_6 = + ((p_y_low_limbs_range_constraint_0_shift + p_y_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_y_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_y_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_y_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + p_y_low_limbs_shift); + tmp_6 *= lagrange_even_in_minicircuit; + tmp_6 *= scaling_factor; + std::get<5>(accumulators) += tmp_6; + + // Contribution 7 , P_y third limb decomposition + auto tmp_7 = ((p_y_high_limbs_range_constraint_0 + p_y_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_high_limbs); + tmp_7 *= lagrange_even_in_minicircuit; + tmp_7 *= scaling_factor; + std::get<6>(accumulators) += tmp_7; + + // Contribution 8 , P_y highest limb decomposition + auto tmp_8 = + ((p_y_high_limbs_range_constraint_0_shift + p_y_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_y_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_y_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + p_y_high_limbs_shift); + tmp_8 *= lagrange_even_in_minicircuit; + tmp_8 *= scaling_factor; + std::get<7>(accumulators) += tmp_8; + + // Contribution 9 , z_1 low limb decomposition + auto tmp_9 = ((z_low_limbs_range_constraint_0 + z_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + z_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_low_limbs); + tmp_9 *= lagrange_even_in_minicircuit; + tmp_9 *= scaling_factor; + std::get<8>(accumulators) += tmp_9; + + // Contribution 10 , z_2 low limb decomposition + auto tmp_10 = ((z_low_limbs_range_constraint_0_shift + z_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + z_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + z_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + z_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + z_low_limbs_shift); + tmp_10 *= lagrange_even_in_minicircuit; + tmp_10 *= scaling_factor; + std::get<9>(accumulators) += tmp_10; + + // Contribution 11 , z_1 high limb decomposition + auto tmp_11 = ((z_high_limbs_range_constraint_0 + z_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + z_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_high_limbs); + tmp_11 *= lagrange_even_in_minicircuit; + tmp_11 *= scaling_factor; + std::get<10>(accumulators) += tmp_11; + + // Contribution 12 , z_2 high limb decomposition + auto tmp_12 = + ((z_high_limbs_range_constraint_0_shift + z_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + z_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + z_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + z_high_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + z_high_limbs_shift); + tmp_12 *= lagrange_even_in_minicircuit; + tmp_12 *= scaling_factor; + std::get<11>(accumulators) += tmp_12; + + // Contributions that decompose 50, 52, 68 or 84 bit limbs used for computation into range-constrained chunks + // Contribution 1 , P_x lowest limb decomposition + auto tmp_13 = ((p_x_low_limbs_range_constraint_0 + p_x_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_low_limbs); + tmp_13 *= lagrange_even_in_minicircuit; + tmp_13 *= scaling_factor; + std::get<12>(accumulators) += tmp_13; + + // Contribution 2 , P_x second lowest limb decomposition + auto tmp_14 = + ((p_x_low_limbs_range_constraint_0_shift + p_x_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_x_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_x_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_x_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + p_x_low_limbs_shift); + tmp_14 *= lagrange_even_in_minicircuit; + tmp_14 *= scaling_factor; + std::get<13>(accumulators) += tmp_14; + + // Contribution 3 , P_x third limb decomposition + auto tmp_15 = ((p_x_high_limbs_range_constraint_0 + p_x_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_high_limbs); + tmp_15 *= lagrange_even_in_minicircuit; + tmp_15 *= scaling_factor; + std::get<14>(accumulators) += tmp_15; + + // Contribution 4 , P_x highest limb decomposition + auto tmp_16 = + ((p_x_high_limbs_range_constraint_0_shift + p_x_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_x_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_x_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + p_x_high_limbs_shift); + tmp_16 *= lagrange_even_in_minicircuit; + tmp_16 *= scaling_factor; + std::get<15>(accumulators) += tmp_16; + + // Contribution 15 , quotient lowest limb decomposition + auto tmp_17 = + ((quotient_low_limbs_range_constraint_0 + quotient_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_low_binary_limbs); + tmp_17 *= lagrange_even_in_minicircuit; + tmp_17 *= scaling_factor; + std::get<16>(accumulators) += tmp_17; + // Contribution 16 , quotient second lowest limb decomposition + auto tmp_18 = ((quotient_low_limbs_range_constraint_0_shift + + quotient_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + quotient_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + quotient_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + quotient_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + quotient_low_binary_limbs_shift); + tmp_18 *= lagrange_even_in_minicircuit; + tmp_18 *= scaling_factor; + std::get<17>(accumulators) += tmp_18; + + // Contribution 19 , quotient second highest limb decomposition + auto tmp_19 = + ((quotient_high_limbs_range_constraint_0 + quotient_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_high_binary_limbs); + tmp_19 *= lagrange_even_in_minicircuit; + tmp_19 *= scaling_factor; + std::get<18>(accumulators) += tmp_19; + // Contribution 20 , quotient highest limb decomposition + auto tmp_20 = ((quotient_high_limbs_range_constraint_0_shift + + quotient_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + quotient_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + quotient_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + quotient_high_binary_limbs_shift); + tmp_20 *= lagrange_even_in_minicircuit; + tmp_20 *= scaling_factor; + std::get<19>(accumulators) += tmp_20; + + // Contribution 21 , decomposition of the low wide relation limb used for the bigfield relation. + // N.B. top microlimbs of relation wide limbs are stored in microlimbs for range constraints of P_x, P_y, + // accumulator and quotient. This is to save space and because these microlimbs are not used by their namesakes, + // since top limbs in 254/6-bit values use one less microlimb for the top 50/52-bit limb + auto tmp_21 = + ((relation_wide_limbs_range_constraint_0 + relation_wide_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + relation_wide_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + + accumulator_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs); + tmp_21 *= lagrange_even_in_minicircuit; + tmp_21 *= scaling_factor; + std::get<20>(accumulators) += tmp_21; + + // Contribution 22 , decomposition of high relation limb + auto tmp_22 = ((relation_wide_limbs_range_constraint_0_shift + + relation_wide_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + relation_wide_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_y_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + + quotient_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs_shift); + tmp_22 *= lagrange_even_in_minicircuit; + tmp_22 *= scaling_factor; + std::get<21>(accumulators) += tmp_22; + + // Contributions enfocing a reduced range constraint on high limbs (these relation force the last microlimb in + // each limb to be more severely range constrained) + + // Contribution 23, range constrain the highest microlimb of lowest P.x limb to be 12 bits (68 % 14 = 12) + auto tmp_23 = p_x_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail; + tmp_23 *= lagrange_even_in_minicircuit; + tmp_23 *= scaling_factor; + std::get<22>(accumulators) += tmp_23; + + // Contribution 24, range constrain the highest microlimb of second lowest P.x limb to be 12 bits + auto tmp_24 = + p_x_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail_shift; + tmp_24 *= lagrange_even_in_minicircuit; + tmp_24 *= scaling_factor; + std::get<23>(accumulators) += tmp_24; + + // Contribution 25, range constrain the highest microlimb of second highest P.x limb to be 12 bits + auto tmp_25 = p_x_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_high_limbs_range_constraint_tail; + tmp_25 *= lagrange_even_in_minicircuit; + tmp_25 *= scaling_factor; + std::get<24>(accumulators) += tmp_25; + + // Contribution 26, range constrain the highest microilmb of highest P.x limb to be 8 bits (50 % 14 = 8) + auto tmp_26 = + (p_x_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_x_high_limbs_range_constraint_4_shift); + + tmp_26 *= lagrange_even_in_minicircuit; + tmp_26 *= scaling_factor; + std::get<25>(accumulators) += tmp_26; + + // Contribution 27, range constrain the highest microlimb of lowest P.y limb to be 12 bits (68 % 14 = 12) + auto tmp_27 = p_y_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail; + tmp_27 *= lagrange_even_in_minicircuit; + tmp_27 *= scaling_factor; + std::get<26>(accumulators) += tmp_27; + + // Contribution 28, range constrain the highest microlimb of second lowest P.y limb to be 12 bits (68 % 14 = 12) + auto tmp_28 = + p_y_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail_shift; + tmp_28 *= lagrange_even_in_minicircuit; + tmp_28 *= scaling_factor; + std::get<27>(accumulators) += tmp_28; + + // Contribution 29, range constrain the highest microlimb of second highest P.y limb to be 12 bits (68 % 14 = + // 12) + auto tmp_29 = p_y_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_high_limbs_range_constraint_tail; + tmp_29 *= lagrange_even_in_minicircuit; + tmp_29 *= scaling_factor; + std::get<28>(accumulators) += tmp_29; + + // Contribution 30, range constrain the highest microlimb of highest P.y limb to be 8 bits (50 % 14 = 8) + auto tmp_30 = + (p_y_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_y_high_limbs_range_constraint_4_shift); + + tmp_30 *= lagrange_even_in_minicircuit; + tmp_30 *= scaling_factor; + std::get<29>(accumulators) += tmp_30; + + // Contribution 31, range constrain the highest microlimb of low z1 limb to be 12 bits (68 % 14 = 12) + auto tmp_31 = (z_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail); + tmp_31 *= lagrange_even_in_minicircuit; + tmp_31 *= scaling_factor; + std::get<30>(accumulators) += tmp_31; + + // Contribution 32, range constrain the highest microlimb of low z2 limb to be 12 bits (68 % 14 = 12) + auto tmp_32 = (z_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail_shift); + tmp_32 *= lagrange_even_in_minicircuit; + tmp_32 *= scaling_factor; + std::get<31>(accumulators) += tmp_32; + + // Contribution 33, range constrain the highest microlimb of high z1 limb to be 4 bits (60 % 14 = 12) + auto tmp_33 = (z_high_limbs_range_constraint_4 * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail); + tmp_33 *= lagrange_even_in_minicircuit; + tmp_33 *= scaling_factor; + std::get<32>(accumulators) += tmp_33; + + // Contribution 34, range constrain the highest microlimb of high z2 limb to be 4 bits (60 % 14 = 12) + auto tmp_34 = + (z_high_limbs_range_constraint_4_shift * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail_shift); + tmp_34 *= lagrange_even_in_minicircuit; + tmp_34 *= scaling_factor; + std::get<33>(accumulators) += tmp_34; + + // Contribution 35, range constrain the highest microlimb of lowest current accumulator limb to be 12 bits (68 % + // 14 = 12) + auto tmp_35 = + (accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_low_limbs_range_constraint_tail); + tmp_35 *= lagrange_even_in_minicircuit; + tmp_35 *= scaling_factor; + std::get<34>(accumulators) += tmp_35; + + // Contribution 36, range constrain the highest microlimb of second lowest current accumulator limb to be 12 + // bits (68 % 14 = 12) + auto tmp_36 = (accumulator_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - + accumulator_low_limbs_range_constraint_tail_shift); + tmp_36 *= lagrange_even_in_minicircuit; + tmp_36 *= scaling_factor; + std::get<35>(accumulators) += tmp_36; + + // Contribution 37, range constrain the highest microlimb of second highest current accumulator limb to be 12 + // bits (68 % 14 = 12) + auto tmp_37 = + (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_high_limbs_range_constraint_tail); + tmp_37 *= lagrange_even_in_minicircuit; + tmp_37 *= scaling_factor; + std::get<36>(accumulators) += tmp_37; + + // Contribution 38, range constrain the highest microlimb of highest current accumulator limb to be 8 bits (50 % + // 14 = 12) + auto tmp_38 = (accumulator_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - + accumulator_high_limbs_range_constraint_4_shift); + tmp_38 *= lagrange_even_in_minicircuit; + tmp_38 *= scaling_factor; + std::get<37>(accumulators) += tmp_38; + + // Contribution 39, range constrain the highest microlimb of lowest quotient limb to be 12 bits (68 % 14 = 12) + auto tmp_39 = + (quotient_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_low_limbs_range_constraint_tail); + tmp_39 *= lagrange_even_in_minicircuit; + tmp_39 *= scaling_factor; + std::get<38>(accumulators) += tmp_39; + + // Contribution 40, range constrain the highest microlimb of second lowest quotient limb to be 12 bits (68 % 14 + // = 12) + auto tmp_40 = (quotient_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - + quotient_low_limbs_range_constraint_tail_shift); + tmp_40 *= lagrange_even_in_minicircuit; + tmp_40 *= scaling_factor; + std::get<39>(accumulators) += tmp_40; + + // Contribution 41, range constrain the highest microlimb of second highest quotient limb to be 12 bits (68 % 14 + // = 12) + auto tmp_41 = + (quotient_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_high_limbs_range_constraint_tail); + tmp_41 *= lagrange_even_in_minicircuit; + tmp_41 *= scaling_factor; + std::get<40>(accumulators) += tmp_41; + + // Contribution 42, range constrain the highest microlimb of highest quotient limb to be 10 bits (52 % 14 = 12) + auto tmp_42 = (quotient_high_limbs_range_constraint_3_shift * SHIFT_10_TO_14 - + quotient_high_limbs_range_constraint_4_shift); + tmp_42 *= lagrange_even_in_minicircuit; + tmp_42 *= scaling_factor; + std::get<41>(accumulators) += tmp_42; + + // Contributions where we decompose initial EccOpQueue values into 68-bit limbs + + // Contribution 43, decompose x_lo + auto tmp_43 = (p_x_low_limbs + p_x_low_limbs_shift * LIMB_SHIFT) - x_lo_y_hi; + tmp_43 *= lagrange_even_in_minicircuit; + tmp_43 *= scaling_factor; + std::get<42>(accumulators) += tmp_43; + + // Contribution 44, decompose x_hi + auto tmp_44 = (p_x_high_limbs + p_x_high_limbs_shift * LIMB_SHIFT) - x_hi_z_1; + tmp_44 *= lagrange_even_in_minicircuit; + tmp_44 *= scaling_factor; + std::get<43>(accumulators) += tmp_44; + // Contribution 45, decompose y_lo + auto tmp_45 = (p_y_low_limbs + p_y_low_limbs_shift * LIMB_SHIFT) - y_lo_z_2; + tmp_45 *= lagrange_even_in_minicircuit; + tmp_45 *= scaling_factor; + std::get<44>(accumulators) += tmp_45; + + // Contribution 46, decompose y_hi + auto tmp_46 = (p_y_high_limbs + p_y_high_limbs_shift * LIMB_SHIFT) - x_lo_y_hi_shift; + tmp_46 *= lagrange_even_in_minicircuit; + tmp_46 *= scaling_factor; + std::get<45>(accumulators) += tmp_46; + + // Contribution 47, decompose z1 + auto tmp_47 = (z_low_limbs + z_high_limbs * LIMB_SHIFT) - x_hi_z_1_shift; + tmp_47 *= lagrange_even_in_minicircuit; + tmp_47 *= scaling_factor; + std::get<46>(accumulators) += tmp_47; + + // Contribution 48, decompose z2 + auto tmp_48 = (z_low_limbs_shift + z_high_limbs_shift * LIMB_SHIFT) - y_lo_z_2_shift; + tmp_48 *= lagrange_even_in_minicircuit; + tmp_48 *= scaling_factor; + std::get<47>(accumulators) += tmp_48; + }(); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp index 344988a16082..10668dd50350 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp @@ -15,15 +15,22 @@ template class TranslatorOpcodeConstraintRelationImpl { // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // degree((lagrange_masking - 1)⋅op ⋅(op - 3)⋅(op - 4)⋅(op - 8)) = 5 - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 6 // opcode constraint relation + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 7, // opcode constraint relation + 7, // opcode constraint relation + 7, // opcode constraint relation + 7, // opcode constraint relation + 7 // opcode constraint relation }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * */ - template inline static bool skip(const AllEntities& in) { return in.op.is_zero(); } + template inline static bool skip(const AllEntities& in) + { + return in.lagrange_even_in_minicircuit.is_zero(); + } /** * @brief Expression for enforcing the value of the Opcode to be {0,3,4,8} * @details This relation enforces the opcode to be one of described values. Since we don't care about even diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp index 860946261690..c08a2e326177 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp @@ -33,18 +33,69 @@ void TranslatorOpcodeConstraintRelationImpl::accumulate(ContainerOverSubrela auto op = View(in.op); auto lagrange_mini_masking = View(in.lagrange_mini_masking); + auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); static const FF minus_three = FF(-3); static const FF minus_four = FF(-4); static const FF minus_eight = FF(-8); static const FF minus_one = FF(-1); + auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); + auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); + auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); + auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); + auto accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); + auto accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); + auto accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); + auto accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); + // Contribution (1) op(op-3)(op-4)(op-8)) auto tmp_1 = op * (op + minus_three); tmp_1 *= (op + minus_four); tmp_1 *= (op + minus_eight); tmp_1 *= (lagrange_mini_masking + minus_one); + tmp_1 *= lagrange_even_in_minicircuit; tmp_1 *= scaling_factor; std::get<0>(accumulators) += tmp_1; + + // Contribution (2) (2-5 ensure that the accumulator stays the same at even indices) + auto tmp_2 = (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); + tmp_2 *= (op + minus_three); + tmp_2 *= (op + minus_four); + tmp_2 *= (op + minus_eight); + tmp_2 *= (lagrange_mini_masking + minus_one); + tmp_2 *= lagrange_even_in_minicircuit; + tmp_2 *= scaling_factor; + std::get<1>(accumulators) += tmp_2; + + // Contribution (3) + auto tmp_3 = (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); + tmp_3 *= (op + minus_three); + tmp_3 *= (op + minus_four); + tmp_3 *= (op + minus_eight); + tmp_3 *= (lagrange_mini_masking + minus_one); + tmp_3 *= lagrange_even_in_minicircuit; + tmp_3 *= scaling_factor; + std::get<2>(accumulators) += tmp_3; + + // Contribution (4) + auto tmp_4 = (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); + tmp_4 *= (op + minus_three); + tmp_4 *= (op + minus_four); + tmp_4 *= (op + minus_eight); + tmp_4 *= (lagrange_mini_masking + minus_one); + tmp_4 *= lagrange_even_in_minicircuit; + tmp_4 *= scaling_factor; + std::get<3>(accumulators) += tmp_4; + + // Contribution (5) + auto tmp_5 = (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); + tmp_5 *= (op + minus_three); + tmp_5 *= (op + minus_four); + tmp_5 *= (op + minus_eight); + tmp_5 *= (lagrange_mini_masking + minus_one); + tmp_5 *= lagrange_even_in_minicircuit; + tmp_5 *= scaling_factor; + std::get<4>(accumulators) += tmp_5; }; /** diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp index 219a208a957e..b3b4839dccd9 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp @@ -16,9 +16,9 @@ template class TranslatorNonNativeFieldRelationImpl { // 1 + polynomial degree of this relation static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, // Lower wide limb subrelation (checks result is 0 mod 2¹³⁶) - 3, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), - 3 // Prime subrelation (checks result in native field) + 4, // Lower wide limb subrelation (checks result is 0 mod 2¹³⁶) + 4, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), + 4 // Prime subrelation (checks result in native field) }; /** diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index 6e5ed427eee4..8b8094deb9b6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -183,7 +183,7 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati // clang-format on // subtract large value; vanishing shows the desired relation holds on low 136-bit limb tmp -= relation_wide_limbs * shiftx2; - tmp *= lagrange_even_in_minicircuit; + tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<0>(accumulators) += tmp; @@ -236,7 +236,7 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati // clang-format on // subtract large value; vanishing shows the desired relation holds on high 136-bit limb tmp -= relation_wide_limbs_shift * shiftx2; - tmp *= lagrange_even_in_minicircuit; + tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<1>(accumulators) += tmp; @@ -278,7 +278,7 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; // clang-format on - tmp *= lagrange_even_in_minicircuit; + tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<2>(accumulators) += tmp; }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 9886a62ffd25..243689c24e10 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -168,8 +168,8 @@ template ecc_op_tuple MegaCircuitBuilder_::populate_ecc_op_wir op_tuple.z_2 = this->add_variable(ultra_op.z_2); // Set the indices for the op values for each of the two rows - uint32_t op_val_idx_1 = op_tuple.op; // genuine op code value - uint32_t op_val_idx_2 = this->zero_idx; // second row value always set to 0 + uint32_t op_val_idx_1 = op_tuple.op; // genuine op code value + uint32_t op_val_idx_2 = op_tuple.op; // second row value always set to 0 // If this is a random operation, the op values are randomized if (ultra_op.op_code.is_random_op) { op_val_idx_1 = this->add_variable(ultra_op.op_code.random_value_1); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 03a9b4389429..3c66be790824 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -751,7 +751,7 @@ template class SumcheckVerifier { const bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); - + info("round result: ", checked); verified = verified && checked; } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 46fb3a8c30cb..961ae97df069 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -93,11 +93,11 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; } - constexpr size_t NUMBER_OF_POSSIBLE_OPCODES = 4; - constexpr std::array possible_opcode_values = { 0, 3, 4, 8 }; + constexpr size_t NUMBER_OF_POSSIBLE_OPCODES = 3; + constexpr std::array possible_opcode_values = { 3, 4, 8 }; // Assign random opcode values - for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { + for (size_t i = 2; i < mini_circuit_size; i++) { prover_polynomials.op.at(i) = possible_opcode_values[static_cast(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)]; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 0420ca323b9b..f53913acac97 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -1,5 +1,6 @@ #include "barretenberg/circuit_checker/translator_circuit_checker.hpp" #include "barretenberg/common/log.hpp" +#include "barretenberg/honk/relation_checker.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/sumcheck/sumcheck_round.hpp" @@ -37,10 +38,20 @@ class TranslatorTests : public ::testing::Test { auto op_queue = std::make_shared(); op_queue->no_op_ultra_only(); - for (size_t i = 0; i < circuit_size_parameter; i++) { + for (size_t i = 0; i < circuit_size_parameter / 2; i++) { op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); } + op_queue->eq_and_reset(); + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + for (size_t i = 0; i < circuit_size_parameter / 2; i++) { + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + } + op_queue->merge(); return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; @@ -91,9 +102,12 @@ TEST_F(TranslatorTests, Basic) EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); auto proving_key = std::make_shared(circuit_builder); + TranslatorProver prover{ proving_key, prover_transcript }; auto proof = prover.construct_proof(); + // RelationChecker::check>( + // proving_key->proving_key->polynomials, prover.relation_parameters, "TranslatorOpcodeConstraintRelation"); auto verifier_transcript = std::make_shared(); verifier_transcript->load_proof(initial_transcript); verifier_transcript->template receive_from_prover("init"); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index efb75138f0e2..61ad6382af4f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -405,7 +405,7 @@ void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra auto& op_wire = std::get(wires); op_wire.push_back(add_variable(ultra_op.op_code.value())); // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(zero_idx); + op_wire.push_back(add_variable(ultra_op.op_code.value())); insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); @@ -528,19 +528,21 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // add two zeros for consistency. // TODO(https://github.com/AztecProtocol/barretenberg/issues/1360): We'll also have to eventually process random // data in the merge protocol (added for zero knowledge)/ - populate_wires_from_ultra_op(ultra_ops[0]); + // populate_wires_from_ultra_op(ultra_ops[0]); for (auto& wire : wires) { - if (wire.empty()) { - wire.push_back(zero_idx); - wire.push_back(zero_idx); - } + wire.push_back(add_variable(zero_idx)); + wire.push_back(add_variable(zero_idx)); } num_gates += 2; // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices. We need to know the previous accumulator to create the gate for (size_t i = 1; i < ultra_ops.size(); i++) { + const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; + if (ultra_op.op_code.value() == 0) { + continue; + } current_accumulator *= evaluation_input_x; const auto [x_256, y_256] = ultra_op.get_base_point_standard_form(); current_accumulator += @@ -555,10 +557,29 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // We don't care about the last value since we'll recompute it during witness generation anyway accumulator_trace.pop_back(); + std::array previous_accumulator_binary_limbs; // Generate witness values from all the UltraOps for (size_t i = 1; i < ultra_ops.size(); i++) { const auto& ultra_op = ultra_ops[i]; - Fq previous_accumulator = 0; + if (ultra_op.op_code.value() == 0) { + for (size_t j = 0; j < ACCUMULATORS_BINARY_LIMBS_0; j++) { + wires[j].push_back(add_variable(zero_idx)); + wires[j].push_back(add_variable(zero_idx)); + } + size_t idx = 0; + for (size_t j = ACCUMULATORS_BINARY_LIMBS_0; j < ACCUMULATORS_BINARY_LIMBS_3 + 1; j++) { + wires[j].push_back(add_variable(previous_accumulator_binary_limbs[idx])); + wires[j].push_back(add_variable(previous_accumulator_binary_limbs[idx])); + idx++; + } + for (size_t j = ACCUMULATORS_BINARY_LIMBS_3 + 1; j < TOTAL_COUNT; j++) { + wires[j].push_back(add_variable(zero_idx)); + wires[j].push_back(add_variable(zero_idx)); + } + num_gates += 2; + continue; + } + Fq previous_accumulator{ 0 }; // Pop the last value from accumulator trace and use it as previous accumulator if (!accumulator_trace.empty()) { previous_accumulator = accumulator_trace.back(); @@ -567,7 +588,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // Compute witness values AccumulationInput one_accumulation_step = generate_witness_values(ultra_op, previous_accumulator, batching_challenge_v, evaluation_input_x); - + previous_accumulator_binary_limbs = one_accumulation_step.previous_accumulator; // And put them into the wires create_accumulation_gate(one_accumulation_step); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 996cb07102ba..1cdadd25c2a6 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -89,6 +89,14 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) op_queue->no_op_ultra_only(); op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + Fq op_accumulator = 0; Fq p_x_accumulator = 0; Fq p_y_accumulator = 0; @@ -97,7 +105,6 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) Fq batching_challenge = fq::random_element(); op_queue->eq_and_reset(); - op_queue->empty_row_for_testing(); op_queue->merge(); // Sample the evaluation input x @@ -108,6 +115,9 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) const auto& ultra_ops = op_queue->get_ultra_ops(); for (size_t i = 1; i < ultra_ops.size(); i++) { const auto& ecc_op = ultra_ops[i]; + if (ecc_op.op_code.value() == 0) { + continue; + } op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); p_x_accumulator = p_x_accumulator * x_inv + x_u256; @@ -116,7 +126,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); } // The degree is ultra_ops.size() - 2 as we ignore the first no-op in computation - Fq x_pow = x.pow(ultra_ops.size() - 2); + Fq x_pow = x.pow(ultra_ops.size() - 5); // Multiply by an appropriate power of x to get rid of the inverses Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index f1b6fb639b5d..7d9102895451 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -74,6 +74,7 @@ class TranslatorProvingKey { // at the end. for (size_t idx = Flavor::NUM_OP_QUEUE_WIRES; idx < wires.size(); idx++) { auto& wire = wires[idx]; + info("wire end index: ", wire.end_index()); for (size_t i = wire.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i < wire.end_index(); i++) { wire.at(i) = FF::random_element(); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index da51e6401834..787e9347242c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,6 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { + info("Sumcheck verification failed"); return false; } diff --git a/proving-systems.code-workspace b/proving-systems.code-workspace index d7f8fc1ce580..e3826976c9fe 100644 --- a/proving-systems.code-workspace +++ b/proving-systems.code-workspace @@ -1,150 +1,146 @@ { - // Each "folder" can define a different project in the main repo, - // relative to `.code-workspace`. - "folders": [ - { - "name": "aztec-packages", - "path": "./" - }, + // Each "folder" can define a different project in the main repo, + // relative to `.code-workspace`. + "folders": [ + { + "name": "aztec-packages", + "path": "./" + } + ], + // List recommended extensions for the whole workspace. + "extensions": { + "recommendations": [ + "GitHub.vscode-pull-request-github", + // Enables CMake integration and configuration + // for easier building + "ms-vscode.cmake-tools", + // Provides a nice UI for listing all Google Test + // tests, including launching a debug session + // for a specific test directly. + // Also provides buttons alongside test definitions. + "matepek.vscode-catch2-test-adapter", + // Integrates the `clangd` language server for + // - code formatting (clang-format) + // - static analysis (clang-tidy) + // - hints, tooltips, and more. + "llvm-vs-code-extensions.vscode-clangd", + // Better syntax highlighting for C++. + // Make sure to select one of the themes suggested + // (e.g. "Dark+") + "jeff-hykin.better-cpp-syntax", + // Handle CMakeLists.txt editing + "twxs.cmake", + // Integrates LLDB debugger + "vadimcn.vscode-lldb", + // Generate nicer Doxygen comments + "cschlosser.doxdocgen", + // Makes the CMake build output slightly + // prettier. + "IBM.output-colorizer", + "eamodio.gitlens", + "esbenp.prettier-vscode" ], - // List recommended extensions for the whole workspace. - "extensions": { - "recommendations": [ - "GitHub.vscode-pull-request-github", - // Enables CMake integration and configuration - // for easier building - "ms-vscode.cmake-tools", - // Provides a nice UI for listing all Google Test - // tests, including launching a debug session - // for a specific test directly. - // Also provides buttons alongside test definitions. - "matepek.vscode-catch2-test-adapter", - // Integrates the `clangd` language server for - // - code formatting (clang-format) - // - static analysis (clang-tidy) - // - hints, tooltips, and more. - "llvm-vs-code-extensions.vscode-clangd", - // Better syntax highlighting for C++. - // Make sure to select one of the themes suggested - // (e.g. "Dark+") - "jeff-hykin.better-cpp-syntax", - // Handle CMakeLists.txt editing - "twxs.cmake", - // Integrates LLDB debugger - "vadimcn.vscode-lldb", - // Generate nicer Doxygen comments - "cschlosser.doxdocgen", - // Makes the CMake build output slightly - // prettier. - "IBM.output-colorizer", - "eamodio.gitlens", - "esbenp.prettier-vscode" - ], - "unwantedRecommendations": [ - // The following may have been installed - // and cause some confusion when running - // tests. - // The options provided by C++ TestMate - // should be good enough. - "ms-vscode.cpptools-themes", - "hbenl.vscode-test-explorer", - "ms-vscode.test-adapter-converter", - "fredericbonnet.cmake-test-adapter", - "ms-vscode.cpptools-extension-pack", - // Used to enable GDB debugging - // Most features are disabled in `settings.json` - // which confict with `clangd` - // Since we ignore GDB, we no longer need this extension - "ms-vscode.cpptools" - ] + "unwantedRecommendations": [ + // The following may have been installed + // and cause some confusion when running + // tests. + // The options provided by C++ TestMate + // should be good enough. + "ms-vscode.cpptools-themes", + "hbenl.vscode-test-explorer", + "ms-vscode.test-adapter-converter", + "fredericbonnet.cmake-test-adapter", + "ms-vscode.cpptools-extension-pack", + // Used to enable GDB debugging + // Most features are disabled in `settings.json` + // which confict with `clangd` + // Since we ignore GDB, we no longer need this extension + "ms-vscode.cpptools" + ] + }, + // Global settings which will apply to all subprojects. + // Each subproject may have their own `.vscode/settings.json` + // for configuring extensions which are specific to a certain project. + // Some settings can only be configured here. + "settings": { + "files.associations": { + "*.tcc": "cpp" }, - // Global settings which will apply to all subprojects. - // Each subproject may have their own `.vscode/settings.json` - // for configuring extensions which are specific to a certain project. - // Some settings can only be configured here. - "settings": { - "files.associations": { - "*.tcc": "cpp", - }, - // - // Clangd. Note that this setting may be overridden by user settings - // to the default value "clangd". - // - "clangd.path": "clangd-20", - // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". - "clangd.arguments": [ - "-header-insertion=never" - ], - // - // CMake - // - // Location of base CMakeLists file - "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp/", - // - // C/C++ (should be disabled) - // - // Make sure all C++ IntelliSense features are disabled - // and don't interfere with clangd - "C_Cpp.intelliSenseEngine": "disabled", - "C_Cpp.autocomplete": "disabled", - "C_Cpp.codeAnalysis.clangTidy.codeAction.formatFixes": false, - "C_Cpp.codeAnalysis.runAutomatically": false, - "C_Cpp.configurationWarnings": "disabled", - "C_Cpp.debugShortcut": false, - "C_Cpp.default.enableConfigurationSquiggles": false, - "C_Cpp.formatting": "disabled", - "C_Cpp.vcpkg.enabled": false, - // - // TestMate - // - // Ensures tests are run from the `build` directory - // which ensures SRS can be read - "testMate.cpp.test.workingDirectory": "${command:cmake.buildDirectory}", - // Filter all binaries that are not tests or benchmarks - "testMate.cpp.test.executables": "${command:cmake.buildDirectory}/bin/*{test,Test,TEST,bench}*", - // - // Other - // - "editor.tokenColorCustomizations": { - "textMateRules": [ - { - "scope": "googletest.failed", - "settings": { - "foreground": "#f00" - } - }, - { - "scope": "googletest.passed", - "settings": { - "foreground": "#0f0" - } - }, - { - "scope": "googletest.run", - "settings": { - "foreground": "#0f0" - } - } - ] + // + // Clangd. Note that this setting may be overridden by user settings + // to the default value "clangd". + // + "clangd.path": "clangd-20", + // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". + "clangd.arguments": ["-header-insertion=never"], + // + // CMake + // + // Location of base CMakeLists file + "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp/", + // + // C/C++ (should be disabled) + // + // Make sure all C++ IntelliSense features are disabled + // and don't interfere with clangd + "C_Cpp.intelliSenseEngine": "disabled", + "C_Cpp.autocomplete": "disabled", + "C_Cpp.codeAnalysis.clangTidy.codeAction.formatFixes": false, + "C_Cpp.codeAnalysis.runAutomatically": false, + "C_Cpp.configurationWarnings": "disabled", + "C_Cpp.debugShortcut": false, + "C_Cpp.default.enableConfigurationSquiggles": false, + "C_Cpp.formatting": "disabled", + "C_Cpp.vcpkg.enabled": false, + // + // TestMate + // + // Ensures tests are run from the `build` directory + // which ensures SRS can be read + "testMate.cpp.test.workingDirectory": "${command:cmake.buildDirectory}", + // Filter all binaries that are not tests or benchmarks + "testMate.cpp.test.executables": "${command:cmake.buildDirectory}/bin/*{test,Test,TEST,bench}*", + // + // Other + // + "editor.tokenColorCustomizations": { + "textMateRules": [ + { + "scope": "googletest.failed", + "settings": { + "foreground": "#f00" + } }, - "[cpp]": { - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + { + "scope": "googletest.passed", + "settings": { + "foreground": "#0f0" + } }, - "cmake.configureArgs": [ - "-G Ninja" - ], - "cmake.useCMakePresets": "always", - "editor.inlayHints.enabled": "offUnlessPressed", - "git.detectSubmodules": false, - "testMate.cpp.discovery.loadOnStartup": false, - "testMate.cpp.debug.configTemplate": { - "type": "lldb", - "MIMode": "lldb", - "program": "${exec}", - "args": "${argsArray}", - "cwd": "${command:cmake.buildDirectory}", - "internalConsoleOptions": "openOnSessionStart", - "console": "internalConsole", + { + "scope": "googletest.run", + "settings": { + "foreground": "#0f0" + } } + ] + }, + "[cpp]": { + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" }, + "cmake.configureArgs": ["-G Ninja"], + "cmake.useCMakePresets": "always", + "editor.inlayHints.enabled": "offUnlessPressed", + "git.detectSubmodules": false, + "testMate.cpp.discovery.loadOnStartup": false, + "testMate.cpp.debug.configTemplate": { + "type": "lldb", + "MIMode": "lldb", + "program": "${exec}", + "args": "${argsArray}", + "cwd": "${command:cmake.buildDirectory}", + "internalConsoleOptions": "openOnSessionStart", + "console": "internalConsole" + } + } } From 9c492704d88b6d3ea6d3ed46e88f72d410f656d8 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 28 Aug 2025 09:41:52 +0000 Subject: [PATCH 02/35] cleanup --- .../src/barretenberg/client_ivc/client_ivc.cpp | 5 +++++ .../cpp/src/barretenberg/goblin/goblin.cpp | 1 + .../src/barretenberg/op_queue/ecc_op_queue.hpp | 15 ++++++++++----- .../barretenberg/op_queue/ecc_op_queue.test.cpp | 6 +++--- .../src/barretenberg/op_queue/ecc_ops_table.hpp | 4 ++++ .../mega_circuit_builder.cpp | 7 ++++--- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 8de0eb0bac75..637ebbd161bd 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -255,6 +255,9 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); + // placeholder for random ops + circuit.queue_ecc_no_op(); + circuit.queue_ecc_no_op(); } return { output_stdlib_verifier_accumulator, pairing_points, merged_table_commitments }; @@ -289,6 +292,8 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // TODO(https://github.com/AztecProtocol/barretenberg/issues/1511): this should check the queue is of size one and // contains an entry of type PG_TAIL, currently it might contain several entries in case it's a minimal transaction // produced by our tests which is not exactly realistic + + // WORKTODO: we should be able to remove this? bool is_tail_kernel = std::any_of(stdlib_verification_queue.begin(), stdlib_verification_queue.end(), [](const auto& entry) { return entry.type == QUEUE_TYPE::PG_TAIL; }); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index e3743c2d68a4..d29a973f8e6b 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -42,6 +42,7 @@ void Goblin::prove_translator() { PROFILE_THIS_NAME("Create TranslatorBuilder and TranslatorProver"); TranslatorBuilder translator_builder(translation_batching_challenge_v, evaluation_challenge_x, op_queue); + info("num gates intranslator ", translator_builder.num_gates); auto translator_key = std::make_shared(translator_builder, commitment_key); TranslatorProver translator_prover(translator_key, transcript); goblin_proof.translator_proof = translator_prover.construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp index 3ca4e070b853..5ac821ab9bd9 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp @@ -48,6 +48,10 @@ class ECCOpQueue { EccvmRowTracker eccvm_row_tracker; public: + static constexpr size_t OP_QUEUE_SIZE = 1 << 13; + + size_t get_unmerged_subtable_size() const { return ultra_ops_table.get_unmerged_subtable_size(); } + /** * @brief Instantiate an initial ECC op subtable. */ @@ -75,7 +79,8 @@ class ECCOpQueue { return ultra_ops_table.construct_table_columns(); } - // Construct polys corresponding to the columns of the aggregate ultra ops table, excluding the most recent subtable + // Construct polys corresponding to the columns of the aggregate ultra ops table, excluding the most recent + // subtable std::array, ULTRA_TABLE_WIDTH> construct_previous_ultra_ops_table_columns() const { return ultra_ops_table.construct_previous_table_columns(); @@ -97,8 +102,8 @@ class ECCOpQueue { size_t get_current_ultra_ops_subtable_num_rows() const { return ultra_ops_table.current_ultra_subtable_size(); } size_t get_previous_ultra_ops_table_num_rows() const { return ultra_ops_table.previous_ultra_table_size(); } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1339): Consider making the ultra and eccvm ops getters - // more memory efficient + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1339): Consider making the ultra and eccvm ops + // getters more memory efficient // Get the full table of ECCVM ops in contiguous memory; construct it if it has not been constructed already std::vector& get_eccvm_ops() @@ -225,8 +230,8 @@ class ECCOpQueue { /** * @brief Writes randomness to the ultra ops table but adds no eccvm operations. * - * @details This method is used to add randomness to the ultra ops table with the aim of randomising the commitment - * and evaluations of its corresponding columns + * @details This method is used to add randomness to the ultra ops table with the aim of randomising the + * commitment and evaluations of its corresponding columns * @return UltraOp */ UltraOp random_op_ultra_only() diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp index 5116a7501076..0a185968cc74 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp @@ -75,9 +75,9 @@ class ECCOpQueueTest { auto eccvm_table = op_queue->get_eccvm_ops(); EXPECT_EQ(eccvm_table.size(), ultra_table.size()); - for (size_t i = 0; i < eccvm_table.size(); ++i) { - EXPECT_EQ(ultra_table[2 * i], eccvm_table[i].op_code.value()); - EXPECT_EQ(ultra_table[2 * i + 1], eccvm_table[i].op_code.value()); + + for (auto [ultra_op, eccvm_op] : zip_view(ultra_table, eccvm_table)) { + EXPECT_EQ(ultra_op.op_code.value(), eccvm_op.op_code.value()); } }; }; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index f80722fa2fac..bb364a185dba 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -131,6 +131,8 @@ template class EccOpsTable { size_t num_subtables() const { return table.size(); } + size_t get_unmerged_subtable_size() const { return current_subtable.size(); } + auto& get() const { return table; } void push(const OpFormat& op) @@ -236,6 +238,8 @@ class UltraEccOpsTable { public: size_t size() const { return table.size(); } + size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } + size_t ultra_table_size() const { size_t base_size = table.size() * NUM_ROWS_PER_OP; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index d744f1c545f6..6039fbdb4e5f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -61,9 +61,10 @@ template void MegaCircuitBuilder_::add_mega_gates_to_ensure_al read_idx = this->add_variable(raw_read_idx); read_return_data(read_idx); - // add dummy mul accum op and an equality op - this->queue_ecc_mul_accum(bb::g1::affine_element::one(), 2); - this->queue_ecc_eq(); + if (op_queue->get_unmerged_subtable_size() == 0) { + this->queue_ecc_add_accum(bb::g1::affine_element::one()); + this->queue_ecc_eq(); + } } /** From b34789fa46b04b2577302b237ea101e238eaacc3 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 28 Aug 2025 13:16:50 +0000 Subject: [PATCH 03/35] cleanup and tests --- .vscode/settings.json | 2 +- .../translator_circuit_checker.cpp | 783 +++++++++--------- .../barretenberg/op_queue/ecc_ops_table.hpp | 3 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 1 - .../relation_correctness.test.cpp | 2 +- .../translator_vm/translator.test.cpp | 134 ++- .../translator_circuit_builder.cpp | 9 +- .../translator_circuit_builder.test.cpp | 135 +-- .../translator_vm/translator_proving_key.hpp | 1 - .../translator_vm/translator_verifier.cpp | 1 - proving-systems.code-workspace | 2 +- 11 files changed, 553 insertions(+), 520 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1165a9ce066c..0964715c3fdf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -167,7 +167,7 @@ // C++/Circuits settings /////////////////////////////////////// "[cpp]": { - "editor.defaultFormatter": "xaver.clang-format", + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd", "editor.formatOnSave": true }, // diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index 0d22f23f92bd..7a3f7fb0d2e5 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -85,435 +85,408 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) return mini_accumulator; }; - // TODO(https: // github.com/AztecProtocol/barretenberg/issues/1367): Report all failures more explicitly and - // consider making use of relations. - - for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { - { - // Get the values of P.x - Fr op_code = circuit.get_variable(op_wire[i]); - Fr op_code_next = circuit.get_variable(op_wire[i + 1]); - if (op_code != op_code_next) { - return report_fail("Mismatch of opcodes for the same UltraOp = ", i); + auto check_binary_limbs_equality = [&](const std::vector& first, const std::vector& second, size_t gate) { + for (const auto [first_limb, second_limb] : zip_view(first, second)) { + if (first_limb != second_limb) { + return report_fail("Binary limbs are not equal = ", gate); } + } + return true; + }; - // Current accumulator (updated value) - const std::vector current_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[i]), - circuit.get_variable(accumulators_binary_limbs_1_wire[i]), - circuit.get_variable(accumulators_binary_limbs_2_wire[i]), - circuit.get_variable(accumulators_binary_limbs_3_wire[i]), - }; - - // Previous accumulator - const std::vector previous_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_1_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_2_wire[i + 1]), - circuit.get_variable(accumulators_binary_limbs_3_wire[i + 1]), + auto check_accumulator_transfer = [&](const std::vector& previous_accumulator, size_t gate) { + if (gate % 2 != 1) { + return report_fail("accumulator transfer should only be checked at odd gates = ", gate); + } + if (gate + 1 < circuit.num_gates - 1) { + // Check that the next gate's current accumulator equals this gate's previous accumulator + const std::vector next_gate_current_accumulator = { + circuit.get_variable(accumulators_binary_limbs_0_wire[gate + 1]), + circuit.get_variable(accumulators_binary_limbs_1_wire[gate + 1]), + circuit.get_variable(accumulators_binary_limbs_2_wire[gate + 1]), + circuit.get_variable(accumulators_binary_limbs_3_wire[gate + 1]), }; - - if (op_code == 0) { - for (auto [curent_limb, previous_limb] : - zip_view(current_accumulator_binary_limbs, previous_accumulator_binary_limbs)) { - if (curent_limb != previous_limb) { - return report_fail("No-op should not change the accumulator = ", i); - } - } - // WORKTODO: check everything else is set to 0 - - size_t odd_gate_index = i + 1; - const std::vector current_accumulator_binary_limbs_copy = { - circuit.get_variable(accumulators_binary_limbs_0_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_1_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_2_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_3_wire[odd_gate_index]), - }; - if (odd_gate_index < circuit.num_gates - 1) { - size_t next_even_gate_index = i + 2; - const std::vector current_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_1_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_2_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_3_wire[next_even_gate_index]), - }; - - for (size_t j = 0; j < current_accumulator_binary_limbs.size(); j++) { - if (current_accumulator_binary_limbs_copy[j] != current_accumulator_binary_limbs[j]) { - return report_fail("accumulator copy failed at row = ", odd_gate_index); - } - } - } else { - // Check accumulator starts at zero - for (const auto& limb : current_accumulator_binary_limbs_copy) { - if (limb != Fr(0)) { - return report_fail("accumulator doesn't start with 0 = ", odd_gate_index); - } - } + if (!check_binary_limbs_equality(next_gate_current_accumulator, previous_accumulator, gate + 1)) { + return false; + } + } else { + // Check accumulator starts at zero + for (const auto& limb : previous_accumulator) { + if (limb != Fr(0)) { + return report_fail("accumulator doesn't start with 0 = ", gate + 1); } - - continue; } + } + return true; + }; - Fr p_x_lo = circuit.get_variable(x_lo_y_hi_wire[i]); - Fr p_x_hi = circuit.get_variable(x_hi_z_1_wire[i]); - Fr p_x_0 = circuit.get_variable(p_x_0_p_x_1_wire[i]); - Fr p_x_1 = circuit.get_variable(p_x_0_p_x_1_wire[i + 1]); - Fr p_x_2 = circuit.get_variable(p_x_2_p_x_3_wire[i]); - Fr p_x_3 = circuit.get_variable(p_x_2_p_x_3_wire[i + 1]); - const std::vector p_x_binary_limbs = { p_x_0, p_x_1, p_x_2, p_x_3 }; - - // P.y - Fr p_y_lo = circuit.get_variable(y_lo_z_2_wire[i]); - Fr p_y_hi = circuit.get_variable(x_lo_y_hi_wire[i + 1]); - Fr p_y_0 = circuit.get_variable(p_y_0_p_y_1_wire[i]); - Fr p_y_1 = circuit.get_variable(p_y_0_p_y_1_wire[i + 1]); - Fr p_y_2 = circuit.get_variable(p_y_2_p_y_3_wire[i]); - Fr p_y_3 = circuit.get_variable(p_y_2_p_y_3_wire[i + 1]); - const std::vector p_y_binary_limbs = { p_y_0, p_y_1, p_y_2, p_y_3 }; - // z1, z2 - Fr z_1 = circuit.get_variable(x_hi_z_1_wire[i + 1]); - Fr z_2 = circuit.get_variable(y_lo_z_2_wire[i + 1]); - - Fr z_1_lo = circuit.get_variable(z_lo_wire[i]); - Fr z_2_lo = circuit.get_variable(z_lo_wire[i + 1]); - Fr z_1_hi = circuit.get_variable(z_hi_wire[i]); - Fr z_2_hi = circuit.get_variable(z_hi_wire[i + 1]); - - const std::vector z_1_binary_limbs = { z_1_lo, z_1_hi }; - const std::vector z_2_binary_limbs = { z_2_lo, z_2_hi }; - // Relation limbs - Fr low_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i]); - Fr high_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i + 1]); - - // Quotient - const std::vector quotient_binary_limbs = { - circuit.get_variable(quotient_low_binary_limbs[i]), - circuit.get_variable(quotient_low_binary_limbs[i + 1]), - circuit.get_variable(quotient_high_binary_limbs[i]), - circuit.get_variable(quotient_high_binary_limbs[i + 1]), - }; - - const size_t NUM_MICRO_LIMBS = Builder::NUM_MICRO_LIMBS; + auto check_no_op = + [&](const std::vector& current_accumulator, const std::vector& previous_accumulator, size_t gate) { + if (!check_binary_limbs_equality(current_accumulator, previous_accumulator, gate)) { + return false; + } + return check_accumulator_transfer(previous_accumulator, gate + 1); + }; - // Get micro chunks for checking decomposition and range - auto p_x_micro_chunks = { - get_sequential_micro_chunks(i, WireIds::P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i, WireIds::P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) - }; - auto p_y_micro_chunks = { - get_sequential_micro_chunks(i, WireIds::P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i, WireIds::P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) - }; - auto z_1_micro_chunks = { - get_sequential_micro_chunks(i, WireIds::Z_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i, WireIds::Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - }; + // TODO(https: // github.com/AztecProtocol/barretenberg/issues/1367): Report all failures more explicitly and + // consider making use of relations. - auto z_2_micro_chunks = { + for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { - get_sequential_micro_chunks(i + 1, WireIds::Z_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) + // Get the values of P.x + Fr op_code = circuit.get_variable(op_wire[i]); + + // Current accumulator (updated value) + const std::vector current_accumulator_binary_limbs = { + circuit.get_variable(accumulators_binary_limbs_0_wire[i]), + circuit.get_variable(accumulators_binary_limbs_1_wire[i]), + circuit.get_variable(accumulators_binary_limbs_2_wire[i]), + circuit.get_variable(accumulators_binary_limbs_3_wire[i]), + }; + + // Previous accumulator + const std::vector previous_accumulator_binary_limbs = { + circuit.get_variable(accumulators_binary_limbs_0_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_1_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_2_wire[i + 1]), + circuit.get_variable(accumulators_binary_limbs_3_wire[i + 1]), + }; + + if (op_code == 0) { + if (!check_no_op(current_accumulator_binary_limbs, previous_accumulator_binary_limbs, i)) { + return false; }; + continue; + } - auto current_accumulator_micro_chunks = { - get_sequential_micro_chunks(i, WireIds::ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i, WireIds::ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), - }; - auto quotient_micro_chunks = { - get_sequential_micro_chunks(i, WireIds::QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i, WireIds::QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), - get_sequential_micro_chunks(i + 1, WireIds::QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), - }; + Fr p_x_lo = circuit.get_variable(x_lo_y_hi_wire[i]); + Fr p_x_hi = circuit.get_variable(x_hi_z_1_wire[i]); + Fr p_x_0 = circuit.get_variable(p_x_0_p_x_1_wire[i]); + Fr p_x_1 = circuit.get_variable(p_x_0_p_x_1_wire[i + 1]); + Fr p_x_2 = circuit.get_variable(p_x_2_p_x_3_wire[i]); + Fr p_x_3 = circuit.get_variable(p_x_2_p_x_3_wire[i + 1]); + const std::vector p_x_binary_limbs = { p_x_0, p_x_1, p_x_2, p_x_3 }; + + // P.y + Fr p_y_lo = circuit.get_variable(y_lo_z_2_wire[i]); + Fr p_y_hi = circuit.get_variable(x_lo_y_hi_wire[i + 1]); + Fr p_y_0 = circuit.get_variable(p_y_0_p_y_1_wire[i]); + Fr p_y_1 = circuit.get_variable(p_y_0_p_y_1_wire[i + 1]); + Fr p_y_2 = circuit.get_variable(p_y_2_p_y_3_wire[i]); + Fr p_y_3 = circuit.get_variable(p_y_2_p_y_3_wire[i + 1]); + const std::vector p_y_binary_limbs = { p_y_0, p_y_1, p_y_2, p_y_3 }; + // z1, z2 + Fr z_1 = circuit.get_variable(x_hi_z_1_wire[i + 1]); + Fr z_2 = circuit.get_variable(y_lo_z_2_wire[i + 1]); + + Fr z_1_lo = circuit.get_variable(z_lo_wire[i]); + Fr z_2_lo = circuit.get_variable(z_lo_wire[i + 1]); + Fr z_1_hi = circuit.get_variable(z_hi_wire[i]); + Fr z_2_hi = circuit.get_variable(z_hi_wire[i + 1]); + + const std::vector z_1_binary_limbs = { z_1_lo, z_1_hi }; + const std::vector z_2_binary_limbs = { z_2_lo, z_2_hi }; + // Relation limbs + Fr low_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i]); + Fr high_wide_relation_limb = circuit.get_variable(relation_wide_limbs_wire[i + 1]); + + // Quotient + const std::vector quotient_binary_limbs = { + circuit.get_variable(quotient_low_binary_limbs[i]), + circuit.get_variable(quotient_low_binary_limbs[i + 1]), + circuit.get_variable(quotient_high_binary_limbs[i]), + circuit.get_variable(quotient_high_binary_limbs[i + 1]), + }; + + const size_t NUM_MICRO_LIMBS = Builder::NUM_MICRO_LIMBS; + + // Get micro chunks for checking decomposition and range + auto p_x_micro_chunks = { + get_sequential_micro_chunks(i, WireIds::P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i, WireIds::P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) + }; + auto p_y_micro_chunks = { + get_sequential_micro_chunks(i, WireIds::P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i, WireIds::P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) + }; + auto z_1_micro_chunks = { + get_sequential_micro_chunks(i, WireIds::Z_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i, WireIds::Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + }; + + auto z_2_micro_chunks = { + + get_sequential_micro_chunks(i + 1, WireIds::Z_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS) + }; + + auto current_accumulator_micro_chunks = { + get_sequential_micro_chunks(i, WireIds::ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i, WireIds::ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0, NUM_MICRO_LIMBS), + }; + auto quotient_micro_chunks = { + get_sequential_micro_chunks(i, WireIds::QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i, WireIds::QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), + get_sequential_micro_chunks(i + 1, WireIds::QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_0, NUM_MICRO_LIMBS), + }; + + // Lambda for checking the correctness of decomposition of values in the Queue into limbs for + // checking the relation + auto check_wide_limb_into_binary_limb_relation = [](const std::vector& wide_limbs, + const std::vector& binary_limbs) { + BB_ASSERT_EQ(wide_limbs.size() * 2, binary_limbs.size()); + for (size_t i = 0; i < wide_limbs.size(); i++) { + if ((binary_limbs[i * 2] + Fr(Builder::SHIFT_1) * binary_limbs[i * 2 + 1]) != wide_limbs[i]) { + return false; + } + } + return true; + }; + // Check that everything has been decomposed correctly + // P.xₗₒ = P.xₗₒ_0 + SHIFT_1 * P.xₗₒ_1 + // P.xₕᵢ = P.xₕᵢ_0 + SHIFT_1 * P.xₕᵢ_1 + // z_1 = z_1ₗₒ + SHIFT_1 * z_1ₕᵢ + // z_2 = z_2ₗₒ + SHIFT_2 * z_1ₕᵢ + if (!(check_wide_limb_into_binary_limb_relation({ p_x_lo, p_x_hi }, p_x_binary_limbs) && + check_wide_limb_into_binary_limb_relation({ p_y_lo, p_y_hi }, p_y_binary_limbs) && + check_wide_limb_into_binary_limb_relation({ z_1 }, z_1_binary_limbs) && + check_wide_limb_into_binary_limb_relation({ z_2 }, z_2_binary_limbs))) { + + return report_fail("wide limb decomposition failied at row = ", i); + } - // Lambda for checking the correctness of decomposition of values in the Queue into limbs for - // checking the relation - auto check_wide_limb_into_binary_limb_relation = [](const std::vector& wide_limbs, - const std::vector& binary_limbs) { - BB_ASSERT_EQ(wide_limbs.size() * 2, binary_limbs.size()); - for (size_t i = 0; i < wide_limbs.size(); i++) { - if ((binary_limbs[i * 2] + Fr(Builder::SHIFT_1) * binary_limbs[i * 2 + 1]) != wide_limbs[i]) { + enum LimbSeriesType { STANDARD_COORDINATE, Z_SCALAR, QUOTIENT }; + + // Check that limbs have been decomposed into microlimbs correctly + // value = ∑ (2ˡ)ⁱ⋅ chunkᵢ, where 2ˡ is the shift + auto check_micro_limb_decomposition_correctness = [&accumulate_limb_from_micro_chunks]( + const std::vector& binary_limbs, + const std::vector>& micro_limbs, + const LimbSeriesType limb_series_type) { + // Shifts for decompositions + constexpr auto SHIFT_12_TO_14 = Fr(4); + constexpr auto SHIFT_10_TO_14 = Fr(16); + constexpr auto SHIFT_8_TO_14 = Fr(64); + constexpr auto SHIFT_4_TO_14 = Fr(1024); + + BB_ASSERT_EQ(binary_limbs.size(), micro_limbs.size()); + // First check that all the microlimbs are properly range constrained + for (auto& micro_limb_series : micro_limbs) { + for (auto& micro_limb : micro_limb_series) { + if (uint256_t(micro_limb) > Builder::MAX_MICRO_LIMB_SIZE) { return false; } } - return true; - }; - // Check that everything has been decomposed correctly - // P.xₗₒ = P.xₗₒ_0 + SHIFT_1 * P.xₗₒ_1 - // P.xₕᵢ = P.xₕᵢ_0 + SHIFT_1 * P.xₕᵢ_1 - // z_1 = z_1ₗₒ + SHIFT_1 * z_1ₕᵢ - // z_2 = z_2ₗₒ + SHIFT_2 * z_1ₕᵢ - if (!(check_wide_limb_into_binary_limb_relation({ p_x_lo, p_x_hi }, p_x_binary_limbs) && - check_wide_limb_into_binary_limb_relation({ p_y_lo, p_y_hi }, p_y_binary_limbs) && - check_wide_limb_into_binary_limb_relation({ z_1 }, z_1_binary_limbs) && - check_wide_limb_into_binary_limb_relation({ z_2 }, z_2_binary_limbs))) { - - return report_fail("wide limb decomposition failied at row = ", i); } - - enum LimbSeriesType { STANDARD_COORDINATE, Z_SCALAR, QUOTIENT }; - - // Check that limbs have been decomposed into microlimbs correctly - // value = ∑ (2ˡ)ⁱ⋅ chunkᵢ, where 2ˡ is the shift - auto check_micro_limb_decomposition_correctness = [&accumulate_limb_from_micro_chunks]( - const std::vector& binary_limbs, - const std::vector>& micro_limbs, - const LimbSeriesType limb_series_type) { - // Shifts for decompositions - constexpr auto SHIFT_12_TO_14 = Fr(4); - constexpr auto SHIFT_10_TO_14 = Fr(16); - constexpr auto SHIFT_8_TO_14 = Fr(64); - constexpr auto SHIFT_4_TO_14 = Fr(1024); - - BB_ASSERT_EQ(binary_limbs.size(), micro_limbs.size()); - // First check that all the microlimbs are properly range constrained - for (auto& micro_limb_series : micro_limbs) { - for (auto& micro_limb : micro_limb_series) { - if (uint256_t(micro_limb) > Builder::MAX_MICRO_LIMB_SIZE) { - return false; - } - } + // For low limbs the last microlimb is used with the shift, so we skip it when reconstructing + // the limb + const size_t SKIPPED_FOR_LOW_LIMBS = 1; + for (size_t i = 0; i < binary_limbs.size() - 1; i++) { + if (binary_limbs[i] != accumulate_limb_from_micro_chunks(micro_limbs[i], SKIPPED_FOR_LOW_LIMBS)) { + return false; } - // For low limbs the last microlimb is used with the shift, so we skip it when reconstructing - // the limb - const size_t SKIPPED_FOR_LOW_LIMBS = 1; - for (size_t i = 0; i < binary_limbs.size() - 1; i++) { - if (binary_limbs[i] != accumulate_limb_from_micro_chunks(micro_limbs[i], SKIPPED_FOR_LOW_LIMBS)) { - return false; - } - // Check last additional constraint (68->70) - if (micro_limbs[i][NUM_MICRO_LIMBS - 1] != (SHIFT_12_TO_14 * micro_limbs[i][NUM_MICRO_LIMBS - 2])) { - return false; - } + // Check last additional constraint (68->70) + if (micro_limbs[i][NUM_MICRO_LIMBS - 1] != (SHIFT_12_TO_14 * micro_limbs[i][NUM_MICRO_LIMBS - 2])) { + return false; } + } - const size_t SKIPPED_FOR_STANDARD = 2; - const size_t SKIPPED_FOR_Z_SCALARS = 1; - const size_t SKIPPED_FOR_QUOTIENT = 2; - switch (limb_series_type) { - case STANDARD_COORDINATE: - // For standard Fq value the highest limb is 50 bits, so we skip the top 2 microlimbs - if (binary_limbs[binary_limbs.size() - 1] != - accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], SKIPPED_FOR_STANDARD)) { - return false; - } - // Check last additional constraint (50->56) - if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_STANDARD] != - (SHIFT_8_TO_14 * - micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_STANDARD - 1])) { - - return false; - } - break; - // For z top limbs we need as many microlimbs as for the low limbs - case Z_SCALAR: - if (binary_limbs[binary_limbs.size() - 1] != - accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], - SKIPPED_FOR_Z_SCALARS)) { - return false; - } - // Check last additional constraint (60->70) - if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_Z_SCALARS] != - (SHIFT_4_TO_14 * - micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_Z_SCALARS - 1])) { - return false; - } - break; - // Quotient also doesn't need the top 2 - case QUOTIENT: - if (binary_limbs[binary_limbs.size() - 1] != - accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], SKIPPED_FOR_QUOTIENT)) { - return false; - } - // Check last additional constraint (52->56) - if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_QUOTIENT] != - (SHIFT_10_TO_14 * - micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_QUOTIENT - 1])) { - return false; - } - break; - default: - abort(); + const size_t SKIPPED_FOR_STANDARD = 2; + const size_t SKIPPED_FOR_Z_SCALARS = 1; + const size_t SKIPPED_FOR_QUOTIENT = 2; + switch (limb_series_type) { + case STANDARD_COORDINATE: + // For standard Fq value the highest limb is 50 bits, so we skip the top 2 microlimbs + if (binary_limbs[binary_limbs.size() - 1] != + accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], SKIPPED_FOR_STANDARD)) { + return false; } + // Check last additional constraint (50->56) + if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_STANDARD] != + (SHIFT_8_TO_14 * + micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_STANDARD - 1])) { - return true; - }; - // Check all micro limb decompositions - if (!check_micro_limb_decomposition_correctness(p_x_binary_limbs, p_x_micro_chunks, STANDARD_COORDINATE)) { - return false; - } - if (!check_micro_limb_decomposition_correctness(p_y_binary_limbs, p_y_micro_chunks, STANDARD_COORDINATE)) { - return false; - } - if (!check_micro_limb_decomposition_correctness(z_1_binary_limbs, z_1_micro_chunks, Z_SCALAR)) { - return false; - } - if (!check_micro_limb_decomposition_correctness(z_2_binary_limbs, z_2_micro_chunks, Z_SCALAR)) { - return false; - } - if (!check_micro_limb_decomposition_correctness( - current_accumulator_binary_limbs, current_accumulator_micro_chunks, STANDARD_COORDINATE)) { - return false; - } - if (!check_micro_limb_decomposition_correctness(quotient_binary_limbs, quotient_micro_chunks, QUOTIENT)) { - return false; - } - - // The logic we are trying to enforce is: - // current_accumulator = previous_accumulator ⋅ x + op_code + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ - // v⁴ mod Fq To ensure this we transform the relation into the form: previous_accumulator ⋅ x + op + - // P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - current_accumulator = 0 However, we - // don't have integers. Despite that, we can approximate integers for a certain range, if we know - // that there will not be any overflows. For now we set the range to 2²⁷² ⋅ r. We can evaluate the - // logic modulo 2²⁷² with range constraints and r is native. - // - // previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - - // current_accumulator = 0 => - // 1. previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ + quotient ⋅ (-p mod - // 2²⁷²) - current_accumulator = 0 mod 2²⁷² - // 2. previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - - // current_accumulator = 0 mod r - // - // The second relation is straightforward and easy to check. The first, not so much. We have to - // evaluate certain bit chunks of the equation and ensure that they are zero. For example, for the - // lowest limb it would be (inclusive ranges): - // - // previous_accumulator[0:67] ⋅ x[0:67] + op + P.x[0:67] ⋅ v[0:67] + P.y[0:67] ⋅ v²[0:67] + - // z_1[0:67] ⋅ v³[0:67] + z_2[0:67] ⋅ v⁴[0:67] + quotient[0:67] ⋅ (-p mod 2²⁷²)[0:67] - - // current_accumulator[0:67] = intermediate_value; (we don't take parts of op, because it's supposed - // to be between 0 and 3) - // - // We could check that this intermediate_value is equal to 0 mod 2⁶⁸ by dividing it by 2⁶⁸ and - // constraining it. For efficiency, we actually compute wider evaluations for 136 bits, which - // require us to also obtain and shift products of [68:135] by [0:67] and [0:67] by [68:135] bits. - // The result of division goes into the next evaluation (the same as a carry flag would) - // So the lowest wide limb is : (∑everything[0:67]⋅everything[0:67] + - // 2⁶⁸⋅(∑everything[0:67]⋅everything[68:135]))/ 2¹³⁶ - // - // The high is: - // (low_limb + ∑everything[0:67]⋅everything[136:203] + ∑everything[68:135]⋅everything[68:135] + - // 2⁶⁸(∑everything[0:67]⋅everything[204:271] + ∑everything[68:135]⋅everything[136:203])) / 2¹³⁶ - // - // We also limit computation on limbs of op, z_1 and z_2, since we know that op has only the lowest - // limb and z_1 and z_2 have only the two lowest limbs - constexpr std::array NEGATIVE_MODULUS_LIMBS = Builder::NEGATIVE_MODULUS_LIMBS; - const uint256_t SHIFT_1 = Builder::SHIFT_1; - const uint256_t SHIFT_2 = Builder::SHIFT_2; - const uint256_t SHIFT_3 = Builder::SHIFT_3; - Fr low_wide_limb_relation_check = - - (previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[0] + op_code + - relation_inputs.v_limbs[0] * p_x_0 + relation_inputs.v_squared_limbs[0] * p_y_0 + - relation_inputs.v_cubed_limbs[0] * z_1_lo + relation_inputs.v_quarted_limbs[0] * z_2_lo + - quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[0] - current_accumulator_binary_limbs[0]) + - (previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[0] + - relation_inputs.v_limbs[1] * p_x_0 + relation_inputs.v_squared_limbs[1] * p_y_0 + - relation_inputs.v_cubed_limbs[1] * z_1_lo + relation_inputs.v_quarted_limbs[1] * z_2_lo + - quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[0] + - previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[1] + - relation_inputs.v_limbs[0] * p_x_1 + relation_inputs.v_squared_limbs[0] * p_y_1 + - relation_inputs.v_cubed_limbs[0] * z_1_hi + relation_inputs.v_quarted_limbs[0] * z_2_hi + - quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[1] - current_accumulator_binary_limbs[1]) * - Fr(SHIFT_1); - if (low_wide_limb_relation_check != (low_wide_relation_limb * SHIFT_2)) { - return false; - } - Fr high_wide_relation_limb_check = - low_wide_relation_limb + previous_accumulator_binary_limbs[2] * relation_inputs.x_limbs[0] + - previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[1] + - previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[2] + relation_inputs.v_limbs[2] * p_x_0 + - relation_inputs.v_limbs[1] * p_x_1 + relation_inputs.v_limbs[0] * p_x_2 + - relation_inputs.v_squared_limbs[2] * p_y_0 + relation_inputs.v_squared_limbs[1] * p_y_1 + - relation_inputs.v_squared_limbs[0] * p_y_2 + relation_inputs.v_cubed_limbs[2] * z_1_lo + - relation_inputs.v_cubed_limbs[1] * z_1_hi + relation_inputs.v_quarted_limbs[2] * z_2_lo + - relation_inputs.v_quarted_limbs[1] * z_2_hi + quotient_binary_limbs[2] * NEGATIVE_MODULUS_LIMBS[0] + - quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[1] + - quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[2] - current_accumulator_binary_limbs[2] + - (previous_accumulator_binary_limbs[3] * relation_inputs.x_limbs[0] + - previous_accumulator_binary_limbs[2] * relation_inputs.x_limbs[1] + - previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[2] + - previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[3] + - relation_inputs.v_limbs[3] * p_x_0 + relation_inputs.v_limbs[2] * p_x_1 + - relation_inputs.v_limbs[1] * p_x_2 + relation_inputs.v_limbs[0] * p_x_3 + - relation_inputs.v_squared_limbs[3] * p_y_0 + relation_inputs.v_squared_limbs[2] * p_y_1 + - relation_inputs.v_squared_limbs[1] * p_y_2 + relation_inputs.v_squared_limbs[0] * p_y_3 + - relation_inputs.v_cubed_limbs[3] * z_1_lo + relation_inputs.v_cubed_limbs[2] * z_1_hi + - relation_inputs.v_quarted_limbs[3] * z_2_lo + relation_inputs.v_quarted_limbs[2] * z_2_hi + - quotient_binary_limbs[3] * NEGATIVE_MODULUS_LIMBS[0] + - quotient_binary_limbs[2] * NEGATIVE_MODULUS_LIMBS[1] + - quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[2] + - quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[3] - current_accumulator_binary_limbs[3]) * - SHIFT_1; - if (high_wide_relation_limb_check != (high_wide_relation_limb * SHIFT_2)) { - return false; - } - // Apart from checking the correctness of the evaluation modulo 2²⁷² we also need to ensure that the - // logic works in our scalar field. For this we reconstruct the scalar field values from individual - // limbs - auto reconstructed_p_x = (p_x_0 + p_x_1 * SHIFT_1 + p_x_2 * SHIFT_2 + p_x_3 * SHIFT_3); - auto reconstructed_p_y = (p_y_0 + p_y_1 * SHIFT_1 + p_y_2 * SHIFT_2 + p_y_3 * SHIFT_3); - auto reconstructed_current_accumulator = - (current_accumulator_binary_limbs[0] + current_accumulator_binary_limbs[1] * SHIFT_1 + - current_accumulator_binary_limbs[2] * SHIFT_2 + current_accumulator_binary_limbs[3] * SHIFT_3); - auto reconstructed_previous_accumulator = - (previous_accumulator_binary_limbs[0] + previous_accumulator_binary_limbs[1] * SHIFT_1 + - previous_accumulator_binary_limbs[2] * SHIFT_2 + previous_accumulator_binary_limbs[3] * SHIFT_3); - - auto reconstructed_z1 = (z_1_lo + z_1_hi * SHIFT_1); - auto reconstructed_z2 = (z_2_lo + z_2_hi * SHIFT_1); - auto reconstructed_quotient = (quotient_binary_limbs[0] + quotient_binary_limbs[1] * SHIFT_1 + - quotient_binary_limbs[2] * SHIFT_2 + quotient_binary_limbs[3] * SHIFT_3); - - // Check the relation - if (!(reconstructed_previous_accumulator * reconstructed_evaluation_input_x + op_code + - reconstructed_p_x * reconstructed_batching_evaluation_v + - reconstructed_p_y * reconstructed_batching_evaluation_v2 + - reconstructed_z1 * reconstructed_batching_evaluation_v3 + - reconstructed_z2 * reconstructed_batching_evaluation_v4 + - reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator) - .is_zero()) { - return false; - }; - } - { - size_t odd_gate_index = i + 1; - const std::vector current_accumulator_binary_limbs_copy = { - circuit.get_variable(accumulators_binary_limbs_0_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_1_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_2_wire[odd_gate_index]), - circuit.get_variable(accumulators_binary_limbs_3_wire[odd_gate_index]), - }; - if (odd_gate_index < circuit.num_gates - 1) { - size_t next_even_gate_index = i + 2; - const std::vector current_accumulator_binary_limbs = { - circuit.get_variable(accumulators_binary_limbs_0_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_1_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_2_wire[next_even_gate_index]), - circuit.get_variable(accumulators_binary_limbs_3_wire[next_even_gate_index]), - }; - - for (size_t j = 0; j < current_accumulator_binary_limbs.size(); j++) { - if (current_accumulator_binary_limbs_copy[j] != current_accumulator_binary_limbs[j]) { - return report_fail("accumulator copy failed at row = ", odd_gate_index); - } + return false; } - } else { - // Check accumulator starts at zero - for (const auto& limb : current_accumulator_binary_limbs_copy) { - if (limb != Fr(0)) { - return report_fail("accumulator doesn't start with 0 = ", odd_gate_index); - } + break; + // For z top limbs we need as many microlimbs as for the low limbs + case Z_SCALAR: + if (binary_limbs[binary_limbs.size() - 1] != + accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], SKIPPED_FOR_Z_SCALARS)) { + return false; + } + // Check last additional constraint (60->70) + if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_Z_SCALARS] != + (SHIFT_4_TO_14 * + micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_Z_SCALARS - 1])) { + return false; + } + break; + // Quotient also doesn't need the top 2 + case QUOTIENT: + if (binary_limbs[binary_limbs.size() - 1] != + accumulate_limb_from_micro_chunks(micro_limbs[binary_limbs.size() - 1], SKIPPED_FOR_QUOTIENT)) { + return false; + } + // Check last additional constraint (52->56) + if (micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_QUOTIENT] != + (SHIFT_10_TO_14 * + micro_limbs[binary_limbs.size() - 1][NUM_MICRO_LIMBS - SKIPPED_FOR_QUOTIENT - 1])) { + return false; } + break; + default: + abort(); } + + return true; + }; + // Check all micro limb decompositions + if (!check_micro_limb_decomposition_correctness(p_x_binary_limbs, p_x_micro_chunks, STANDARD_COORDINATE)) { + return false; + } + if (!check_micro_limb_decomposition_correctness(p_y_binary_limbs, p_y_micro_chunks, STANDARD_COORDINATE)) { + return false; + } + if (!check_micro_limb_decomposition_correctness(z_1_binary_limbs, z_1_micro_chunks, Z_SCALAR)) { + return false; + } + if (!check_micro_limb_decomposition_correctness(z_2_binary_limbs, z_2_micro_chunks, Z_SCALAR)) { + return false; + } + if (!check_micro_limb_decomposition_correctness( + current_accumulator_binary_limbs, current_accumulator_micro_chunks, STANDARD_COORDINATE)) { + return false; + } + if (!check_micro_limb_decomposition_correctness(quotient_binary_limbs, quotient_micro_chunks, QUOTIENT)) { + return false; } - } + + // The logic we are trying to enforce is: + // current_accumulator = previous_accumulator ⋅ x + op_code + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ + // v⁴ mod Fq To ensure this we transform the relation into the form: previous_accumulator ⋅ x + op + + // P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - current_accumulator = 0 However, we + // don't have integers. Despite that, we can approximate integers for a certain range, if we know + // that there will not be any overflows. For now we set the range to 2²⁷² ⋅ r. We can evaluate the + // logic modulo 2²⁷² with range constraints and r is native. + // + // previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - + // current_accumulator = 0 => + // 1. previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ + quotient ⋅ (-p mod + // 2²⁷²) - current_accumulator = 0 mod 2²⁷² + // 2. previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² + z_1 ⋅ v³ + z_2 ⋅ v⁴ - quotient ⋅ p - + // current_accumulator = 0 mod r + // + // The second relation is straightforward and easy to check. The first, not so much. We have to + // evaluate certain bit chunks of the equation and ensure that they are zero. For example, for the + // lowest limb it would be (inclusive ranges): + // + // previous_accumulator[0:67] ⋅ x[0:67] + op + P.x[0:67] ⋅ v[0:67] + P.y[0:67] ⋅ v²[0:67] + + // z_1[0:67] ⋅ v³[0:67] + z_2[0:67] ⋅ v⁴[0:67] + quotient[0:67] ⋅ (-p mod 2²⁷²)[0:67] - + // current_accumulator[0:67] = intermediate_value; (we don't take parts of op, because it's supposed + // to be between 0 and 3) + // + // We could check that this intermediate_value is equal to 0 mod 2⁶⁸ by dividing it by 2⁶⁸ and + // constraining it. For efficiency, we actually compute wider evaluations for 136 bits, which + // require us to also obtain and shift products of [68:135] by [0:67] and [0:67] by [68:135] bits. + // The result of division goes into the next evaluation (the same as a carry flag would) + // So the lowest wide limb is : (∑everything[0:67]⋅everything[0:67] + + // 2⁶⁸⋅(∑everything[0:67]⋅everything[68:135]))/ 2¹³⁶ + // + // The high is: + // (low_limb + ∑everything[0:67]⋅everything[136:203] + ∑everything[68:135]⋅everything[68:135] + + // 2⁶⁸(∑everything[0:67]⋅everything[204:271] + ∑everything[68:135]⋅everything[136:203])) / 2¹³⁶ + // + // We also limit computation on limbs of op, z_1 and z_2, since we know that op has only the lowest + // limb and z_1 and z_2 have only the two lowest limbs + constexpr std::array NEGATIVE_MODULUS_LIMBS = Builder::NEGATIVE_MODULUS_LIMBS; + const uint256_t SHIFT_1 = Builder::SHIFT_1; + const uint256_t SHIFT_2 = Builder::SHIFT_2; + const uint256_t SHIFT_3 = Builder::SHIFT_3; + Fr low_wide_limb_relation_check = + + (previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[0] + op_code + + relation_inputs.v_limbs[0] * p_x_0 + relation_inputs.v_squared_limbs[0] * p_y_0 + + relation_inputs.v_cubed_limbs[0] * z_1_lo + relation_inputs.v_quarted_limbs[0] * z_2_lo + + quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[0] - current_accumulator_binary_limbs[0]) + + (previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[0] + relation_inputs.v_limbs[1] * p_x_0 + + relation_inputs.v_squared_limbs[1] * p_y_0 + relation_inputs.v_cubed_limbs[1] * z_1_lo + + relation_inputs.v_quarted_limbs[1] * z_2_lo + quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[0] + + previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[1] + relation_inputs.v_limbs[0] * p_x_1 + + relation_inputs.v_squared_limbs[0] * p_y_1 + relation_inputs.v_cubed_limbs[0] * z_1_hi + + relation_inputs.v_quarted_limbs[0] * z_2_hi + quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[1] - + current_accumulator_binary_limbs[1]) * + Fr(SHIFT_1); + if (low_wide_limb_relation_check != (low_wide_relation_limb * SHIFT_2)) { + return false; + } + Fr high_wide_relation_limb_check = + low_wide_relation_limb + previous_accumulator_binary_limbs[2] * relation_inputs.x_limbs[0] + + previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[1] + + previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[2] + relation_inputs.v_limbs[2] * p_x_0 + + relation_inputs.v_limbs[1] * p_x_1 + relation_inputs.v_limbs[0] * p_x_2 + + relation_inputs.v_squared_limbs[2] * p_y_0 + relation_inputs.v_squared_limbs[1] * p_y_1 + + relation_inputs.v_squared_limbs[0] * p_y_2 + relation_inputs.v_cubed_limbs[2] * z_1_lo + + relation_inputs.v_cubed_limbs[1] * z_1_hi + relation_inputs.v_quarted_limbs[2] * z_2_lo + + relation_inputs.v_quarted_limbs[1] * z_2_hi + quotient_binary_limbs[2] * NEGATIVE_MODULUS_LIMBS[0] + + quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[1] + + quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[2] - current_accumulator_binary_limbs[2] + + (previous_accumulator_binary_limbs[3] * relation_inputs.x_limbs[0] + + previous_accumulator_binary_limbs[2] * relation_inputs.x_limbs[1] + + previous_accumulator_binary_limbs[1] * relation_inputs.x_limbs[2] + + previous_accumulator_binary_limbs[0] * relation_inputs.x_limbs[3] + relation_inputs.v_limbs[3] * p_x_0 + + relation_inputs.v_limbs[2] * p_x_1 + relation_inputs.v_limbs[1] * p_x_2 + + relation_inputs.v_limbs[0] * p_x_3 + relation_inputs.v_squared_limbs[3] * p_y_0 + + relation_inputs.v_squared_limbs[2] * p_y_1 + relation_inputs.v_squared_limbs[1] * p_y_2 + + relation_inputs.v_squared_limbs[0] * p_y_3 + relation_inputs.v_cubed_limbs[3] * z_1_lo + + relation_inputs.v_cubed_limbs[2] * z_1_hi + relation_inputs.v_quarted_limbs[3] * z_2_lo + + relation_inputs.v_quarted_limbs[2] * z_2_hi + quotient_binary_limbs[3] * NEGATIVE_MODULUS_LIMBS[0] + + quotient_binary_limbs[2] * NEGATIVE_MODULUS_LIMBS[1] + + quotient_binary_limbs[1] * NEGATIVE_MODULUS_LIMBS[2] + + quotient_binary_limbs[0] * NEGATIVE_MODULUS_LIMBS[3] - current_accumulator_binary_limbs[3]) * + SHIFT_1; + if (high_wide_relation_limb_check != (high_wide_relation_limb * SHIFT_2)) { + return false; + } + // Apart from checking the correctness of the evaluation modulo 2²⁷² we also need to ensure that the + // logic works in our scalar field. For this we reconstruct the scalar field values from individual + // limbs + auto reconstructed_p_x = (p_x_0 + p_x_1 * SHIFT_1 + p_x_2 * SHIFT_2 + p_x_3 * SHIFT_3); + auto reconstructed_p_y = (p_y_0 + p_y_1 * SHIFT_1 + p_y_2 * SHIFT_2 + p_y_3 * SHIFT_3); + auto reconstructed_current_accumulator = + (current_accumulator_binary_limbs[0] + current_accumulator_binary_limbs[1] * SHIFT_1 + + current_accumulator_binary_limbs[2] * SHIFT_2 + current_accumulator_binary_limbs[3] * SHIFT_3); + auto reconstructed_previous_accumulator = + (previous_accumulator_binary_limbs[0] + previous_accumulator_binary_limbs[1] * SHIFT_1 + + previous_accumulator_binary_limbs[2] * SHIFT_2 + previous_accumulator_binary_limbs[3] * SHIFT_3); + + auto reconstructed_z1 = (z_1_lo + z_1_hi * SHIFT_1); + auto reconstructed_z2 = (z_2_lo + z_2_hi * SHIFT_1); + auto reconstructed_quotient = (quotient_binary_limbs[0] + quotient_binary_limbs[1] * SHIFT_1 + + quotient_binary_limbs[2] * SHIFT_2 + quotient_binary_limbs[3] * SHIFT_3); + + // Check the relation + if (!(reconstructed_previous_accumulator * reconstructed_evaluation_input_x + op_code + + reconstructed_p_x * reconstructed_batching_evaluation_v + + reconstructed_p_y * reconstructed_batching_evaluation_v2 + + reconstructed_z1 * reconstructed_batching_evaluation_v3 + + reconstructed_z2 * reconstructed_batching_evaluation_v4 + + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator) + .is_zero()) { + return false; + }; + + if (!check_accumulator_transfer(previous_accumulator_binary_limbs, i + 1)) { + return false; + } + }; return true; -}; +} }; // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index bb364a185dba..ce08bb291af4 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -327,8 +327,7 @@ class UltraEccOpsTable { column_polynomials[1].at(row_idx) = op.x_lo; column_polynomials[2].at(row_idx) = op.x_hi; column_polynomials[3].at(row_idx) = op.y_lo; - column_polynomials[0].at(row_idx + 1) = - !op.op_code.is_random_op ? op.op_code.value() : op.op_code.random_value_2; + column_polynomials[0].at(row_idx + 1) = !op.op_code.is_random_op ? 0 : op.op_code.random_value_2; column_polynomials[1].at(row_idx + 1) = op.y_hi; column_polynomials[2].at(row_idx + 1) = op.z_1; column_polynomials[3].at(row_idx + 1) = op.z_2; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 3c66be790824..518710286032 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -751,7 +751,6 @@ template class SumcheckVerifier { const bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); - info("round result: ", checked); verified = verified && checked; } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 961ae97df069..63ebfc5ebbc3 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -97,7 +97,7 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) constexpr std::array possible_opcode_values = { 3, 4, 8 }; // Assign random opcode values - for (size_t i = 2; i < mini_circuit_size; i++) { + for (size_t i = 2; i < mini_circuit_size; i += 2) { prover_polynomials.op.at(i) = possible_opcode_values[static_cast(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)]; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index f53913acac97..73ff0904030b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -25,61 +25,109 @@ class TranslatorTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } - // Construct a test circuit based on some random operations - static CircuitBuilder generate_test_circuit(const Fq& batching_challenge_v, - const Fq& evaluation_challenge_x, - const size_t circuit_size_parameter = 500) + // Helper function to add no-op operations + static void add_no_ops(std::shared_ptr& op_queue, size_t count = 1) + { + for (size_t i = 0; i < count; i++) { + op_queue->no_op_ultra_only(); + } + } + + // Helper function to add mixed add and mul operations + static void add_mixed_ops(std::shared_ptr& op_queue, size_t count = 100) { auto P1 = G1::random_element(); auto P2 = G1::random_element(); auto z = Fr::random_element(); - - // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = std::make_shared(); - op_queue->no_op_ultra_only(); - - for (size_t i = 0; i < circuit_size_parameter / 2; i++) { + for (size_t i = 0; i < count; i++) { op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); } op_queue->eq_and_reset(); - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); - for (size_t i = 0; i < circuit_size_parameter / 2; i++) { - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); + } + + // Construct a test circuit based on some random operations + static CircuitBuilder generate_test_circuit(const Fq& batching_challenge_v, + const Fq& evaluation_challenge_x, + const size_t circuit_size_parameter = 500, + const bool add_no_ops_region = false) + { + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + add_no_ops(op_queue); + + add_mixed_ops(op_queue, circuit_size_parameter / 2); + if (add_no_ops_region) { + add_no_ops(op_queue, 4); } + add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } + + /** + * @brief Check that size of a Translator proof matches the corresponding constant + *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: + * - Proof length formula in translator_flavor.hpp, etc... + * - translator_transcript.test.cpp + * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol + */ + + // Helper function to setup prover transcript with initial value + // Helper function to create a complete proof-verification setup + static bool prove_and_verify(const CircuitBuilder& circuit_builder, + const Fq& evaluation_challenge_x, + const Fq& batching_challenge_v) + { + // Setup prover transcript + auto prover_transcript = std::make_shared(); + prover_transcript->send_to_verifier("init", Fq::random_element()); + auto initial_transcript = prover_transcript->export_proof(); + + // Setup verifier transcript + auto verifier_transcript = std::make_shared(); + verifier_transcript->load_proof(initial_transcript); + verifier_transcript->template receive_from_prover("init"); + + // Create proving key and prover + auto proving_key = std::make_shared(circuit_builder); + TranslatorProver prover{ proving_key, prover_transcript }; + + // Generate proof + auto proof = prover.construct_proof(); + + // Create verifier + auto verification_key = std::make_shared(proving_key->proving_key); + TranslatorVerifier verifier(verification_key, verifier_transcript); + + // Verify proof and return result + return verifier.verify_proof(proof, evaluation_challenge_x, batching_challenge_v); + } }; -} // namespace -/** - * @brief Check that size of a Translator proof matches the corresponding constant - *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: - * - Proof length formula in translator_flavor.hpp, etc... - * - translator_transcript.test.cpp - * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol - */ TEST_F(TranslatorTests, ProofLengthCheck) { using Fq = fq; - auto prover_transcript = std::make_shared(); Fq batching_challenge_v = Fq::random_element(); Fq evaluation_challenge_x = Fq::random_element(); // Generate a circuit and its verification key (computed at runtime from the proving key) CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); + // Setup prover transcript + auto prover_transcript = std::make_shared(); + prover_transcript->send_to_verifier("init", Fq::random_element()); + prover_transcript->export_proof(); auto proving_key = std::make_shared(circuit_builder); TranslatorProver prover{ proving_key, prover_transcript }; + + // Generate proof auto proof = prover.construct_proof(); + EXPECT_EQ(proof.size(), TranslatorFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS); } @@ -87,33 +135,34 @@ TEST_F(TranslatorTests, ProofLengthCheck) * @brief Test simple circuit with public inputs * */ -TEST_F(TranslatorTests, Basic) +TEST_F(TranslatorTests, BasicWithoutNoOps) { using Fq = fq; - auto prover_transcript = std::make_shared(); - prover_transcript->send_to_verifier("init", Fq::random_element()); - auto initial_transcript = prover_transcript->export_proof(); Fq batching_challenge_v = Fq::random_element(); Fq evaluation_challenge_x = Fq::random_element(); - // Generate a circuit and its verification key (computed at runtime from the proving key) + // Generate a circuit without no-ops CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); - auto proving_key = std::make_shared(circuit_builder); + bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); + EXPECT_TRUE(verified); +} - TranslatorProver prover{ proving_key, prover_transcript }; - auto proof = prover.construct_proof(); +TEST_F(TranslatorTests, BasicWithNoOps) +{ + using Fq = fq; - // RelationChecker::check>( - // proving_key->proving_key->polynomials, prover.relation_parameters, "TranslatorOpcodeConstraintRelation"); - auto verifier_transcript = std::make_shared(); - verifier_transcript->load_proof(initial_transcript); - verifier_transcript->template receive_from_prover("init"); - auto verification_key = std::make_shared(proving_key->proving_key); - TranslatorVerifier verifier(verification_key, verifier_transcript); - bool verified = verifier.verify_proof(proof, evaluation_challenge_x, batching_challenge_v); + Fq batching_challenge_v = Fq::random_element(); + Fq evaluation_challenge_x = Fq::random_element(); + + // Generate a circuit and its verification key (computed at runtime from the proving key) + CircuitBuilder circuit_builder = generate_test_circuit( + batching_challenge_v, evaluation_challenge_x, /*circuit_size_parameter=*/500, /*add_no_ops_region=*/true); + + EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); + bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); EXPECT_TRUE(verified); } @@ -163,3 +212,4 @@ TEST_F(TranslatorTests, FixedVK) compare_computed_vk_against_fixed(circuit_size_parameter_1); compare_computed_vk_against_fixed(circuit_size_parameter_2); } +} // namespace diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 61ad6382af4f..09add4e496b0 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -405,7 +405,7 @@ void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra auto& op_wire = std::get(wires); op_wire.push_back(add_variable(ultra_op.op_code.value())); // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(add_variable(ultra_op.op_code.value())); + op_wire.push_back(zero_idx); insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); @@ -554,10 +554,11 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ accumulator_trace.push_back(current_accumulator); } - // We don't care about the last value since we'll recompute it during witness generation anyway + // Accumulator final value is recomputed during witness generation anyway + Fq final_accumulator_state = accumulator_trace.back(); accumulator_trace.pop_back(); - std::array previous_accumulator_binary_limbs; + std::array previous_accumulator_binary_limbs = split_fq_into_limbs(final_accumulator_state); // Generate witness values from all the UltraOps for (size_t i = 1; i < ultra_ops.size(); i++) { const auto& ultra_op = ultra_ops[i]; @@ -588,6 +589,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // Compute witness values AccumulationInput one_accumulation_step = generate_witness_values(ultra_op, previous_accumulator, batching_challenge_v, evaluation_input_x); + + // Save the state of accumulator in case the next operation encountered is a no-op previous_accumulator_binary_limbs = one_accumulation_step.previous_accumulator; // And put them into the wires create_accumulation_gate(one_accumulation_step); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 1cdadd25c2a6..7d4f7a1add5e 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -80,67 +80,78 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) using scalar = fr; using Fq = fq; - auto P1 = point::random_element(); - auto P2 = point::random_element(); - auto z = scalar::random_element(); - - // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = std::make_shared(); - op_queue->no_op_ultra_only(); - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - - Fq op_accumulator = 0; - Fq p_x_accumulator = 0; - Fq p_y_accumulator = 0; - Fq z_1_accumulator = 0; - Fq z_2_accumulator = 0; - Fq batching_challenge = fq::random_element(); - - op_queue->eq_and_reset(); - op_queue->merge(); - - // Sample the evaluation input x - Fq x = Fq::random_element(); - // Get an inverse - Fq x_inv = x.invert(); - // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& ultra_ops = op_queue->get_ultra_ops(); - for (size_t i = 1; i < ultra_ops.size(); i++) { - const auto& ecc_op = ultra_ops[i]; - if (ecc_op.op_code.value() == 0) { - continue; + auto test_with_no_ops = [](size_t no_op_count = 0, bool start_with_no_ops = false) { + auto P1 = point::random_element(); + auto P2 = point::random_element(); + auto z = scalar::random_element(); + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + op_queue->no_op_ultra_only(); + if (!start_with_no_ops) { + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); } - op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); - const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); - p_x_accumulator = p_x_accumulator * x_inv + x_u256; - p_y_accumulator = p_y_accumulator * x_inv + y_u256; - z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); - z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); - } - // The degree is ultra_ops.size() - 2 as we ignore the first no-op in computation - Fq x_pow = x.pow(ultra_ops.size() - 5); - - // Multiply by an appropriate power of x to get rid of the inverses - Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * - batching_challenge + - p_x_accumulator) * - batching_challenge + - op_accumulator) * - x_pow; - - // Create circuit builder and feed the queue inside - auto circuit_builder = TranslatorCircuitBuilder(batching_challenge, x, op_queue); - // Check that the circuit passes - EXPECT_TRUE(CircuitChecker::check(circuit_builder)); - // Check the accumulation result stored as 4 limbs in the circuit and then reconstructed is consistent with the - // value computed by hand. - EXPECT_EQ(result, CircuitChecker::get_computation_result(circuit_builder)); + + for (size_t i = 0; i < no_op_count; ++i) { + op_queue->no_op_ultra_only(); + } + + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + + Fq op_accumulator = 0; + Fq p_x_accumulator = 0; + Fq p_y_accumulator = 0; + Fq z_1_accumulator = 0; + Fq z_2_accumulator = 0; + Fq batching_challenge = fq::random_element(); + + op_queue->eq_and_reset(); + op_queue->merge(); + + // Sample the evaluation input x + Fq x = Fq::random_element(); + // Get an inverse + Fq x_inv = x.invert(); + // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) + const auto& ultra_ops = op_queue->get_ultra_ops(); + for (size_t i = 1; i < ultra_ops.size(); i++) { + const auto& ecc_op = ultra_ops[i]; + if (ecc_op.op_code.value() == 0) { + continue; + } + op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); + const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); + p_x_accumulator = p_x_accumulator * x_inv + x_u256; + p_y_accumulator = p_y_accumulator * x_inv + y_u256; + z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); + z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); + } + // The degree is ultra_ops.size() - 2 as we ignore the first no-op in computation + Fq x_pow = x.pow(ultra_ops.size() - (2 + no_op_count)); + + // Multiply by an appropriate power of x to get rid of the inverses + Fq result = + ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * + batching_challenge + + p_x_accumulator) * + batching_challenge + + op_accumulator) * + x_pow; + + // Create circuit builder and feed the queue inside + auto circuit_builder = TranslatorCircuitBuilder(batching_challenge, x, op_queue); + // Check that the circuit passes + EXPECT_TRUE(CircuitChecker::check(circuit_builder)); + // Check the accumulation result stored as 4 limbs in the circuit and then reconstructed is consistent with the + // value computed by hand. + EXPECT_EQ(result, CircuitChecker::get_computation_result(circuit_builder)); + }; + + test_with_no_ops(); + test_with_no_ops(5); + test_with_no_ops(5, true); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index 7d9102895451..f1b6fb639b5d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -74,7 +74,6 @@ class TranslatorProvingKey { // at the end. for (size_t idx = Flavor::NUM_OP_QUEUE_WIRES; idx < wires.size(); idx++) { auto& wire = wires[idx]; - info("wire end index: ", wire.end_index()); for (size_t i = wire.end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; i < wire.end_index(); i++) { wire.at(i) = FF::random_element(); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 787e9347242c..da51e6401834 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,7 +125,6 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { - info("Sumcheck verification failed"); return false; } diff --git a/proving-systems.code-workspace b/proving-systems.code-workspace index e3826976c9fe..1f4752d91bce 100644 --- a/proving-systems.code-workspace +++ b/proving-systems.code-workspace @@ -5,7 +5,7 @@ { "name": "aztec-packages", "path": "./" - } + }, ], // List recommended extensions for the whole workspace. "extensions": { From 9e3b3025a785398f1d510a445e1231e68a3c833e Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 28 Aug 2025 15:00:35 +0000 Subject: [PATCH 04/35] cleanup --- avm-transpiler/Cargo.lock | 32 +++++++++---------- .../cpp/src/barretenberg/goblin/goblin.cpp | 1 - .../barretenberg/op_queue/ecc_op_queue.hpp | 6 ++-- .../barretenberg/op_queue/ecc_ops_table.hpp | 5 +-- .../stdlib/encryption/ecdsa/ecdsa_impl.hpp | 4 +-- .../mega_circuit_builder.cpp | 6 ++-- .../src/barretenberg/sumcheck/sumcheck.hpp | 1 + bb-pilcom/powdr | 1 - proving-systems.code-workspace | 14 +++++--- 9 files changed, 36 insertions(+), 34 deletions(-) delete mode 160000 bb-pilcom/powdr diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index bf28cdd42245..e39bb5b5271f 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "acir" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir_field", "base64 0.22.1", @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "ark-bn254", "ark-ff", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -54,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "blake2", @@ -467,7 +467,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "brillig" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir_field", "serde", @@ -499,7 +499,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "fm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "codespan-reporting", "iter-extended", @@ -1122,7 +1122,7 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "iter-extended" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" [[package]] name = "itertools" @@ -1224,7 +1224,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "noir_protobuf" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "color-eyre", "prost", @@ -1232,7 +1232,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "iter-extended", @@ -1247,11 +1247,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" [[package]] name = "noirc_errors" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "base64 0.22.1", @@ -1268,7 +1268,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1326,7 +1326,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "iter-extended", diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index d29a973f8e6b..e3743c2d68a4 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -42,7 +42,6 @@ void Goblin::prove_translator() { PROFILE_THIS_NAME("Create TranslatorBuilder and TranslatorProver"); TranslatorBuilder translator_builder(translation_batching_challenge_v, evaluation_challenge_x, op_queue); - info("num gates intranslator ", translator_builder.num_gates); auto translator_key = std::make_shared(translator_builder, commitment_key); TranslatorProver translator_prover(translator_key, transcript); goblin_proof.translator_proof = translator_prover.construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp index 5ac821ab9bd9..afb970dda9ee 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp @@ -48,10 +48,6 @@ class ECCOpQueue { EccvmRowTracker eccvm_row_tracker; public: - static constexpr size_t OP_QUEUE_SIZE = 1 << 13; - - size_t get_unmerged_subtable_size() const { return ultra_ops_table.get_unmerged_subtable_size(); } - /** * @brief Instantiate an initial ECC op subtable. */ @@ -67,6 +63,8 @@ class ECCOpQueue { ultra_ops_table.create_new_subtable(); } + size_t get_unmerged_subtable_size() const { return ultra_ops_table.get_unmerged_subtable_size(); } + void merge(MergeSettings settings = MergeSettings::PREPEND, std::optional ultra_fixed_offset = std::nullopt) { eccvm_ops_table.merge(settings); diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index ce08bb291af4..dd0a193eff5e 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -130,7 +130,6 @@ template class EccOpsTable { } size_t num_subtables() const { return table.size(); } - size_t get_unmerged_subtable_size() const { return current_subtable.size(); } auto& get() const { return table; } @@ -238,7 +237,7 @@ class UltraEccOpsTable { public: size_t size() const { return table.size(); } - size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } + // size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } size_t ultra_table_size() const { @@ -274,6 +273,8 @@ class UltraEccOpsTable { } } + size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } + std::vector get_reconstructed() const { return table.get_reconstructed(); } // Construct the columns of the full ultra ecc ops table diff --git a/barretenberg/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp index df3e90c22297..3560d971101e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp @@ -211,9 +211,9 @@ bool_t ecdsa_verify_signature(const stdlib::byte_array& hashed // Logging if (is_signature_valid.get_value()) { - info("Signature verification succeeded."); + vinfo("Signature verification succeeded."); } else { - info("Signature verification failed"); + vinfo("Signature verification failed"); } return is_signature_valid; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 6039fbdb4e5f..4ca0a747a529 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -62,7 +62,7 @@ template void MegaCircuitBuilder_::add_mega_gates_to_ensure_al read_return_data(read_idx); if (op_queue->get_unmerged_subtable_size() == 0) { - this->queue_ecc_add_accum(bb::g1::affine_element::one()); + this->queue_ecc_mul_accum(bb::g1::affine_element::one(), 2); this->queue_ecc_eq(); } } @@ -168,8 +168,8 @@ template ecc_op_tuple MegaCircuitBuilder_::populate_ecc_op_wir op_tuple.z_2 = this->add_variable(ultra_op.z_2); // Set the indices for the op values for each of the two rows - uint32_t op_val_idx_1 = op_tuple.op; // genuine op code value - uint32_t op_val_idx_2 = op_tuple.op; // second row value always set to 0 + uint32_t op_val_idx_1 = op_tuple.op; // genuine op code value + uint32_t op_val_idx_2 = this->zero_idx; // second row value always set to 0 // If this is a random operation, the op values are randomized if (ultra_op.op_code.is_random_op) { op_val_idx_1 = this->add_variable(ultra_op.op_code.random_value_1); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 518710286032..03a9b4389429 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -751,6 +751,7 @@ template class SumcheckVerifier { const bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); + verified = verified && checked; } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge diff --git a/bb-pilcom/powdr b/bb-pilcom/powdr deleted file mode 160000 index c3006c11819d..000000000000 --- a/bb-pilcom/powdr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c3006c11819d9b53fb183c9c12a10b83481bb631 diff --git a/proving-systems.code-workspace b/proving-systems.code-workspace index 1f4752d91bce..0c5287367e02 100644 --- a/proving-systems.code-workspace +++ b/proving-systems.code-workspace @@ -64,7 +64,7 @@ // Some settings can only be configured here. "settings": { "files.associations": { - "*.tcc": "cpp" + "*.tcc": "cpp", }, // // Clangd. Note that this setting may be overridden by user settings @@ -72,7 +72,9 @@ // "clangd.path": "clangd-20", // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". - "clangd.arguments": ["-header-insertion=never"], + "clangd.arguments": [ + "-header-insertion=never" + ], // // CMake // @@ -128,7 +130,9 @@ "[cpp]": { "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" }, - "cmake.configureArgs": ["-G Ninja"], + "cmake.configureArgs": [ + "-G Ninja" + ], "cmake.useCMakePresets": "always", "editor.inlayHints.enabled": "offUnlessPressed", "git.detectSubmodules": false, @@ -140,7 +144,7 @@ "args": "${argsArray}", "cwd": "${command:cmake.buildDirectory}", "internalConsoleOptions": "openOnSessionStart", - "console": "internalConsole" - } + "console": "internalConsole", } + }, } From aa12502207efdcfcff2eeea6b4e76e2cd225a153 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 28 Aug 2025 15:04:29 +0000 Subject: [PATCH 05/35] undo changes --- proving-systems.code-workspace | 272 ++++++++++++++++----------------- 1 file changed, 136 insertions(+), 136 deletions(-) diff --git a/proving-systems.code-workspace b/proving-systems.code-workspace index 0c5287367e02..44360824f666 100644 --- a/proving-systems.code-workspace +++ b/proving-systems.code-workspace @@ -1,150 +1,150 @@ { - // Each "folder" can define a different project in the main repo, - // relative to `.code-workspace`. - "folders": [ - { - "name": "aztec-packages", - "path": "./" + // Each "folder" can define a different project in the main repo, + // relative to `.code-workspace`. + "folders": [ + { + "name": "aztec-packages", + "path": "./" }, - ], - // List recommended extensions for the whole workspace. - "extensions": { - "recommendations": [ - "GitHub.vscode-pull-request-github", - // Enables CMake integration and configuration - // for easier building - "ms-vscode.cmake-tools", - // Provides a nice UI for listing all Google Test - // tests, including launching a debug session - // for a specific test directly. - // Also provides buttons alongside test definitions. - "matepek.vscode-catch2-test-adapter", - // Integrates the `clangd` language server for - // - code formatting (clang-format) - // - static analysis (clang-tidy) - // - hints, tooltips, and more. - "llvm-vs-code-extensions.vscode-clangd", - // Better syntax highlighting for C++. - // Make sure to select one of the themes suggested - // (e.g. "Dark+") - "jeff-hykin.better-cpp-syntax", - // Handle CMakeLists.txt editing - "twxs.cmake", - // Integrates LLDB debugger - "vadimcn.vscode-lldb", - // Generate nicer Doxygen comments - "cschlosser.doxdocgen", - // Makes the CMake build output slightly - // prettier. - "IBM.output-colorizer", - "eamodio.gitlens", - "esbenp.prettier-vscode" ], - "unwantedRecommendations": [ - // The following may have been installed - // and cause some confusion when running - // tests. - // The options provided by C++ TestMate - // should be good enough. - "ms-vscode.cpptools-themes", - "hbenl.vscode-test-explorer", - "ms-vscode.test-adapter-converter", - "fredericbonnet.cmake-test-adapter", - "ms-vscode.cpptools-extension-pack", - // Used to enable GDB debugging - // Most features are disabled in `settings.json` - // which confict with `clangd` - // Since we ignore GDB, we no longer need this extension - "ms-vscode.cpptools" - ] - }, - // Global settings which will apply to all subprojects. - // Each subproject may have their own `.vscode/settings.json` - // for configuring extensions which are specific to a certain project. - // Some settings can only be configured here. - "settings": { - "files.associations": { - "*.tcc": "cpp", + // List recommended extensions for the whole workspace. + "extensions": { + "recommendations": [ + "GitHub.vscode-pull-request-github", + // Enables CMake integration and configuration + // for easier building + "ms-vscode.cmake-tools", + // Provides a nice UI for listing all Google Test + // tests, including launching a debug session + // for a specific test directly. + // Also provides buttons alongside test definitions. + "matepek.vscode-catch2-test-adapter", + // Integrates the `clangd` language server for + // - code formatting (clang-format) + // - static analysis (clang-tidy) + // - hints, tooltips, and more. + "llvm-vs-code-extensions.vscode-clangd", + // Better syntax highlighting for C++. + // Make sure to select one of the themes suggested + // (e.g. "Dark+") + "jeff-hykin.better-cpp-syntax", + // Handle CMakeLists.txt editing + "twxs.cmake", + // Integrates LLDB debugger + "vadimcn.vscode-lldb", + // Generate nicer Doxygen comments + "cschlosser.doxdocgen", + // Makes the CMake build output slightly + // prettier. + "IBM.output-colorizer", + "eamodio.gitlens", + "esbenp.prettier-vscode" + ], + "unwantedRecommendations": [ + // The following may have been installed + // and cause some confusion when running + // tests. + // The options provided by C++ TestMate + // should be good enough. + "ms-vscode.cpptools-themes", + "hbenl.vscode-test-explorer", + "ms-vscode.test-adapter-converter", + "fredericbonnet.cmake-test-adapter", + "ms-vscode.cpptools-extension-pack", + // Used to enable GDB debugging + // Most features are disabled in `settings.json` + // which confict with `clangd` + // Since we ignore GDB, we no longer need this extension + "ms-vscode.cpptools" + ] }, - // - // Clangd. Note that this setting may be overridden by user settings - // to the default value "clangd". - // - "clangd.path": "clangd-20", - // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". + // Global settings which will apply to all subprojects. + // Each subproject may have their own `.vscode/settings.json` + // for configuring extensions which are specific to a certain project. + // Some settings can only be configured here. + "settings": { + "files.associations": { + "*.tcc": "cpp", + }, + // + // Clangd. Note that this setting may be overridden by user settings + // to the default value "clangd". + // + "clangd.path": "clangd-16", + // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". "clangd.arguments": [ "-header-insertion=never" ], - // - // CMake - // - // Location of base CMakeLists file - "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp/", - // - // C/C++ (should be disabled) - // - // Make sure all C++ IntelliSense features are disabled - // and don't interfere with clangd - "C_Cpp.intelliSenseEngine": "disabled", - "C_Cpp.autocomplete": "disabled", - "C_Cpp.codeAnalysis.clangTidy.codeAction.formatFixes": false, - "C_Cpp.codeAnalysis.runAutomatically": false, - "C_Cpp.configurationWarnings": "disabled", - "C_Cpp.debugShortcut": false, - "C_Cpp.default.enableConfigurationSquiggles": false, - "C_Cpp.formatting": "disabled", - "C_Cpp.vcpkg.enabled": false, - // - // TestMate - // - // Ensures tests are run from the `build` directory - // which ensures SRS can be read - "testMate.cpp.test.workingDirectory": "${command:cmake.buildDirectory}", - // Filter all binaries that are not tests or benchmarks - "testMate.cpp.test.executables": "${command:cmake.buildDirectory}/bin/*{test,Test,TEST,bench}*", - // - // Other - // - "editor.tokenColorCustomizations": { - "textMateRules": [ - { - "scope": "googletest.failed", - "settings": { - "foreground": "#f00" - } + // + // CMake + // + // Location of base CMakeLists file + "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp/", + // + // C/C++ (should be disabled) + // + // Make sure all C++ IntelliSense features are disabled + // and don't interfere with clangd + "C_Cpp.intelliSenseEngine": "disabled", + "C_Cpp.autocomplete": "disabled", + "C_Cpp.codeAnalysis.clangTidy.codeAction.formatFixes": false, + "C_Cpp.codeAnalysis.runAutomatically": false, + "C_Cpp.configurationWarnings": "disabled", + "C_Cpp.debugShortcut": false, + "C_Cpp.default.enableConfigurationSquiggles": false, + "C_Cpp.formatting": "disabled", + "C_Cpp.vcpkg.enabled": false, + // + // TestMate + // + // Ensures tests are run from the `build` directory + // which ensures SRS can be read + "testMate.cpp.test.workingDirectory": "${command:cmake.buildDirectory}", + // Filter all binaries that are not tests or benchmarks + "testMate.cpp.test.executables": "${command:cmake.buildDirectory}/bin/*{test,Test,TEST,bench}*", + // + // Other + // + "editor.tokenColorCustomizations": { + "textMateRules": [ + { + "scope": "googletest.failed", + "settings": { + "foreground": "#f00" + } + }, + { + "scope": "googletest.passed", + "settings": { + "foreground": "#0f0" + } + }, + { + "scope": "googletest.run", + "settings": { + "foreground": "#0f0" + } + } + ] }, - { - "scope": "googletest.passed", - "settings": { - "foreground": "#0f0" - } + "[cpp]": { + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" }, - { - "scope": "googletest.run", - "settings": { - "foreground": "#0f0" - } - } - ] - }, - "[cpp]": { - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" - }, "cmake.configureArgs": [ "-G Ninja" ], - "cmake.useCMakePresets": "always", - "editor.inlayHints.enabled": "offUnlessPressed", - "git.detectSubmodules": false, - "testMate.cpp.discovery.loadOnStartup": false, - "testMate.cpp.debug.configTemplate": { - "type": "lldb", - "MIMode": "lldb", - "program": "${exec}", - "args": "${argsArray}", - "cwd": "${command:cmake.buildDirectory}", - "internalConsoleOptions": "openOnSessionStart", + "cmake.useCMakePresets": "always", + "editor.inlayHints.enabled": "offUnlessPressed", + "git.detectSubmodules": false, + "testMate.cpp.discovery.loadOnStartup": false, + "testMate.cpp.debug.configTemplate": { + "type": "lldb", + "MIMode": "lldb", + "program": "${exec}", + "args": "${argsArray}", + "cwd": "${command:cmake.buildDirectory}", + "internalConsoleOptions": "openOnSessionStart", "console": "internalConsole", - } + } }, -} +} \ No newline at end of file From 4fb977e049ececb1451664ea229bfce98c2825e4 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 28 Aug 2025 15:40:13 +0000 Subject: [PATCH 06/35] undo x2 --- .../barretenberg/translator_vm/translator_circuit_builder.cpp | 2 +- barretenberg/sol/lib/forge-std | 1 + barretenberg/sol/lib/openzeppelin-contracts | 1 + barretenberg/sol/lib/solidity-stringutils | 1 + bb-pilcom/powdr | 1 + proving-systems.code-workspace | 4 ++-- 6 files changed, 7 insertions(+), 3 deletions(-) create mode 160000 barretenberg/sol/lib/forge-std create mode 160000 barretenberg/sol/lib/openzeppelin-contracts create mode 160000 barretenberg/sol/lib/solidity-stringutils create mode 160000 bb-pilcom/powdr diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 09add4e496b0..a51016cfe783 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -528,7 +528,6 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // add two zeros for consistency. // TODO(https://github.com/AztecProtocol/barretenberg/issues/1360): We'll also have to eventually process random // data in the merge protocol (added for zero knowledge)/ - // populate_wires_from_ultra_op(ultra_ops[0]); for (auto& wire : wires) { wire.push_back(add_variable(zero_idx)); wire.push_back(add_variable(zero_idx)); @@ -541,6 +540,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; if (ultra_op.op_code.value() == 0) { + // Skip no-ops as continue; } current_accumulator *= evaluation_input_x; diff --git a/barretenberg/sol/lib/forge-std b/barretenberg/sol/lib/forge-std new file mode 160000 index 000000000000..74cfb77e308d --- /dev/null +++ b/barretenberg/sol/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 74cfb77e308dd188d2f58864aaf44963ae6b88b1 diff --git a/barretenberg/sol/lib/openzeppelin-contracts b/barretenberg/sol/lib/openzeppelin-contracts new file mode 160000 index 000000000000..e50c24f5839d --- /dev/null +++ b/barretenberg/sol/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit e50c24f5839db17f46991478384bfda14acfb830 diff --git a/barretenberg/sol/lib/solidity-stringutils b/barretenberg/sol/lib/solidity-stringutils new file mode 160000 index 000000000000..46983c6d9462 --- /dev/null +++ b/barretenberg/sol/lib/solidity-stringutils @@ -0,0 +1 @@ +Subproject commit 46983c6d9462a80229cf0d5bab8ea3b3ee31066c diff --git a/bb-pilcom/powdr b/bb-pilcom/powdr new file mode 160000 index 000000000000..c3006c11819d --- /dev/null +++ b/bb-pilcom/powdr @@ -0,0 +1 @@ +Subproject commit c3006c11819d9b53fb183c9c12a10b83481bb631 diff --git a/proving-systems.code-workspace b/proving-systems.code-workspace index 44360824f666..d7f8fc1ce580 100644 --- a/proving-systems.code-workspace +++ b/proving-systems.code-workspace @@ -70,7 +70,7 @@ // Clangd. Note that this setting may be overridden by user settings // to the default value "clangd". // - "clangd.path": "clangd-16", + "clangd.path": "clangd-20", // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". "clangd.arguments": [ "-header-insertion=never" @@ -147,4 +147,4 @@ "console": "internalConsole", } }, -} \ No newline at end of file +} From 12d59ca648c1675640e079b91b92de3d72e6bed4 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 29 Aug 2025 11:26:09 +0000 Subject: [PATCH 07/35] I fixed the size of the op queue --- .../barretenberg/client_ivc/client_ivc.cpp | 6 ++ .../client_ivc/client_ivc.test.cpp | 1 - .../cpp/src/barretenberg/goblin/goblin.cpp | 19 +++++- .../barretenberg/op_queue/ecc_op_queue.hpp | 1 + .../barretenberg/op_queue/ecc_ops_table.hpp | 61 +++++++++++++++++-- .../op_queue/ecc_ops_table.test.cpp | 33 ++++++++++ .../translator_circuit_builder.cpp | 2 +- .../translator_vm/translator_proving_key.hpp | 2 +- .../translator_vm/translator_verifier.cpp | 1 + .../barretenberg/ultra_honk/merge_prover.cpp | 10 ++- 10 files changed, 126 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 999a191ccca8..3315c18f5db6 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -269,6 +269,10 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); + // Placeholder for randomness (will be removed) + circuit.queue_ecc_no_op(); + circuit.queue_ecc_no_op(); + info("num ops in hiding kernel ", circuit.op_queue->get_unmerged_subtable_size()); } return { output_verifier_accumulator, pairing_points, merged_table_commitments }; @@ -312,6 +316,8 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { circuit.queue_ecc_no_op(); + circuit.queue_ecc_no_op(); + circuit.queue_ecc_no_op(); } circuit.queue_ecc_eq(); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index eadf345d8aef..f90c4bff9605 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -88,7 +88,6 @@ TEST_F(ClientIVCTests, BasicStructured) EXPECT_TRUE(ClientIVC::verify(proof, vk)); }; - /** * @brief Check that the IVC fails if an intermediate fold proof is invalid * @details When accumulating 4 circuits, there are 3 fold proofs to verify (the first two are recursively verfied and diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index e3743c2d68a4..3779e04812ed 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -45,6 +45,23 @@ void Goblin::prove_translator() auto translator_key = std::make_shared(translator_builder, commitment_key); TranslatorProver translator_prover(translator_key, transcript); goblin_proof.translator_proof = translator_prover.construct_proof(); + // auto op = op_queue->construct_ultra_ops_table_columns()[0]; + // auto op_translator = op_queue->get_ultra_ops(); + // info(op.size(), " ", op_translator.size()); + // for (size_t i = 0; i < op_translator.size(); i++) {} + + // if + // info(op.size(), " ", translator_key->proving_key->polynomials.op.size()); + // for (size_t i = 0; i < op.size(); i++) { + // if (op.at(i) != translator_key->proving_key->polynomials.op[i]) { + // info("mismatch at ", + // i, + // " op_queue: ", + // op.at(i), + // " translator_key: ", + // translator_key->proving_key->polynomials.op[i]); + // } + // } } GoblinProof Goblin::prove(const MergeSettings merge_settings) @@ -52,7 +69,7 @@ GoblinProof Goblin::prove(const MergeSettings merge_settings) PROFILE_THIS_NAME("Goblin::prove"); prove_merge(transcript, merge_settings); // Use shared transcript for merge proving - info("Constructing a Goblin proof with num ultra ops = ", op_queue->get_ultra_ops_table_num_rows()); + info("Constructing a Goblin proof with num ultra ops = ", op_queue->get_ultra_ops().size()); BB_ASSERT_EQ(merge_verification_queue.size(), 1U, diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp index afb970dda9ee..048667444d57 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp @@ -48,6 +48,7 @@ class ECCOpQueue { EccvmRowTracker eccvm_row_tracker; public: + static const size_t OP_QUEUE_SIZE = 1 << 13; /** * @brief Instantiate an initial ECC op subtable. */ diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index dd0a193eff5e..cddb3c9dd7a2 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -74,6 +74,8 @@ struct UltraOp { Fr z_2; bool return_is_infinity; + bool operator==(const UltraOp& other) const = default; + /** * @brief Get the point in standard form i.e. as two coordinates x and y in the base field or as a point at * infinity whose coordinates are set to (0,0). @@ -237,7 +239,6 @@ class UltraEccOpsTable { public: size_t size() const { return table.size(); } - // size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } size_t ultra_table_size() const { @@ -249,7 +250,8 @@ class UltraEccOpsTable { // The last subtable in deque is the fixed-location one last_subtable_size = table.get().back().size() * NUM_ROWS_PER_OP; } - return std::max(base_size, fixed_append_offset.value() + last_subtable_size); + info("here"); + return std::max(base_size, (fixed_append_offset.value() * NUM_ROWS_PER_OP) + last_subtable_size); } return base_size; } @@ -275,7 +277,54 @@ class UltraEccOpsTable { size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } - std::vector get_reconstructed() const { return table.get_reconstructed(); } + std::vector get_reconstructed() const + { + if (has_fixed_append) { + return get_reconstructed_with_fixed_append(); + } + return table.get_reconstructed(); + } + std::vector get_reconstructed_with_fixed_append() const + { + + ASSERT(get_unmerged_subtable_size() == 0, + "current subtable should be merged before reconstructing the full table of operations."); + info("Reconstructing with fixed append"); + + std::vector reconstructed_table; + // reconstructed_table.reserve(reconstructed_table_size); + + for (size_t subtable_idx = 0; subtable_idx < table.num_subtables() - 1; subtable_idx++) { + const auto& subtable = table.get()[subtable_idx]; + for (const auto& op : subtable) { + reconstructed_table.push_back(op); + } + } + info("Size before shift: ", reconstructed_table.size()); + + // Add zeros if fixed offset is larger than current size + if (has_fixed_append && fixed_append_offset.has_value()) { + size_t current_size = reconstructed_table.size(); + size_t target_offset = fixed_append_offset.value(); + + // Fill gap with no-ops if needed + while (current_size < target_offset) { + UltraOp no_op = {}; + // no_op.op_code is already initialized with all false values (no operation) + reconstructed_table.push_back(no_op); + current_size++; + } + } + + // Add the final subtable (appended at fixed location) + info("Size before appending final subtable: ", reconstructed_table.size()); + const auto& final_subtable = table.get()[table.num_subtables() - 1]; + for (const auto& op : final_subtable) { + reconstructed_table.push_back(op); + } + info("Reconstructed table size: ", reconstructed_table.size()); + return reconstructed_table; + } // Construct the columns of the full ultra ecc ops table ColumnPolynomials construct_table_columns() const @@ -283,6 +332,7 @@ class UltraEccOpsTable { const size_t poly_size = ultra_table_size(); if (has_fixed_append) { + info("we should construct with fixed append ", poly_size); // Handle fixed-location append: prepended tables first, then appended table at fixed offset return construct_column_polynomials_with_fixed_append(poly_size); } @@ -347,7 +397,7 @@ class UltraEccOpsTable { // Process all prepended subtables (all except last) size_t i = 0; - for (size_t subtable_idx = 0; subtable_idx < table.num_subtables() - 1; ++subtable_idx) { + for (size_t subtable_idx = 0; subtable_idx < table.num_subtables() - 1; subtable_idx++) { const auto& subtable = table.get()[subtable_idx]; for (const auto& op : subtable) { write_op_to_polynomials(column_polynomials, op, i); @@ -356,7 +406,8 @@ class UltraEccOpsTable { } // Place the appended subtable at the fixed offset - size_t append_position = fixed_append_offset.value_or(i); + size_t append_position = fixed_append_offset.value_or(i) * NUM_ROWS_PER_OP; + info("append position: ", append_position); const auto& appended_subtable = table.get()[table.num_subtables() - 1]; size_t j = append_position; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp index aed854b8981f..6c12016cdf2d 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp @@ -329,6 +329,39 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) EXPECT_EQ(ultra_op_poly.at(fixed_offset + row), expected_poly[row]); } } + + // Mimic get_reconstructed by unifying all the ops from subtables into a single vector with the appropiate gap of + // no-ops + { + // Compute how many no-op operations are needed to span the gap (fixed_offset and prepended_size are in rows) + + std::vector expected_reconstructed; + expected_reconstructed.reserve(expected_num_ops + fixed_offset); + + // Order: subtable[1], subtable[0], gap (no-ops), subtable[2] + for (const auto& op : subtables[1]) { + expected_reconstructed.push_back(op); + } + for (const auto& op : subtables[0]) { + expected_reconstructed.push_back(op); + } + + // Construct a canonical "no-op" UltraOp (fields zeroed) + UltraOp no_op = {}; + size_t size_before = expected_reconstructed.size(); + for (size_t i = size_before; i < fixed_offset; i++) { + expected_reconstructed.push_back(no_op); + } + + for (const auto& op : subtables[2]) { + expected_reconstructed.push_back(op); + } + + EXPECT_EQ(expected_reconstructed.size(), ultra_ops_table.get_reconstructed().size()); + + // Compare to the op-queue's reconstruction (should include the gap as no-ops) + EXPECT_EQ(expected_reconstructed, ultra_ops_table.get_reconstructed()); + } } // Ensure EccvmOpsTable correctly constructs a concatenated table from successively prepended subtables diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index a51016cfe783..7f071f84e70d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -540,7 +540,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; if (ultra_op.op_code.value() == 0) { - // Skip no-ops as + // Skip no-ops as they should not affect the computation of the accumulator (or) continue; } current_accumulator *= evaluation_input_x; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index f1b6fb639b5d..c94a1e2e2ebd 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -49,7 +49,7 @@ class TranslatorProvingKey { PROFILE_THIS_NAME("TranslatorProvingKey(TranslatorCircuit&)"); // Check that the Translator Circuit does not exceed the fixed upper bound, the current value amounts to // a number of EccOps sufficient for 10 rounds of folding (so 20 circuits) - if (circuit.num_gates > Flavor::MINI_CIRCUIT_SIZE - NUM_DISABLED_ROWS_IN_SUMCHECK) { + if (circuit.num_gates > Flavor::MINI_CIRCUIT_SIZE) { throw_or_abort("The Translator circuit size has exceeded the fixed upper bound"); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index da51e6401834..6a6593004fcc 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -204,6 +204,7 @@ bool TranslatorVerifier::verify_translation(const TranslationEvaluations& transl */ bool TranslatorVerifier::verify_consistency_with_final_merge(const std::array& merge_commitments) { + if (op_queue_commitments[0] != merge_commitments[0]) { info("Consistency check failed: op commitment mismatch"); return false; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index e1f4c9095c1a..37dd3c5748af 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -25,7 +25,15 @@ MergeProver::MergeProver(const std::shared_ptr& op_queue, { // Merge the current subtable (for which a merge proof is being constructed) prior to // procedeing with proving. - op_queue->merge(settings); + if (settings == MergeSettings::APPEND) { + + op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - 293); + info("hiding kernel subtable size? ", op_queue->get_current_ultra_ops_subtable_num_rows() / 2); + + } else { + op_queue->merge(settings); + } + pcs_commitment_key = commitment_key.initialized() ? commitment_key : CommitmentKey(op_queue->get_ultra_ops_table_num_rows()); }; From 9e4ed2c0ed806b85331d93389facb7b5cf2faef5 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 29 Aug 2025 13:55:29 +0000 Subject: [PATCH 08/35] zk --- .../barretenberg/client_ivc/client_ivc.cpp | 8 +++---- .../cpp/src/barretenberg/goblin/goblin.cpp | 10 ++++---- .../translator_circuit_builder.cpp | 24 +++++++++++++++---- .../translator_circuit_builder.hpp | 2 +- .../translator_vm/translator_fixed_vk.hpp | 12 +++++----- .../translator_vm/translator_flavor.hpp | 2 +- .../translator_vm/translator_proving_key.cpp | 2 +- .../translator_vm/translator_verifier.cpp | 1 + 8 files changed, 39 insertions(+), 22 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 3315c18f5db6..abf02982ec69 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -270,8 +270,8 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); // Placeholder for randomness (will be removed) - circuit.queue_ecc_no_op(); - circuit.queue_ecc_no_op(); + circuit.queue_ecc_random_op(); + circuit.queue_ecc_random_op(); info("num ops in hiding kernel ", circuit.op_queue->get_unmerged_subtable_size()); } @@ -316,8 +316,8 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { circuit.queue_ecc_no_op(); - circuit.queue_ecc_no_op(); - circuit.queue_ecc_no_op(); + circuit.queue_ecc_random_op(); + circuit.queue_ecc_random_op(); } circuit.queue_ecc_eq(); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index 3779e04812ed..e2f8b9906ee0 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -135,11 +135,11 @@ bool Goblin::verify(const GoblinProof& proof, bool op_queue_consistency_verified = translator_verifier.verify_consistency_with_final_merge(merged_table_commitments); - vinfo("merge verified?: ", merge_verified); - vinfo("eccvm verified?: ", eccvm_verified); - vinfo("accumulator construction_verified?: ", accumulator_construction_verified); - vinfo("translation verified?: ", translation_verified); - vinfo("consistency verified?: ", op_queue_consistency_verified); + info("merge verified?: ", merge_verified); + info("eccvm verified?: ", eccvm_verified); + info("accumulator construction_verified?: ", accumulator_construction_verified); + info("translation verified?: ", translation_verified); + info("consistency verified?: ", op_queue_consistency_verified); return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified && op_queue_consistency_verified; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 7f071f84e70d..d826ad4e95ad 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -403,9 +403,10 @@ void TranslatorCircuitBuilder::assert_well_formed_accumulation_input(const Accum void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra_op) { auto& op_wire = std::get(wires); - op_wire.push_back(add_variable(ultra_op.op_code.value())); + op_wire.push_back( + add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_1 : ultra_op.op_code.value())); // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(zero_idx); + op_wire.push_back(add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_2 : zero_idx)); insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); @@ -534,9 +535,22 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ } num_gates += 2; + auto process_random_up = [&](const UltraOp& ultra_op) { + // ASSERT(ultra_op.op_code.is_random_op, "should be random op "); + populate_wires_from_ultra_op(ultra_op); + for (size_t i = WireIds::Y_LOW_Z_2 + 1; i < wires.size(); i++) { + wires[i].push_back(add_variable(zero_idx)); + wires[i].push_back(add_variable(zero_idx)); + } + num_gates += 2; + }; + + process_random_up(ultra_ops[1]); + process_random_up(ultra_ops[2]); + // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices. We need to know the previous accumulator to create the gate - for (size_t i = 1; i < ultra_ops.size(); i++) { + for (size_t i = 3; i < ultra_ops.size() - 2; i++) { const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; if (ultra_op.op_code.value() == 0) { @@ -560,7 +574,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ std::array previous_accumulator_binary_limbs = split_fq_into_limbs(final_accumulator_state); // Generate witness values from all the UltraOps - for (size_t i = 1; i < ultra_ops.size(); i++) { + for (size_t i = 3; i < ultra_ops.size() - 2; i++) { const auto& ultra_op = ultra_ops[i]; if (ultra_op.op_code.value() == 0) { for (size_t j = 0; j < ACCUMULATORS_BINARY_LIMBS_0; j++) { @@ -595,5 +609,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // And put them into the wires create_accumulation_gate(one_accumulation_step); } + process_random_up(ultra_ops[ultra_ops.size() - 2]); + process_random_up(ultra_ops[ultra_ops.size() - 1]); } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index 8939e0210688..ea9eff6c2162 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -239,7 +239,7 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1; // Index at which the evaluation result is stored in the circuit - static constexpr size_t RESULT_ROW = 2; + static constexpr size_t RESULT_ROW = 6; // How much you'd need to multiply a value by to perform a shift to a higher binary limb static constexpr auto SHIFT_1 = uint256_t(1) << NUM_LIMB_BITS; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp index 4a7cd65cbf40..6edf3077e00d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp @@ -35,16 +35,16 @@ struct TranslatorFixedVKCommitments { uint256_t("0x174caee01a8d7fb79e7834367d842900e5893e35054a6cbbc67dfa8b0aa6bea5")), // lagrange_odd_in_minicircuit - Commitment(uint256_t("0x0591a96bc0c2563ef56776e98c255ce466f557b435e3601f85c40e1124a8f454"), - uint256_t("0x125d3362d8654aebf99e88f68a78224aa6bd5c05ce5246c7fc70445dc5bda9af")), + Commitment(uint256_t("0x23a983a5963d5075a40b895e7864c215e84ba1c92a5585485057ab8981e763ff"), + uint256_t("0x062238be20d523bd606a9c2727fcf1567babbb86f24c5ae0d2d008e10a5270ca")), // lagrange_even_in_minicircuit - Commitment(uint256_t("0x08feb8f4803e9da4fae6e23ebf57809b419a2ae2be9fb224c6646a824d30231f"), - uint256_t("0x2e79d6919ccec15895485c12850cb0ec63e0b93d0e920cac07a4175c68a8d0d2")), + Commitment(uint256_t("0x08033ad1c8aa97c7b58d5053702f7795ec1f421523626e88ca5161c09533f03c"), + uint256_t("0x25730345e6886b41058e42f29586102a2e00fd46650628d67156b1445d358608")), // lagrange_result_row - Commitment(uint256_t("0x020ad6e43ccd48a6a39e43897cc85187bd364919be8a3b82d4809715cfe489db"), - uint256_t("0x21a79ebae2ea3d92b49c521407d2600ac061146f2c188c6c6a33c598179e4543")), + Commitment(uint256_t("0x262d212add82bcbcf96d0773c59926e1b8e68e45c662f9348f2e4f64770595b3"), + uint256_t("0x2fe4de705da2b7bfb03cb3baa199ed4cc97e6ce620d0e939b603493223e88703")), // lagrange_last_in_minicircuit Commitment(uint256_t("0x199c9a28f7a5d9e583b74f41c6a8b85a659a6bfd134ed40158d2e46c882db82d"), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index ffdd110b4f2b..5333f37462d5 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -687,7 +687,7 @@ class TranslatorFlavor { // Initialize some one-off polys with special structure lagrange_first = Polynomial{ /*size*/ 1, /*virtual_size*/ circuit_size }; - lagrange_result_row = Polynomial{ /*size*/ 3, /*virtual_size*/ circuit_size }; + lagrange_result_row = Polynomial{ /*size*/ RESULT_ROW + 1, /*virtual_size*/ circuit_size }; lagrange_even_in_minicircuit = Polynomial{ /*size*/ MINI_CIRCUIT_SIZE, /*virtual_size*/ circuit_size }; lagrange_odd_in_minicircuit = Polynomial{ /*size*/ MINI_CIRCUIT_SIZE, /*virtual_size*/ circuit_size }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index 84ed23e8fb91..a8bd0cfeb9c5 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -254,7 +254,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() // Translator VM processes two rows of its execution trace at a time, establishing different relations between // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations // should trigger at odd indices and which at even. - for (size_t i = 2; i < dyadic_mini_circuit_size_without_masking; i += 2) { + for (size_t i = 6; i < dyadic_mini_circuit_size_without_masking; i += 2) { proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1; proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 6a6593004fcc..6a1f017e1c1d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,6 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { + info("here?"); return false; } From 7204197c3416de7d5a364aacdc571c94396fb697 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 11:14:20 +0000 Subject: [PATCH 09/35] cleanup, fix tests, docs --- ...test_civc_standalone_vks_havent_changed.sh | 2 +- .../barretenberg/client_ivc/client_ivc.cpp | 4 +- .../client_ivc/client_ivc.test.cpp | 1 + .../cpp/src/barretenberg/constants.hpp | 5 + .../cpp/src/barretenberg/goblin/goblin.cpp | 19 +-- .../barretenberg/op_queue/ecc_op_queue.hpp | 2 +- .../op_queue/ecc_op_queue.test.cpp | 14 +- .../barretenberg/op_queue/ecc_ops_table.hpp | 12 +- .../op_queue/ecc_ops_table.test.cpp | 21 ++- .../translator_decomposition_relation.hpp | 18 +-- ...translator_decomposition_relation_impl.hpp | 23 +-- .../translator_extra_relations.hpp | 4 +- .../translator_extra_relations_impl.hpp | 153 ++++++++++-------- ...nslator_non_native_field_relation_impl.hpp | 4 +- .../translator_relation_consistency.test.cpp | 123 ++++++++------ .../mega_circuit_builder.cpp | 2 + .../translator_vm/translator.test.cpp | 24 ++- .../translator_circuit_builder.cpp | 10 +- .../translator_circuit_builder.test.cpp | 5 +- .../translator_vm/translator_flavor.hpp | 2 +- .../translator_vm/translator_verifier.cpp | 1 - .../barretenberg/ultra_honk/merge_prover.cpp | 5 +- 22 files changed, 237 insertions(+), 217 deletions(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 73a4c77fae46..7570148ee850 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -11,7 +11,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="869efec4" +pinned_short_hash="9b31056f" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 3315c18f5db6..c3af653dbd25 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -269,10 +269,9 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); - // Placeholder for randomness (will be removed) + // Placeholder for randomness at the end of the hiding circuit circuit.queue_ecc_no_op(); circuit.queue_ecc_no_op(); - info("num ops in hiding kernel ", circuit.op_queue->get_unmerged_subtable_size()); } return { output_verifier_accumulator, pairing_points, merged_table_commitments }; @@ -316,6 +315,7 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { circuit.queue_ecc_no_op(); + // Placeholder for randomness at the beginning of tail circuit circuit.queue_ecc_no_op(); circuit.queue_ecc_no_op(); } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index f90c4bff9605..eadf345d8aef 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -88,6 +88,7 @@ TEST_F(ClientIVCTests, BasicStructured) EXPECT_TRUE(ClientIVC::verify(proof, vk)); }; + /** * @brief Check that the IVC fails if an intermediate fold proof is invalid * @details When accumulating 4 circuits, there are 3 fold proofs to verify (the first two are recursively verfied and diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 69943225f0e9..19fe32271169 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -8,6 +8,11 @@ namespace bb { // permutation argument polynomials (sigmas, ids) are unique, e.g. id[i][j] == id[m][n] iff (i == m && j == n) constexpr uint32_t PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28; +static constexpr uint32_t CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 14; + +// -1 as each op occupies two rows in Translator trace +static constexpr uint32_t CONST_OP_QUEUE_LOG_SIZE = CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE - 1; + // The log of the max circuit size assumed in order to achieve constant sized Honk proofs // TODO(https://github.com/AztecProtocol/barretenberg/issues/1046): Remove the need for const sized proofs static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index 3779e04812ed..e3743c2d68a4 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -45,23 +45,6 @@ void Goblin::prove_translator() auto translator_key = std::make_shared(translator_builder, commitment_key); TranslatorProver translator_prover(translator_key, transcript); goblin_proof.translator_proof = translator_prover.construct_proof(); - // auto op = op_queue->construct_ultra_ops_table_columns()[0]; - // auto op_translator = op_queue->get_ultra_ops(); - // info(op.size(), " ", op_translator.size()); - // for (size_t i = 0; i < op_translator.size(); i++) {} - - // if - // info(op.size(), " ", translator_key->proving_key->polynomials.op.size()); - // for (size_t i = 0; i < op.size(); i++) { - // if (op.at(i) != translator_key->proving_key->polynomials.op[i]) { - // info("mismatch at ", - // i, - // " op_queue: ", - // op.at(i), - // " translator_key: ", - // translator_key->proving_key->polynomials.op[i]); - // } - // } } GoblinProof Goblin::prove(const MergeSettings merge_settings) @@ -69,7 +52,7 @@ GoblinProof Goblin::prove(const MergeSettings merge_settings) PROFILE_THIS_NAME("Goblin::prove"); prove_merge(transcript, merge_settings); // Use shared transcript for merge proving - info("Constructing a Goblin proof with num ultra ops = ", op_queue->get_ultra_ops().size()); + info("Constructing a Goblin proof with num ultra ops = ", op_queue->get_ultra_ops_table_num_rows()); BB_ASSERT_EQ(merge_verification_queue.size(), 1U, diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp index 048667444d57..7252eb4f850e 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.hpp @@ -48,7 +48,7 @@ class ECCOpQueue { EccvmRowTracker eccvm_row_tracker; public: - static const size_t OP_QUEUE_SIZE = 1 << 13; + static const size_t OP_QUEUE_SIZE = 1 << CONST_OP_QUEUE_LOG_SIZE; /** * @brief Instantiate an initial ECC op subtable. */ diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp index 0a185968cc74..f6a95676bcda 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_op_queue.test.cpp @@ -54,7 +54,9 @@ class ECCOpQueueTest { } else { // APPEND merge performs concatenation directly to end of previous table or at a specified fixed offset const size_t prev_table_size = op_queue->get_previous_ultra_ops_table_num_rows(); // k - const size_t shift_magnitude = ultra_fixed_offset.value_or(prev_table_size); + const size_t shift_magnitude = ultra_fixed_offset.has_value() + ? ultra_fixed_offset.value() * bb::UltraEccOpsTable::NUM_ROWS_PER_OP + : prev_table_size; // k // T(x) = T_prev(x) + x^k * t_current(x), where k is the shift magnitude const Fr prev_table_eval = prev_table_poly.evaluate(eval_challenge); // T_prev(x) const Fr shifted_subtable_eval = @@ -74,10 +76,12 @@ class ECCOpQueueTest { auto ultra_table = op_queue->get_ultra_ops(); auto eccvm_table = op_queue->get_eccvm_ops(); - EXPECT_EQ(eccvm_table.size(), ultra_table.size()); - - for (auto [ultra_op, eccvm_op] : zip_view(ultra_table, eccvm_table)) { - EXPECT_EQ(ultra_op.op_code.value(), eccvm_op.op_code.value()); + size_t j = 0; + for (const auto& ultra_op : ultra_table) { + if (ultra_op.op_code.value() == 0) { + continue; + } + EXPECT_EQ(ultra_op.op_code.value(), eccvm_table[j++].op_code.value()); } }; }; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index cddb3c9dd7a2..6c39fae66183 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -239,7 +239,6 @@ class UltraEccOpsTable { public: size_t size() const { return table.size(); } - size_t ultra_table_size() const { size_t base_size = table.size() * NUM_ROWS_PER_OP; @@ -250,7 +249,6 @@ class UltraEccOpsTable { // The last subtable in deque is the fixed-location one last_subtable_size = table.get().back().size() * NUM_ROWS_PER_OP; } - info("here"); return std::max(base_size, (fixed_append_offset.value() * NUM_ROWS_PER_OP) + last_subtable_size); } return base_size; @@ -279,7 +277,7 @@ class UltraEccOpsTable { std::vector get_reconstructed() const { - if (has_fixed_append) { + if (has_fixed_append && fixed_append_offset.has_value()) { return get_reconstructed_with_fixed_append(); } return table.get_reconstructed(); @@ -289,7 +287,6 @@ class UltraEccOpsTable { ASSERT(get_unmerged_subtable_size() == 0, "current subtable should be merged before reconstructing the full table of operations."); - info("Reconstructing with fixed append"); std::vector reconstructed_table; // reconstructed_table.reserve(reconstructed_table_size); @@ -300,7 +297,6 @@ class UltraEccOpsTable { reconstructed_table.push_back(op); } } - info("Size before shift: ", reconstructed_table.size()); // Add zeros if fixed offset is larger than current size if (has_fixed_append && fixed_append_offset.has_value()) { @@ -317,12 +313,10 @@ class UltraEccOpsTable { } // Add the final subtable (appended at fixed location) - info("Size before appending final subtable: ", reconstructed_table.size()); const auto& final_subtable = table.get()[table.num_subtables() - 1]; for (const auto& op : final_subtable) { reconstructed_table.push_back(op); } - info("Reconstructed table size: ", reconstructed_table.size()); return reconstructed_table; } @@ -332,7 +326,6 @@ class UltraEccOpsTable { const size_t poly_size = ultra_table_size(); if (has_fixed_append) { - info("we should construct with fixed append ", poly_size); // Handle fixed-location append: prepended tables first, then appended table at fixed offset return construct_column_polynomials_with_fixed_append(poly_size); } @@ -406,8 +399,7 @@ class UltraEccOpsTable { } // Place the appended subtable at the fixed offset - size_t append_position = fixed_append_offset.value_or(i) * NUM_ROWS_PER_OP; - info("append position: ", append_position); + size_t append_position = fixed_append_offset.has_value() ? fixed_append_offset.value() * NUM_ROWS_PER_OP : i; const auto& appended_subtable = table.get()[table.num_subtables() - 1]; size_t j = append_position; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp index 6c12016cdf2d..4ec210d09c9b 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp @@ -267,8 +267,9 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) // Define a fixed offset at which to append the table (must be greater than the total size of the prepended tables) const size_t fixed_offset = 20; + const size_t fixed_offset_num_rows = fixed_offset * ULTRA_ROWS_PER_OP; const size_t prepended_size = (subtable_op_counts[0] + subtable_op_counts[1]) * ULTRA_ROWS_PER_OP; - ASSERT(fixed_offset > prepended_size); + ASSERT(fixed_offset_num_rows > prepended_size); // Construct the ultra ops table for (size_t i = 0; i < NUM_SUBTABLES; ++i) { @@ -290,7 +291,7 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) EXPECT_EQ(ultra_ops_table.size(), expected_num_ops); // Check that the polynomials have the correct size (including gap) - size_t expected_poly_size = fixed_offset + (subtable_op_counts[2] * ULTRA_ROWS_PER_OP); + size_t expected_poly_size = fixed_offset_num_rows + (subtable_op_counts[2] * ULTRA_ROWS_PER_OP); EXPECT_EQ(ultra_ops_table.ultra_table_size(), expected_poly_size); // Construct polynomials corresponding to the columns of the ultra ops table @@ -316,7 +317,7 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) // Check gap from offset to appended subtable is filled with zeros for (auto ultra_op_poly : ultra_ops_table_polynomials) { - for (size_t row = prepended_size; row < fixed_offset; ++row) { + for (size_t row = prepended_size; row < fixed_offset_num_rows; ++row) { EXPECT_EQ(ultra_op_poly.at(row), Fr::zero()); } } @@ -325,20 +326,18 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) std::vector> appended_subtables = { subtables[2] }; EccOpsTableTest::MockUltraOpsTable expected_appended_table(appended_subtables); for (auto [ultra_op_poly, expected_poly] : zip_view(ultra_ops_table_polynomials, expected_appended_table.columns)) { - for (size_t row = 0; row < subtable_op_counts[2] * ULTRA_ROWS_PER_OP; ++row) { - EXPECT_EQ(ultra_op_poly.at(fixed_offset + row), expected_poly[row]); + for (size_t row = 0; row < subtable_op_counts[2] * ULTRA_ROWS_PER_OP; row++) { + EXPECT_EQ(ultra_op_poly.at(fixed_offset_num_rows + row), expected_poly[row]); } } - // Mimic get_reconstructed by unifying all the ops from subtables into a single vector with the appropiate gap of - // no-ops + // Mimic get_reconstructed by unifying all the ops from subtables into a single vector with the appropiate append + // offset { - // Compute how many no-op operations are needed to span the gap (fixed_offset and prepended_size are in rows) - std::vector expected_reconstructed; expected_reconstructed.reserve(expected_num_ops + fixed_offset); - // Order: subtable[1], subtable[0], gap (no-ops), subtable[2] + // Order: subtable[1], subtable[0], no-ops range, subtable[2] for (const auto& op : subtables[1]) { expected_reconstructed.push_back(op); } @@ -346,7 +345,7 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) expected_reconstructed.push_back(op); } - // Construct a canonical "no-op" UltraOp (fields zeroed) + // Add the range of noops UltraOp no_op = {}; size_t size_before = expected_reconstructed.size(); for (size_t i = size_before; i < fixed_offset; i++) { diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp index 175706f7d947..00af4d0bf823 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp @@ -16,12 +16,12 @@ template class TranslatorDecompositionRelationImpl { // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = - 3; // degree(lagrange_even_in_minicircuit_in_minicircuit(a - a_0 - a_1*2¹⁴ ... - a_l⋅2¹⁴ˡ )) = 2 + 4; // degree(lagrange_even_in_minicircuit_in_minicircuit(a - a_0 - a_1*2¹⁴ ... - a_l⋅2¹⁴ˡ )op) = 3 static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 4, // decomposition of P.x limb 0 into microlimbs subrelation - 4, // decomposition of P.x limb 1 into microlimbs subrelation - 4, // decomposition of P.x limb 2 into microlimbs subrelation - 4, // decomposition of P.x limb 3 into microlimbs subrelation + 4, // decomposition of accumulator limb 0 into microlimbs subrelation + 4, // decomposition of accumulator limb 1 into microlimbs subrelation + 4, // decomposition of accumulator limb 2 into microlimbs subrelation + 4, // decomposition of accumulator limb 3 into microlimbs subrelation 3, // decomposition of P.y limb 0 into microlimbs subrelation 3, // decomposition of P.y limb 1 into microlimbs subrelation 3, // decomposition of P.y limb 2 into microlimbs subrelation @@ -30,10 +30,10 @@ template class TranslatorDecompositionRelationImpl { 3, // decomposition of z2 limb 0 into microlimbs subrelation 3, // decomposition of z1 limb 1 into microlimbs subrelation 3, // decomposition of z2 limb 1 into microlimbs subrelation - 3, // decomposition of accumulator limb 0 into microlimbs subrelation - 3, // decomposition of accumulator limb 1 into microlimbs subrelation - 3, // decomposition of accumulator limb 2 into microlimbs subrelation - 3, // decomposition of accumulator limb 3 into microlimbs subrelation + 3, // decomposition of P.x limb 0 into microlimbs subrelation + 3, // decomposition of P.x limb 1 into microlimbs subrelation + 3, // decomposition of P.x limb 2 into microlimbs subrelation + 3, // decomposition of P.x limb 3 into microlimbs subrelation 3, // decomposition of quotient limb 0 into microlimbs subrelation 3, // decomposition of quotient limb 1 into microlimbs subrelation 3, // decomposition of quotient limb 2 into microlimbs subrelation diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp index 8e04b27453e4..a4dd45514186 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp @@ -37,8 +37,9 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio static constexpr size_t NUM_LIMB_BITS = 68; // Number of bits in a standard limb used for bigfield operations static constexpr size_t NUM_MICRO_LIMB_BITS = 14; // Number of bits in a standard limb used for bigfield operations - // Contribution 13, accumulator lowest limb decomposition [&]() { + // Within the no-op range i.e. when the op polynomial is 0 at even index the 2 Translator trace rows are empty + // except for the accumulator binary limbs which get transferred across the no-op range using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; using View = typename Accumulator::View; @@ -74,7 +75,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio auto op = View(in.op); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - // Contribution 13, accumulator lowest limb decomposition + // Contribution 1, accumulator lowest limb decomposition auto tmp_1 = ((accumulator_low_limbs_range_constraint_0 + accumulator_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + accumulator_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + @@ -85,7 +86,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_1 *= scaling_factor; std::get<0>(accumulators) += tmp_1; - // Contribution 14, accumulator second limb decomposition + // Contribution 2, accumulator second limb decomposition auto tmp_2 = ((accumulator_low_limbs_range_constraint_0_shift + accumulator_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + accumulator_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + @@ -96,7 +97,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_2 *= scaling_factor; std::get<1>(accumulators) += tmp_2; - // Contribution 15, accumulator second highest limb decomposition + // Contribution 3, accumulator second highest limb decomposition auto tmp_3 = ((accumulator_high_limbs_range_constraint_0 + accumulator_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + accumulator_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + @@ -107,7 +108,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_3 *= scaling_factor; std::get<2>(accumulators) += tmp_3; - // Contribution 16, accumulator highest limb decomposition + // Contribution 4, accumulator highest limb decomposition auto tmp_4 = ((accumulator_high_limbs_range_constraint_0_shift + accumulator_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + @@ -367,7 +368,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio std::get<11>(accumulators) += tmp_12; // Contributions that decompose 50, 52, 68 or 84 bit limbs used for computation into range-constrained chunks - // Contribution 1 , P_x lowest limb decomposition + // Contribution 13, P_x lowest limb decomposition auto tmp_13 = ((p_x_low_limbs_range_constraint_0 + p_x_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + p_x_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + p_x_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + @@ -377,7 +378,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_13 *= scaling_factor; std::get<12>(accumulators) += tmp_13; - // Contribution 2 , P_x second lowest limb decomposition + // Contribution 14 , P_x second lowest limb decomposition auto tmp_14 = ((p_x_low_limbs_range_constraint_0_shift + p_x_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + p_x_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + @@ -388,7 +389,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_14 *= scaling_factor; std::get<13>(accumulators) += tmp_14; - // Contribution 3 , P_x third limb decomposition + // Contribution 15 , P_x third limb decomposition auto tmp_15 = ((p_x_high_limbs_range_constraint_0 + p_x_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + p_x_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + p_x_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + @@ -398,7 +399,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_15 *= scaling_factor; std::get<14>(accumulators) += tmp_15; - // Contribution 4 , P_x highest limb decomposition + // Contribution 16 , P_x highest limb decomposition auto tmp_16 = ((p_x_high_limbs_range_constraint_0_shift + p_x_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + p_x_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + @@ -408,7 +409,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_16 *= scaling_factor; std::get<15>(accumulators) += tmp_16; - // Contribution 15 , quotient lowest limb decomposition + // Contribution 17 , quotient lowest limb decomposition auto tmp_17 = ((quotient_low_limbs_range_constraint_0 + quotient_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + quotient_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + @@ -418,7 +419,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio tmp_17 *= lagrange_even_in_minicircuit; tmp_17 *= scaling_factor; std::get<16>(accumulators) += tmp_17; - // Contribution 16 , quotient second lowest limb decomposition + // Contribution 18 , quotient second lowest limb decomposition auto tmp_18 = ((quotient_low_limbs_range_constraint_0_shift + quotient_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + quotient_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp index 10668dd50350..52b85378807f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp @@ -14,9 +14,9 @@ template class TranslatorOpcodeConstraintRelationImpl { using FF = FF_; // 1 + polynomial degree of this relation - static constexpr size_t RELATION_LENGTH = 6; // degree((lagrange_masking - 1)⋅op ⋅(op - 3)⋅(op - 4)⋅(op - 8)) = 5 + static constexpr size_t RELATION_LENGTH = 6; static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 7, // opcode constraint relation + 6, // opcode constraint relation 7, // opcode constraint relation 7, // opcode constraint relation 7, // opcode constraint relation diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp index c08a2e326177..11f04648bba3 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp @@ -28,74 +28,87 @@ void TranslatorOpcodeConstraintRelationImpl::accumulate(ContainerOverSubrela const FF& scaling_factor) { - using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - - auto op = View(in.op); - auto lagrange_mini_masking = View(in.lagrange_mini_masking); - auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - static const FF minus_three = FF(-3); - static const FF minus_four = FF(-4); - static const FF minus_eight = FF(-8); - static const FF minus_one = FF(-1); - - auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); - auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); - auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); - auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - auto accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); - auto accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); - auto accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); - auto accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); - - // Contribution (1) op(op-3)(op-4)(op-8)) - auto tmp_1 = op * (op + minus_three); - tmp_1 *= (op + minus_four); - tmp_1 *= (op + minus_eight); - tmp_1 *= (lagrange_mini_masking + minus_one); - tmp_1 *= lagrange_even_in_minicircuit; - tmp_1 *= scaling_factor; - std::get<0>(accumulators) += tmp_1; - - // Contribution (2) (2-5 ensure that the accumulator stays the same at even indices) - auto tmp_2 = (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); - tmp_2 *= (op + minus_three); - tmp_2 *= (op + minus_four); - tmp_2 *= (op + minus_eight); - tmp_2 *= (lagrange_mini_masking + minus_one); - tmp_2 *= lagrange_even_in_minicircuit; - tmp_2 *= scaling_factor; - std::get<1>(accumulators) += tmp_2; - - // Contribution (3) - auto tmp_3 = (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); - tmp_3 *= (op + minus_three); - tmp_3 *= (op + minus_four); - tmp_3 *= (op + minus_eight); - tmp_3 *= (lagrange_mini_masking + minus_one); - tmp_3 *= lagrange_even_in_minicircuit; - tmp_3 *= scaling_factor; - std::get<2>(accumulators) += tmp_3; - - // Contribution (4) - auto tmp_4 = (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); - tmp_4 *= (op + minus_three); - tmp_4 *= (op + minus_four); - tmp_4 *= (op + minus_eight); - tmp_4 *= (lagrange_mini_masking + minus_one); - tmp_4 *= lagrange_even_in_minicircuit; - tmp_4 *= scaling_factor; - std::get<3>(accumulators) += tmp_4; - - // Contribution (5) - auto tmp_5 = (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); - tmp_5 *= (op + minus_three); - tmp_5 *= (op + minus_four); - tmp_5 *= (op + minus_eight); - tmp_5 *= (lagrange_mini_masking + minus_one); - tmp_5 *= lagrange_even_in_minicircuit; - tmp_5 *= scaling_factor; - std::get<4>(accumulators) += tmp_5; + [&]() { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + auto op = View(in.op); + auto lagrange_mini_masking = View(in.lagrange_mini_masking); + static const FF minus_three = FF(-3); + static const FF minus_four = FF(-4); + static const FF minus_eight = FF(-8); + static const FF minus_one = FF(-1); + + // Contribution (1) op(op-3)(op-4)(op-8)) + auto tmp_1 = op * (op + minus_three); + tmp_1 *= (op + minus_four); + tmp_1 *= (op + minus_eight); + tmp_1 *= (lagrange_mini_masking + minus_one); + tmp_1 *= scaling_factor; + std::get<0>(accumulators) += tmp_1; + }(); + + [&]() { + using Accumulator = std::tuple_element_t<1, ContainerOverSubrelations>; + using View = typename Accumulator::View; + auto op = View(in.op); + auto lagrange_mini_masking = View(in.lagrange_mini_masking); + auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); + static const FF minus_three = FF(-3); + static const FF minus_four = FF(-4); + static const FF minus_eight = FF(-8); + static const FF minus_one = FF(-1); + + auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); + auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); + auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); + auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); + auto accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); + auto accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); + auto accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); + auto accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); + + // Contribution (2) (2-5 ensure that the accumulator stays the same at even indices within the no-op range if + // one exists) + auto tmp_2 = (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); + tmp_2 *= (op + minus_three); + tmp_2 *= (op + minus_four); + tmp_2 *= (op + minus_eight); + tmp_2 *= (lagrange_mini_masking + minus_one); + tmp_2 *= lagrange_even_in_minicircuit; + tmp_2 *= scaling_factor; + std::get<1>(accumulators) += tmp_2; + + // Contribution (3) + auto tmp_3 = (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); + tmp_3 *= (op + minus_three); + tmp_3 *= (op + minus_four); + tmp_3 *= (op + minus_eight); + tmp_3 *= (lagrange_mini_masking + minus_one); + tmp_3 *= lagrange_even_in_minicircuit; + tmp_3 *= scaling_factor; + std::get<2>(accumulators) += tmp_3; + + // Contribution (4) + auto tmp_4 = (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); + tmp_4 *= (op + minus_three); + tmp_4 *= (op + minus_four); + tmp_4 *= (op + minus_eight); + tmp_4 *= (lagrange_mini_masking + minus_one); + tmp_4 *= lagrange_even_in_minicircuit; + tmp_4 *= scaling_factor; + std::get<3>(accumulators) += tmp_4; + + // Contribution (5) + auto tmp_5 = (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); + tmp_5 *= (op + minus_three); + tmp_5 *= (op + minus_four); + tmp_5 *= (op + minus_eight); + tmp_5 *= (lagrange_mini_masking + minus_one); + tmp_5 *= lagrange_even_in_minicircuit; + tmp_5 *= scaling_factor; + std::get<4>(accumulators) += tmp_5; + }(); }; /** @@ -126,8 +139,8 @@ void TranslatorAccumulatorTransferRelationImpl::accumulate(ContainerOverSubr // Lagrange ensuring the accumulator result is validated at the correct row auto lagrange_result_row = View(in.lagrange_result_row); - // Lagrange at index (size of minicircuit - 1) is used to enforce that the accumulator is initialized to zero in the - // circuit + // Lagrange at index (size of minicircuit - 1) is used to enforce that the accumulator is initialized to zero in + // the circuit auto lagrange_last_in_minicircuit = View(in.lagrange_last_in_minicircuit); // Locations of randomness in the minicircuit diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index 8b8094deb9b6..10d8da453e2e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -63,7 +63,9 @@ namespace bb { * which we need to calculate non-permutation relations). All other indices are set to zero. Each EccOpQueue entry * (operation) occupies 2 rows in bn254 transcripts. So the Translator VM has a 2-row cycle and we need to * switch the checks being performed depending on which row we are at right now. We have half a cycle of - * accumulation, where we perform this computation, and half a cycle where we just copy accumulator data. + * accumulation, where we perform this computation, and half a cycle where we just copy accumulator data. They also get + * multiplied by the op because the no-op range within the trace (if one exits) should imply the accumulator doesn't + * change (fully enforced by the AccumulatorTransferRelation and OpcodeRelation ) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp index cf6baecc73b8..094e15d62a9c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp @@ -382,6 +382,7 @@ TEST_F(TranslatorRelationConsistency, DecompositionRelation) const auto& x_lo_y_hi_shift = input_elements.x_lo_y_hi_shift; const auto& x_hi_z_1_shift = input_elements.x_hi_z_1_shift; const auto& y_lo_z_2_shift = input_elements.y_lo_z_2_shift; + const auto& op = input_elements.op; const auto& lagrange_even_in_minicircuit = input_elements.lagrange_even_in_minicircuit; @@ -509,29 +510,29 @@ TEST_F(TranslatorRelationConsistency, DecompositionRelation) }; // Check decomposition 50-72 bit limbs into microlimbs - expected_values[0] = check_standard_limb_decomposition(p_x_low_limbs_range_constraint_0, - p_x_low_limbs_range_constraint_1, - p_x_low_limbs_range_constraint_2, - p_x_low_limbs_range_constraint_3, - p_x_low_limbs_range_constraint_4, - p_x_low_limbs); - expected_values[1] = check_standard_limb_decomposition(p_x_low_limbs_range_constraint_0_shift, - p_x_low_limbs_range_constraint_1_shift, - p_x_low_limbs_range_constraint_2_shift, - p_x_low_limbs_range_constraint_3_shift, - p_x_low_limbs_range_constraint_4_shift, - p_x_low_limbs_shift); - expected_values[2] = check_standard_limb_decomposition(p_x_high_limbs_range_constraint_0, - p_x_high_limbs_range_constraint_1, - p_x_high_limbs_range_constraint_2, - p_x_high_limbs_range_constraint_3, - p_x_high_limbs_range_constraint_4, - p_x_high_limbs); - expected_values[3] = check_standard_top_limb_decomposition(p_x_high_limbs_range_constraint_0_shift, - p_x_high_limbs_range_constraint_1_shift, - p_x_high_limbs_range_constraint_2_shift, - p_x_high_limbs_range_constraint_3_shift, - p_x_high_limbs_shift); + expected_values[0] = op * check_standard_limb_decomposition(accumulator_low_limbs_range_constraint_0, + accumulator_low_limbs_range_constraint_1, + accumulator_low_limbs_range_constraint_2, + accumulator_low_limbs_range_constraint_3, + accumulator_low_limbs_range_constraint_4, + accumulators_binary_limbs_0); + expected_values[1] = op * check_standard_limb_decomposition(accumulator_low_limbs_range_constraint_0_shift, + accumulator_low_limbs_range_constraint_1_shift, + accumulator_low_limbs_range_constraint_2_shift, + accumulator_low_limbs_range_constraint_3_shift, + accumulator_low_limbs_range_constraint_4_shift, + accumulators_binary_limbs_1); + expected_values[2] = op * check_standard_limb_decomposition(accumulator_high_limbs_range_constraint_0, + accumulator_high_limbs_range_constraint_1, + accumulator_high_limbs_range_constraint_2, + accumulator_high_limbs_range_constraint_3, + accumulator_high_limbs_range_constraint_4, + accumulators_binary_limbs_2); + expected_values[3] = op * check_standard_top_limb_decomposition(accumulator_high_limbs_range_constraint_0_shift, + accumulator_high_limbs_range_constraint_1_shift, + accumulator_high_limbs_range_constraint_2_shift, + accumulator_high_limbs_range_constraint_3_shift, + accumulators_binary_limbs_3); expected_values[4] = check_standard_limb_decomposition(p_y_low_limbs_range_constraint_0, p_y_low_limbs_range_constraint_1, @@ -580,29 +581,30 @@ TEST_F(TranslatorRelationConsistency, DecompositionRelation) z_high_limbs_range_constraint_3_shift, z_high_limbs_range_constraint_4_shift, z_high_limbs_shift); - expected_values[12] = check_standard_limb_decomposition(accumulator_low_limbs_range_constraint_0, - accumulator_low_limbs_range_constraint_1, - accumulator_low_limbs_range_constraint_2, - accumulator_low_limbs_range_constraint_3, - accumulator_low_limbs_range_constraint_4, - accumulators_binary_limbs_0); - expected_values[13] = check_standard_limb_decomposition(accumulator_low_limbs_range_constraint_0_shift, - accumulator_low_limbs_range_constraint_1_shift, - accumulator_low_limbs_range_constraint_2_shift, - accumulator_low_limbs_range_constraint_3_shift, - accumulator_low_limbs_range_constraint_4_shift, - accumulators_binary_limbs_1); - expected_values[14] = check_standard_limb_decomposition(accumulator_high_limbs_range_constraint_0, - accumulator_high_limbs_range_constraint_1, - accumulator_high_limbs_range_constraint_2, - accumulator_high_limbs_range_constraint_3, - accumulator_high_limbs_range_constraint_4, - accumulators_binary_limbs_2); - expected_values[15] = check_standard_top_limb_decomposition(accumulator_high_limbs_range_constraint_0_shift, - accumulator_high_limbs_range_constraint_1_shift, - accumulator_high_limbs_range_constraint_2_shift, - accumulator_high_limbs_range_constraint_3_shift, - accumulators_binary_limbs_3); + expected_values[12] = check_standard_limb_decomposition(p_x_low_limbs_range_constraint_0, + p_x_low_limbs_range_constraint_1, + p_x_low_limbs_range_constraint_2, + p_x_low_limbs_range_constraint_3, + p_x_low_limbs_range_constraint_4, + p_x_low_limbs); + expected_values[13] = check_standard_limb_decomposition(p_x_low_limbs_range_constraint_0_shift, + p_x_low_limbs_range_constraint_1_shift, + p_x_low_limbs_range_constraint_2_shift, + p_x_low_limbs_range_constraint_3_shift, + p_x_low_limbs_range_constraint_4_shift, + p_x_low_limbs_shift); + expected_values[14] = check_standard_limb_decomposition(p_x_high_limbs_range_constraint_0, + p_x_high_limbs_range_constraint_1, + p_x_high_limbs_range_constraint_2, + p_x_high_limbs_range_constraint_3, + p_x_high_limbs_range_constraint_4, + p_x_high_limbs); + expected_values[15] = check_standard_top_limb_decomposition(p_x_high_limbs_range_constraint_0_shift, + p_x_high_limbs_range_constraint_1_shift, + p_x_high_limbs_range_constraint_2_shift, + p_x_high_limbs_range_constraint_3_shift, + p_x_high_limbs_shift); + expected_values[16] = check_standard_limb_decomposition(quotient_low_limbs_range_constraint_0, quotient_low_limbs_range_constraint_1, quotient_low_limbs_range_constraint_2, @@ -735,15 +737,32 @@ TEST_F(TranslatorRelationConsistency, OpcodeConstraintRelation) const InputElements input_elements = random_inputs ? get_random_input() : get_special_input(); const auto& op = input_elements.op; + const auto& accumulators_binary_limbs_0 = input_elements.accumulators_binary_limbs_0; + const auto& accumulators_binary_limbs_1 = input_elements.accumulators_binary_limbs_1; + const auto& accumulators_binary_limbs_2 = input_elements.accumulators_binary_limbs_2; + const auto& accumulators_binary_limbs_3 = input_elements.accumulators_binary_limbs_3; + const auto& accumulators_binary_limbs_0_shift = input_elements.accumulators_binary_limbs_0_shift; + const auto& accumulators_binary_limbs_1_shift = input_elements.accumulators_binary_limbs_1_shift; + const auto& accumulators_binary_limbs_2_shift = input_elements.accumulators_binary_limbs_2_shift; + const auto& accumulators_binary_limbs_3_shift = input_elements.accumulators_binary_limbs_3_shift; + const auto& lagrange_mini_masking = input_elements.lagrange_mini_masking; + const auto& lagrange_even_in_minicircuit = input_elements.lagrange_even_in_minicircuit; RelationValues expected_values; const auto parameters = RelationParameters::get_random(); - // (Contribution 1) - auto contribution_1 = op * (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * (lagrange_mini_masking - FF(1)); - expected_values[0] = contribution_1; + // Opcode constraints - ensure op is 0, 3, 4, or 8 + expected_values[0] = op * (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * (lagrange_mini_masking - FF(1)); + + auto shared = + (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * (lagrange_mini_masking - FF(1)) * lagrange_even_in_minicircuit; + // Accumulator transfer constraints when op != 0 + expected_values[1] = shared * (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); + expected_values[2] = shared * (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); + expected_values[3] = shared * (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); + expected_values[4] = shared * (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); validate_relation_execution(expected_values, input_elements, parameters); }; @@ -1119,7 +1138,7 @@ TEST_F(TranslatorRelationConsistency, NonNativeFieldRelation) quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * shift - relation_wide_limbs * shiftx2) * - lagrange_even_in_minicircuit; + lagrange_even_in_minicircuit * op; // Higher wide limb subrelation expected_values[1] = @@ -1161,7 +1180,7 @@ TEST_F(TranslatorRelationConsistency, NonNativeFieldRelation) quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * shift - relation_wide_limbs_shift * shiftx2) * - lagrange_even_in_minicircuit; + lagrange_even_in_minicircuit * op; auto reconstructed_p_x = (p_x_low_limbs + p_x_low_limbs_shift * shift + p_x_high_limbs * shiftx2 + p_x_high_limbs_shift * shiftx3); auto reconstructed_p_y = @@ -1185,7 +1204,7 @@ TEST_F(TranslatorRelationConsistency, NonNativeFieldRelation) reconstructed_z1 * parameters.batching_challenge_v[2][4] + reconstructed_z2 * parameters.batching_challenge_v[3][4] + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator) * - lagrange_even_in_minicircuit; + lagrange_even_in_minicircuit * op; validate_relation_execution(expected_values, input_elements, parameters); }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 4ca0a747a529..8eb78aacf99c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -62,6 +62,8 @@ template void MegaCircuitBuilder_::add_mega_gates_to_ensure_al read_return_data(read_idx); if (op_queue->get_unmerged_subtable_size() == 0) { + // Add a mul dummy op if the subtable to avoid column polynomial being zero (it has to be a mul rather than an + // add to ensure all 4 column polynomials contain some data) this->queue_ecc_mul_accum(bb::g1::affine_element::one(), 2); this->queue_ecc_eq(); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 73ff0904030b..0334c079631a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -1,6 +1,5 @@ #include "barretenberg/circuit_checker/translator_circuit_checker.hpp" #include "barretenberg/common/log.hpp" -#include "barretenberg/honk/relation_checker.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/sumcheck/sumcheck_round.hpp" @@ -25,7 +24,7 @@ class TranslatorTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } - // Helper function to add no-op operations + // Helper function to add no-ops static void add_no_ops(std::shared_ptr& op_queue, size_t count = 1) { for (size_t i = 0; i < count; i++) { @@ -33,7 +32,7 @@ class TranslatorTests : public ::testing::Test { } } - // Helper function to add mixed add and mul operations + // Helper function to create an MSM static void add_mixed_ops(std::shared_ptr& op_queue, size_t count = 100) { auto P1 = G1::random_element(); @@ -68,16 +67,6 @@ class TranslatorTests : public ::testing::Test { return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } - /** - * @brief Check that size of a Translator proof matches the corresponding constant - *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: - * - Proof length formula in translator_flavor.hpp, etc... - * - translator_transcript.test.cpp - * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol - */ - - // Helper function to setup prover transcript with initial value - // Helper function to create a complete proof-verification setup static bool prove_and_verify(const CircuitBuilder& circuit_builder, const Fq& evaluation_challenge_x, const Fq& batching_challenge_v) @@ -108,6 +97,13 @@ class TranslatorTests : public ::testing::Test { } }; +/** + * @brief Check that size of a Translator proof matches the corresponding constant + *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: + * - Proof length formula in translator_flavor.hpp, etc... + * - translator_transcript.test.cpp + * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol + */ TEST_F(TranslatorTests, ProofLengthCheck) { using Fq = fq; @@ -135,7 +131,7 @@ TEST_F(TranslatorTests, ProofLengthCheck) * @brief Test simple circuit with public inputs * */ -TEST_F(TranslatorTests, BasicWithoutNoOps) +TEST_F(TranslatorTests, Basic) { using Fq = fq; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 7f071f84e70d..3ff25f603326 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -537,10 +537,9 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices. We need to know the previous accumulator to create the gate for (size_t i = 1; i < ultra_ops.size(); i++) { - const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; if (ultra_op.op_code.value() == 0) { - // Skip no-ops as they should not affect the computation of the accumulator (or) + // Skip no-ops as they should not affect the computation of the accumulator continue; } current_accumulator *= evaluation_input_x; @@ -554,7 +553,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ accumulator_trace.push_back(current_accumulator); } - // Accumulator final value is recomputed during witness generation anyway + // Accumulator final value,recomputed during witness generation and expected at RESULT_ROW Fq final_accumulator_state = accumulator_trace.back(); accumulator_trace.pop_back(); @@ -563,6 +562,11 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ for (size_t i = 1; i < ultra_ops.size(); i++) { const auto& ultra_op = ultra_ops[i]; if (ultra_op.op_code.value() == 0) { + // Within the no-op range the translator trace is empty except for the accumulator binary limbs which gets + // copied from the last row k where an op happened (i.e. the op wire the even index has a non-zero value). + // Then, during proving we perform all the checks to estabilish wires at k are well formed and that we + // appropriately transfered the accumulator value at k across the entire no-op range, both in even and odd + // indices. for (size_t j = 0; j < ACCUMULATORS_BINARY_LIMBS_0; j++) { wires[j].push_back(add_variable(zero_idx)); wires[j].push_back(add_variable(zero_idx)); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 7d4f7a1add5e..eef7dfd7abe9 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -130,8 +130,9 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); } - // The degree is ultra_ops.size() - 2 as we ignore the first no-op in computation - Fq x_pow = x.pow(ultra_ops.size() - (2 + no_op_count)); + // Compute the degree ignoring the start no-op (which ensures we can shift polynomials) and also the no-op rage + // if one exists within the trace + Fq x_pow = x.pow(ultra_ops.size() - 1 - (1 + no_op_count)); // Multiply by an appropriate power of x to get rid of the inverses Fq result = diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index ffdd110b4f2b..8f9de3a7737d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -62,7 +62,7 @@ class TranslatorFlavor { // The fixed log size of Translator circuit determining the size most polynomials (except the ones // involved in the interleaving subprotocol). It should be determined by the size of the EccOpQueue. - static constexpr size_t LOG_MINI_CIRCUIT_SIZE = 14; + static constexpr size_t LOG_MINI_CIRCUIT_SIZE = CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE; // Log of size of interleaved_* and ordered_* polynomials static constexpr size_t CONST_TRANSLATOR_LOG_N = LOG_MINI_CIRCUIT_SIZE + numeric::get_msb(INTERLEAVING_GROUP_SIZE); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 6a6593004fcc..da51e6401834 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -204,7 +204,6 @@ bool TranslatorVerifier::verify_translation(const TranslationEvaluations& transl */ bool TranslatorVerifier::verify_consistency_with_final_merge(const std::array& merge_commitments) { - if (op_queue_commitments[0] != merge_commitments[0]) { info("Consistency check failed: op commitment mismatch"); return false; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 37dd3c5748af..7682ad731858 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -26,9 +26,8 @@ MergeProver::MergeProver(const std::shared_ptr& op_queue, // Merge the current subtable (for which a merge proof is being constructed) prior to // procedeing with proving. if (settings == MergeSettings::APPEND) { - - op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - 293); - info("hiding kernel subtable size? ", op_queue->get_current_ultra_ops_subtable_num_rows() / 2); + size_t last_subtable_size = op_queue->get_unmerged_subtable_size(); + op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size); } else { op_queue->merge(settings); From c9ac144a866a0e0315cf8a22902fdb17d3d32609 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 13:56:59 +0000 Subject: [PATCH 10/35] ugh --- .../cpp/src/barretenberg/client_ivc/client_ivc.cpp | 7 ------- .../barretenberg/translator_vm/translator_proving_key.cpp | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 1451042f65f8..2803218fbdc8 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -268,16 +268,9 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); -<<<<<<< HEAD - // Placeholder for randomness (will be removed) - circuit.queue_ecc_random_op(); - circuit.queue_ecc_random_op(); - info("num ops in hiding kernel ", circuit.op_queue->get_unmerged_subtable_size()); -======= // Placeholder for randomness at the end of the hiding circuit circuit.queue_ecc_random_op(); circuit.queue_ecc_random_op(); ->>>>>>> mm/fix-op-queue } return { output_verifier_accumulator, pairing_points, merged_table_commitments }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index a8bd0cfeb9c5..e8099ebcf02d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -248,6 +248,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() // Location of randomness for wires defined within the mini circuit for (size_t i = dyadic_mini_circuit_size_without_masking; i < mini_circuit_dyadic_size; i++) { + proving_key->polynomials.lagrange_mini_masking.at(i - dyadic_mini_circuit_size_without_masking) = 1; proving_key->polynomials.lagrange_mini_masking.at(i) = 1; } From d002636f3a3396a93332c782acab89e0ae5a6d07 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 13:57:51 +0000 Subject: [PATCH 11/35] hm --- barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index ebe9ce59ee18..7b20f0ff07c8 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -268,7 +268,7 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); - // Placeholder for randomness at the end of the hiding circuit + // Placeholder for randomness at the end of the hiding circuit (to be handled in subsequent PR) circuit.queue_ecc_no_op(); circuit.queue_ecc_no_op(); } From f60efd24308f65d598f4ac1cd5932663854faac4 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 14:21:24 +0000 Subject: [PATCH 12/35] update vks --- .../cpp/scripts/test_civc_standalone_vks_havent_changed.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 7570148ee850..5c084f94aa58 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -11,7 +11,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="9b31056f" +pinned_short_hash="c08772b2" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { From ede88d2962864b0ba0221274e48c126ab1f6e4a1 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 14:43:59 +0000 Subject: [PATCH 13/35] fix op relation --- .../translator_extra_relations.hpp | 10 +- .../translator_extra_relations_impl.hpp | 146 ++++++++---------- 2 files changed, 70 insertions(+), 86 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp index 52b85378807f..e3abe1497d28 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp @@ -17,10 +17,10 @@ template class TranslatorOpcodeConstraintRelationImpl { static constexpr size_t RELATION_LENGTH = 6; static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 6, // opcode constraint relation - 7, // opcode constraint relation - 7, // opcode constraint relation - 7, // opcode constraint relation - 7 // opcode constraint relation + 6, // opcode constraint relation + 6, // opcode constraint relation + 6, // opcode constraint relation + 6 // opcode constraint relation }; /** @@ -29,7 +29,7 @@ template class TranslatorOpcodeConstraintRelationImpl { */ template inline static bool skip(const AllEntities& in) { - return in.lagrange_even_in_minicircuit.is_zero(); + return (in.lagrange_even_in_minicircuit + in.lagrange_mini_masking).is_zero(); } /** * @brief Expression for enforcing the value of the Opcode to be {0,3,4,8} diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp index 11f04648bba3..e838fcedfd8b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations_impl.hpp @@ -28,87 +28,71 @@ void TranslatorOpcodeConstraintRelationImpl::accumulate(ContainerOverSubrela const FF& scaling_factor) { - [&]() { - using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - - auto op = View(in.op); - auto lagrange_mini_masking = View(in.lagrange_mini_masking); - static const FF minus_three = FF(-3); - static const FF minus_four = FF(-4); - static const FF minus_eight = FF(-8); - static const FF minus_one = FF(-1); - - // Contribution (1) op(op-3)(op-4)(op-8)) - auto tmp_1 = op * (op + minus_three); - tmp_1 *= (op + minus_four); - tmp_1 *= (op + minus_eight); - tmp_1 *= (lagrange_mini_masking + minus_one); - tmp_1 *= scaling_factor; - std::get<0>(accumulators) += tmp_1; - }(); - - [&]() { - using Accumulator = std::tuple_element_t<1, ContainerOverSubrelations>; - using View = typename Accumulator::View; - auto op = View(in.op); - auto lagrange_mini_masking = View(in.lagrange_mini_masking); - auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - static const FF minus_three = FF(-3); - static const FF minus_four = FF(-4); - static const FF minus_eight = FF(-8); - static const FF minus_one = FF(-1); - - auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); - auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); - auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); - auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - auto accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); - auto accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); - auto accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); - auto accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); - - // Contribution (2) (2-5 ensure that the accumulator stays the same at even indices within the no-op range if - // one exists) - auto tmp_2 = (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); - tmp_2 *= (op + minus_three); - tmp_2 *= (op + minus_four); - tmp_2 *= (op + minus_eight); - tmp_2 *= (lagrange_mini_masking + minus_one); - tmp_2 *= lagrange_even_in_minicircuit; - tmp_2 *= scaling_factor; - std::get<1>(accumulators) += tmp_2; - - // Contribution (3) - auto tmp_3 = (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); - tmp_3 *= (op + minus_three); - tmp_3 *= (op + minus_four); - tmp_3 *= (op + minus_eight); - tmp_3 *= (lagrange_mini_masking + minus_one); - tmp_3 *= lagrange_even_in_minicircuit; - tmp_3 *= scaling_factor; - std::get<2>(accumulators) += tmp_3; - - // Contribution (4) - auto tmp_4 = (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); - tmp_4 *= (op + minus_three); - tmp_4 *= (op + minus_four); - tmp_4 *= (op + minus_eight); - tmp_4 *= (lagrange_mini_masking + minus_one); - tmp_4 *= lagrange_even_in_minicircuit; - tmp_4 *= scaling_factor; - std::get<3>(accumulators) += tmp_4; - - // Contribution (5) - auto tmp_5 = (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); - tmp_5 *= (op + minus_three); - tmp_5 *= (op + minus_four); - tmp_5 *= (op + minus_eight); - tmp_5 *= (lagrange_mini_masking + minus_one); - tmp_5 *= lagrange_even_in_minicircuit; - tmp_5 *= scaling_factor; - std::get<4>(accumulators) += tmp_5; - }(); + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + auto op = View(in.op); + auto lagrange_mini_masking = View(in.lagrange_mini_masking); + static const FF minus_three = FF(-3); + static const FF minus_four = FF(-4); + static const FF minus_eight = FF(-8); + static const FF minus_one = FF(-1); + + // Contribution (1) op(op-3)(op-4)(op-8)) + auto tmp_1 = op * (op + minus_three); + tmp_1 *= (op + minus_four); + tmp_1 *= (op + minus_eight); + tmp_1 *= (lagrange_mini_masking + minus_one); + tmp_1 *= scaling_factor; + std::get<0>(accumulators) += tmp_1; + + auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); + + auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); + auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); + auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); + auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); + auto accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); + auto accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); + auto accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); + auto accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); + + // Contribution (2) (2-5 ensure that the accumulator stays the same at even indices within the no-op range if + // one exists) + auto tmp_2 = (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); + tmp_2 *= (op + minus_three); + tmp_2 *= (op + minus_four); + tmp_2 *= (op + minus_eight); + tmp_2 *= lagrange_even_in_minicircuit; + tmp_2 *= scaling_factor; + std::get<1>(accumulators) += tmp_2; + + // Contribution (3) + auto tmp_3 = (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); + tmp_3 *= (op + minus_three); + tmp_3 *= (op + minus_four); + tmp_3 *= (op + minus_eight); + tmp_3 *= lagrange_even_in_minicircuit; + tmp_3 *= scaling_factor; + std::get<2>(accumulators) += tmp_3; + + // Contribution (4) + auto tmp_4 = (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); + tmp_4 *= (op + minus_three); + tmp_4 *= (op + minus_four); + tmp_4 *= (op + minus_eight); + tmp_4 *= lagrange_even_in_minicircuit; + tmp_4 *= scaling_factor; + std::get<3>(accumulators) += tmp_4; + + // Contribution (5) + auto tmp_5 = (accumulators_binary_limbs_3 - accumulators_binary_limbs_3_shift); + tmp_5 *= (op + minus_three); + tmp_5 *= (op + minus_four); + tmp_5 *= (op + minus_eight); + tmp_5 *= lagrange_even_in_minicircuit; + tmp_5 *= scaling_factor; + std::get<4>(accumulators) += tmp_5; }; /** From 42252d68da8a4ce72cd6c83f26834d79ffce1d08 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 2 Sep 2025 17:05:05 +0000 Subject: [PATCH 14/35] fix test --- .../translator_vm/translator_relation_consistency.test.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp index 094e15d62a9c..c60a2925ee38 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_relation_consistency.test.cpp @@ -756,9 +756,7 @@ TEST_F(TranslatorRelationConsistency, OpcodeConstraintRelation) // Opcode constraints - ensure op is 0, 3, 4, or 8 expected_values[0] = op * (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * (lagrange_mini_masking - FF(1)); - auto shared = - (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * (lagrange_mini_masking - FF(1)) * lagrange_even_in_minicircuit; - // Accumulator transfer constraints when op != 0 + auto shared = (op - FF(3)) * (op - FF(4)) * (op - FF(8)) * lagrange_even_in_minicircuit; expected_values[1] = shared * (accumulators_binary_limbs_0 - accumulators_binary_limbs_0_shift); expected_values[2] = shared * (accumulators_binary_limbs_1 - accumulators_binary_limbs_1_shift); expected_values[3] = shared * (accumulators_binary_limbs_2 - accumulators_binary_limbs_2_shift); From d9b8f06b6557b0716c48d43a4334cd2052c11bf3 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 3 Sep 2025 11:46:40 +0000 Subject: [PATCH 15/35] docs need to update tests --- avm-transpiler/Cargo.lock | 32 ++++++------- .../barretenberg/client_ivc/client_ivc.cpp | 48 ++++++++++++++++--- .../barretenberg/client_ivc/client_ivc.hpp | 1 + .../translator_circuit_builder.cpp | 34 +++++++------ .../translator_circuit_builder.hpp | 2 +- .../translator_vm/translator_fixed_vk.hpp | 4 +- .../translator_vm/translator_verifier.cpp | 2 +- 7 files changed, 83 insertions(+), 40 deletions(-) diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index bf28cdd42245..e39bb5b5271f 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "acir" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir_field", "base64 0.22.1", @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "ark-bn254", "ark-ff", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -54,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "blake2", @@ -467,7 +467,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "brillig" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir_field", "serde", @@ -499,7 +499,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acir", "acvm_blackbox_solver", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "fm" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "codespan-reporting", "iter-extended", @@ -1122,7 +1122,7 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "iter-extended" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" [[package]] name = "itertools" @@ -1224,7 +1224,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "noir_protobuf" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "color-eyre", "prost", @@ -1232,7 +1232,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "iter-extended", @@ -1247,11 +1247,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" [[package]] name = "noirc_errors" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "base64 0.22.1", @@ -1268,7 +1268,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1326,7 +1326,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "1.0.0-beta.10" +version = "1.0.0-beta.11" dependencies = [ "acvm", "iter-extended", diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 2803218fbdc8..e645dcade186 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -268,9 +268,9 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); - // Placeholder for randomness at the end of the hiding circuit - circuit.queue_ecc_random_op(); - circuit.queue_ecc_random_op(); + // Add randomness at the end of the hiding kernel (whose ecc ops fall right at the end of the op queue) to + // ensure the CIVC proof doesn't leak information about the actual content of the op queue + hide_op_queue_content(circuit); } return { output_verifier_accumulator, pairing_points, merged_table_commitments }; @@ -314,8 +314,9 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { circuit.queue_ecc_no_op(); - circuit.queue_ecc_random_op(); - circuit.queue_ecc_random_op(); + // Add randomness at the begining of the tail kernel (whose ecc ops fall at the beginning of the op queue) to + // ensure the CIVC proof doesn't leak information about the actual content of the op queue + hide_op_queue_content(circuit); } circuit.queue_ecc_eq(); @@ -520,7 +521,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr previous_accumulator_binary_limbs = split_fq_into_limbs(final_accumulator_state); - // Generate witness values from all the UltraOps + // Generate witness values and accumulation gates from all the actual UltraOps for (size_t i = 3; i < ultra_ops.size() - 2; i++) { const auto& ultra_op = ultra_ops[i]; if (ultra_op.op_code.value() == 0) { @@ -614,7 +618,9 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // And put them into the wires create_accumulation_gate(one_accumulation_step); } - process_random_up(ultra_ops[ultra_ops.size() - 2]); - process_random_up(ultra_ops[ultra_ops.size() - 1]); + // Also process the last two random ops present at the end of the op queue to hide the ecc ops of the last circuit + // whose ops are added to the op queue + process_random_op(ultra_ops[ultra_ops.size() - 2]); + process_random_op(ultra_ops[ultra_ops.size() - 1]); } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index ea9eff6c2162..38547e173f21 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -238,7 +238,7 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { // Maximum size of 2 higher limbs concatenated static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1; - // Index at which the evaluation result is stored in the circuit + // Index at which the evaluation result is stored in the circuit, coming after one no-op and two random ops static constexpr size_t RESULT_ROW = 6; // How much you'd need to multiply a value by to perform a shift to a higher binary limb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp index 6edf3077e00d..101f151b13dc 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp @@ -55,8 +55,8 @@ struct TranslatorFixedVKCommitments { uint256_t("0x0e0602fc16675e0f0e11b9c509608a43fd8ac75d779ae3f69cbbba7a647c736a")), // lagrange_mini_masking - Commitment(uint256_t("0x0d196a5c600fbdd14809692103339b55ed2196ba9157657c154ce47583db6451"), - uint256_t("0x168bd1b1498c739037b4ba885c603bf7db03fe1cf3401f16e3beac898abc52cf")), + Commitment(uint256_t("0x0f30d7db2ef1e38f496c696565d2edbb6c7790c5e29aa5de577778ab50cc4bc8"), + uint256_t("0x17bc6c20e905302778f27555c1ee2126de382211d6c31a85a0c592912d41fce1")), // lagrange_real_last // lagrange_last diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 52d40e778804..2cf9dae17d61 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,7 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { - info("here?"); + vinfo("translator verifier: sumcheck failed"); return false; } From c475254f95a8abd72b1524a7d652b2683a044244 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 10:17:21 +0000 Subject: [PATCH 16/35] improve tests --- .../graph_description_goblin.test.cpp | 2 +- .../cpp/src/barretenberg/goblin/goblin.cpp | 10 +- .../src/barretenberg/goblin/mock_circuits.hpp | 26 +++- .../goblin_recursive_verifier.test.cpp | 48 +++--- .../translator_recursive_verifier.test.cpp | 44 ++++-- .../translator_vm/translator.test.cpp | 36 ++--- .../translator_circuit_builder.test.cpp | 139 ++++++++---------- .../barretenberg/ultra_honk/merge_prover.cpp | 2 + 8 files changed, 163 insertions(+), 144 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp index cabd60033ee3..c2c7c91e7db6 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp @@ -55,7 +55,7 @@ class BoomerangGoblinRecursiveVerifierTests : public testing::Test { Goblin goblin_final; goblin_final.op_queue = goblin.op_queue; MegaCircuitBuilder builder{ goblin_final.op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder, /*last_circuit=*/true); + GoblinMockCircuits::construct_simple_circuit(builder); goblin_final.op_queue->merge(); // Subtable values and commitments - needed for (Recursive)MergeVerifier MergeCommitments merge_commitments; diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index e3743c2d68a4..5eb7ae31b416 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -118,11 +118,11 @@ bool Goblin::verify(const GoblinProof& proof, bool op_queue_consistency_verified = translator_verifier.verify_consistency_with_final_merge(merged_table_commitments); - vinfo("merge verified?: ", merge_verified); - vinfo("eccvm verified?: ", eccvm_verified); - vinfo("accumulator construction_verified?: ", accumulator_construction_verified); - vinfo("translation verified?: ", translation_verified); - vinfo("consistency verified?: ", op_queue_consistency_verified); + info("merge verified?: ", merge_verified); + info("eccvm verified?: ", eccvm_verified); + info("accumulator construction_verified?: ", accumulator_construction_verified); + info("translation verified?: ", translation_verified); + info("consistency verified?: ", op_queue_consistency_verified); return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified && op_queue_consistency_verified; diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index a94125d857a8..f79af1acbcf8 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -12,6 +12,7 @@ #include "barretenberg/crypto/merkle_tree/memory_store.hpp" #include "barretenberg/crypto/merkle_tree/merkle_tree.hpp" #include "barretenberg/flavor/mega_flavor.hpp" +#include "barretenberg/goblin/goblin.hpp" #include "barretenberg/srs/global_crs.hpp" #include "barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp" #include "barretenberg/stdlib/hash/keccak/keccak.hpp" @@ -136,19 +137,34 @@ class GoblinMockCircuits { * * @param builder */ - static void construct_simple_circuit(MegaBuilder& builder, bool last_circuit = false) + static void construct_simple_circuit(MegaBuilder& builder) { PROFILE_THIS(); - // The last circuit to be accumulated must contain a no-op - if (last_circuit) { - builder.queue_ecc_no_op(); - } add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); bb::stdlib::recursion::honk::DefaultIO::add_default(builder); } + static void construct_and_merge_mock_circuits(Goblin& goblin, const size_t num_circuits = 3) + { + for (size_t idx = 0; idx < num_circuits - 1; ++idx) { + MegaCircuitBuilder builder{ goblin.op_queue }; + if (idx == num_circuits - 2) { + // Last circuit appended needs to begin with a no-op for translator to be shiftable + builder.queue_ecc_no_op(); + } + construct_simple_circuit(builder); + goblin.prove_merge(); + // Pop the merge proof from the queue, Goblin will be verified at the end + goblin.merge_verification_queue.pop_front(); + } + MegaCircuitBuilder builder{ goblin.op_queue }; + GoblinMockCircuits::construct_simple_circuit(builder); + builder.queue_ecc_no_op(); + builder.queue_ecc_no_op(); + } + /** * @brief Construct a mock kernel circuit * @details Construct an arbitrary circuit meant to represent the aztec private function execution kernel. Recursive diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp index 6488a0e469c8..165605775b9f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp @@ -40,30 +40,21 @@ class GoblinRecursiveVerifierTests : public testing::Test { * * @return ProverOutput */ - static ProverOutput create_goblin_prover_output(Builder* outer_builder = nullptr, const size_t NUM_CIRCUITS = 3) + static ProverOutput create_goblin_prover_output(Builder* outer_builder = nullptr, + [[maybe_unused]] const size_t NUM_CIRCUITS = 3) { + // TODO: do something here which is going to be painful Goblin goblin; - // Construct and accumulate multiple circuits - for (size_t idx = 0; idx < NUM_CIRCUITS - 1; ++idx) { - MegaCircuitBuilder builder{ goblin.op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder); - goblin.prove_merge(); - } - - Goblin goblin_final; - goblin_final.op_queue = goblin.op_queue; - MegaCircuitBuilder builder{ goblin_final.op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder, /*last_circuit=*/true); + GoblinMockCircuits::construct_and_merge_mock_circuits(goblin, 5); // Merge the ecc ops from the newly constructed circuit - goblin_final.op_queue->merge(); - + auto goblin_proof = goblin.prove(MergeSettings::APPEND); // Subtable values and commitments - needed for (Recursive)MergeVerifier MergeCommitments merge_commitments; - auto t_current = goblin_final.op_queue->construct_current_ultra_ops_subtable_columns(); - auto T_prev = goblin_final.op_queue->construct_previous_ultra_ops_table_columns(); - CommitmentKey pcs_commitment_key(goblin_final.op_queue->get_ultra_ops_table_num_rows()); + auto t_current = goblin.op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = goblin.op_queue->construct_previous_ultra_ops_table_columns(); + CommitmentKey pcs_commitment_key(goblin.op_queue->get_ultra_ops_table_num_rows()); for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { merge_commitments.t_commitments[idx] = pcs_commitment_key.commit(t_current[idx]); merge_commitments.T_prev_commitments[idx] = pcs_commitment_key.commit(T_prev[idx]); @@ -80,7 +71,7 @@ class GoblinRecursiveVerifierTests : public testing::Test { } // Output is a goblin proof plus ECCVM/Translator verification keys - return { goblin_final.prove(), + return { goblin_proof, { std::make_shared(), std::make_shared() }, merge_commitments, recursive_merge_commitments }; @@ -97,7 +88,7 @@ TEST_F(GoblinRecursiveVerifierTests, NativeVerification) std::shared_ptr verifier_transcript = std::make_shared(); - EXPECT_TRUE(Goblin::verify(proof, merge_commitments, verifier_transcript)); + EXPECT_TRUE(Goblin::verify(proof, merge_commitments, verifier_transcript, MergeSettings::APPEND)); } /** @@ -112,7 +103,7 @@ TEST_F(GoblinRecursiveVerifierTests, Basic) create_goblin_prover_output(&builder); GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments); + GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND); output.points_accumulator.set_public(); info("Recursive Verifier: num gates = ", builder.num_gates); @@ -146,7 +137,8 @@ TEST_F(GoblinRecursiveVerifierTests, IndependentVKHash) create_goblin_prover_output(&builder, inner_size); GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments); + GoblinRecursiveVerifierOutput output = + verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND); output.points_accumulator.set_public(); info("Recursive Verifier: num gates = ", builder.num_gates); @@ -231,7 +223,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorFailure) } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(tampered_proof, recursive_merge_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(tampered_proof, recursive_merge_commitments, MergeSettings::APPEND); EXPECT_FALSE(CircuitChecker::check(builder)); } // Tamper with the Translator proof non-preamble values @@ -258,7 +251,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorFailure) } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(tampered_proof, recursive_merge_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(tampered_proof, recursive_merge_commitments, MergeSettings::APPEND); EXPECT_FALSE(CircuitChecker::check(builder)); } } @@ -281,7 +275,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslationEvaluationsFailure) proof.eccvm_proof.pre_ipa_proof[op_limb_index] += 1; GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(proof, recursive_merge_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND); EXPECT_FALSE(CircuitChecker::check(builder)); } @@ -306,7 +301,7 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorMergeConsistencyFailure) std::shared_ptr verifier_transcript = std::make_shared(); // Check natively that the proof is correct. - EXPECT_TRUE(Goblin::verify(proof, merge_commitments, verifier_transcript)); + EXPECT_TRUE(Goblin::verify(proof, merge_commitments, verifier_transcript, MergeSettings::APPEND)); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1298): // Better recursion testing - create more flexible proof tampering tests. @@ -333,7 +328,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorMergeConsistencyFailure) // Construct and check the Goblin Recursive Verifier circuit GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(proof, recursive_merge_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND); EXPECT_FALSE(CircuitChecker::check(builder)); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index 6099c46f0e70..c9ebfb85aa5c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -44,29 +44,49 @@ class TranslatorRecursiveTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } - static std::shared_ptr create_op_queue(const size_t num_ops) + // Helper function to add no-ops + static void add_no_ops(std::shared_ptr& op_queue, size_t count = 1) + { + for (size_t i = 0; i < count; i++) { + op_queue->no_op_ultra_only(); + } + } + + // Helper function to create an MSM + static void add_mixed_ops(std::shared_ptr& op_queue, size_t count = 100) { auto P1 = InnerG1::random_element(); auto P2 = InnerG1::random_element(); auto z = InnerFF::random_element(); - - // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = std::make_shared(); - op_queue->no_op_ultra_only(); - - for (size_t i = 0; i < num_ops; i++) { + for (size_t i = 0; i < count; i++) { op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); } + op_queue->eq_and_reset(); + } + + // Construct a test circuit based on some random operations + static InnerBuilder generate_test_circuit(const InnerBF& batching_challenge_v, + const InnerBF& evaluation_challenge_x, + const size_t circuit_size_parameter = 500) + { + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + add_no_ops(op_queue); + add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); - return op_queue; + add_mixed_ops(op_queue, circuit_size_parameter / 2); + add_no_ops(op_queue, 2); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); + + return InnerBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } static void test_recursive_verification() { using NativeVerifierCommitmentKey = InnerFlavor::VerifierCommitmentKey; // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = create_op_queue(500); auto prover_transcript = std::make_shared(); prover_transcript->send_to_verifier("init", InnerBF::random_element()); @@ -76,7 +96,7 @@ class TranslatorRecursiveTests : public ::testing::Test { InnerBF batching_challenge_v = InnerBF::random_element(); InnerBF evaluation_challenge_x = InnerBF::random_element(); - auto circuit_builder = InnerBuilder(batching_challenge_v, evaluation_challenge_x, op_queue); + InnerBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); auto proving_key = std::make_shared(circuit_builder); InnerProver prover{ proving_key, prover_transcript }; @@ -142,8 +162,6 @@ class TranslatorRecursiveTests : public ::testing::Test { // Retrieves the trace blocks (each consisting of a specific gate) from the recursive verifier circuit auto get_blocks = [](size_t num_ops) -> std::tuple> { - auto op_queue = create_op_queue(num_ops); - auto prover_transcript = std::make_shared(); prover_transcript->send_to_verifier("init", InnerBF::random_element()); @@ -152,7 +170,7 @@ class TranslatorRecursiveTests : public ::testing::Test { InnerBF batching_challenge_v = InnerBF::random_element(); InnerBF evaluation_challenge_x = InnerBF::random_element(); - auto inner_circuit = InnerBuilder(batching_challenge_v, evaluation_challenge_x, op_queue); + InnerBuilder inner_circuit = generate_test_circuit(batching_challenge_v, evaluation_challenge_x, num_ops); // Generate a proof over the inner circuit auto inner_proving_key = std::make_shared(inner_circuit); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 0334c079631a..3fb792bccfd1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -48,21 +48,17 @@ class TranslatorTests : public ::testing::Test { // Construct a test circuit based on some random operations static CircuitBuilder generate_test_circuit(const Fq& batching_challenge_v, const Fq& evaluation_challenge_x, - const size_t circuit_size_parameter = 500, - const bool add_no_ops_region = false) + const size_t circuit_size_parameter = 500) { // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); add_no_ops(op_queue); - - add_mixed_ops(op_queue, circuit_size_parameter / 2); - if (add_no_ops_region) { - add_no_ops(op_queue, 4); - } - add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); + add_mixed_ops(op_queue, circuit_size_parameter / 2); + add_no_ops(op_queue, 2); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } @@ -146,21 +142,21 @@ TEST_F(TranslatorTests, Basic) EXPECT_TRUE(verified); } -TEST_F(TranslatorTests, BasicWithNoOps) -{ - using Fq = fq; +// TEST_F(TranslatorTests, BasicWithNoOps) +// { +// using Fq = fq; - Fq batching_challenge_v = Fq::random_element(); - Fq evaluation_challenge_x = Fq::random_element(); +// Fq batching_challenge_v = Fq::random_element(); +// Fq evaluation_challenge_x = Fq::random_element(); - // Generate a circuit and its verification key (computed at runtime from the proving key) - CircuitBuilder circuit_builder = generate_test_circuit( - batching_challenge_v, evaluation_challenge_x, /*circuit_size_parameter=*/500, /*add_no_ops_region=*/true); +// // Generate a circuit and its verification key (computed at runtime from the proving key) +// CircuitBuilder circuit_builder = generate_test_circuit( +// batching_challenge_v, evaluation_challenge_x, /*circuit_size_parameter=*/500, /*add_no_ops_region=*/true); - EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); - bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); - EXPECT_TRUE(verified); -} +// EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); +// bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); +// EXPECT_TRUE(verified); +// } /** * @brief Ensure that the fixed VK from the default constructor agrees with those computed manually for an arbitrary diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index eef7dfd7abe9..9272479ad572 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -80,79 +80,70 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) using scalar = fr; using Fq = fq; - auto test_with_no_ops = [](size_t no_op_count = 0, bool start_with_no_ops = false) { - auto P1 = point::random_element(); - auto P2 = point::random_element(); - auto z = scalar::random_element(); - - // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = std::make_shared(); - op_queue->no_op_ultra_only(); - if (!start_with_no_ops) { - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - } - - for (size_t i = 0; i < no_op_count; ++i) { - op_queue->no_op_ultra_only(); - } - - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - op_queue->add_accumulate(P1); - op_queue->mul_accumulate(P2, z); - - Fq op_accumulator = 0; - Fq p_x_accumulator = 0; - Fq p_y_accumulator = 0; - Fq z_1_accumulator = 0; - Fq z_2_accumulator = 0; - Fq batching_challenge = fq::random_element(); - - op_queue->eq_and_reset(); - op_queue->merge(); - - // Sample the evaluation input x - Fq x = Fq::random_element(); - // Get an inverse - Fq x_inv = x.invert(); - // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& ultra_ops = op_queue->get_ultra_ops(); - for (size_t i = 1; i < ultra_ops.size(); i++) { - const auto& ecc_op = ultra_ops[i]; - if (ecc_op.op_code.value() == 0) { - continue; - } - op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); - const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); - p_x_accumulator = p_x_accumulator * x_inv + x_u256; - p_y_accumulator = p_y_accumulator * x_inv + y_u256; - z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); - z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); + auto P1 = point::random_element(); + auto P2 = point::random_element(); + auto z = scalar::random_element(); + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + op_queue->no_op_ultra_only(); + + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->eq_and_reset(); + op_queue->merge(); + + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->eq_and_reset(); + // Placeholder for randomness + op_queue->no_op_ultra_only(); + op_queue->no_op_ultra_only(); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); + + Fq op_accumulator = 0; + Fq p_x_accumulator = 0; + Fq p_y_accumulator = 0; + Fq z_1_accumulator = 0; + Fq z_2_accumulator = 0; + Fq batching_challenge = fq::random_element(); + + // Sample the evaluation input x + Fq x = Fq::random_element(); + Fq x_pow = Fq(1); + // Get an inverse + Fq x_inv = x.invert(); + // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) + const auto& ultra_ops = op_queue->get_ultra_ops(); + for (size_t i = 1; i < ultra_ops.size(); i++) { + const auto& ecc_op = ultra_ops[i]; + if (ecc_op.op_code.value() == 0) { + continue; } - // Compute the degree ignoring the start no-op (which ensures we can shift polynomials) and also the no-op rage - // if one exists within the trace - Fq x_pow = x.pow(ultra_ops.size() - 1 - (1 + no_op_count)); - - // Multiply by an appropriate power of x to get rid of the inverses - Fq result = - ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * - batching_challenge + - p_x_accumulator) * - batching_challenge + - op_accumulator) * - x_pow; - - // Create circuit builder and feed the queue inside - auto circuit_builder = TranslatorCircuitBuilder(batching_challenge, x, op_queue); - // Check that the circuit passes - EXPECT_TRUE(CircuitChecker::check(circuit_builder)); - // Check the accumulation result stored as 4 limbs in the circuit and then reconstructed is consistent with the - // value computed by hand. - EXPECT_EQ(result, CircuitChecker::get_computation_result(circuit_builder)); - }; - - test_with_no_ops(); - test_with_no_ops(5); - test_with_no_ops(5, true); + op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); + const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); + p_x_accumulator = p_x_accumulator * x_inv + x_u256; + p_y_accumulator = p_y_accumulator * x_inv + y_u256; + z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); + z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); + x_pow *= x; + } + x_pow *= x_inv; + // Multiply by an appropriate power of x to get rid of the inverses + Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * + batching_challenge + + p_x_accumulator) * + batching_challenge + + op_accumulator) * + x_pow; + + // Create circuit builder and feed the queue inside + auto circuit_builder = TranslatorCircuitBuilder(batching_challenge, x, op_queue); + // Check that the circuit passes + EXPECT_TRUE(CircuitChecker::check(circuit_builder)); + // Check the accumulation result stored as 4 limbs in the circuit and then reconstructed is consistent with the + // value computed by hand. + EXPECT_EQ(result, CircuitChecker::get_computation_result(circuit_builder)); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 7682ad731858..1660206b78be 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -26,10 +26,12 @@ MergeProver::MergeProver(const std::shared_ptr& op_queue, // Merge the current subtable (for which a merge proof is being constructed) prior to // procedeing with proving. if (settings == MergeSettings::APPEND) { + info("appending now"); size_t last_subtable_size = op_queue->get_unmerged_subtable_size(); op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size); } else { + info("here"); op_queue->merge(settings); } From 3f8b86cc2694a6c8d963c56df4c9144e821e2331 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 11:52:15 +0000 Subject: [PATCH 17/35] resolve comments from tests --- .../graph_description_goblin.test.cpp | 30 ++++++------------- .../cpp/src/barretenberg/constants.hpp | 2 ++ ...translator_decomposition_relation_impl.hpp | 13 ++++---- .../goblin_recursive_verifier.test.cpp | 14 ++++----- .../mega_circuit_builder.cpp | 2 +- .../translator_vm/translator.test.cpp | 21 +------------ .../translator_circuit_builder.cpp | 14 ++++----- .../translator_circuit_builder.test.cpp | 1 + 8 files changed, 32 insertions(+), 65 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp index c2c7c91e7db6..f081bf17708b 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp @@ -40,37 +40,25 @@ class BoomerangGoblinRecursiveVerifierTests : public testing::Test { * * @return ProverOutput */ - static ProverOutput create_goblin_prover_output(const size_t NUM_CIRCUITS = 3) + static ProverOutput create_goblin_prover_output() { Goblin goblin; - // Construct and accumulate multiple circuits - for (size_t idx = 0; idx < NUM_CIRCUITS - 1; ++idx) { - MegaCircuitBuilder builder{ goblin.op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder); - goblin.prove_merge(); - } - - auto goblin_transcript = std::make_shared(); + GoblinMockCircuits::construct_and_merge_mock_circuits(goblin, 5); - Goblin goblin_final; - goblin_final.op_queue = goblin.op_queue; - MegaCircuitBuilder builder{ goblin_final.op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder); - goblin_final.op_queue->merge(); + // Merge the ecc ops from the newly constructed circuit + auto goblin_proof = goblin.prove(MergeSettings::APPEND); // Subtable values and commitments - needed for (Recursive)MergeVerifier MergeCommitments merge_commitments; - auto t_current = goblin_final.op_queue->construct_current_ultra_ops_subtable_columns(); - auto T_prev = goblin_final.op_queue->construct_previous_ultra_ops_table_columns(); - CommitmentKey pcs_commitment_key(goblin_final.op_queue->get_ultra_ops_table_num_rows()); + auto t_current = goblin.op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = goblin.op_queue->construct_previous_ultra_ops_table_columns(); + CommitmentKey pcs_commitment_key(goblin.op_queue->get_ultra_ops_table_num_rows()); for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { merge_commitments.t_commitments[idx] = pcs_commitment_key.commit(t_current[idx]); merge_commitments.T_prev_commitments[idx] = pcs_commitment_key.commit(T_prev[idx]); } // Output is a goblin proof plus ECCVM/Translator verification keys - return { goblin_final.prove(), - { std::make_shared(), std::make_shared() }, - merge_commitments }; + return { goblin_proof, { std::make_shared(), std::make_shared() }, merge_commitments }; } }; @@ -94,7 +82,7 @@ TEST_F(BoomerangGoblinRecursiveVerifierTests, graph_description_basic) } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments); + GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND); output.points_accumulator.set_public(); // Construct and verify a proof for the Goblin Recursive Verifier circuit { diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 19fe32271169..3897a7fb79fe 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -8,6 +8,8 @@ namespace bb { // permutation argument polynomials (sigmas, ids) are unique, e.g. id[i][j] == id[m][n] iff (i == m && j == n) constexpr uint32_t PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28; +// The fixed size of the Translator trace where each accumulation gate, corresponding to one UltraOp, will occupy two +// rows. static constexpr uint32_t CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 14; // -1 as each op occupies two rows in Translator trace diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp index a4dd45514186..6ccaa6b737b4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp @@ -74,6 +74,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); auto op = View(in.op); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); + auto not_even_or_no_op_scaled = lagrange_even_in_minicircuit * op * scaling_factor; // Contribution 1, accumulator lowest limb decomposition auto tmp_1 = @@ -82,8 +83,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio accumulator_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + accumulator_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_0); - tmp_1 *= lagrange_even_in_minicircuit * op; - tmp_1 *= scaling_factor; + tmp_1 *= not_even_or_no_op_scaled; std::get<0>(accumulators) += tmp_1; // Contribution 2, accumulator second limb decomposition @@ -93,8 +93,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio accumulator_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + accumulator_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_1); - tmp_2 *= lagrange_even_in_minicircuit * op; - tmp_2 *= scaling_factor; + tmp_2 *= not_even_or_no_op_scaled; std::get<1>(accumulators) += tmp_2; // Contribution 3, accumulator second highest limb decomposition @@ -104,8 +103,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio accumulator_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + accumulator_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_2); - tmp_3 *= lagrange_even_in_minicircuit * op; - tmp_3 *= scaling_factor; + tmp_3 *= not_even_or_no_op_scaled; std::get<2>(accumulators) += tmp_3; // Contribution 4, accumulator highest limb decomposition @@ -114,8 +112,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + accumulator_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - accumulators_binary_limbs_3); - tmp_4 *= lagrange_even_in_minicircuit * op; - tmp_4 *= scaling_factor; + tmp_4 *= not_even_or_no_op_scaled; std::get<3>(accumulators) += tmp_4; }(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp index 165605775b9f..ea81dc61ae72 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp @@ -40,13 +40,11 @@ class GoblinRecursiveVerifierTests : public testing::Test { * * @return ProverOutput */ - static ProverOutput create_goblin_prover_output(Builder* outer_builder = nullptr, - [[maybe_unused]] const size_t NUM_CIRCUITS = 3) + static ProverOutput create_goblin_prover_output(Builder* outer_builder = nullptr, const size_t num_circuits = 5) { - // TODO: do something here which is going to be painful Goblin goblin; - GoblinMockCircuits::construct_and_merge_mock_circuits(goblin, 5); + GoblinMockCircuits::construct_and_merge_mock_circuits(goblin, num_circuits); // Merge the ecc ops from the newly constructed circuit auto goblin_proof = goblin.prove(MergeSettings::APPEND); @@ -152,11 +150,11 @@ TEST_F(GoblinRecursiveVerifierTests, IndependentVKHash) return { builder.blocks, outer_verification_key }; }; - auto [blocks_2, verification_key_2] = get_blocks(2); - auto [blocks_4, verification_key_4] = get_blocks(4); + auto [blocks_5, verification_key_5] = get_blocks(5); + auto [blocks_6, verification_key_6] = get_blocks(6); - compare_ultra_blocks_and_verification_keys({ blocks_2, blocks_4 }, - { verification_key_2, verification_key_4 }); + compare_ultra_blocks_and_verification_keys({ blocks_5, blocks_6 }, + { verification_key_5, verification_key_6 }); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 8eb78aacf99c..4facf0ddad92 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -62,7 +62,7 @@ template void MegaCircuitBuilder_::add_mega_gates_to_ensure_al read_return_data(read_idx); if (op_queue->get_unmerged_subtable_size() == 0) { - // Add a mul dummy op if the subtable to avoid column polynomial being zero (it has to be a mul rather than an + // Add a mul dummy op in the subtable to avoid column polynomial being zero (it has to be a mul rather than an // add to ensure all 4 column polynomials contain some data) this->queue_ecc_mul_accum(bb::g1::affine_element::one(), 2); this->queue_ecc_eq(); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 3fb792bccfd1..d1133387c9b2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -10,11 +10,10 @@ #include using namespace bb; -namespace { using CircuitBuilder = TranslatorFlavor::CircuitBuilder; using Transcript = TranslatorFlavor::Transcript; using OpQueue = ECCOpQueue; -auto& engine = numeric::get_debug_randomness(); +static auto& engine = numeric::get_debug_randomness(); class TranslatorTests : public ::testing::Test { using G1 = g1::affine_element; @@ -32,7 +31,6 @@ class TranslatorTests : public ::testing::Test { } } - // Helper function to create an MSM static void add_mixed_ops(std::shared_ptr& op_queue, size_t count = 100) { auto P1 = G1::random_element(); @@ -142,22 +140,6 @@ TEST_F(TranslatorTests, Basic) EXPECT_TRUE(verified); } -// TEST_F(TranslatorTests, BasicWithNoOps) -// { -// using Fq = fq; - -// Fq batching_challenge_v = Fq::random_element(); -// Fq evaluation_challenge_x = Fq::random_element(); - -// // Generate a circuit and its verification key (computed at runtime from the proving key) -// CircuitBuilder circuit_builder = generate_test_circuit( -// batching_challenge_v, evaluation_challenge_x, /*circuit_size_parameter=*/500, /*add_no_ops_region=*/true); - -// EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); -// bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); -// EXPECT_TRUE(verified); -// } - /** * @brief Ensure that the fixed VK from the default constructor agrees with those computed manually for an arbitrary * circuit @@ -204,4 +186,3 @@ TEST_F(TranslatorTests, FixedVK) compare_computed_vk_against_fixed(circuit_size_parameter_1); compare_computed_vk_against_fixed(circuit_size_parameter_2); } -} // namespace diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 3ff25f603326..e915f61239a2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -405,7 +405,7 @@ void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra auto& op_wire = std::get(wires); op_wire.push_back(add_variable(ultra_op.op_code.value())); // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(zero_idx); + op_wire.push_back(add_variable(0)); insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); @@ -529,8 +529,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // TODO(https://github.com/AztecProtocol/barretenberg/issues/1360): We'll also have to eventually process random // data in the merge protocol (added for zero knowledge)/ for (auto& wire : wires) { - wire.push_back(add_variable(zero_idx)); - wire.push_back(add_variable(zero_idx)); + wire.push_back(add_variable(0)); + wire.push_back(add_variable(0)); } num_gates += 2; @@ -568,8 +568,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // appropriately transfered the accumulator value at k across the entire no-op range, both in even and odd // indices. for (size_t j = 0; j < ACCUMULATORS_BINARY_LIMBS_0; j++) { - wires[j].push_back(add_variable(zero_idx)); - wires[j].push_back(add_variable(zero_idx)); + wires[j].push_back(add_variable(0)); + wires[j].push_back(add_variable(0)); } size_t idx = 0; for (size_t j = ACCUMULATORS_BINARY_LIMBS_0; j < ACCUMULATORS_BINARY_LIMBS_3 + 1; j++) { @@ -578,8 +578,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ idx++; } for (size_t j = ACCUMULATORS_BINARY_LIMBS_3 + 1; j < TOTAL_COUNT; j++) { - wires[j].push_back(add_variable(zero_idx)); - wires[j].push_back(add_variable(zero_idx)); + wires[j].push_back(add_variable(0)); + wires[j].push_back(add_variable(0)); } num_gates += 2; continue; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 9272479ad572..951531a49d49 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -112,6 +112,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Sample the evaluation input x Fq x = Fq::random_element(); + // Compute x_pow (power given by the degree of the polynomial) to be number of real ultra ops - 1 Fq x_pow = Fq(1); // Get an inverse Fq x_inv = x.invert(); From 8aab49b5ce2bc993aec6acc374df11984a58599d Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 12:32:33 +0000 Subject: [PATCH 18/35] undo unwanted change and fix vk hash --- ...test_civc_standalone_vks_havent_changed.sh | 2 +- .../src/private_kernel_inner.nr | 64 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 0f372f2144b6..5398118bbc2f 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -13,7 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="db894edb" +pinned_short_hash="f1a98f26" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index f1792876c43e..55bf0c47d951 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -6,7 +6,9 @@ use crate::components::{ }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + kernel_circuit_public_inputs::{ + PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths, + }, private_circuit_public_inputs::PrivateCircuitPublicInputs, private_kernel::private_call_data::{PrivateCallData, PrivateCallDataWithoutPublicInputs}, private_kernel_data::{PrivateKernelData, PrivateKernelDataWithoutPublicInputs}, @@ -45,41 +47,41 @@ impl PrivateKernelInnerCircuitPrivateInputs { } pub fn execute(self) -> PrivateKernelCircuitPublicInputs { - // Validate inputs. + // Generate output. + // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. + let output = unsafe { self.generate_output() }; + // Validate inputs. let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel); - - previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, false); + previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); let private_call_data_validator = PrivateCallDataValidator::new(self.private_call); - - // Pop the next call of the stack, and process it now. - let start_private_call_stack_length = - self.previous_kernel.public_inputs.end.private_call_stack.length; - let call_request = self.previous_kernel.public_inputs.end.private_call_stack.array[ - start_private_call_stack_length - - 1]; - - private_call_data_validator.verify_proof(false /* is_first_app */); - private_call_data_validator.validate_common( - self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, - ); - private_call_data_validator.validate_against_call_request(call_request); - private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); - - // Generate output. - // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. - let output = unsafe { self.generate_output() }; - - // Validate output. - if dep::types::validate::should_validate_output() { - PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + let previous_kernel_array_lengths = + PrivateKernelCircuitPublicInputsArrayLengths::new(self.previous_kernel.public_inputs); + let private_call_stack_size = previous_kernel_array_lengths.private_call_stack; + let call_request = + self.previous_kernel.public_inputs.end.private_call_stack[private_call_stack_size - 1]; + private_call_data_validator.validate_proof(false /* is_first_app */); + private_call_data_validator.validate_against_call_request(call_request); + private_call_data_validator.validate_against_previous_kernel( self.previous_kernel.public_inputs, - self.private_call, ); + private_call_data_validator.validate_data( + output.end.note_hashes, + self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, + ); + + // Validate output. + if dep::types::validate::should_validate_output() { + PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + self.previous_kernel.public_inputs, + previous_kernel_array_lengths, + self.private_call, + private_call_data_validator.array_lengths, + ); + } + output } - output -} } mod tests { @@ -142,7 +144,7 @@ mod tests { let public_inputs = builder.execute(); assert_array_eq( - public_inputs.validation_requests.note_hash_read_requests.array, + public_inputs.validation_requests.note_hash_read_requests, [ prev_note_hash_read_requests[0], curr_note_hash_read_requests[0], @@ -150,7 +152,7 @@ mod tests { ], ); assert_array_eq( - public_inputs.end.private_logs.array, + public_inputs.end.private_logs, [prev_private_logs[0], prev_private_logs[1], curr_private_logs[0]], ); } From 416bd4c5fcd5cc222a745a8854af803e52ab9170 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 12:35:03 +0000 Subject: [PATCH 19/35] now remove unwanted files --- barretenberg/sol/foundry.lock | 23 ------- barretenberg/sol/scripts/init.sh | 9 --- .../src/private_kernel_inner.nr | 64 +++++++++---------- 3 files changed, 31 insertions(+), 65 deletions(-) delete mode 100644 barretenberg/sol/foundry.lock delete mode 100755 barretenberg/sol/scripts/init.sh diff --git a/barretenberg/sol/foundry.lock b/barretenberg/sol/foundry.lock deleted file mode 100644 index 5f4b05ff549d..000000000000 --- a/barretenberg/sol/foundry.lock +++ /dev/null @@ -1,23 +0,0 @@ -{ - "../../bb-pilcom/powdr": { - "rev": "c3006c11819d9b53fb183c9c12a10b83481bb631" - }, - "../../l1-contracts/lib/circuits": { - "rev": "e47bcd526f5e38f9603d07d0791984ec53efd254" - }, - "../../l1-contracts/lib/forge-std": { - "rev": "0e7097750918380d84dd3cfdef595bee74dabb70" - }, - "../../l1-contracts/lib/openzeppelin-contracts": { - "rev": "448efeea6640bbbc09373f03fbc9c88e280147ba" - }, - "lib/forge-std": { - "rev": "74cfb77e308dd188d2f58864aaf44963ae6b88b1" - }, - "lib/openzeppelin-contracts": { - "rev": "e50c24f5839db17f46991478384bfda14acfb830" - }, - "lib/solidity-stringutils": { - "rev": "46983c6d9462a80229cf0d5bab8ea3b3ee31066c" - } -} \ No newline at end of file diff --git a/barretenberg/sol/scripts/init.sh b/barretenberg/sol/scripts/init.sh deleted file mode 100755 index ed8e3fd9341b..000000000000 --- a/barretenberg/sol/scripts/init.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -SRS_PATH="$HOME/.bb-crs" -OUTPUT_PATH="./src/ultra" - -../cpp/build/bin/solidity_key_gen add2 $OUTPUT_PATH $SRS_PATH -../cpp/build/bin/solidity_key_gen blake $OUTPUT_PATH $SRS_PATH -../cpp/build/bin/solidity_key_gen ecdsa $OUTPUT_PATH $SRS_PATH -../cpp/build/bin/solidity_key_gen recursive $OUTPUT_PATH $SRS_PATH diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 55bf0c47d951..f1792876c43e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -6,9 +6,7 @@ use crate::components::{ }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::{ - PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths, - }, + kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, private_circuit_public_inputs::PrivateCircuitPublicInputs, private_kernel::private_call_data::{PrivateCallData, PrivateCallDataWithoutPublicInputs}, private_kernel_data::{PrivateKernelData, PrivateKernelDataWithoutPublicInputs}, @@ -47,41 +45,41 @@ impl PrivateKernelInnerCircuitPrivateInputs { } pub fn execute(self) -> PrivateKernelCircuitPublicInputs { - // Generate output. - // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. - let output = unsafe { self.generate_output() }; - // Validate inputs. + let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel); - previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); + + previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, false); let private_call_data_validator = PrivateCallDataValidator::new(self.private_call); - let previous_kernel_array_lengths = - PrivateKernelCircuitPublicInputsArrayLengths::new(self.previous_kernel.public_inputs); - let private_call_stack_size = previous_kernel_array_lengths.private_call_stack; - let call_request = - self.previous_kernel.public_inputs.end.private_call_stack[private_call_stack_size - 1]; - private_call_data_validator.validate_proof(false /* is_first_app */); - private_call_data_validator.validate_against_call_request(call_request); - private_call_data_validator.validate_against_previous_kernel( + + // Pop the next call of the stack, and process it now. + let start_private_call_stack_length = + self.previous_kernel.public_inputs.end.private_call_stack.length; + let call_request = self.previous_kernel.public_inputs.end.private_call_stack.array[ + start_private_call_stack_length + - 1]; + + private_call_data_validator.verify_proof(false /* is_first_app */); + private_call_data_validator.validate_common( + self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, + ); + private_call_data_validator.validate_against_call_request(call_request); + private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); + + // Generate output. + // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. + let output = unsafe { self.generate_output() }; + + // Validate output. + if dep::types::validate::should_validate_output() { + PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( self.previous_kernel.public_inputs, + self.private_call, ); - private_call_data_validator.validate_data( - output.end.note_hashes, - self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, - ); - - // Validate output. - if dep::types::validate::should_validate_output() { - PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( - self.previous_kernel.public_inputs, - previous_kernel_array_lengths, - self.private_call, - private_call_data_validator.array_lengths, - ); - } - output } + output +} } mod tests { @@ -144,7 +142,7 @@ mod tests { let public_inputs = builder.execute(); assert_array_eq( - public_inputs.validation_requests.note_hash_read_requests, + public_inputs.validation_requests.note_hash_read_requests.array, [ prev_note_hash_read_requests[0], curr_note_hash_read_requests[0], @@ -152,7 +150,7 @@ mod tests { ], ); assert_array_eq( - public_inputs.end.private_logs, + public_inputs.end.private_logs.array, [prev_private_logs[0], prev_private_logs[1], curr_private_logs[0]], ); } From 8f24def6e48b805e9d2cba5df11d6252d6708417 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 12:36:24 +0000 Subject: [PATCH 20/35] remove unwanted changes From f5d445fbc8eff945a4f1a473b29c16e087225798 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 12:38:25 +0000 Subject: [PATCH 21/35] undo formating of file --- .../src/private_kernel_inner.nr | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index f1792876c43e..5e315f3b6bdf 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -60,26 +60,28 @@ impl PrivateKernelInnerCircuitPrivateInputs { start_private_call_stack_length - 1]; - private_call_data_validator.verify_proof(false /* is_first_app */); - private_call_data_validator.validate_common( - self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, - ); - private_call_data_validator.validate_against_call_request(call_request); - private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); - - // Generate output. - // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. - let output = unsafe { self.generate_output() }; - - // Validate output. - if dep::types::validate::should_validate_output() { - PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + private_call_data_validator.verify_proof(false /* is_first_app */); + private_call_data_validator.validate_common( + self.previous_kernel.public_inputs.constants.protocol_contract_tree_root, + ); + private_call_data_validator.validate_against_call_request(call_request); + private_call_data_validator.validate_against_previous_kernel( self.previous_kernel.public_inputs, - self.private_call, ); + + // Generate output. + // Safety: The output is validated below by PrivateKernelCircuitOutputValidator. + let output = unsafe { self.generate_output() }; + + // Validate output. + if dep::types::validate::should_validate_output() { + PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( + self.previous_kernel.public_inputs, + self.private_call, + ); + } + output } - output -} } mod tests { From df9c7a6124fe37bce10fa7f1c390a02b4a37ed44 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 15:55:56 +0000 Subject: [PATCH 22/35] confusion --- .../circuit_checker/translator_circuit_checker.cpp | 2 +- .../cpp/src/barretenberg/client_ivc/client_ivc.cpp | 14 +++++++++----- .../cpp/src/barretenberg/client_ivc/client_ivc.hpp | 3 ++- .../translator_vm/translator_circuit_builder.cpp | 7 ++++--- .../translator_vm/translator_circuit_builder.hpp | 2 +- .../translator_vm/translator_proving_key.cpp | 7 +++++-- .../translator_vm/translator_proving_key.hpp | 2 +- 7 files changed, 23 insertions(+), 14 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index 7a3f7fb0d2e5..2fc05ee0ab15 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -131,7 +131,7 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) // TODO(https: // github.com/AztecProtocol/barretenberg/issues/1367): Report all failures more explicitly and // consider making use of relations. - for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { + for (size_t i = 8; i < circuit.num_gates - 5; i += 2) { // Get the values of P.x Fr op_code = circuit.get_variable(op_wire[i]); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index e645dcade186..1df131925b77 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -270,7 +270,7 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(decider_pairing_points); // Add randomness at the end of the hiding kernel (whose ecc ops fall right at the end of the op queue) to // ensure the CIVC proof doesn't leak information about the actual content of the op queue - hide_op_queue_content(circuit); + hide_op_queue_content_in_hiding(circuit); } return { output_verifier_accumulator, pairing_points, merged_table_commitments }; @@ -316,7 +316,7 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) circuit.queue_ecc_no_op(); // Add randomness at the begining of the tail kernel (whose ecc ops fall at the beginning of the op queue) to // ensure the CIVC proof doesn't leak information about the actual content of the op queue - hide_op_queue_content(circuit); + hide_op_queue_content_in_tail(circuit); } circuit.queue_ecc_eq(); @@ -568,7 +568,13 @@ void ClientIVC::hide_op_queue_accumulation_result(ClientCircuit& circuit) * ecc op queue table, merged_table in the merge protocol, there is an evaluation at κ in merge and two during * Translator proving given all polynomials except op will be shifted. */ -void ClientIVC::hide_op_queue_content(ClientCircuit& circuit) +void ClientIVC::hide_op_queue_content_in_tail(ClientCircuit& circuit) +{ + circuit.queue_ecc_random_op(); + circuit.queue_ecc_random_op(); + circuit.queue_ecc_random_op(); +} +void ClientIVC::hide_op_queue_content_in_hiding(ClientCircuit& circuit) { circuit.queue_ecc_random_op(); circuit.queue_ecc_random_op(); @@ -577,8 +583,6 @@ void ClientIVC::hide_op_queue_content(ClientCircuit& circuit) /** * @brief Construct a zero-knowledge proof for the hiding circuit, which recursively verifies the last folding, * merge and decider proof. - * - * @return HonkProof - a ZK Mega proof */ HonkProof ClientIVC::construct_mega_proof_for_hiding_kernel(ClientCircuit& circuit) { diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index 3e5a5e2918a7..8441505478c1 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -271,7 +271,8 @@ class ClientIVC { Proof prove(); static void hide_op_queue_accumulation_result(ClientCircuit& circuit); - static void hide_op_queue_content(ClientCircuit& circuit); + static void hide_op_queue_content_in_tail(ClientCircuit& circuit); + static void hide_op_queue_content_in_hiding(ClientCircuit& circuit); HonkProof construct_mega_proof_for_hiding_kernel(ClientCircuit& circuit); static bool verify(const Proof& proof, const VerificationKey& vk); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 5f62d1e64c2b..2dc564099db4 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -406,7 +406,7 @@ void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra op_wire.push_back( add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_1 : ultra_op.op_code.value())); // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(add_variable(0)); + op_wire.push_back(add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_2 : 0)); insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); @@ -546,6 +546,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // actual content of the op queue process_random_op(ultra_ops[1]); process_random_op(ultra_ops[2]); + process_random_op(ultra_ops[3]); // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices and we need to know the previous accumulator to create the gate. Both when computing the @@ -555,7 +556,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // context. However, we achieve this by ensuring a genuine operation, but with values generated randomly, is added // to the op queue during the CIVC processing. - for (size_t i = 3; i < ultra_ops.size() - 2; i++) { + for (size_t i = 3; i < ultra_ops.size() - 3; i++) { const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; if (ultra_op.op_code.value() == 0) { // Skip no-ops as they should not affect the computation of the accumulator @@ -578,7 +579,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ std::array previous_accumulator_binary_limbs = split_fq_into_limbs(final_accumulator_state); // Generate witness values and accumulation gates from all the actual UltraOps - for (size_t i = 3; i < ultra_ops.size() - 2; i++) { + for (size_t i = 4; i < ultra_ops.size() - 2; i++) { const auto& ultra_op = ultra_ops[i]; if (ultra_op.op_code.value() == 0) { // Within the no-op range the translator trace is empty except for the accumulator binary limbs which gets diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index 38547e173f21..e77a214463a3 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -239,7 +239,7 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1; // Index at which the evaluation result is stored in the circuit, coming after one no-op and two random ops - static constexpr size_t RESULT_ROW = 6; + static constexpr size_t RESULT_ROW = 8; // How much you'd need to multiply a value by to perform a shift to a higher binary limb static constexpr auto SHIFT_1 = uint256_t(1) << NUM_LIMB_BITS; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index cc6f721f88cd..14eef399b786 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -246,16 +246,19 @@ void TranslatorProvingKey::compute_lagrange_polynomials() proving_key->polynomials.lagrange_masking.at(i) = 1; } + for (size_t i = 2; i < 8; i++) { + proving_key->polynomials.lagrange_mini_masking.at(i) = 1; + } + // Location of randomness for wires defined within the mini circuit for (size_t i = dyadic_mini_circuit_size_without_masking; i < mini_circuit_dyadic_size; i++) { - proving_key->polynomials.lagrange_mini_masking.at(i - dyadic_mini_circuit_size_without_masking + 2) = 1; proving_key->polynomials.lagrange_mini_masking.at(i) = 1; } // Translator VM processes two rows of its execution trace at a time, establishing different relations between // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations // should trigger at odd indices and which at even. - for (size_t i = 6; i < dyadic_mini_circuit_size_without_masking; i += 2) { + for (size_t i = 2; i < dyadic_mini_circuit_size_without_masking; i += 2) { proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1; proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index c94a1e2e2ebd..c107ed4e666b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -46,7 +46,7 @@ class TranslatorProvingKey { : batching_challenge_v(circuit.batching_challenge_v) , evaluation_input_x(circuit.evaluation_input_x) { - PROFILE_THIS_NAME("TranslatorProvingKey(TranslatorCircuit&)"); + // BB_BENCH_NAME("TranslatorProvingKey(TranslatorCircuit&)"); // Check that the Translator Circuit does not exceed the fixed upper bound, the current value amounts to // a number of EccOps sufficient for 10 rounds of folding (so 20 circuits) if (circuit.num_gates > Flavor::MINI_CIRCUIT_SIZE) { From 9d90883eb33ddaf6d30bdebd4dd63d7e4c1cd6d5 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 4 Sep 2025 15:59:48 +0000 Subject: [PATCH 23/35] cleanup --- barretenberg/cpp/src/barretenberg/goblin/goblin.cpp | 10 +++++----- .../cpp/src/barretenberg/op_queue/ecc_ops_table.hpp | 1 - .../cpp/src/barretenberg/ultra_honk/merge_prover.cpp | 2 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index 3c5ff5d86c12..638aa290e794 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -114,11 +114,11 @@ bool Goblin::verify(const GoblinProof& proof, bool op_queue_consistency_verified = translator_verifier.verify_consistency_with_final_merge(merged_table_commitments); - info("merge verified?: ", merge_verified); - info("eccvm verified?: ", eccvm_verified); - info("accumulator construction_verified?: ", accumulator_construction_verified); - info("translation verified?: ", translation_verified); - info("consistency verified?: ", op_queue_consistency_verified); + vinfo("merge verified?: ", merge_verified); + vinfo("eccvm verified?: ", eccvm_verified); + vinfo("accumulator construction_verified?: ", accumulator_construction_verified); + vinfo("translation verified?: ", translation_verified); + vinfo("consistency verified?: ", op_queue_consistency_verified); return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified && op_queue_consistency_verified; diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index 6c39fae66183..f490888a3f5f 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -289,7 +289,6 @@ class UltraEccOpsTable { "current subtable should be merged before reconstructing the full table of operations."); std::vector reconstructed_table; - // reconstructed_table.reserve(reconstructed_table_size); for (size_t subtable_idx = 0; subtable_idx < table.num_subtables() - 1; subtable_idx++) { const auto& subtable = table.get()[subtable_idx]; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 1660206b78be..7682ad731858 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -26,12 +26,10 @@ MergeProver::MergeProver(const std::shared_ptr& op_queue, // Merge the current subtable (for which a merge proof is being constructed) prior to // procedeing with proving. if (settings == MergeSettings::APPEND) { - info("appending now"); size_t last_subtable_size = op_queue->get_unmerged_subtable_size(); op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size); } else { - info("here"); op_queue->merge(settings); } From 0a3166cc682c59839c9149fe7bef3d3c630968b8 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 5 Sep 2025 08:39:39 +0000 Subject: [PATCH 24/35] works --- .../translator_vm/translator.test.cpp | 9 +++++---- .../translator_vm/translator_circuit_builder.cpp | 4 ++-- .../translator_vm/translator_fixed_vk.hpp | 16 ++++++++-------- .../translator_vm/translator_proving_key.cpp | 2 +- .../translator_vm/translator_verifier.cpp | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index d1133387c9b2..74b214ea10b3 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -24,10 +24,10 @@ class TranslatorTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } // Helper function to add no-ops - static void add_no_ops(std::shared_ptr& op_queue, size_t count = 1) + static void add_random_ops(std::shared_ptr& op_queue, size_t count = 1) { for (size_t i = 0; i < count; i++) { - op_queue->no_op_ultra_only(); + op_queue->random_op_ultra_only(); } } @@ -51,11 +51,12 @@ class TranslatorTests : public ::testing::Test { // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); - add_no_ops(op_queue); + op_queue->no_op_ultra_only(); + add_random_ops(op_queue, 3); add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_no_ops(op_queue, 2); + add_random_ops(op_queue, 2); op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 2dc564099db4..964d3950bdff 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -536,8 +536,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ populate_wires_from_ultra_op(ultra_op); // Populate the other wires with zeros for (size_t i = WireIds::Y_LOW_Z_2 + 1; i < wires.size(); i++) { - wires[i].push_back(add_variable(zero_idx)); - wires[i].push_back(add_variable(zero_idx)); + wires[i].push_back(add_variable(0)); + wires[i].push_back(add_variable(0)); } num_gates += 2; }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp index 101f151b13dc..ed793932b47a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_fixed_vk.hpp @@ -35,16 +35,16 @@ struct TranslatorFixedVKCommitments { uint256_t("0x174caee01a8d7fb79e7834367d842900e5893e35054a6cbbc67dfa8b0aa6bea5")), // lagrange_odd_in_minicircuit - Commitment(uint256_t("0x23a983a5963d5075a40b895e7864c215e84ba1c92a5585485057ab8981e763ff"), - uint256_t("0x062238be20d523bd606a9c2727fcf1567babbb86f24c5ae0d2d008e10a5270ca")), + Commitment(uint256_t("0x16491ef34583b8dcf02b72539420bd9f6f136d67f0b89bb1f5a6cf4807262e41"), + uint256_t("0x0245dde06e03313da7eb50fd0abb975e7815123c78cba60f7c1ffd5fccac3130")), // lagrange_even_in_minicircuit - Commitment(uint256_t("0x08033ad1c8aa97c7b58d5053702f7795ec1f421523626e88ca5161c09533f03c"), - uint256_t("0x25730345e6886b41058e42f29586102a2e00fd46650628d67156b1445d358608")), + Commitment(uint256_t("0x26e60bb02bfab925e3c071d634db06c34cc13f374f6d428d7f53026879729685"), + uint256_t("0x009edf9703a9135d5b60254628aa1fb96fe3d07aedbfef6f2bb985af12c595a7")), // lagrange_result_row - Commitment(uint256_t("0x262d212add82bcbcf96d0773c59926e1b8e68e45c662f9348f2e4f64770595b3"), - uint256_t("0x2fe4de705da2b7bfb03cb3baa199ed4cc97e6ce620d0e939b603493223e88703")), + Commitment(uint256_t("0x2c4e3788efe883d91b423233818890599ad233cecf88be80debce9e5ac727e29"), + uint256_t("0x0d79fb9abbbde1fdb4c53d148cfcf083e84f3153e6817f5a19f0560e831dda8f")), // lagrange_last_in_minicircuit Commitment(uint256_t("0x199c9a28f7a5d9e583b74f41c6a8b85a659a6bfd134ed40158d2e46c882db82d"), @@ -55,8 +55,8 @@ struct TranslatorFixedVKCommitments { uint256_t("0x0e0602fc16675e0f0e11b9c509608a43fd8ac75d779ae3f69cbbba7a647c736a")), // lagrange_mini_masking - Commitment(uint256_t("0x0f30d7db2ef1e38f496c696565d2edbb6c7790c5e29aa5de577778ab50cc4bc8"), - uint256_t("0x17bc6c20e905302778f27555c1ee2126de382211d6c31a85a0c592912d41fce1")), + Commitment(uint256_t("0x22b8edd8420b3d1a0bc80615304be63370f52186965801d4dfdec63b5566420e"), + uint256_t("0x23b5474c89f47b8de3ed3a606fbe4889a1cd22fd88ffb11d10b229ad07ee7b2d")), // lagrange_real_last // lagrange_last diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index 14eef399b786..cdf32ad8479f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -258,7 +258,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() // Translator VM processes two rows of its execution trace at a time, establishing different relations between // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations // should trigger at odd indices and which at even. - for (size_t i = 2; i < dyadic_mini_circuit_size_without_masking; i += 2) { + for (size_t i = 8; i < dyadic_mini_circuit_size_without_masking; i += 2) { proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1; proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 2cf9dae17d61..b8e5926b1a3b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,7 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { - vinfo("translator verifier: sumcheck failed"); + info("translator verifier: sumcheck failed"); return false; } From 51d4b6105e6d0569f182719a430f2071d5bfc84f Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 5 Sep 2025 09:08:02 +0000 Subject: [PATCH 25/35] resolve comments --- avm-transpiler/Cargo.lock | 2 +- .../cpp/src/barretenberg/client_ivc/client_ivc.cpp | 3 +++ .../cpp/src/barretenberg/op_queue/ecc_ops_table.hpp | 9 ++------- .../cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp | 2 +- .../translator_recursive_verifier.test.cpp | 2 +- .../src/barretenberg/translator_vm/translator.test.cpp | 2 +- .../translator_vm/translator_circuit_builder.test.cpp | 2 +- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 7cf66991fadb..e39bb5b5271f 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -63,6 +63,7 @@ dependencies = [ "keccak", "libaes", "log", + "num-bigint", "p256", "sha2", "thiserror", @@ -1276,7 +1277,6 @@ dependencies = [ "fm", "fxhash", "im", - "indexmap 2.10.0", "iter-extended", "noirc_errors", "noirc_frontend", diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 57e72c7af295..32f2fc972116 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -313,6 +313,9 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // to ensure the op queue wires in translator are shiftable, i.e. their 0th coefficient is 0. (The tail kernel // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { + BB_ASSERT_EQ(circuit.op_queue->get_unmerged_subtable_size(), + 0U, + "tail kernel ecc ops table should be empty at this point"); circuit.queue_ecc_no_op(); // Placeholder for randomness at the beginning of tail circuit circuit.queue_ecc_no_op(); diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index f490888a3f5f..f5239f8adaff 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -289,6 +289,7 @@ class UltraEccOpsTable { "current subtable should be merged before reconstructing the full table of operations."); std::vector reconstructed_table; + reconstructed_table.reserve(1 << CONST_OP_QUEUE_LOG_SIZE); for (size_t subtable_idx = 0; subtable_idx < table.num_subtables() - 1; subtable_idx++) { const auto& subtable = table.get()[subtable_idx]; @@ -301,14 +302,8 @@ class UltraEccOpsTable { if (has_fixed_append && fixed_append_offset.has_value()) { size_t current_size = reconstructed_table.size(); size_t target_offset = fixed_append_offset.value(); - // Fill gap with no-ops if needed - while (current_size < target_offset) { - UltraOp no_op = {}; - // no_op.op_code is already initialized with all false values (no operation) - reconstructed_table.push_back(no_op); - current_size++; - } + reconstructed_table.insert(reconstructed_table.end(), target_offset - current_size, UltraOp{ /*no-op*/ }); } // Add the final subtable (appended at fixed location) diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp index 4ec210d09c9b..cf4511632361 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.test.cpp @@ -331,7 +331,7 @@ TEST(EccOpsTableTest, UltraOpsFixedLocationAppendWithGap) } } - // Mimic get_reconstructed by unifying all the ops from subtables into a single vector with the appropiate append + // Mimic get_reconstructed by unifying all the ops from subtables into a single vector with the appropriate append // offset { std::vector expected_reconstructed; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index c9ebfb85aa5c..471e304c3afd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -78,7 +78,7 @@ class TranslatorRecursiveTests : public ::testing::Test { op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); add_no_ops(op_queue, 2); - op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); return InnerBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index d1133387c9b2..337ac8219c0c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -56,7 +56,7 @@ class TranslatorTests : public ::testing::Test { op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); add_no_ops(op_queue, 2); - op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 951531a49d49..eba893dccaea 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -101,7 +101,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Placeholder for randomness op_queue->no_op_ultra_only(); op_queue->no_op_ultra_only(); - op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_unmerged_subtable_size()); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); Fq op_accumulator = 0; Fq p_x_accumulator = 0; From f40dd8d1ee3f4ec3d60031f1a33ae3a80dba988a Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 08:37:54 +0000 Subject: [PATCH 26/35] cleanup --- .../translator_circuit_checker.cpp | 30 ++- .../barretenberg/client_ivc/client_ivc.cpp | 60 ++--- .../src/barretenberg/goblin/mock_circuits.hpp | 12 +- .../barretenberg/op_queue/ecc_op_queue.hpp | 2 +- .../barretenberg/op_queue/ecc_ops_table.hpp | 6 +- .../translator_recursive_verifier.test.cpp | 9 +- .../mega_circuit_builder.cpp | 2 +- .../relation_correctness.test.cpp | 206 +++++++++--------- .../translator_circuit_builder.cpp | 21 +- .../translator_circuit_builder.hpp | 4 +- .../translator_circuit_builder.test.cpp | 130 +++++------ .../translator_vm/translator_proving_key.cpp | 7 +- .../translator_vm/translator_verifier.cpp | 2 +- .../barretenberg/ultra_honk/merge_prover.cpp | 2 +- 14 files changed, 270 insertions(+), 223 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index 2fc05ee0ab15..e3e4a104a59f 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -27,6 +27,9 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) return false; }; + BB_ASSERT_EQ( + circuit.num_gates, 1U << CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE, "TranslatorCircuit size is incorrect"); + // Compute the limbs of evaluation_input_x and powers of batching_challenge_v (these go into the relation) RelationInputs relation_inputs = compute_relation_inputs_limbs(circuit.batching_challenge_v, circuit.evaluation_input_x); @@ -128,13 +131,34 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) return check_accumulator_transfer(previous_accumulator, gate + 1); }; + auto check_random_op_code = [&](const Fr op_code, size_t gate) { + if (gate % 2 == 0) { + if (op_code == Fr(0) || op_code == Fr(3) || op_code == Fr(4) || op_code == Fr(8)) { + return report_fail("Opcode should be random value at even gate = ", gate); + } + } else { + if (op_code == Fr(0)) { + return report_fail("Opcode should be 0 at odd gate = ", gate); + } + } + return true; + }; + // TODO(https: // github.com/AztecProtocol/barretenberg/issues/1367): Report all failures more explicitly and // consider making use of relations. + auto in_random_range = [&](size_t i) { + return (i >= 2 && i < RESULT_ROW) || (i > circuit.num_gates - 5 && i < circuit.num_gates); + }; + for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { - for (size_t i = 8; i < circuit.num_gates - 5; i += 2) { - - // Get the values of P.x + // Ensure random op is present in in expected ranges Fr op_code = circuit.get_variable(op_wire[i]); + if (in_random_range(i)) { + check_random_op_code(op_code, i); + Fr op_code_next = circuit.get_variable(op_wire[i + 1]); + check_random_op_code(op_code_next, i + 1); + continue; + } // Current accumulator (updated value) const std::vector current_accumulator_binary_limbs = { diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 78017fe81bd1..40b4917bbd62 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -268,7 +268,7 @@ ClientIVC::perform_recursive_verification_and_databus_consistency_checks( pairing_points.aggregate(nested_pairing_points); if (is_hiding_kernel) { pairing_points.aggregate(decider_pairing_points); - // Add randomness at the end of the hiding kernel (whose ecc ops fall right at the end of the op queue) to + // Add randomness at the end of the hiding kernel (whose ecc ops fall right at the end of the op queue table) to // ensure the CIVC proof doesn't leak information about the actual content of the op queue hide_op_queue_content_in_hiding(circuit); } @@ -313,12 +313,12 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // to ensure the op queue wires in translator are shiftable, i.e. their 0th coefficient is 0. (The tail kernel // subtable is at the top of the final aggregate table since it is the last to be prepended). if (is_tail_kernel) { - BB_ASSERT_EQ(circuit.op_queue->get_unmerged_subtable_size(), + BB_ASSERT_EQ(circuit.op_queue->get_current_subtable_size(), 0U, "tail kernel ecc ops table should be empty at this point"); circuit.queue_ecc_no_op(); - // Add randomness at the begining of the tail kernel (whose ecc ops fall at the beginning of the op queue) to - // ensure the CIVC proof doesn't leak information about the actual content of the op queue + // Add randomness at the begining of the tail kernel (whose ecc ops fall at the beginning of the op queue table) + // to ensure the CIVC proof doesn't leak information about the actual content of the op queue hide_op_queue_content_in_tail(circuit); } circuit.queue_ecc_eq(); @@ -524,7 +524,8 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr ultra_fixed_offset = std::nullopt) { diff --git a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp index f5239f8adaff..19cbf6ffe7ae 100644 --- a/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/op_queue/ecc_ops_table.hpp @@ -132,7 +132,7 @@ template class EccOpsTable { } size_t num_subtables() const { return table.size(); } - size_t get_unmerged_subtable_size() const { return current_subtable.size(); } + size_t get_current_subtable_size() const { return current_subtable.size(); } auto& get() const { return table; } @@ -273,7 +273,7 @@ class UltraEccOpsTable { } } - size_t get_unmerged_subtable_size() const { return table.get_unmerged_subtable_size(); } + size_t get_current_subtable_size() const { return table.get_current_subtable_size(); } std::vector get_reconstructed() const { @@ -285,7 +285,7 @@ class UltraEccOpsTable { std::vector get_reconstructed_with_fixed_append() const { - ASSERT(get_unmerged_subtable_size() == 0, + ASSERT(get_current_subtable_size() == 0, "current subtable should be merged before reconstructing the full table of operations."); std::vector reconstructed_table; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index 471e304c3afd..9b1dd85317d7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -45,10 +45,10 @@ class TranslatorRecursiveTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } // Helper function to add no-ops - static void add_no_ops(std::shared_ptr& op_queue, size_t count = 1) + static void add_random_ops(std::shared_ptr& op_queue, size_t count = 1) { for (size_t i = 0; i < count; i++) { - op_queue->no_op_ultra_only(); + op_queue->random_op_ultra_only(); } } @@ -73,11 +73,12 @@ class TranslatorRecursiveTests : public ::testing::Test { // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); - add_no_ops(op_queue); + op_queue->no_op_ultra_only(); + add_random_ops(op_queue, 3); add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_no_ops(op_queue, 2); + add_random_ops(op_queue, 2); op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); return InnerBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 4facf0ddad92..5e58f1a36677 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -61,7 +61,7 @@ template void MegaCircuitBuilder_::add_mega_gates_to_ensure_al read_idx = this->add_variable(raw_read_idx); read_return_data(read_idx); - if (op_queue->get_unmerged_subtable_size() == 0) { + if (op_queue->get_current_subtable_size() == 0) { // Add a mul dummy op in the subtable to avoid column polynomial being zero (it has to be a mul rather than an // add to ensure all 4 column polynomials contain some data) this->queue_ecc_mul_accum(bb::g1::affine_element::one(), 2); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 63ebfc5ebbc3..17d393518190 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -483,109 +483,109 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) * @brief Test the correctness of TranslatorFlavor's NonNativeField Relation * */ -TEST_F(TranslatorRelationCorrectnessTests, NonNative) -{ - using Flavor = TranslatorFlavor; - using FF = typename Flavor::FF; - using BF = typename Flavor::BF; - using ProverPolynomials = typename Flavor::ProverPolynomials; - using GroupElement = typename Flavor::GroupElement; - - constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; - constexpr auto mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE; - - auto& engine = numeric::get_debug_randomness(); - - auto op_queue = std::make_shared(); - - // Generate random EccOpQueue actions - - for (size_t i = 0; i < ((mini_circuit_size >> 1) - 2); i++) { - switch (engine.get_random_uint8() & 3) { - case 0: - op_queue->empty_row_for_testing(); - break; - case 1: - op_queue->eq_and_reset(); - break; - case 2: - op_queue->add_accumulate(GroupElement::random_element(&engine)); - break; - case 3: - op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); - break; - } - } - op_queue->merge(); - const auto batching_challenge_v = BF::random_element(&engine); - const auto evaluation_input_x = BF::random_element(&engine); - - // Generating all the values is pretty tedious, so just use CircuitBuilder - auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue); - - // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs - RelationParameters params; - auto v_power = BF::one(); - for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) { - v_power *= batching_challenge_v; - auto uint_v_power = uint256_t(v_power); - params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS), - uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), - uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), - uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), - uint_v_power }; - } - auto uint_input_x = uint256_t(evaluation_input_x); - params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS), - uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), - uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), - uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), - uint_input_x }; - - // Create storage for polynomials - ProverPolynomials prover_polynomials = TranslatorFlavor::ProverPolynomials(); - - // Copy values of wires used in the non-native field relation from the circuit builder - for (size_t i = 1; i < circuit_builder.get_estimated_num_finalized_gates(); i++) { - prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); - prover_polynomials.p_x_low_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]); - prover_polynomials.p_x_high_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]); - prover_polynomials.p_y_low_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]); - prover_polynomials.p_y_high_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]); - prover_polynomials.z_low_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]); - prover_polynomials.z_high_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]); - prover_polynomials.accumulators_binary_limbs_0.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]); - prover_polynomials.accumulators_binary_limbs_1.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]); - prover_polynomials.accumulators_binary_limbs_2.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]); - prover_polynomials.accumulators_binary_limbs_3.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]); - prover_polynomials.quotient_low_binary_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]); - prover_polynomials.quotient_high_binary_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]); - prover_polynomials.relation_wide_limbs.at(i) = - circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]); - } - - // Fill in lagrange odd polynomial - for (size_t i = 2; i < mini_circuit_size; i += 2) { - prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; - prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; - } - - // Check that Non-Native Field relation is satisfied across each row of the prover polynomials - RelationChecker::check>( - prover_polynomials, params, "TranslatorNonNativeFieldRelation"); -} +// TEST_F(TranslatorRelationCorrectnessTests, NonNative) +// { +// using Flavor = TranslatorFlavor; +// using FF = typename Flavor::FF; +// using BF = typename Flavor::BF; +// using ProverPolynomials = typename Flavor::ProverPolynomials; +// using GroupElement = typename Flavor::GroupElement; + +// constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; +// constexpr auto mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE; + +// auto& engine = numeric::get_debug_randomness(); + +// auto op_queue = std::make_shared(); + +// // Generate random EccOpQueue actions + +// for (size_t i = 0; i < ((mini_circuit_size >> 1) - 2); i++) { +// switch (engine.get_random_uint8() & 3) { +// case 0: +// op_queue->no_op_ultra_only(); +// break; +// case 1: +// op_queue->eq_and_reset(); +// break; +// case 2: +// op_queue->add_accumulate(GroupElement::random_element(&engine)); +// break; +// case 3: +// op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); +// break; +// } +// } +// op_queue->merge(); +// const auto batching_challenge_v = BF::random_element(&engine); +// const auto evaluation_input_x = BF::random_element(&engine); + +// // Generating all the values is pretty tedious, so just use CircuitBuilder +// auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue); + +// // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs +// RelationParameters params; +// auto v_power = BF::one(); +// for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) { +// v_power *= batching_challenge_v; +// auto uint_v_power = uint256_t(v_power); +// params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS), +// uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), +// uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), +// uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), +// uint_v_power }; +// } +// auto uint_input_x = uint256_t(evaluation_input_x); +// params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS), +// uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), +// uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), +// uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), +// uint_input_x }; + +// // Create storage for polynomials +// ProverPolynomials prover_polynomials = TranslatorFlavor::ProverPolynomials(); + +// // Copy values of wires used in the non-native field relation from the circuit builder +// for (size_t i = 1; i < circuit_builder.get_estimated_num_finalized_gates(); i++) { +// prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); +// prover_polynomials.p_x_low_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]); +// prover_polynomials.p_x_high_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]); +// prover_polynomials.p_y_low_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]); +// prover_polynomials.p_y_high_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]); +// prover_polynomials.z_low_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]); +// prover_polynomials.z_high_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]); +// prover_polynomials.accumulators_binary_limbs_0.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]); +// prover_polynomials.accumulators_binary_limbs_1.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]); +// prover_polynomials.accumulators_binary_limbs_2.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]); +// prover_polynomials.accumulators_binary_limbs_3.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]); +// prover_polynomials.quotient_low_binary_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]); +// prover_polynomials.quotient_high_binary_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]); +// prover_polynomials.relation_wide_limbs.at(i) = +// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]); +// } + +// // Fill in lagrange odd polynomial +// for (size_t i = 2; i < mini_circuit_size; i += 2) { +// prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; +// prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; +// } + +// // Check that Non-Native Field relation is satisfied across each row of the prover polynomials +// RelationChecker::check>( +// prover_polynomials, params, "TranslatorNonNativeFieldRelation"); +// } TEST_F(TranslatorRelationCorrectnessTests, ZeroKnowledgePermutation) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 964d3950bdff..4a9727f52112 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -403,11 +403,15 @@ void TranslatorCircuitBuilder::assert_well_formed_accumulation_input(const Accum void TranslatorCircuitBuilder::populate_wires_from_ultra_op(const UltraOp& ultra_op) { auto& op_wire = std::get(wires); - op_wire.push_back( - add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_1 : ultra_op.op_code.value())); - // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index - op_wire.push_back(add_variable(ultra_op.op_code.is_random_op ? ultra_op.op_code.random_value_2 : 0)); - + if (ultra_op.op_code.is_random_op) { + op_wire.push_back(add_variable(ultra_op.op_code.random_value_1)); + op_wire.push_back(add_variable(ultra_op.op_code.random_value_2)); + } else { + op_wire.push_back(add_variable(ultra_op.op_code.value())); + // Similarly to the ColumnPolynomials in the merge protocol, the op_wire is 0 at every second index for a + // genuine op + op_wire.push_back(zero_idx); + } insert_pair_into_wire(WireIds::X_LOW_Y_HI, ultra_op.x_lo, ultra_op.y_hi); insert_pair_into_wire(WireIds::X_HIGH_Z_1, ultra_op.x_hi, ultra_op.z_1); @@ -542,8 +546,11 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ num_gates += 2; }; - // Follow with two random ops, to ensure the commitment and evaluations of the op queue do not reveal data about the - // actual content of the op queue + // When encountering the random operation in the op queue, populate the op wire without creating accumulation gates + // These are present in the op queue at the beginning and end to ensure commitments and evaluations to op queue + // polynomials do not reveal information about data in the op queue + // The position and number of these random ops are explained in ClientIVC::hide_op_queue_content_tail_kernel and + // ClientIVC::hide_op_queue_content_hiding_kernel process_random_op(ultra_ops[1]); process_random_op(ultra_ops[2]); process_random_op(ultra_ops[3]); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index bc424aebabc3..68f646eab9ed 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -238,7 +238,9 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { // Maximum size of 2 higher limbs concatenated static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1; - // Index at which the evaluation result is stored in the circuit, coming after one no-op and two random ops + // Index at which the evaluation result is stored in the circuit, preceeded by one no-op that ensures translator + // polynomials are shiftable and three random ops that contribute to ensuring the Translator proof does not lead + // information about the op queue content linked to the circuits being proven static constexpr size_t RESULT_ROW = 8; // How much you'd need to multiply a value by to perform a shift to a higher binary limb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index eba893dccaea..6e14d4d96326 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -15,60 +15,60 @@ using CircuitChecker = TranslatorCircuitChecker; * @brief Check that a single accumulation gate is created correctly * */ -TEST(TranslatorCircuitBuilder, CircuitBuilderBaseCase) -{ - using Fq = ::curve::BN254::BaseField; - using Fr = ::curve::BN254::ScalarField; - - constexpr size_t NUM_LIMB_BITS = TranslatorCircuitBuilder::NUM_LIMB_BITS; - constexpr size_t NUM_Z_BITS = TranslatorCircuitBuilder::NUM_Z_BITS; - - // Generate random EccOpQueue transcript values - EccOpCode op_code; - switch (engine.get_random_uint8() % 4) { - case 0: - op_code = {}; - break; - case 1: - op_code = { .eq = true, .reset = true }; - break; - case 2: - op_code = { .mul = true }; - break; - case 3: - op_code = { .add = true }; - break; - } - auto get_random_z_scalar = []() { return Fr(engine.get_random_uint256().slice(0, NUM_Z_BITS)); }; - - Fq p_x = Fq::random_element(); - Fr p_x_lo = uint256_t(p_x).slice(0, 2 * NUM_LIMB_BITS); - Fr p_x_hi = uint256_t(p_x).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); - Fq p_y = Fq::random_element(); - Fr p_y_lo = uint256_t(p_y).slice(0, 2 * NUM_LIMB_BITS); - Fr p_y_hi = uint256_t(p_y).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); - Fr z_1 = get_random_z_scalar(); - Fr z_2 = get_random_z_scalar(); - Fq v = Fq::random_element(); - Fq x = Fq::random_element(); - - Fq previous_accumulator = Fq(0); - - // Create a circuit builder - auto circuit_builder = TranslatorCircuitBuilder(v, x); - UltraOp op = UltraOp{ - .op_code = op_code, .x_lo = p_x_lo, .x_hi = p_x_hi, .y_lo = p_y_lo, .y_hi = p_y_hi, .z_1 = z_1, .z_2 = z_2 - }; - - // Generate the witness for a single step - TranslatorCircuitBuilder::AccumulationInput single_accumulation_step = - TranslatorCircuitBuilder::generate_witness_values(op, previous_accumulator, v, x); - - // Submit one accumulation step in the builder - circuit_builder.create_accumulation_gate(single_accumulation_step); - // Check if the circuit fails - EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); -} +// TEST(TranslatorCircuitBuilder, CircuitBuilderBaseCase) +// { +// using Fq = ::curve::BN254::BaseField; +// using Fr = ::curve::BN254::ScalarField; + +// constexpr size_t NUM_LIMB_BITS = TranslatorCircuitBuilder::NUM_LIMB_BITS; +// constexpr size_t NUM_Z_BITS = TranslatorCircuitBuilder::NUM_Z_BITS; + +// // Generate random EccOpQueue transcript values +// EccOpCode op_code; +// switch (engine.get_random_uint8() % 4) { +// case 0: +// op_code = {}; +// break; +// case 1: +// op_code = { .eq = true, .reset = true }; +// break; +// case 2: +// op_code = { .mul = true }; +// break; +// case 3: +// op_code = { .add = true }; +// break; +// } +// auto get_random_z_scalar = []() { return Fr(engine.get_random_uint256().slice(0, NUM_Z_BITS)); }; + +// Fq p_x = Fq::random_element(); +// Fr p_x_lo = uint256_t(p_x).slice(0, 2 * NUM_LIMB_BITS); +// Fr p_x_hi = uint256_t(p_x).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); +// Fq p_y = Fq::random_element(); +// Fr p_y_lo = uint256_t(p_y).slice(0, 2 * NUM_LIMB_BITS); +// Fr p_y_hi = uint256_t(p_y).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); +// Fr z_1 = get_random_z_scalar(); +// Fr z_2 = get_random_z_scalar(); +// Fq v = Fq::random_element(); +// Fq x = Fq::random_element(); + +// Fq previous_accumulator = Fq(0); + +// // Create a circuit builder +// auto circuit_builder = TranslatorCircuitBuilder(v, x); +// UltraOp op = UltraOp{ +// .op_code = op_code, .x_lo = p_x_lo, .x_hi = p_x_hi, .y_lo = p_y_lo, .y_hi = p_y_hi, .z_1 = z_1, .z_2 = z_2 +// }; + +// // Generate the witness for a single step +// TranslatorCircuitBuilder::AccumulationInput single_accumulation_step = +// TranslatorCircuitBuilder::generate_witness_values(op, previous_accumulator, v, x); + +// // Submit one accumulation step in the builder +// circuit_builder.create_accumulation_gate(single_accumulation_step); +// // Check if the circuit fails +// EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); +// } /** * @brief Check that the circuit can handle several accumulations @@ -87,7 +87,9 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); op_queue->no_op_ultra_only(); - + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); op_queue->eq_and_reset(); @@ -99,8 +101,8 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) op_queue->mul_accumulate(P2, z); op_queue->eq_and_reset(); // Placeholder for randomness - op_queue->no_op_ultra_only(); - op_queue->no_op_ultra_only(); + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); Fq op_accumulator = 0; @@ -118,17 +120,17 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) Fq x_inv = x.invert(); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) const auto& ultra_ops = op_queue->get_ultra_ops(); - for (size_t i = 1; i < ultra_ops.size(); i++) { - const auto& ecc_op = ultra_ops[i]; - if (ecc_op.op_code.value() == 0) { + for (const auto& ultra_op : ultra_ops) { + + if (ultra_op.op_code.is_random_op || ultra_op.op_code.value() == 0) { continue; } - op_accumulator = op_accumulator * x_inv + ecc_op.op_code.value(); - const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); + op_accumulator = op_accumulator * x_inv + ultra_op.op_code.value(); + const auto [x_u256, y_u256] = ultra_op.get_base_point_standard_form(); p_x_accumulator = p_x_accumulator * x_inv + x_u256; p_y_accumulator = p_y_accumulator * x_inv + y_u256; - z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ecc_op.z_1); - z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ecc_op.z_2); + z_1_accumulator = z_1_accumulator * x_inv + uint256_t(ultra_op.z_1); + z_2_accumulator = z_2_accumulator * x_inv + uint256_t(ultra_op.z_2); x_pow *= x; } x_pow *= x_inv; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index cdf32ad8479f..b2cbfa30fbfd 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -246,7 +246,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() proving_key->polynomials.lagrange_masking.at(i) = 1; } - for (size_t i = 2; i < 8; i++) { + for (size_t i = 2; i < Flavor::RESULT_ROW; i++) { proving_key->polynomials.lagrange_mini_masking.at(i) = 1; } @@ -257,8 +257,9 @@ void TranslatorProvingKey::compute_lagrange_polynomials() // Translator VM processes two rows of its execution trace at a time, establishing different relations between // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations - // should trigger at odd indices and which at even. - for (size_t i = 8; i < dyadic_mini_circuit_size_without_masking; i += 2) { + // should trigger at odd indices and which at even. These polynomials need to only be active within the range of + // Translatort race that processes actual ecc ops + for (size_t i = Flavor::RESULT_ROW; i < dyadic_mini_circuit_size_without_masking; i += 2) { proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1; proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index b8e5926b1a3b..2cf9dae17d61 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,7 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { - info("translator verifier: sumcheck failed"); + vinfo("translator verifier: sumcheck failed"); return false; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 7682ad731858..6c983225ca75 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -26,7 +26,7 @@ MergeProver::MergeProver(const std::shared_ptr& op_queue, // Merge the current subtable (for which a merge proof is being constructed) prior to // procedeing with proving. if (settings == MergeSettings::APPEND) { - size_t last_subtable_size = op_queue->get_unmerged_subtable_size(); + size_t last_subtable_size = op_queue->get_current_subtable_size(); op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size); } else { From e7b9ec11605583b76b1f0d52948e5db93c8db980 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 09:20:10 +0000 Subject: [PATCH 27/35] cleanup and zk for dummies --- ...test_civc_standalone_vks_havent_changed.sh | 2 +- .../barretenberg/client_ivc/client_ivc.cpp | 60 ++++++++++++------- barretenberg/sol/foundry.lock | 23 +++++++ 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 barretenberg/sol/foundry.lock diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 5398118bbc2f..f9cffe06e2a5 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -13,7 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="f1a98f26" +pinned_short_hash="d57cc6d9" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 40b4917bbd62..6473dcfd934b 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -544,34 +544,47 @@ void ClientIVC::hide_op_queue_accumulation_result(ClientCircuit& circuit) } /** - * @brief Adds thre random ops to the tail kernel. + * @brief Adds three random ops to the tail kernel. + * + * @note The explanation below does not serve as a proof of zero-knowledge but rather as intuition for why the number + * of random ops and their position in the op queue. * * @details The ClientIVC proof is sent to the rollup and so it has to be zero-knowledge. In turn, this implies that * commitments and evaluations to the op queue, when regarded as 4 polynomials in UltraOp format (op, x_lo_y_hi, - * x_hi_z_1, y_lo_z_2 ), should not leak information about the actual content of the op queue with provenence from - * circuit operations that have been accumulated in CIVC. Since the op queue is used across several provers, - * randomising these polynomials has to be handled in a special way. Normally, to hide a witness we'd add randomness at - * proving time when populating ProverPolynomials. However, due to the consistency checks present throughout CIVC to - * ensure all components use the same op queue data (Merge and Translator on the entire op queue table and Merge and - * Mega on each subtable), randomness has to be added in a common place, this place naturally being ClientIVC. ECCVM is - * not affected by the concerns above, randomness being add to wires at proving time as per usual, because the - * consistency of ECCVMOps processing and UltraOps processing between Translator and ECCVM is achieved via the - * translation evalution check and avoiding an information leak there is ensured by + * x_hi_z_1, y_lo_z_2), should not leak information about the actual content of the op queue with provenance from + * circuit operations that have been accumulated in CIVC. Since the op queue is used across several provers, + * randomising these polynomials has to be handled in a special way. Normally, to hide a witness we'd add random + * coefficients at proving time when populating ProverPolynomials. However, due to the consistency checks present + * throughout CIVC, to ensure all components use the same op queue data (Merge and Translator on the entire op queue + * table and Merge and Oink on each subtable), randomness has to be added in a common place, this place naturally + * being ClientIVC. ECCVM is not affected by the concerns above, randomness being added to wires at proving time as per + * usual, because the consistency of ECCVMOps processing and UltraOps processing between Translator and ECCVM is + * achieved via the translation evaluation check and avoiding an information leak there is ensured by * `ClientIVC::hide_op_queue_accumulation_result()` and SmallSubgroupIPA in ECCVM. * - * We need each op queue polynomial to have 9 random coefficient (so the op queue needs to contain 6 random ops). + * We need each op queue polynomial to have 9 random coefficients (so the op queue needs to contain 6 random ops). + * + * For the last subtable of ecc ops belonging to the hiding kernel, merged via appended to the full op queue, its data + * appears as the ecc_op_wires in the MegaZK proof, wires that are not going to be shifted, so the proof contains, + * for each wire, its commitment and evaluation to the Sumcheck challenge. As at least 3 random coefficients are + * needed in each op queue polynomial, we add 2 random ops to the hiding kernel. * - * For the last subtable of ecc ops, merged via appended to the full op queue, its data appears as the ecc_op_wires in - * the MegaZK proof, wires that are not going to be shifted, so the proof containts, for each wire, its commitment and - * evaluation to the Sumcheck challenge. In the Merge protocol, as the subtable has been appended, it's evaluation at - * kappa only + * The op queue state previous to the append of the last subtable, is the `left_table` in the merge protocol, so for + * the degree check, we construct its inverse polynomial `left_table_inverse`. The MergeProof will contain the + * commitment to the `left_table_inverse` plus its evaluation at Merge protocol challenge κ. Also for the degree check, + * prover needs to send the evaluation of the `left_table` at κ⁻¹. We need to ensure random coefficients are added to + * one of the kernels as not to affect Apps verification keys so the best choice is to add them to the beginning of the + * tail kernel as to not complicate Translator relations. The above advises that another 4 random coefficients are + * needed in the `left_table` (so, 2 random ops). * - * The op queue state previous to the append of the last subtable, left_table in the merge protocol, is also evaluated - * at κ and κ^{-1} in the last iteration of Merge and also "left_table_reversed" is evaluated at κ and commited to, so - * for these we need four random coefficients. For the full ecc op queue table, merged_table in the merge protocol, - * there is an evaluation at κ in merge and two during Translator proving given all polynomials except op will also be - * shifted in Translator, So, we add three random ops at the beginning of the tail kernel subtable which will fall at - * the beginning of the op queue. + * Finally, the 4 polynomials representing the full ecc op queue table are committed to (in fact, in both Merge + * protocol and Translator but they are commitments to the same data). `x_lo_y_hi`, `x_hi_z_1` and `x_lo_z_2` are + * shifted polynomials in Translator so the Translator proof will contain their evaluation and evaluation of their + * shifts at the Sumcheck challenge. On top of that, the Shplonk proof sent in the last iteration of Merge also + * ascertains the opening of partially_evaluated_difference = left_table + κ^{shift -1 } * right_table - merged_table + * at κ is 0, so a batched quotient commitment is sent in the Merge proof. In total, for each op queue polynomial (or + * parts of its data), there are 4 commitments and 5 evaluations across the CIVC proof so the sweet spot is 5 random + * ops. */ void ClientIVC::hide_op_queue_content_in_tail(ClientCircuit& circuit) { @@ -583,7 +596,10 @@ void ClientIVC::hide_op_queue_content_in_tail(ClientCircuit& circuit) /** * @brief Adds two random ops to the hiding kernel. * - * @details See `hide_op_queue_content_in_tail`. + * @details For the last subtable of ecc ops belonging to the hiding kernel, merged via appended to the full op + * queue, its data appears as the ecc_op_wires in the MegaZK proof, wires that are not going to be shifted, so the proof + * containts, for each wire, its commitment and evaluation to the Sumcheck challenge. As at least 3 random coefficients + * are needed in each op queue polynomial, we add 2 random ops. More details in `hide_op_queue_content_in_tail`. */ void ClientIVC::hide_op_queue_content_in_hiding(ClientCircuit& circuit) { diff --git a/barretenberg/sol/foundry.lock b/barretenberg/sol/foundry.lock new file mode 100644 index 000000000000..5f4b05ff549d --- /dev/null +++ b/barretenberg/sol/foundry.lock @@ -0,0 +1,23 @@ +{ + "../../bb-pilcom/powdr": { + "rev": "c3006c11819d9b53fb183c9c12a10b83481bb631" + }, + "../../l1-contracts/lib/circuits": { + "rev": "e47bcd526f5e38f9603d07d0791984ec53efd254" + }, + "../../l1-contracts/lib/forge-std": { + "rev": "0e7097750918380d84dd3cfdef595bee74dabb70" + }, + "../../l1-contracts/lib/openzeppelin-contracts": { + "rev": "448efeea6640bbbc09373f03fbc9c88e280147ba" + }, + "lib/forge-std": { + "rev": "74cfb77e308dd188d2f58864aaf44963ae6b88b1" + }, + "lib/openzeppelin-contracts": { + "rev": "e50c24f5839db17f46991478384bfda14acfb830" + }, + "lib/solidity-stringutils": { + "rev": "46983c6d9462a80229cf0d5bab8ea3b3ee31066c" + } +} \ No newline at end of file From 0c35be6c4f7dd58628e35f63698f19361313357a Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 10:38:38 +0000 Subject: [PATCH 28/35] fix merge and cleanups --- ...test_civc_standalone_vks_havent_changed.sh | 4 - .../translator_circuit_checker.cpp | 5 +- .../src/barretenberg/goblin/mock_circuits.hpp | 4 +- .../translator_recursive_verifier.test.cpp | 18 +- .../translator_vm/translator.test.cpp | 229 +++++++++--------- .../translator_circuit_builder.cpp | 25 +- .../translator_circuit_builder.hpp | 8 +- .../translator_circuit_builder.test.cpp | 58 ----- .../translator_vm/translator_proving_key.cpp | 2 +- .../translator_vm/translator_verifier.cpp | 1 - 10 files changed, 150 insertions(+), 204 deletions(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 221257ab3d26..f9cffe06e2a5 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -13,11 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -<<<<<<< HEAD pinned_short_hash="d57cc6d9" -======= -pinned_short_hash="d6f612e1" ->>>>>>> origin/merge-train/barretenberg pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index e3e4a104a59f..f8b81c9e284d 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -147,11 +147,12 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) // TODO(https: // github.com/AztecProtocol/barretenberg/issues/1367): Report all failures more explicitly and // consider making use of relations. auto in_random_range = [&](size_t i) { - return (i >= 2 && i < RESULT_ROW) || (i > circuit.num_gates - 5 && i < circuit.num_gates); + return (i >= 2 * Builder::NUM_NO_OPS_START && i < RESULT_ROW) || + (i >= circuit.num_gates - 2 * Builder::NUM_RANDOM_OPS_END && i < circuit.num_gates); }; for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { - // Ensure random op is present in in expected ranges + // Ensure random op is present in expected ranges Fr op_code = circuit.get_variable(op_wire[i]); if (in_random_range(i)) { check_random_op_code(op_code, i); diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index e96f978d72d2..3b1a6c632922 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -155,7 +155,7 @@ class GoblinMockCircuits { if (idx == num_circuits - 2) { // Last circuit appended needs to begin with a no-op for translator to be shiftable builder.queue_ecc_no_op(); - randomise_op_queue(builder, 3); + randomise_op_queue(builder, TranslatorCircuitBuilder::NUM_RANDOM_OPS_START); } construct_simple_circuit(builder); goblin.prove_merge(); @@ -164,7 +164,7 @@ class GoblinMockCircuits { } MegaCircuitBuilder builder{ goblin.op_queue }; GoblinMockCircuits::construct_simple_circuit(builder); - randomise_op_queue(builder, 2); + randomise_op_queue(builder, TranslatorCircuitBuilder::NUM_RANDOM_OPS_END); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index 9b7c9b5bc017..bbc831c08ed3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -73,19 +73,19 @@ class TranslatorRecursiveTests : public ::testing::Test { // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); -<<<<<<< HEAD op_queue->no_op_ultra_only(); - add_random_ops(op_queue, 3); + add_random_ops(op_queue, InnerBuilder::NUM_RANDOM_OPS_START); add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_random_ops(op_queue, 2); - add_no_ops(op_queue); - add_mixed_ops(op_queue, circuit_size_parameter / 2); - op_queue->merge(); - add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_no_ops(op_queue, 2); ->>>>>>> origin/merge-train/barretenberg + add_random_ops(op_queue, InnerBuilder::NUM_RANDOM_OPS_END); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); + + return InnerBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; + } + + static void test_recursive_verification() + { using NativeVerifierCommitmentKey = InnerFlavor::VerifierCommitmentKey; // Add the same operations to the ECC op queue; the native computation is performed under the hood. diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index a048cd6e3a8f..28007c5e8289 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -51,140 +51,139 @@ class TranslatorTests : public ::testing::Test { // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); -<<<<<<< HEAD op_queue->no_op_ultra_only(); - add_random_ops(op_queue, 3); + add_random_ops(op_queue, CircuitBuilder::NUM_RANDOM_OPS_START); add_mixed_ops(op_queue, circuit_size_parameter / 2); op_queue->merge(); add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_random_ops(op_queue, 2); - add_no_ops(op_queue); - add_mixed_ops(op_queue, circuit_size_parameter / 2); - op_queue->merge(); - add_mixed_ops(op_queue, circuit_size_parameter / 2); - add_no_ops(op_queue, 2); ->>>>>>> origin/merge-train/barretenberg - const Fq& batching_challenge_v) - { - // Setup prover transcript - auto prover_transcript = std::make_shared(); - prover_transcript->send_to_verifier("init", Fq::random_element()); - auto initial_transcript = prover_transcript->export_proof(); - - // Setup verifier transcript - auto verifier_transcript = std::make_shared(); - verifier_transcript->load_proof(initial_transcript); - verifier_transcript->template receive_from_prover("init"); - - // Create proving key and prover - auto proving_key = std::make_shared(circuit_builder); - TranslatorProver prover{ proving_key, prover_transcript }; - - // Generate proof - auto proof = prover.construct_proof(); - - // Create verifier - auto verification_key = - std::make_shared(proving_key->proving_key); - TranslatorVerifier verifier(verification_key, verifier_transcript); - - // Verify proof and return result - return verifier.verify_proof(proof, evaluation_challenge_x, batching_challenge_v); - } - }; + add_random_ops(op_queue, CircuitBuilder::NUM_RANDOM_OPS_END); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); - /** - * @brief Check that size of a Translator proof matches the corresponding constant - *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: - * - Proof length formula in translator_flavor.hpp, etc... - * - translator_transcript.test.cpp - * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol - */ - TEST_F(TranslatorTests, ProofLengthCheck) - { - using Fq = fq; - - Fq batching_challenge_v = Fq::random_element(); - Fq evaluation_challenge_x = Fq::random_element(); - - // Generate a circuit and its verification key (computed at runtime from the proving key) - CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); + return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue }; + } + static bool prove_and_verify(const CircuitBuilder& circuit_builder, + const Fq& evaluation_challenge_x, + const Fq& batching_challenge_v) + { // Setup prover transcript auto prover_transcript = std::make_shared(); prover_transcript->send_to_verifier("init", Fq::random_element()); - prover_transcript->export_proof(); + auto initial_transcript = prover_transcript->export_proof(); + + // Setup verifier transcript + auto verifier_transcript = std::make_shared(); + verifier_transcript->load_proof(initial_transcript); + verifier_transcript->template receive_from_prover("init"); + + // Create proving key and prover auto proving_key = std::make_shared(circuit_builder); TranslatorProver prover{ proving_key, prover_transcript }; // Generate proof auto proof = prover.construct_proof(); - EXPECT_EQ(proof.size(), TranslatorFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS); + // Create verifier + auto verification_key = std::make_shared(proving_key->proving_key); + TranslatorVerifier verifier(verification_key, verifier_transcript); + + // Verify proof and return result + return verifier.verify_proof(proof, evaluation_challenge_x, batching_challenge_v); } +}; + +/** + * @brief Check that size of a Translator proof matches the corresponding constant + *@details If this test FAILS, then the following (non-exhaustive) list should probably be updated as well: + * - Proof length formula in translator_flavor.hpp, etc... + * - translator_transcript.test.cpp + * - constants in yarn-project in: constants.nr, constants.gen.ts, ConstantsGen.sol + */ +TEST_F(TranslatorTests, ProofLengthCheck) +{ + using Fq = fq; - /** - * @brief Test simple circuit with public inputs - * - */ - TEST_F(TranslatorTests, Basic) - { - using Fq = fq; + Fq batching_challenge_v = Fq::random_element(); + Fq evaluation_challenge_x = Fq::random_element(); - Fq batching_challenge_v = Fq::random_element(); - Fq evaluation_challenge_x = Fq::random_element(); + // Generate a circuit and its verification key (computed at runtime from the proving key) + CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); - // Generate a circuit without no-ops - CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); + // Setup prover transcript + auto prover_transcript = std::make_shared(); + prover_transcript->send_to_verifier("init", Fq::random_element()); + prover_transcript->export_proof(); + auto proving_key = std::make_shared(circuit_builder); + TranslatorProver prover{ proving_key, prover_transcript }; - EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); - bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); - EXPECT_TRUE(verified); - } + // Generate proof + auto proof = prover.construct_proof(); - /** - * @brief Ensure that the fixed VK from the default constructor agrees with those computed manually for an arbitrary - * circuit - * @note If this test fails, it may be because the constant CONST_TRANSLATOR_LOG_N has changed and the fixed VK - * commitments in TranslatorFixedVKCommitments must be updated accordingly. Their values can be taken right from the - * output of this test. - * - */ - TEST_F(TranslatorTests, FixedVK) - { - using Fq = fq; + EXPECT_EQ(proof.size(), TranslatorFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS); +} - auto prover_transcript = std::make_shared(); - prover_transcript->send_to_verifier("init", Fq::random_element()); - prover_transcript->export_proof(); - Fq batching_challenge_v = Fq::random_element(); - Fq evaluation_challenge_x = Fq::random_element(); - - // Generate the default fixed VK - TranslatorFlavor::VerificationKey fixed_vk{}; - - // Lambda for manually computing a verification key for a given circuit and comparing it to the fixed VK - auto compare_computed_vk_against_fixed = [&](size_t circuit_size_parameter) { - CircuitBuilder circuit_builder = - generate_test_circuit(batching_challenge_v, evaluation_challenge_x, circuit_size_parameter); - auto proving_key = std::make_shared(circuit_builder); - TranslatorProver prover{ proving_key, prover_transcript }; - TranslatorFlavor::VerificationKey computed_vk(proving_key->proving_key); - auto labels = TranslatorFlavor::VerificationKey::get_labels(); - size_t index = 0; - for (auto [vk_commitment, fixed_commitment] : zip_view(computed_vk.get_all(), fixed_vk.get_all())) { - EXPECT_EQ(vk_commitment, fixed_commitment) - << "Mismatch between computed vk_commitment and fixed_commitment at label: " << labels[index]; - ++index; - } - - EXPECT_EQ(computed_vk, fixed_vk); - }; - - // Check consistency of the fixed VK with the computed VK for some different circuit sizes - const size_t circuit_size_parameter_1 = 1 << 2; - const size_t circuit_size_parameter_2 = 1 << 3; - - compare_computed_vk_against_fixed(circuit_size_parameter_1); - compare_computed_vk_against_fixed(circuit_size_parameter_2); - } +/** + * @brief Test simple circuit with public inputs + * + */ +TEST_F(TranslatorTests, Basic) +{ + using Fq = fq; + + Fq batching_challenge_v = Fq::random_element(); + Fq evaluation_challenge_x = Fq::random_element(); + + // Generate a circuit without no-ops + CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x); + + EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); + bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); + EXPECT_TRUE(verified); +} + +/** + * @brief Ensure that the fixed VK from the default constructor agrees with those computed manually for an arbitrary + * circuit + * @note If this test fails, it may be because the constant CONST_TRANSLATOR_LOG_N has changed and the fixed VK + * commitments in TranslatorFixedVKCommitments must be updated accordingly. Their values can be taken right from the + * output of this test. + * + */ +TEST_F(TranslatorTests, FixedVK) +{ + using Fq = fq; + + auto prover_transcript = std::make_shared(); + prover_transcript->send_to_verifier("init", Fq::random_element()); + prover_transcript->export_proof(); + Fq batching_challenge_v = Fq::random_element(); + Fq evaluation_challenge_x = Fq::random_element(); + + // Generate the default fixed VK + TranslatorFlavor::VerificationKey fixed_vk{}; + + // Lambda for manually computing a verification key for a given circuit and comparing it to the fixed VK + auto compare_computed_vk_against_fixed = [&](size_t circuit_size_parameter) { + CircuitBuilder circuit_builder = + generate_test_circuit(batching_challenge_v, evaluation_challenge_x, circuit_size_parameter); + auto proving_key = std::make_shared(circuit_builder); + TranslatorProver prover{ proving_key, prover_transcript }; + TranslatorFlavor::VerificationKey computed_vk(proving_key->proving_key); + auto labels = TranslatorFlavor::VerificationKey::get_labels(); + size_t index = 0; + for (auto [vk_commitment, fixed_commitment] : zip_view(computed_vk.get_all(), fixed_vk.get_all())) { + EXPECT_EQ(vk_commitment, fixed_commitment) + << "Mismatch between computed vk_commitment and fixed_commitment at label: " << labels[index]; + ++index; + } + + EXPECT_EQ(computed_vk, fixed_vk); + }; + + // Check consistency of the fixed VK with the computed VK for some different circuit sizes + const size_t circuit_size_parameter_1 = 1 << 2; + const size_t circuit_size_parameter_2 = 1 << 3; + + compare_computed_vk_against_fixed(circuit_size_parameter_1); + compare_computed_vk_against_fixed(circuit_size_parameter_2); +} diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 3ea3c0b12c0a..baaab7d8e325 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -555,9 +555,13 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // polynomials do not reveal information about data in the op queue // The position and number of these random ops are explained in ClientIVC::hide_op_queue_content_tail_kernel and // ClientIVC::hide_op_queue_content_hiding_kernel - process_random_op(ultra_ops[1]); - process_random_op(ultra_ops[2]); - process_random_op(ultra_ops[3]); + for (size_t i = NUM_NO_OPS_START; i <= NUM_RANDOM_OPS_START; ++i) { + process_random_op(ultra_ops[i]); + } + + // Range of UltraOps for which we should construct accumulation gates + std::span ultra_ops_span(ultra_ops.begin() + static_cast(NUM_NO_OPS_START + NUM_RANDOM_OPS_START), + ultra_ops.begin() + static_cast(ultra_ops.size() - NUM_RANDOM_OPS_END)); // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices and we need to know the previous accumulator to create the gate. Both when computing the @@ -566,9 +570,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // accumulation result (i.e. value at index RESULT_ROW) is sent as part of the proof, we also need to hide its // context. However, we achieve this by ensuring a genuine operation, but with values generated randomly, is added // to the op queue during the CIVC processing. - - for (size_t i = 3; i < ultra_ops.size() - 3; i++) { - const auto& ultra_op = ultra_ops[ultra_ops.size() - i]; + // Processes the range of actual ecc ops in reverse order + for (const auto& ultra_op : std::ranges::reverse_view(ultra_ops_span)) { if (ultra_op.op_code.value() == 0) { // Skip no-ops as they should not affect the computation of the accumulator continue; @@ -589,9 +592,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ accumulator_trace.pop_back(); std::array previous_accumulator_binary_limbs = split_fq_into_limbs(final_accumulator_state); - // Generate witness values and accumulation gates from all the actual UltraOps - for (size_t i = 4; i < ultra_ops.size() - 2; i++) { - const auto& ultra_op = ultra_ops[i]; + // Generate witness values and accumulation gates from all the actual UltraOps, starting from beginning + for (const auto& ultra_op : ultra_ops_span) { if (ultra_op.op_code.value() == 0) { // Within the no-op range the translator trace is empty except for the accumulator binary limbs which gets // copied from the last row k where an op happened (i.e. the op wire the even index has a non-zero value). @@ -632,7 +634,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ } // Also process the last two random ops present at the end of the op queue to hide the ecc ops of the last circuit // whose ops are added to the op queue - process_random_op(ultra_ops[ultra_ops.size() - 2]); - process_random_op(ultra_ops[ultra_ops.size() - 1]); + for (size_t i = ultra_ops.size() - NUM_RANDOM_OPS_END; i < ultra_ops.size(); ++i) { + process_random_op(ultra_ops[i]); + } } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index 9d57923fd899..c73b2ba47382 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -239,9 +239,15 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1; // Index at which the evaluation result is stored in the circuit, preceeded by one no-op that ensures translator - // polynomials are shiftable and three random ops that contribute to ensuring the Translator proof does not lead + // polynomials are shiftable and three random ops that contribute to ensuring the Translator proof does not leak // information about the op queue content linked to the circuits being proven static constexpr size_t RESULT_ROW = 8; + static constexpr size_t NUM_NO_OPS_START = 1; + static_assert(NUM_NO_OPS_START == 1); + static constexpr size_t NUM_RANDOM_OPS_START = 3; + static_assert(NUM_RANDOM_OPS_START == 3); + static constexpr size_t NUM_RANDOM_OPS_END = 2; + static_assert(NUM_RANDOM_OPS_END == 2); // How much you'd need to multiply a value by to perform a shift to a higher binary limb static constexpr auto SHIFT_1 = uint256_t(1) << NUM_LIMB_BITS; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 6e14d4d96326..b63a866324a0 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -11,64 +11,6 @@ namespace { auto& engine = numeric::get_debug_randomness(); } using CircuitChecker = TranslatorCircuitChecker; -/** - * @brief Check that a single accumulation gate is created correctly - * - */ -// TEST(TranslatorCircuitBuilder, CircuitBuilderBaseCase) -// { -// using Fq = ::curve::BN254::BaseField; -// using Fr = ::curve::BN254::ScalarField; - -// constexpr size_t NUM_LIMB_BITS = TranslatorCircuitBuilder::NUM_LIMB_BITS; -// constexpr size_t NUM_Z_BITS = TranslatorCircuitBuilder::NUM_Z_BITS; - -// // Generate random EccOpQueue transcript values -// EccOpCode op_code; -// switch (engine.get_random_uint8() % 4) { -// case 0: -// op_code = {}; -// break; -// case 1: -// op_code = { .eq = true, .reset = true }; -// break; -// case 2: -// op_code = { .mul = true }; -// break; -// case 3: -// op_code = { .add = true }; -// break; -// } -// auto get_random_z_scalar = []() { return Fr(engine.get_random_uint256().slice(0, NUM_Z_BITS)); }; - -// Fq p_x = Fq::random_element(); -// Fr p_x_lo = uint256_t(p_x).slice(0, 2 * NUM_LIMB_BITS); -// Fr p_x_hi = uint256_t(p_x).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); -// Fq p_y = Fq::random_element(); -// Fr p_y_lo = uint256_t(p_y).slice(0, 2 * NUM_LIMB_BITS); -// Fr p_y_hi = uint256_t(p_y).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS); -// Fr z_1 = get_random_z_scalar(); -// Fr z_2 = get_random_z_scalar(); -// Fq v = Fq::random_element(); -// Fq x = Fq::random_element(); - -// Fq previous_accumulator = Fq(0); - -// // Create a circuit builder -// auto circuit_builder = TranslatorCircuitBuilder(v, x); -// UltraOp op = UltraOp{ -// .op_code = op_code, .x_lo = p_x_lo, .x_hi = p_x_hi, .y_lo = p_y_lo, .y_hi = p_y_hi, .z_1 = z_1, .z_2 = z_2 -// }; - -// // Generate the witness for a single step -// TranslatorCircuitBuilder::AccumulationInput single_accumulation_step = -// TranslatorCircuitBuilder::generate_witness_values(op, previous_accumulator, v, x); - -// // Submit one accumulation step in the builder -// circuit_builder.create_accumulation_gate(single_accumulation_step); -// // Check if the circuit fails -// EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); -// } /** * @brief Check that the circuit can handle several accumulations diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index b2cbfa30fbfd..5a06f33d8709 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -258,7 +258,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() // Translator VM processes two rows of its execution trace at a time, establishing different relations between // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations // should trigger at odd indices and which at even. These polynomials need to only be active within the range of - // Translatort race that processes actual ecc ops + // Translator trace that processes actual ecc ops. for (size_t i = Flavor::RESULT_ROW; i < dyadic_mini_circuit_size_without_masking; i += 2) { proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1; proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 2cf9dae17d61..da51e6401834 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -125,7 +125,6 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { - vinfo("translator verifier: sumcheck failed"); return false; } From e4f39ebb3953657ef200ba0549616dc5b07c8055 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 10:46:26 +0000 Subject: [PATCH 29/35] update vk hash --- .../cpp/scripts/test_civc_standalone_vks_havent_changed.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index f9cffe06e2a5..4f2680f3a05b 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -13,7 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="d57cc6d9" +pinned_short_hash="7b8a64b3" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload { From 62d39b7925c0d0a29b16bdebdc438b32d7d52711 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 11:08:46 +0000 Subject: [PATCH 30/35] fix tests --- .../relation_correctness.test.cpp | 235 ++++++++++-------- .../translator_circuit_builder.cpp | 2 - .../translator_vm/translator_flavor.hpp | 4 + .../translator_vm/translator_proving_key.cpp | 2 +- .../translator_vm/translator_proving_key.hpp | 4 +- 5 files changed, 139 insertions(+), 108 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 17d393518190..8ea9153b3bd7 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -483,109 +483,138 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) * @brief Test the correctness of TranslatorFlavor's NonNativeField Relation * */ -// TEST_F(TranslatorRelationCorrectnessTests, NonNative) -// { -// using Flavor = TranslatorFlavor; -// using FF = typename Flavor::FF; -// using BF = typename Flavor::BF; -// using ProverPolynomials = typename Flavor::ProverPolynomials; -// using GroupElement = typename Flavor::GroupElement; - -// constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; -// constexpr auto mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE; - -// auto& engine = numeric::get_debug_randomness(); - -// auto op_queue = std::make_shared(); - -// // Generate random EccOpQueue actions - -// for (size_t i = 0; i < ((mini_circuit_size >> 1) - 2); i++) { -// switch (engine.get_random_uint8() & 3) { -// case 0: -// op_queue->no_op_ultra_only(); -// break; -// case 1: -// op_queue->eq_and_reset(); -// break; -// case 2: -// op_queue->add_accumulate(GroupElement::random_element(&engine)); -// break; -// case 3: -// op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); -// break; -// } -// } -// op_queue->merge(); -// const auto batching_challenge_v = BF::random_element(&engine); -// const auto evaluation_input_x = BF::random_element(&engine); - -// // Generating all the values is pretty tedious, so just use CircuitBuilder -// auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue); - -// // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs -// RelationParameters params; -// auto v_power = BF::one(); -// for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) { -// v_power *= batching_challenge_v; -// auto uint_v_power = uint256_t(v_power); -// params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS), -// uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), -// uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), -// uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), -// uint_v_power }; -// } -// auto uint_input_x = uint256_t(evaluation_input_x); -// params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS), -// uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), -// uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), -// uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), -// uint_input_x }; - -// // Create storage for polynomials -// ProverPolynomials prover_polynomials = TranslatorFlavor::ProverPolynomials(); - -// // Copy values of wires used in the non-native field relation from the circuit builder -// for (size_t i = 1; i < circuit_builder.get_estimated_num_finalized_gates(); i++) { -// prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); -// prover_polynomials.p_x_low_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]); -// prover_polynomials.p_x_high_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]); -// prover_polynomials.p_y_low_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]); -// prover_polynomials.p_y_high_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]); -// prover_polynomials.z_low_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]); -// prover_polynomials.z_high_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]); -// prover_polynomials.accumulators_binary_limbs_0.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]); -// prover_polynomials.accumulators_binary_limbs_1.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]); -// prover_polynomials.accumulators_binary_limbs_2.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]); -// prover_polynomials.accumulators_binary_limbs_3.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]); -// prover_polynomials.quotient_low_binary_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]); -// prover_polynomials.quotient_high_binary_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]); -// prover_polynomials.relation_wide_limbs.at(i) = -// circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]); -// } - -// // Fill in lagrange odd polynomial -// for (size_t i = 2; i < mini_circuit_size; i += 2) { -// prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; -// prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; -// } - -// // Check that Non-Native Field relation is satisfied across each row of the prover polynomials -// RelationChecker::check>( -// prover_polynomials, params, "TranslatorNonNativeFieldRelation"); -// } +TEST_F(TranslatorRelationCorrectnessTests, NonNative) +{ + using Flavor = TranslatorFlavor; + using Builder = Flavor::CircuitBuilder; + using FF = typename Flavor::FF; + using BF = typename Flavor::BF; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using GroupElement = typename Flavor::GroupElement; + + constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; + constexpr size_t mini_circuit_size = TranslatorFlavor::MINI_CIRCUIT_SIZE; + constexpr size_t mini_circuit_size_without_masking = + TranslatorFlavor::MINI_CIRCUIT_SIZE - TranslatorFlavor::NUM_MASKED_ROWS_END; + + auto& engine = numeric::get_debug_randomness(); + + auto op_queue = std::make_shared(); + op_queue->no_op_ultra_only(); + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); + + // Generate random EccOpQueue actions + + for (size_t i = 0; i < (mini_circuit_size >> 1) / 2; i++) { + switch (engine.get_random_uint8() & 3) { + case 0: + op_queue->no_op_ultra_only(); + break; + case 1: + op_queue->eq_and_reset(); + break; + case 2: + op_queue->add_accumulate(GroupElement::random_element(&engine)); + break; + case 3: + op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); + break; + } + } + op_queue->merge(); + for (size_t i = 0; i < 100; i++) { + switch (engine.get_random_uint8() & 3) { + case 0: + op_queue->no_op_ultra_only(); + break; + case 1: + op_queue->eq_and_reset(); + break; + case 2: + op_queue->add_accumulate(GroupElement::random_element(&engine)); + break; + case 3: + op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); + break; + } + } + op_queue->random_op_ultra_only(); + op_queue->random_op_ultra_only(); + op_queue->merge(MergeSettings::APPEND, ECCOpQueue::OP_QUEUE_SIZE - op_queue->get_current_subtable_size()); + + const auto batching_challenge_v = BF::random_element(&engine); + const auto evaluation_input_x = BF::random_element(&engine); + + // Generating all the values is pretty tedious, so just use CircuitBuilder + auto circuit_builder = TranslatorCircuitBuilder(batching_challenge_v, evaluation_input_x, op_queue); + + // The non-native field relation uses limbs of evaluation_input_x and powers of batching_challenge_v as inputs + RelationParameters params; + auto v_power = BF::one(); + for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) { + v_power *= batching_challenge_v; + auto uint_v_power = uint256_t(v_power); + params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS), + uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + uint_v_power }; + } + auto uint_input_x = uint256_t(evaluation_input_x); + params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS), + uint_input_x.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + uint_input_x.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + uint_input_x.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + uint_input_x }; + + // Create storage for polynomials + ProverPolynomials prover_polynomials = TranslatorFlavor::ProverPolynomials(); + + // Copy values of wires used in the non-native field relation from the circuit builder + for (size_t i = Builder::NUM_NO_OPS_START + Builder::NUM_RANDOM_OPS_START; + i < circuit_builder.num_gates - Builder::NUM_RANDOM_OPS_END; + i++) { + prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); + prover_polynomials.p_x_low_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]); + prover_polynomials.p_x_high_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]); + prover_polynomials.p_y_low_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]); + prover_polynomials.p_y_high_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]); + prover_polynomials.z_low_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]); + prover_polynomials.z_high_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]); + prover_polynomials.accumulators_binary_limbs_0.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]); + prover_polynomials.accumulators_binary_limbs_1.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]); + prover_polynomials.accumulators_binary_limbs_2.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]); + prover_polynomials.accumulators_binary_limbs_3.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]); + prover_polynomials.quotient_low_binary_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]); + prover_polynomials.quotient_high_binary_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]); + prover_polynomials.relation_wide_limbs.at(i) = + circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]); + } + + // Fill in lagrange odd polynomial + for (size_t i = Flavor::RESULT_ROW; i < mini_circuit_size_without_masking; i += 2) { + prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; + prover_polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1; + } + + // Check that Non-Native Field relation is satisfied across each row of the prover polynomials + RelationChecker::check>( + prover_polynomials, params, "TranslatorNonNativeFieldRelation"); +} TEST_F(TranslatorRelationCorrectnessTests, ZeroKnowledgePermutation) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index baaab7d8e325..e7a706a678ff 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -531,8 +531,6 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // polynomials in translator start with 0 (required for shifted polynomials in the proving system). Technically, // we'd need only first index to be a zero but, given each "real" UltraOp populates two indices in a polynomial we // add two zeros for consistency. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1360): We'll also have to eventually process random - // data in the merge protocol (added for zero knowledge)/ for (auto& wire : wires) { wire.push_back(zero_idx); wire.push_back(zero_idx); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 053701551c3e..cf314e7b4d7d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -86,6 +86,10 @@ class TranslatorFlavor { // responsible for checking it against the evaluations received from ECCVM. static constexpr size_t RESULT_ROW = CircuitBuilder::RESULT_ROW; + // Number of random ops found at he end of Translator trace multiplied by 2 as each accumulation gates occupies two + // rows. + static constexpr size_t NUM_MASKED_ROWS_END = CircuitBuilder::NUM_RANDOM_OPS_END * 2; + // The bitness of the range constraint static constexpr size_t MICRO_LIMB_BITS = CircuitBuilder::MICRO_LIMB_BITS; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index 5a06f33d8709..337ffc564b08 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -246,7 +246,7 @@ void TranslatorProvingKey::compute_lagrange_polynomials() proving_key->polynomials.lagrange_masking.at(i) = 1; } - for (size_t i = 2; i < Flavor::RESULT_ROW; i++) { + for (size_t i = Flavor::CircuitBuilder::NUM_NO_OPS_START * 2; i < Flavor::RESULT_ROW; i++) { proving_key->polynomials.lagrange_mini_masking.at(i) = 1; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index 8f1ca6074ae3..bbc581965885 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -31,9 +31,9 @@ class TranslatorProvingKey { // hiding of polynomial commitments and evaluation). Bound to change, but it has to be even as translator works two // rows at a time static constexpr size_t dyadic_mini_circuit_size_without_masking = - mini_circuit_dyadic_size - NUM_DISABLED_ROWS_IN_SUMCHECK; + mini_circuit_dyadic_size - Flavor::NUM_MASKED_ROWS_END; static constexpr size_t dyadic_circuit_size_without_masking = - dyadic_circuit_size - NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE; + dyadic_circuit_size - Flavor::NUM_MASKED_ROWS_END * Flavor::INTERLEAVING_GROUP_SIZE; std::shared_ptr proving_key; From 8fb3bb889228601fc63e2dd71a24014ece2b2739 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 8 Sep 2025 12:27:47 +0000 Subject: [PATCH 31/35] reflect changes in goblin avm recursive verifier --- .../translator_circuit_checker.cpp | 6 ++---- .../cpp/src/barretenberg/goblin/goblin.cpp | 2 +- .../cpp/src/barretenberg/goblin/goblin.hpp | 5 +++++ .../translator_vm/translator.test.cpp | 20 +++++++++++++++++++ .../translator_circuit_builder.cpp | 8 ++++---- .../translator_circuit_builder.hpp | 15 ++++++++++---- .../goblin_avm_recursive_verifier.hpp | 5 ++++- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp index f8b81c9e284d..79e509e8593b 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/translator_circuit_checker.cpp @@ -27,9 +27,6 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) return false; }; - BB_ASSERT_EQ( - circuit.num_gates, 1U << CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE, "TranslatorCircuit size is incorrect"); - // Compute the limbs of evaluation_input_x and powers of batching_challenge_v (these go into the relation) RelationInputs relation_inputs = compute_relation_inputs_limbs(circuit.batching_challenge_v, circuit.evaluation_input_x); @@ -148,7 +145,8 @@ bool TranslatorCircuitChecker::check(const Builder& circuit) // consider making use of relations. auto in_random_range = [&](size_t i) { return (i >= 2 * Builder::NUM_NO_OPS_START && i < RESULT_ROW) || - (i >= circuit.num_gates - 2 * Builder::NUM_RANDOM_OPS_END && i < circuit.num_gates); + (i >= circuit.num_gates - (circuit.avm_mode ? 0 : 2 * Builder::NUM_RANDOM_OPS_END) && + i < circuit.num_gates); }; for (size_t i = 2; i < circuit.num_gates - 1; i += 2) { diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index 638aa290e794..bd44d208d341 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -43,7 +43,7 @@ void Goblin::prove_eccvm() void Goblin::prove_translator() { BB_BENCH_NAME("Goblin::prove_translator"); - TranslatorBuilder translator_builder(translation_batching_challenge_v, evaluation_challenge_x, op_queue); + TranslatorBuilder translator_builder(translation_batching_challenge_v, evaluation_challenge_x, op_queue, avm_mode); auto translator_key = std::make_shared(translator_builder, commitment_key); TranslatorProver translator_prover(translator_key, transcript); goblin_proof.translator_proof = translator_prover.construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 504b511e70d9..032c6fda3857 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -56,6 +56,11 @@ class Goblin { std::deque merge_verification_queue; // queue of merge proofs to be verified + // In AVM we only use Goblin for a single circuit (it's recursive verifier) whose proof is not required to be + // zero-knowledge. While Translator will still expect to find random ops at the beginning to ensure the accumulation + // result remains at a fixed row we opt for not adding random ops at the end of the op queue. + bool avm_mode = false; + struct VerificationKey { std::shared_ptr eccvm_verification_key = std::make_shared(); std::shared_ptr translator_verification_key = diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 28007c5e8289..8149460cb9dd 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -141,6 +141,26 @@ TEST_F(TranslatorTests, Basic) EXPECT_TRUE(verified); } +TEST_F(TranslatorTests, BasicAvmMode) +{ + using Fq = fq; + + Fq batching_challenge_v = Fq::random_element(); + Fq evaluation_challenge_x = Fq::random_element(); + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + op_queue->no_op_ultra_only(); + add_random_ops(op_queue, CircuitBuilder::NUM_RANDOM_OPS_START); + add_mixed_ops(op_queue, 100); + op_queue->merge(); + auto circuit_builder = CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue, true }; + + EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); + bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); + EXPECT_TRUE(verified); +} + /** * @brief Ensure that the fixed VK from the default constructor agrees with those computed manually for an arbitrary * circuit diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index e7a706a678ff..88f23ad05425 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -517,7 +517,7 @@ void TranslatorCircuitBuilder::create_accumulation_gate(const AccumulationInput& bb::constexpr_for<0, TOTAL_COUNT, 1>([&]() { BB_ASSERT_EQ(std::get(wires).size(), num_gates); }); } -void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr ecc_op_queue) +void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr& ecc_op_queue) { using Fq = bb::fq; const auto& ultra_ops = ecc_op_queue->get_ultra_ops(); @@ -556,10 +556,10 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ for (size_t i = NUM_NO_OPS_START; i <= NUM_RANDOM_OPS_START; ++i) { process_random_op(ultra_ops[i]); } - + const size_t ops_end = avm_mode ? ultra_ops.size() : ultra_ops.size() - NUM_RANDOM_OPS_END; // Range of UltraOps for which we should construct accumulation gates std::span ultra_ops_span(ultra_ops.begin() + static_cast(NUM_NO_OPS_START + NUM_RANDOM_OPS_START), - ultra_ops.begin() + static_cast(ultra_ops.size() - NUM_RANDOM_OPS_END)); + ultra_ops.begin() + static_cast(ops_end)); // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices and we need to know the previous accumulator to create the gate. Both when computing the @@ -632,7 +632,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ } // Also process the last two random ops present at the end of the op queue to hide the ecc ops of the last circuit // whose ops are added to the op queue - for (size_t i = ultra_ops.size() - NUM_RANDOM_OPS_END; i < ultra_ops.size(); ++i) { + for (size_t i = ops_end; i < ultra_ops.size(); ++i) { process_random_op(ultra_ops[i]); } } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index c73b2ba47382..28189e9a90ce 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -318,6 +318,8 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { // The input we evaluate polynomials on Fq evaluation_input_x; + bool avm_mode = false; + std::array, NUM_WIRES> wires; /** @@ -328,10 +330,11 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { * @param batching_challenge_v_ * @param evaluation_input_x_ */ - TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_) + TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, bool avm_mode_ = false) : CircuitBuilderBase(DEFAULT_TRANSLATOR_VM_LENGTH) , batching_challenge_v(batching_challenge_v_) , evaluation_input_x(evaluation_input_x_) + , avm_mode(avm_mode_) { this->zero_idx = add_variable(Fr::zero()); }; @@ -346,8 +349,12 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { * @param evaluation_input_x_ * @param op_queue */ - TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, std::shared_ptr op_queue) - : TranslatorCircuitBuilder(batching_challenge_v_, evaluation_input_x_) + TranslatorCircuitBuilder(Fq batching_challenge_v_, + Fq evaluation_input_x_, + std::shared_ptr op_queue, + bool avm_mode = false) + : TranslatorCircuitBuilder(batching_challenge_v_, evaluation_input_x_, avm_mode) + { BB_BENCH_NAME("TranslatorCircuitBuilder::constructor"); feed_ecc_op_queue_into_circuit(std::move(op_queue)); @@ -419,7 +426,7 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { * * @param ecc_op_queue The queue */ - void feed_ecc_op_queue_into_circuit(const std::shared_ptr ecc_op_queue); + void feed_ecc_op_queue_into_circuit(const std::shared_ptr& ecc_op_queue); static AccumulationInput generate_witness_values(const UltraOp& ultra_op, const Fq& previous_accumulator, diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp index 1f4a37a489ea..36b6f934a193 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp @@ -191,7 +191,9 @@ class AvmGoblinRecursiveVerifier { Goblin goblin; MegaBuilder mega_builder(goblin.op_queue); mega_builder.queue_ecc_no_op(); - + mega_builder.queue_ecc_random_op(); + mega_builder.queue_ecc_random_op(); + mega_builder.queue_ecc_random_op(); // lambda to convert from Ultra to Mega stdlib field buffer and add all elements to respective hash buffers std::vector mega_hash_buffer; auto convert_stdlib_ultra_to_stdlib_mega = [&](const std::vector& ultra_object) { @@ -246,6 +248,7 @@ class AvmGoblinRecursiveVerifier { MegaProver mega_prover(mega_proving_key, mega_vk, transcript); HonkProof mega_proof = mega_prover.construct_proof(); goblin.transcript = transcript; + goblin.avm_mode = true; // Construct corresponding Goblin proof \pi_G (includes Merge, ECCVM, and Translator proofs) GoblinProof goblin_proof = goblin.prove(); From a932f66387cac09e47b1f64185e92c285db0d376 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 9 Sep 2025 09:25:47 +0000 Subject: [PATCH 32/35] address review comments --- barretenberg/cpp/src/barretenberg/goblin/goblin.cpp | 9 +++++++++ barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 11 +++++++++++ .../cpp/src/barretenberg/goblin/mock_circuits.hpp | 2 +- .../translator_recursive_verifier.test.cpp | 2 +- .../barretenberg/translator_vm/translator.test.cpp | 7 ++++++- .../translator_vm/translator_circuit_builder.cpp | 2 +- .../translator_vm/translator_circuit_builder.hpp | 5 ++++- .../recursion/goblin_avm_recursive_verifier.hpp | 6 ++---- 8 files changed, 35 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index bd44d208d341..6a2f0acc3298 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -124,4 +124,13 @@ bool Goblin::verify(const GoblinProof& proof, op_queue_consistency_verified; } +void Goblin::ensure_well_formed_op_queue_for_avm(MegaBuilder& builder) const +{ + BB_ASSERT_EQ(avm_mode, true, "ensure_well_formed_op_queue should only be called for avm"); + builder.queue_ecc_no_op(); + builder.queue_ecc_random_op(); + builder.queue_ecc_random_op(); + builder.queue_ecc_random_op(); +} + } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 032c6fda3857..d65de0c9cf16 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -128,6 +128,17 @@ class Goblin { const MergeCommitments& merge_commitments, const std::shared_ptr& transcript, const MergeSettings merge_settings = MergeSettings::PREPEND); + + /** + * @brief Translator requires the op queue to start with a no-op to ensure op queue polynomials are shiftable and + * then expects three random ops. This is due to the ZK requirement in ClientIVC. We need to also ensure these ops + * are present when Goblin is used for AVM, although we only ever have a single table of ecc ops and no ZK + * requiements. + * + * @todo (https://github.com/AztecProtocol/barretenberg/issues/1537) Asses whether two Translator variants (one with + * Zk and one without) would be a better option + */ + void ensure_well_formed_op_queue_for_avm(MegaBuilder& builder) const; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 3b1a6c632922..839cb895ab16 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -126,7 +126,7 @@ class GoblinMockCircuits { /** * @brief Add some randomness into the op queue. */ - static void randomise_op_queue(MegaBuilder& builder, size_t num_ops = 0) + static void randomise_op_queue(MegaBuilder& builder, size_t num_ops) { for (size_t i = 0; i < num_ops; ++i) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index bbc831c08ed3..a3bddd2a6387 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -45,7 +45,7 @@ class TranslatorRecursiveTests : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } // Helper function to add no-ops - static void add_random_ops(std::shared_ptr& op_queue, size_t count = 1) + static void add_random_ops(std::shared_ptr& op_queue, size_t count) { for (size_t i = 0; i < count; i++) { op_queue->random_op_ultra_only(); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 8149460cb9dd..1c652651a40a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -141,6 +141,11 @@ TEST_F(TranslatorTests, Basic) EXPECT_TRUE(verified); } +/** + * @brief Test Translator operates correctly for AVM i.e. when we only run Goblin on a single table of ecc ops and we + * should not expect random ops to appear at the end of Translator trace. + * + */ TEST_F(TranslatorTests, BasicAvmMode) { using Fq = fq; @@ -154,7 +159,7 @@ TEST_F(TranslatorTests, BasicAvmMode) add_random_ops(op_queue, CircuitBuilder::NUM_RANDOM_OPS_START); add_mixed_ops(op_queue, 100); op_queue->merge(); - auto circuit_builder = CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue, true }; + auto circuit_builder = CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue, /*avm_mode=*/true }; EXPECT_TRUE(TranslatorCircuitChecker::check(circuit_builder)); bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 88f23ad05425..a88f2fd03e1e 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -564,7 +564,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices and we need to know the previous accumulator to create the gate. Both when computing the // accumulator and the actual accumulation gates, we skip the beginning and end of the op queue (where first no-op - // and random ops exist) as they should not affectt he computation of the accumulation result. However, given the + // and random ops exist) as they should not affect the computation of the accumulation result. However, given the // accumulation result (i.e. value at index RESULT_ROW) is sent as part of the proof, we also need to hide its // context. However, we achieve this by ensuring a genuine operation, but with values generated randomly, is added // to the op queue during the CIVC processing. diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index 28189e9a90ce..80d422f1139d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -243,9 +243,12 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { // information about the op queue content linked to the circuits being proven static constexpr size_t RESULT_ROW = 8; static constexpr size_t NUM_NO_OPS_START = 1; - static_assert(NUM_NO_OPS_START == 1); + + // Number of random ops at the beginning of Translator trace static constexpr size_t NUM_RANDOM_OPS_START = 3; static_assert(NUM_RANDOM_OPS_START == 3); + + // Number of random ops at the end of Translator trace static constexpr size_t NUM_RANDOM_OPS_END = 2; static_assert(NUM_RANDOM_OPS_END == 2); diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp index 36b6f934a193..645435f3f62d 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp @@ -189,11 +189,9 @@ class AvmGoblinRecursiveVerifier { // Instantiate Mega builder for the inner circuit (AVM2 proof recursive verifier) Goblin goblin; + goblin.avm_mode = true; MegaBuilder mega_builder(goblin.op_queue); - mega_builder.queue_ecc_no_op(); - mega_builder.queue_ecc_random_op(); - mega_builder.queue_ecc_random_op(); - mega_builder.queue_ecc_random_op(); + goblin.ensure_well_formed_op_queue(mega_builder); // lambda to convert from Ultra to Mega stdlib field buffer and add all elements to respective hash buffers std::vector mega_hash_buffer; auto convert_stdlib_ultra_to_stdlib_mega = [&](const std::vector& ultra_object) { From e44b0f0fcd4aed1a7cfcbc3be1391698786e601a Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 9 Sep 2025 09:33:43 +0000 Subject: [PATCH 33/35] fix typo --- .../constraining/recursion/goblin_avm_recursive_verifier.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp index 645435f3f62d..50f5af2d0d67 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp @@ -191,7 +191,7 @@ class AvmGoblinRecursiveVerifier { Goblin goblin; goblin.avm_mode = true; MegaBuilder mega_builder(goblin.op_queue); - goblin.ensure_well_formed_op_queue(mega_builder); + goblin.ensure_well_formed_op_queue_for_avm(mega_builder); // lambda to convert from Ultra to Mega stdlib field buffer and add all elements to respective hash buffers std::vector mega_hash_buffer; auto convert_stdlib_ultra_to_stdlib_mega = [&](const std::vector& ultra_object) { From 0131cfc73bde38c9a60d93a92ec80bf1f6263a31 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 9 Sep 2025 09:36:47 +0000 Subject: [PATCH 34/35] fix build --- barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp | 3 ++- .../cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 6473dcfd934b..8fce41b4714b 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -562,7 +562,8 @@ void ClientIVC::hide_op_queue_accumulation_result(ClientCircuit& circuit) * achieved via the translation evaluation check and avoiding an information leak there is ensured by * `ClientIVC::hide_op_queue_accumulation_result()` and SmallSubgroupIPA in ECCVM. * - * We need each op queue polynomial to have 9 random coefficients (so the op queue needs to contain 6 random ops). + * We need each op queue polynomial to have 9 random coefficients (so the op queue needs to contain 5 random ops, every + * UltraOp adding two coefficients to each of the 4 polynomials). * * For the last subtable of ecc ops belonging to the hiding kernel, merged via appended to the full op queue, its data * appears as the ecc_op_wires in the MegaZK proof, wires that are not going to be shifted, so the proof contains, diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index e694d9383f85..dddbdaac71e4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -539,7 +539,7 @@ TYPED_TEST(MegaHonkTests, OpQueueWithRandomValues) // Test for randomness added at the beginning { Builder builder; - GoblinMockCircuits::randomise_op_queue(builder); + GoblinMockCircuits::randomise_op_queue(builder, 2); GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof @@ -551,7 +551,7 @@ TYPED_TEST(MegaHonkTests, OpQueueWithRandomValues) { Builder builder; GoblinMockCircuits::construct_simple_circuit(builder); - GoblinMockCircuits::randomise_op_queue(builder); + GoblinMockCircuits::randomise_op_queue(builder, 2); // Construct and verify Honk proof bool honk_verified = this->construct_and_verify_honk_proof(builder); From 11f1bfa62104e84a16873ccbf2239c2cc9b7d8d9 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 9 Sep 2025 09:49:34 +0000 Subject: [PATCH 35/35] update pinned hash --- .../cpp/scripts/test_civc_standalone_vks_havent_changed.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index 7ba40203f725..9b4fd1229ff3 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -13,7 +13,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_short_hash="24a6d200" +pinned_short_hash="d06b78a2" pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz" function compress_and_upload {