diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh index a013a7129b3..30548202ad3 100755 --- a/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh +++ b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh @@ -3,7 +3,7 @@ # BIN: to specify a different binary to test with (e.g. bb.js or bb.js-dev). set -eu -BIN=${BIN:-../cpp/build-debug/bin/bb} +BIN=${BIN:-../cpp/build/bin/bb} CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:-} diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp index 6e7069f08ae..f735d2cfb19 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp @@ -65,7 +65,7 @@ BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); -BENCHMARK(execute_relation_for_pg_univariates>); +BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); // Goblin-Ultra only relations (PG prover combiner work) @@ -79,7 +79,7 @@ BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); -BENCHMARK(execute_relation_for_univariates>); +BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); // Goblin-Ultra only relations (Sumcheck prover work) @@ -93,7 +93,7 @@ BENCHMARK(execute_relation_for_values>) BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); -BENCHMARK(execute_relation_for_values>); +BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); // Goblin-Ultra only relations (verifier work) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp index 005a50ea156..5d1eec57741 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" #include @@ -104,6 +105,22 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) EXPECT_EQ(result, true); } +TEST(ultra_circuit_constructor, bad_lookup_failure) +{ + UltraCircuitBuilder builder; + MockCircuits::add_lookup_gates(builder); + + // Erroneously set a non-zero wire value to zero in one of the lookup gates + for (auto& wire_3_witness_idx : builder.blocks.lookup.w_o()) { + if (wire_3_witness_idx != builder.zero_idx) { + wire_3_witness_idx = builder.zero_idx; + break; + } + } + + EXPECT_FALSE(CircuitChecker::check(builder)); +} + TEST(ultra_circuit_constructor, base_case) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index b752a861a90..7b788531c91 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -6,7 +6,6 @@ #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp index 0ca1c00e747..88c518cb4b3 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp @@ -48,4 +48,79 @@ std::shared_ptr compute_verification_key_common( // silencing for now but need to figure out where to extract type of VerifierCrs from :-/ std::shared_ptr> const& vrs); +/** + * @brief Construct polynomials containing the sorted concatenation of the lookups and the lookup tables + * + * @tparam Flavor + * @param circuit + * @param dyadic_circuit_size + * @param additional_offset Additional space needed in polynomials to add randomness for zk (Plonk only) + * @return std::array + */ +template +std::array construct_sorted_list_polynomials(typename Flavor::CircuitBuilder& circuit, + const size_t dyadic_circuit_size, + size_t additional_offset = 0) +{ + using Polynomial = typename Flavor::Polynomial; + std::array sorted_polynomials; + // Initialise the sorted concatenated list polynomials for the lookup argument + for (auto& s_i : sorted_polynomials) { + s_i = Polynomial(dyadic_circuit_size); + } + + // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so + // that these entries are written into the last indices of the polynomials. The values on the first + // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the + // polynomial constructor. + size_t s_index = dyadic_circuit_size - (circuit.get_tables_size() + circuit.get_lookups_size()) - additional_offset; + ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + + for (auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + auto& lookup_gates = table.lookup_gates; + for (size_t i = 0; i < table.size(); ++i) { + if (table.use_twin_keys) { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + table.column_2[i].from_montgomery_form().data[0], + }, + { + table.column_3[i], + 0, + }, + }); + } else { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + 0, + }, + { + table.column_2[i], + table.column_3[i], + }, + }); + } + } + +#ifdef NO_TBB + std::sort(lookup_gates.begin(), lookup_gates.end()); +#else + std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); +#endif + + for (const auto& entry : lookup_gates) { + const auto components = entry.to_table_components(table.use_twin_keys); + sorted_polynomials[0][s_index] = components[0]; + sorted_polynomials[1][s_index] = components[1]; + sorted_polynomials[2][s_index] = components[2]; + sorted_polynomials[3][s_index] = table_index; + ++s_index; + } + } + return sorted_polynomials; +} + } // namespace bb::plonk diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt index d3024bcdbb1..7603c0f6775 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(plonk_honk_shared polynomials) \ No newline at end of file +barretenberg_module(plonk_honk_shared polynomials ultra_honk) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp index 7745a853c58..d4e75dc9e14 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/ref_array.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/polynomials/polynomial_store.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp" #include @@ -20,6 +21,7 @@ void construct_lookup_table_polynomials(RefArray // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments // | table randomness // ignored, as used for regular constraints and padding to the next power of 2. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace ASSERT(dyadic_circuit_size > circuit.get_tables_size() + additional_offset); size_t offset = dyadic_circuit_size - circuit.get_tables_size() - additional_offset; @@ -37,78 +39,40 @@ void construct_lookup_table_polynomials(RefArray } /** - * @brief Construct polynomials containing the sorted concatenation of the lookups and the lookup tables - * - * @tparam Flavor - * @param circuit - * @param dyadic_circuit_size - * @param additional_offset Additional space needed in polynomials to add randomness for zk (Plonk only) - * @return std::array + * @brief Construct polynomial whose value at index i is the number of times the table entry at that index has been + * read. + * @details Read counts are needed for the log derivative lookup argument. The table polynomials are constructed as a + * concatenation of basic 3-column tables. Similarly, the read counts polynomial is constructed as the concatenation of + * read counts for the individual tables. */ template -std::array construct_sorted_list_polynomials(typename Flavor::CircuitBuilder& circuit, - const size_t dyadic_circuit_size, - size_t additional_offset = 0) +void construct_lookup_read_counts(typename Flavor::Polynomial& read_counts, + typename Flavor::Polynomial& read_tags, + typename Flavor::CircuitBuilder& circuit, + size_t dyadic_circuit_size) { - using Polynomial = typename Flavor::Polynomial; - std::array sorted_polynomials; - // Initialise the sorted concatenated list polynomials for the lookup argument - for (auto& s_i : sorted_polynomials) { - s_i = Polynomial(dyadic_circuit_size); - } - - // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so - // that these entries are written into the last indices of the polynomials. The values on the first - // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the - // polynomial constructor. - size_t s_index = dyadic_circuit_size - (circuit.get_tables_size() + circuit.get_lookups_size()) - additional_offset; - ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace + size_t offset = dyadic_circuit_size - circuit.get_tables_size(); + size_t table_offset = offset; // offset of the present table in the table polynomials + // loop over all tables used in the circuit; each table contains data about the lookups made on it for (auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); - auto& lookup_gates = table.lookup_gates; - for (size_t i = 0; i < table.size(); ++i) { - if (table.use_twin_keys) { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - table.column_2[i].from_montgomery_form().data[0], - }, - { - table.column_3[i], - 0, - }, - }); - } else { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - 0, - }, - { - table.column_2[i], - table.column_3[i], - }, - }); - } - } + table.initialize_index_map(); + + for (auto& gate_data : table.lookup_gates) { + // convert lookup gate data to an array of three field elements, one for each of the 3 columns + auto table_entry = gate_data.to_table_components(table.use_twin_keys); -#ifdef NO_TBB - std::sort(lookup_gates.begin(), lookup_gates.end()); -#else - std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); -#endif + // find the index of the entry in the table + auto index_in_table = table.index_map[table_entry]; - for (const auto& entry : lookup_gates) { - const auto components = entry.to_sorted_list_components(table.use_twin_keys); - sorted_polynomials[0][s_index] = components[0]; - sorted_polynomials[1][s_index] = components[1]; - sorted_polynomials[2][s_index] = components[2]; - sorted_polynomials[3][s_index] = table_index; - ++s_index; + // increment the read count at the corresponding index in the full polynomial + size_t index_in_poly = table_offset + index_in_table; + read_counts[index_in_poly]++; + read_tags[index_in_poly] = 1; // tag is 1 if entry has been read 1 or more times } + table_offset += table.size(); // set the offset of the next table within the polynomials } - return sorted_polynomials; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp index 94219c72a48..33534bc958d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp @@ -1,21 +1,78 @@ #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" -#include "barretenberg/common/slab_allocator.hpp" -#include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" + #include #include using namespace bb; class ComposerLibTests : public ::testing::Test { + public: + using Flavor = UltraFlavor; + using FF = typename Flavor::FF; + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; + +/** + * @brief A test to demonstrate that lookup read counts/tags are computed correctly for a simple 'hand-computable' case + * using the uint32 XOR table + * + */ +TEST_F(ComposerLibTests, LookupReadCounts) +{ + using Builder = UltraCircuitBuilder; using Flavor = UltraFlavor; using FF = typename Flavor::FF; - Flavor::CircuitBuilder circuit_constructor; - Flavor::ProvingKey proving_key = []() { - auto crs_factory = srs::factories::CrsFactory(); - auto crs = crs_factory.get_prover_crs(4); - return Flavor::ProvingKey(/*circuit_size=*/8, /*num_public_inputs=*/0); - }(); -}; \ No newline at end of file + using Polynomial = typename Flavor::Polynomial; + auto UINT32_XOR = plookup::MultiTableId::UINT32_XOR; + + Builder builder; + + // define some very simply inputs to XOR + FF left{ 1 }; + FF right{ 5 }; + + auto left_idx = builder.add_variable(left); + auto right_idx = builder.add_variable(right); + + // create a single lookup from the uint32 XOR table + auto accumulators = plookup::get_lookup_accumulators(UINT32_XOR, left, right, /*is_2_to_1_lookup*/ true); + builder.create_gates_from_plookup_accumulators(UINT32_XOR, accumulators, left_idx, right_idx); + + EXPECT_EQ(builder.lookup_tables.size(), 1); // we only used a single table + EXPECT_EQ(builder.lookup_tables[0].size(), 4096); // table has size 64*64 (6 bit operands) + + size_t circuit_size = 8192; + + Polynomial read_counts{ circuit_size }; + Polynomial read_tags{ circuit_size }; + + construct_lookup_read_counts(read_counts, read_tags, builder, circuit_size); + + // The table polys are constructed at the bottom of the trace, thus so to are the counts/tags + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace + size_t offset = circuit_size - builder.get_tables_size(); + + // The uint32 XOR lookup table is constructed for 6 bit operands via double for loop that iterates through the left + // operand externally (0 to 63) then the right operand internally (0 to 63). Computing (1 XOR 5) will thus result in + // 1 lookup from the (1*64 + 5)th index in the table and 5 lookups from the (0*64 + 0)th index (for the remaining 5 + // limbs that are all 0). The counts and tags at all other indices should be zero. + size_t idx = 0; + for (auto [count, tag] : zip_view(read_counts, read_tags)) { + if (idx == (0 + offset)) { + EXPECT_EQ(count, 5); + EXPECT_EQ(tag, 1); + } else if (idx == (69 + offset)) { + EXPECT_EQ(count, 1); + EXPECT_EQ(tag, 1); + } else { + EXPECT_EQ(count, 0); + EXPECT_EQ(tag, 0); + } + idx++; + } +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 6c717c1d126..da09210655f 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -136,12 +136,10 @@ template class ProtoGalaxyTests : public testing::Test { instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); - if constexpr (IsGoblinFlavor) { - instance->proving_key.compute_logderivative_inverse(instance->relation_parameters); - } + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); for (auto& alpha : instance->alphas) { @@ -311,21 +309,94 @@ template class ProtoGalaxyTests : public testing::Test { } /** - * @brief Testing one valid round of folding followed by the decider. - * @brief For additional robustness we give one of the circuits more public inputs than the other + * @brief Testing one valid round of folding (plus decider) for two inhomogeneous circuits + * @details For robustness we fold circuits with different numbers/types of gates (but the same dyadic size) * */ - static void test_full_protogalaxy_simple() + static void test_protogalaxy_inhomogeneous() { - // Construct a first circuit with some public inputs - Builder builder1; - construct_circuit(builder1); - bb::MockCircuits::add_arithmetic_gates_with_public_inputs(builder1, /*num_gates=*/4); + auto check_fold_and_decide = [](Builder& circuit_1, Builder& circuit_2) { + // Construct the prover/verifier instances for each + TupleOfInstances instances; + construct_prover_and_verifier_instance(instances, circuit_1); + construct_prover_and_verifier_instance(instances, circuit_2); + + // Perform prover and verifier folding + auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); + check_accumulator_target_sum_manual(prover_accumulator, true); + + // Run decider + decide_and_verify(prover_accumulator, verifier_accumulator, true); + }; + + // One circuit has more arithmetic gates + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add some arithmetic gates + bb::MockCircuits::add_arithmetic_gates(builder1, /*num_gates=*/4); + + check_fold_and_decide(builder1, builder2); + } + + // One circuit has more arithmetic gates with public inputs + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add some arithmetic gates with public inputs to the first circuit + bb::MockCircuits::add_arithmetic_gates_with_public_inputs(builder1, /*num_gates=*/4); + + check_fold_and_decide(builder1, builder2); + } + + // One circuit has more lookup gates + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add a different number of lookup gates to each circuit + bb::MockCircuits::add_lookup_gates(builder1, /*num_iterations=*/2); // 12 gates plus 4096 table + bb::MockCircuits::add_lookup_gates(builder2, /*num_iterations=*/1); // 6 gates plus 4096 table + + check_fold_and_decide(builder1, builder2); + } + } - // Construct a second circuit with no public inputs + /** + * @brief Ensure failure for a bad lookup gate in one of the circuits being folded + * + */ + static void test_protogalaxy_bad_lookup_failure() + { + // Construct two equivalent circuits + Builder builder1; Builder builder2; + construct_circuit(builder1); construct_circuit(builder2); + // Add a different number of lookup gates to each circuit + bb::MockCircuits::add_lookup_gates(builder1, /*num_iterations=*/2); // 12 gates plus 4096 table + bb::MockCircuits::add_lookup_gates(builder2, /*num_iterations=*/1); // 6 gates plus 4096 table + + // Erroneously set a non-zero wire value to zero in one of the lookup gates + for (auto& wire_3_witness_idx : builder1.blocks.lookup.w_o()) { + if (wire_3_witness_idx != builder1.zero_idx) { + wire_3_witness_idx = builder1.zero_idx; + break; + } + } + // Construct the prover/verifier instances for each TupleOfInstances instances; construct_prover_and_verifier_instance(instances, builder1); @@ -333,9 +404,11 @@ template class ProtoGalaxyTests : public testing::Test { // Perform prover and verifier folding auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); - check_accumulator_target_sum_manual(prover_accumulator, true); - decide_and_verify(prover_accumulator, verifier_accumulator, true); + // Expect failure in manual target sum check and decider + bool expected_result = false; + check_accumulator_target_sum_manual(prover_accumulator, expected_result); + decide_and_verify(prover_accumulator, verifier_accumulator, expected_result); } /** @@ -517,9 +590,9 @@ TYPED_TEST(ProtoGalaxyTests, CombineAlpha) TestFixture::test_combine_alpha(); } -TYPED_TEST(ProtoGalaxyTests, FullProtogalaxySimple) +TYPED_TEST(ProtoGalaxyTests, ProtogalaxyInhomogeneous) { - TestFixture::test_full_protogalaxy_simple(); + TestFixture::test_protogalaxy_inhomogeneous(); } TYPED_TEST(ProtoGalaxyTests, FullProtogalaxyTest) @@ -546,6 +619,11 @@ TYPED_TEST(ProtoGalaxyTests, TamperedAccumulatorPolynomial) TestFixture::test_tampered_accumulator_polynomial(); } +TYPED_TEST(ProtoGalaxyTests, BadLookupFailure) +{ + TestFixture::test_protogalaxy_bad_lookup_failure(); +} + // We only fold one instance currently due to significant compile time added by multiple instances TYPED_TEST(ProtoGalaxyTests, Fold1Instance) { diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index 3091c0259e2..cbfbe35cbda 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -364,7 +364,6 @@ template class ProtoGalaxyProver_ { const FF& scaling_factor) { using Relation = std::tuple_element_t; - // WORKTODO: disable skipping for the combiner for now.. // Check if the relation is skippable to speed up accumulation if constexpr (!isSkippable) { // If not, accumulate normally diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp index f38ff10b3e1..36774b7c25f 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp @@ -187,7 +187,12 @@ FoldingResult ProtoGalaxyProver_proving_key.circuit_size == instances[idx + 1]->proving_key.circuit_size); + if (instances[idx]->proving_key.circuit_size != instances[idx + 1]->proving_key.circuit_size) { + info("ProtogalaxyProver: circuit size mismatch!"); + info("Instance ", idx, " size = ", instances[idx]->proving_key.circuit_size); + info("Instance ", idx + 1, " size = ", instances[idx + 1]->proving_key.circuit_size); + ASSERT(false); + } } preparation_round(); perturbator_round(); diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index 3c897ce3909..c0ec529cdd7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -243,24 +243,24 @@ template class DatabusLookupRelationImpl { const auto inverses = View(BusData::inverses(in)); // Degree 1 const auto read_counts = View(BusData::read_counts(in)); // Degree 1 - const auto read_term = compute_read_term(in, params); // Degree 1 - const auto write_term = compute_write_term(in, params); // Degree 1 - const auto inverse_exists = compute_inverse_exists(in); // Degree 1 + const auto read_term = compute_read_term(in, params); // Degree 1 (2) + const auto write_term = compute_write_term(in, params); // Degree 1 (2) + const auto inverse_exists = compute_inverse_exists(in); // Degree 2 const auto read_selector = get_read_selector(in); // Degree 2 - const auto write_inverse = inverses * read_term; // Degree 2 - const auto read_inverse = inverses * write_term; // Degree 2 + const auto write_inverse = inverses * read_term; // Degree 2 (3) + const auto read_inverse = inverses * write_term; // Degree 2 (3) // Determine which pair of subrelations to update based on which bus column is being read constexpr size_t subrel_idx_1 = 2 * bus_idx; constexpr size_t subrel_idx_2 = 2 * bus_idx + 1; // Establish the correctness of the polynomial of inverses I. Note: inverses is computed so that the value is 0 - // if !inverse_exists. Degree 3 + // if !inverse_exists. Degree 3 (5) std::get(accumulator) += (read_term * write_term * inverses - inverse_exists) * scaling_factor; // Establish validity of the read. Note: no scaling factor here since this constraint is enforced across the - // entire trace, not on a per-row basis - std::get(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Degree 4 + // entire trace, not on a per-row basis. + std::get(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Deg 4 (5) } /** diff --git a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp new file mode 100644 index 00000000000..92078db8e85 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp @@ -0,0 +1,207 @@ +#pragma once +#include +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace bb { + +template class LogDerivLookupRelationImpl { + public: + using FF = FF_; + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + // 1 + polynomial degree of this relation + static constexpr size_t LENGTH = 5; // both subrelations are degree 4 + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + LENGTH, // inverse construction sub-relation + LENGTH // log derivative lookup argument sub-relation + }; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1036): Scrutinize these adjustment factors. Counting + // degrees suggests the first subrelation should require an adjustment of 2. + static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ + 1, // inverse construction sub-relation + 1 // log derivative lookup argument sub-relation + }; + + static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; + + template inline static bool skip(const AllEntities& in) + { + // Ensure the input does not contain a lookup gate or data that is being read + return in.q_lookup.is_zero() && in.lookup_read_counts.is_zero(); + } + + /** + * @brief Does the provided row contain data relevant to table lookups; Used to determine whether the polynomial of + * inverses must be computed at a given row + * @details In order to avoid unnecessary computation, the polynomial of inverses I is only computed for rows at + * which the lookup relation is "active". It is active if either (1) the present row contains a lookup gate (i.e. + * q_lookup == 1), or (2) the present row contains table data that has been looked up in this circuit + * (lookup_read_tags == 1, or equivalently, if the row in consideration has index i, the data in polynomials table_i + * has been utlized in the circuit). + * + */ + template static bool operation_exists_at_row(const AllValues& row) + { + // is the row a lookup gate or does it contain table data that has been read at some point in this circuit + return (row.q_lookup == 1) || (row.lookup_read_tags == 1); + } + + // Get the inverse polynomial for this relation + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } + + // Used in the inverse correctness subrelation; facilitates only computing inverses where necessary + template + static Accumulator compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + + const auto row_has_write = View(in.lookup_read_tags); + const auto row_has_read = View(in.q_lookup); + return row_has_write + row_has_read - (row_has_write * row_has_read); + } + + template + static Accumulator lookup_read_counts(const AllEntities& in) + { + using View = typename Accumulator::View; + return Accumulator(View(in.lookup_read_counts)); + } + + // Compute table_1 + gamma + table_2 * eta + table_3 * eta_2 + table_4 * eta_3 + template + static Accumulator compute_write_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + using ParameterView = GetParameterView; + + static_assert(write_index < WRITE_TERMS); + + const auto& gamma = ParameterView(params.gamma); + const auto& eta = ParameterView(params.eta); + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); + + auto table_1 = View(in.table_1); + auto table_2 = View(in.table_2); + auto table_3 = View(in.table_3); + auto table_4 = View(in.table_4); + + return table_1 + gamma + table_2 * eta + table_3 * eta_two + table_4 * eta_three; + } + + template + static Accumulator compute_read_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + using ParameterView = GetParameterView; + + const auto& gamma = ParameterView(params.gamma); + const auto& eta = ParameterView(params.eta); + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); + + auto w_1 = View(in.w_l); + auto w_2 = View(in.w_r); + auto w_3 = View(in.w_o); + + auto w_1_shift = View(in.w_l_shift); + auto w_2_shift = View(in.w_r_shift); + auto w_3_shift = View(in.w_o_shift); + + auto table_index = View(in.q_o); + auto negative_column_1_step_size = View(in.q_r); + auto negative_column_2_step_size = View(in.q_m); + auto negative_column_3_step_size = View(in.q_c); + + // The wire values for lookup gates are accumulators structured in such a way that the differences w_i - + // step_size*w_i_shift result in values present in column i of a corresponding table. See the documentation in + // method get_lookup_accumulators() in for a detailed explanation. + auto derived_table_entry_1 = w_1 + gamma + negative_column_1_step_size * w_1_shift; + auto derived_table_entry_2 = w_2 + negative_column_2_step_size * w_2_shift; + auto derived_table_entry_3 = w_3 + negative_column_3_step_size * w_3_shift; + + // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. + // deg 2 or 3 + return derived_table_entry_1 + derived_table_entry_2 * eta + derived_table_entry_3 * eta_two + + table_index * eta_three; + } + + /** + * @brief Log-derivative style lookup argument for conventional lookups form tables with 3 or fewer columns + * @details The identity to be checked is of the form + * + * \sum{i=0}^{n-1} \frac{read_counts_i}{write_term_i} - \frac{q_lookup}{read_term_i} = 0 + * + * where write_term = table_col_1 + \gamma + table_col_2 * \eta_1 + table_col_3 * \eta_2 + table_index * \eta_3 + * and read_term = derived_table_entry_1 + \gamma + derived_table_entry_2 * \eta_1 + derived_table_entry_3 * \eta_2 + * + table_index * \eta_3, with derived_table_entry_i = w_i - col_step_size_i\cdot w_i_shift. (The table entries + * must be 'derived' from wire values in this way since the stored witnesses are actually successive accumulators, + * the differences of which are equal to entries in a table. This is an efficiency trick to avoid using additional + * gates to reconstruct full size values from the limbs contained in tables). + * + * In practice this identity is expressed in terms of polynomials by defining a polynomial of inverses I_i = + * \frac{1}{read_term_i\cdot write_term_i} then rewriting the above identity as + * + * (1) \sum{i=0}^{n-1} (read_counts_i\cdot I_i\cdot read_term_i) - (q_lookup\cdot I_i\cdot write_term_i) = 0 + * + * This requires a second subrelation to check that polynomial I was computed correctly. For all i, it must hold + * that + * + * (2) I_i\cdot read_term_i\cdot write_term_i - 1 = 0 + * + * Note that (1) is 'linearly dependent' in the sense that it holds only as a sum across the entire execution trace. + * (2) on the other hand holds independently at every row. Finally, note that to avoid unnecessary computation, we + * only compute I_i at indices where the relation is 'active', i.e. on rows which either contain a lookup gate or + * table data that has been read. For inactive rows i, we set I_i = 0. We can thus rewrite (2) as + * + * (2) I_i\cdot read_term_i\cdot write_term_i - is_active_i + * + * where is_active = q_lookup + read_tags - q_lookup\cdot read_tags + * + * and read_tags is a polynomial taking boolean values indicating whether the table entry at the corresponding row + * has been read or not. + * @note This relation utilizes functionality in the log-derivative library to compute the polynomial of inverses + * + */ + template + static void accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) + { + BB_OP_COUNT_TIME_NAME("Lookup::accumulate"); + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + const auto inverses = View(in.lookup_inverses); // Degree 1 + const auto read_counts = View(in.lookup_read_counts); // Degree 1 + const auto read_selector = View(in.q_lookup); // Degree 1 + const auto inverse_exists = compute_inverse_exists(in); // Degree 2 + const auto read_term = compute_read_term(in, params); // Degree 2 (3) + const auto write_term = compute_write_term(in, params); // Degree 1 (2) + const auto write_inverse = inverses * read_term; // Degree 3 (4) + const auto read_inverse = inverses * write_term; // Degree 2 (3) + + // Establish the correctness of the polynomial of inverses I. Note: inverses is computed so that the value is 0 + // if !inverse_exists. + // Degrees: 2 (3) 1 (2) 1 1 + std::get<0>(accumulator) += (read_term * write_term * inverses - inverse_exists) * scaling_factor; // Deg 4 (6) + + // Establish validity of the read. Note: no scaling factor here since this constraint is 'linearly dependent, + // i.e. enforced across the entire trace, not on a per-row basis. + // Degrees: 1 2 (3) 1 3 (4) + std::get<1>(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Deg 4 (5) + } +}; + +template using LogDerivLookupRelation = Relation>; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp deleted file mode 100644 index 46b70df7cab..00000000000 --- a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once -#include "barretenberg/relations/relation_types.hpp" - -namespace bb { - -/** - * @brief LookupRelationImpl defines the algebra for the lookup polynomial: - * - * ∏ (1 + β) ⋅ (q_lookup*f_k + γ) ⋅ (t_k + βt_{k+1} + γ(1 + β)) - * Z_lookup(g^j) = -------------------------------------------------------------------------- - * ∏ (s_k + βs_{k+1} + γ(1 + β)) - * - * - * The method `compute_numerator_term` computes polynomials f, t and incorporate them into terms that are ultimately - * needed to construct the grand product polynomial Z_lookup(X): Note 1: In the above, 't' is associated with table - * values (and is not to be confused with the quotient polynomial, also refered to as 't' elsewhere). Polynomial 's' is - * the sorted concatenation of the witnesses and the table values. - * - * @tparam FF parametrises the prime field class being used - */ -template class LookupRelationImpl { - public: - using FF = FF_; - - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 6, // grand product construction sub-relation - 3 // left-shiftable polynomial sub-relation - }; - - static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ - 4, // grand product construction sub-relation - 0 // left-shiftable polynomial sub-relation - }; - - /** - * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero - * - */ - template inline static bool skip([[maybe_unused]] const AllEntities& in) - { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/952): figure out why skip condition described in - // issue causes failures in acir tests. - return false; - } - - /** - * @brief Get the grand product polynomial object (either from the proving key or AllEntities depending on context) - * - * @param input - * @return auto& either std::span or Flavor::Polynomial depending on context - */ - inline static auto& get_grand_product_polynomial(auto& input) { return input.z_lookup; } - - /** - * @brief Get the shifted grand product polynomial object (either from the proving key or AllEntities depending on - * context) - * - * @param input - * @return auto& either std::span or Flavor::Polynomial depending on context - */ - inline static auto& get_shifted_grand_product_polynomial(auto& input) { return input.z_lookup_shift; } - - /** - * @brief Compute numerator term of the lookup relation: - * - * N_{index} = (1 + β) ⋅ ∏ (q_lookup*f_k + γ) ⋅ (t_k + βt_{k+1} + γ(1 + β)) - * - * @tparam AccumulatorTypes - * @param in - * @param relation_parameters - * @param index If calling this method over vector inputs, index >= 0 - */ - template - inline static Accumulator compute_grand_product_numerator(const AllEntities& in, const Parameters& params) - { - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& beta = ParameterView(params.beta); - const auto& gamma = ParameterView(params.gamma); - const auto& eta = ParameterView(params.eta); - const auto& eta_two = ParameterView(params.eta_two); - const auto& eta_three = ParameterView(params.eta_three); - - const auto one_plus_beta = beta + FF(1); - const auto gamma_by_one_plus_beta = gamma * one_plus_beta; - - auto w_1 = View(in.w_l); - auto w_2 = View(in.w_r); - auto w_3 = View(in.w_o); - - auto w_1_shift = View(in.w_l_shift); - auto w_2_shift = View(in.w_r_shift); - auto w_3_shift = View(in.w_o_shift); - - auto table_1 = View(in.table_1); - auto table_2 = View(in.table_2); - auto table_3 = View(in.table_3); - auto table_4 = View(in.table_4); - - auto table_1_shift = View(in.table_1_shift); - auto table_2_shift = View(in.table_2_shift); - auto table_3_shift = View(in.table_3_shift); - auto table_4_shift = View(in.table_4_shift); - - auto table_index = View(in.q_o); - auto column_1_step_size = View(in.q_r); - auto column_2_step_size = View(in.q_m); - auto column_3_step_size = View(in.q_c); - auto q_lookup = View(in.q_lookup); - - // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. - // deg 2 or 3 - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - - // t_1 + ηt_2 + η₂t_3 + η₃t_4 - // deg 1 or 2 - auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; - - // t_1_shift + ηt_2_shift + η₂t_3_shift + η₃t_4_shift - // deg 1 or 2 - auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; - - auto tmp = (q_lookup * wire_accum + gamma); // deg 3 or 4 - tmp *= (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 3 - tmp *= one_plus_beta; // deg 0 or 1 - return tmp; // deg 4 or 8 - } - - /** - * @brief Compute denominator term of the lookup relation: - * - * (s_k + βs_{k+1} + γ(1 + β)) - * - * @tparam AccumulatorTypes - * @param in - * @param relation_parameters - * @param index - */ - template - inline static Accumulator compute_grand_product_denominator(const AllEntities& in, const Parameters& params) - { - - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& beta = ParameterView(params.beta); - const auto& gamma = ParameterView(params.gamma); - - const auto one_plus_beta = beta + FF(1); - const auto gamma_by_one_plus_beta = gamma * one_plus_beta; // deg 0 or 2 - - // Contribution (1) - auto s_accum = View(in.sorted_accum); - auto s_accum_shift = View(in.sorted_accum_shift); - - auto tmp = (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 2 - return tmp; - } - - /** - * @brief Compute contribution of the lookup grand prod relation for a given edge (internal function) - * - * @details This the relation confirms faithful calculation of the lookup grand - * product polynomial Z_lookup. The contribution is - * z_lookup * (1 + β) * [q_lookup * f + γ] * (t_accum_k + βt_accum_{k+1} + γ(1 + β)) - - * z_lookup_shift * (s_accum_k + βs_accum_{k+1} + γ(1 + β)) - * where - * f = (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index, - * t_accum = table_1 + ηtable_2 + η²table_3 + η³table_4, and - * s_accum = s_1 + ηs_2 + η²s_3 + η³s_4. - * Note: Selectors q_2, q_m and q_c are repurposed as 'column step size' for lookup gates. - * - * @param evals transformed to `evals + C(in(X)...)*scaling_factor` - * @param in an std::array containing the fully extended Univariate edges. - * @param parameters contains beta, gamma, and public_input_delta, .... - * @param scaling_factor optional term to scale the evaluation before adding to evals. - */ - template - inline static void accumulate(ContainerOverSubrelations& accumulators, - const AllEntities& in, - const Parameters& params, - const FF& scaling_factor) - { - BB_OP_COUNT_TIME_NAME("Lookup::accumulate"); - { - using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& grand_product_delta = ParameterView(params.lookup_grand_product_delta); - - auto z_lookup = View(in.z_lookup); - auto z_lookup_shift = View(in.z_lookup_shift); - - auto lagrange_first = View(in.lagrange_first); - auto lagrange_last = View(in.lagrange_last); - - const auto lhs = compute_grand_product_numerator(in, params); // deg 4 or 8 - const auto rhs = compute_grand_product_denominator(in, params); // deg 1 or 2 - - // (deg 5 or 9) - (deg 3 or 5) - const auto tmp = - lhs * (z_lookup + lagrange_first) - rhs * (z_lookup_shift + lagrange_last * grand_product_delta); - std::get<0>(accumulators) += tmp * scaling_factor; - }; - - { - using Accumulator = std::tuple_element_t<1, ContainerOverSubrelations>; - using View = typename Accumulator::View; - auto z_lookup_shift = View(in.z_lookup_shift); - auto lagrange_last = View(in.lagrange_last); - - // Contribution (2) - std::get<1>(accumulators) += (lagrange_last * z_lookup_shift) * scaling_factor; - }; - }; -}; - -template using LookupRelation = Relation>; - -} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 0406f82bcef..b40b45da3c6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -16,7 +16,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/poseidon2_external_relation.hpp" #include "barretenberg/relations/poseidon2_internal_relation.hpp" @@ -204,84 +203,6 @@ TEST_F(UltraRelationConsistency, UltraPermutationRelation) run_test(/*random_inputs=*/true); }; -TEST_F(UltraRelationConsistency, LookupRelation) -{ - const auto run_test = [](bool random_inputs) { - using Relation = LookupRelation; - using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; - - const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); - const auto& w_1 = input_elements.w_l; - const auto& w_2 = input_elements.w_r; - const auto& w_3 = input_elements.w_o; - - const auto& w_1_shift = input_elements.w_l_shift; - const auto& w_2_shift = input_elements.w_r_shift; - const auto& w_3_shift = input_elements.w_o_shift; - - const auto& table_1 = input_elements.table_1; - const auto& table_2 = input_elements.table_2; - const auto& table_3 = input_elements.table_3; - const auto& table_4 = input_elements.table_4; - - const auto& table_1_shift = input_elements.table_1_shift; - const auto& table_2_shift = input_elements.table_2_shift; - const auto& table_3_shift = input_elements.table_3_shift; - const auto& table_4_shift = input_elements.table_4_shift; - - const auto& s_accum = input_elements.sorted_accum; - const auto& s_accum_shift = input_elements.sorted_accum_shift; - const auto& z_lookup = input_elements.z_lookup; - const auto& z_lookup_shift = input_elements.z_lookup_shift; - - const auto& table_index = input_elements.q_o; - const auto& column_1_step_size = input_elements.q_r; - const auto& column_2_step_size = input_elements.q_m; - const auto& column_3_step_size = input_elements.q_c; - const auto& q_lookup = input_elements.q_lookup; - - const auto& lagrange_first = input_elements.lagrange_first; - const auto& lagrange_last = input_elements.lagrange_last; - - SumcheckArrayOfValuesOverSubrelations expected_values; - - const auto parameters = RelationParameters::get_random(); - - const auto eta = parameters.eta; - const auto eta_two = parameters.eta_two; - const auto eta_three = parameters.eta_three; - const auto beta = parameters.beta; - const auto gamma = parameters.gamma; - auto grand_product_delta = parameters.lookup_grand_product_delta; - - // Extract the extended edges for manual computation of relation contribution - auto one_plus_beta = FF::one() + beta; - auto gamma_by_one_plus_beta = gamma * one_plus_beta; - - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - - auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; - auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; - - // Contribution 1 - auto contribution_1 = (z_lookup + lagrange_first) * (q_lookup * wire_accum + gamma) * - (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta) * one_plus_beta; - contribution_1 -= (z_lookup_shift + lagrange_last * grand_product_delta) * - (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); - expected_values[0] = contribution_1; - - // Contribution 2 - auto contribution_2 = z_lookup_shift * lagrange_last; - expected_values[1] = contribution_2; - - validate_relation_execution(expected_values, input_elements, parameters); - }; - run_test(/*random_inputs=*/false); - run_test(/*random_inputs=*/true); -}; - TEST_F(UltraRelationConsistency, DeltaRangeConstraintRelation) { const auto run_test = [](bool random_inputs) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index daedb38fd71..0a1b48068bd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -53,17 +53,26 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst domain_separator + "_" + labels.return_data_read_counts); } - // Get challenge for sorted list batching and wire four memory records commitment + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "_eta", domain_separator + "_eta_two", domain_separator + "_eta_three"); - witness_commitments.sorted_accum = - transcript->template receive_from_prover(domain_separator + "_" + labels.sorted_accum); + + // Receive commitments to lookup argument polynomials + witness_commitments.lookup_read_counts = + transcript->template receive_from_prover(domain_separator + "_" + labels.lookup_read_counts); + witness_commitments.lookup_read_tags = + transcript->template receive_from_prover(domain_separator + "_" + labels.lookup_read_tags); + + // Receive commitments to wire 4 witness_commitments.w_4 = transcript->template receive_from_prover(domain_separator + "_" + labels.w_4); // Get permutation challenges and commitment to permutation and lookup grand products auto [beta, gamma] = transcript->template get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); + witness_commitments.lookup_inverses = transcript->template receive_from_prover( + domain_separator + "_" + commitment_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial if constexpr (IsGoblinFlavor) { witness_commitments.calldata_inverses = transcript->template receive_from_prover( @@ -74,8 +83,6 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst witness_commitments.z_perm = transcript->template receive_from_prover(domain_separator + "_" + labels.z_perm); - witness_commitments.z_lookup = - transcript->template receive_from_prover(domain_separator + "_" + labels.z_lookup); // Compute correction terms for grand products const FF public_input_delta = diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp index a0cc18d3141..f609464efec 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp @@ -91,19 +91,25 @@ std::array UltraRecursiveVerifier_::ve transcript->template receive_from_prover(commitment_labels.return_data_read_counts); } - // Get challenge for sorted list batching and wire four memory records + // Get eta challenges; used in RAM/ROM memory records and log derivative lookup argument auto [eta, eta_two, eta_three] = transcript->template get_challenges("eta", "eta_two", "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - // Get commitments to sorted list accumulator and fourth wire - commitments.sorted_accum = transcript->template receive_from_prover(commitment_labels.sorted_accum); + // Get commitments to lookup argument polynomials and fourth wire + commitments.lookup_read_counts = + transcript->template receive_from_prover(commitment_labels.lookup_read_counts); + commitments.lookup_read_tags = + transcript->template receive_from_prover(commitment_labels.lookup_read_tags); commitments.w_4 = transcript->template receive_from_prover(commitment_labels.w_4); // Get permutation challenges auto [beta, gamma] = transcript->template get_challenges("beta", "gamma"); + commitments.lookup_inverses = + transcript->template receive_from_prover(commitment_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial if constexpr (IsGoblinFlavor) { commitments.calldata_inverses = @@ -123,7 +129,6 @@ std::array UltraRecursiveVerifier_::ve // Get commitment to permutation and lookup grand products commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); - commitments.z_lookup = transcript->template receive_from_prover(commitment_labels.z_lookup); // Execute Sumcheck Verifier and extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported // multivariate evaluations at u diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp index f8658a39fe3..605b44b702f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp @@ -227,7 +227,7 @@ template class RecursiveVerifierTest : public testing // Arbitrarily tamper with the proof to be verified inner_prover.transcript->deserialize_full_transcript(); - inner_prover.transcript->sorted_accum_comm = InnerCommitment::one() * InnerFF::random_element(); + inner_prover.transcript->z_perm_comm = InnerCommitment::one() * InnerFF::random_element(); inner_prover.transcript->serialize_full_transcript(); inner_proof = inner_prover.export_proof(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp index 9ab7c789f67..0bf80a8db8c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp @@ -146,134 +146,6 @@ template class GrandProductTests : public testing::Test { // Check consistency between locally computed z_perm and the one computed by the prover library EXPECT_EQ(prover_polynomials.z_perm, z_permutation_expected); }; - - /** - * @brief Check consistency of the computation of the lookup grand product polynomial z_lookup. - * @details This test compares a simple, unoptimized, easily readable calculation of the grand product z_lookup - * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization - * introduced into the calculation has not changed the result. - * @note This test does confirm the correctness of z_lookup, only that the two implementations yield an - * identical result. - */ - static void test_lookup_grand_product_construction() - { - using Flavor = UltraFlavor; - using ProverPolynomials = typename Flavor::ProverPolynomials; - - // Set a mock circuit size - static const size_t circuit_size = 8; - - // Construct a ProverPolynomials object with completely random polynomials - ProverPolynomials prover_polynomials; - for (auto& poly : prover_polynomials.get_unshifted()) { - poly = get_random_polynomial(circuit_size); - poly[0] = 0; // for shiftability - } - prover_polynomials.set_shifted(); - - // Get random challenges - auto beta = FF::random_element(); - auto gamma = FF::random_element(); - auto eta = FF::random_element(); - auto eta_two = FF::random_element(); - auto eta_three = FF::random_element(); - - RelationParameters params{ - .eta = eta, - .eta_two = eta_two, - .eta_three = eta_three, - .beta = beta, - .gamma = gamma, - .public_input_delta = 1, - .lookup_grand_product_delta = 1, - }; - - // Method 1: Compute z_lookup using the prover library method - constexpr size_t LOOKUP_RELATION_INDEX = 1; - using LHS = typename std::tuple_element::type; - using RHS = LookupRelation; - static_assert(std::same_as); - compute_grand_product(prover_polynomials, params); - - // Method 2: Compute the lookup grand product polynomial Z_lookup: - // - // ∏(1 + β) ⋅ ∏(q_lookup*f_k + γ) ⋅ ∏(t_k + βt_{k+1} + γ(1 + β)) - // Z_lookup(X_j) = ----------------------------------------------------------------- - // ∏(s_k + βs_{k+1} + γ(1 + β)) - // - // in a way that is simple to read (but inefficient). See prover library method for more details. - - std::array accumulators; - for (size_t i = 0; i < 4; ++i) { - accumulators[i] = Polynomial{ circuit_size }; - } - - // Step (1) - - auto wires = prover_polynomials.get_wires(); - auto tables = prover_polynomials.get_tables(); - auto sorted_batched = prover_polynomials.sorted_accum; - auto column_1_step_size = prover_polynomials.q_r; - auto column_2_step_size = prover_polynomials.q_m; - auto column_3_step_size = prover_polynomials.q_c; - auto lookup_index_selector = prover_polynomials.q_o; - auto lookup_selector = prover_polynomials.q_lookup; - - // Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k - const size_t block_mask = circuit_size - 1; - // Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω) - FF table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_two + tables[3][0] * eta_three; - for (size_t i = 0; i < circuit_size; ++i) { - size_t shift_idx = (i + 1) & block_mask; - - // f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index. - FF f_i = (wires[0][i] + wires[0][shift_idx] * column_1_step_size[i]) + - (wires[1][i] + wires[1][shift_idx] * column_2_step_size[i]) * eta + - (wires[2][i] + wires[2][shift_idx] * column_3_step_size[i]) * eta_two + - eta_three * lookup_index_selector[i]; - - // q_lookup * f + γ - accumulators[0][i] = lookup_selector[i] * f_i + gamma; - - // t = t_1 + ηt_2 + η²t_3 + η³t_4 - FF table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_two * tables[2][shift_idx] + - eta_three * tables[3][shift_idx]; - - // t + βt(Xω) + γ(1 + β) - accumulators[1][i] = table_i + table_i_plus_1 * beta + gamma * (FF::one() + beta); - - // (1 + β) - accumulators[2][i] = FF::one() + beta; - - // s + βs(Xω) + γ(1 + β) - accumulators[3][i] = sorted_batched[i] + beta * sorted_batched[shift_idx] + gamma * (FF::one() + beta); - - // Set t(X_i) for next iteration - table_i = table_i_plus_1; - } - - // Step (2) - for (auto& accum : accumulators) { - for (size_t i = 0; i < circuit_size - 1; ++i) { - accum[i + 1] *= accum[i]; - } - } - - // Step (3) - Polynomial z_lookup_expected(circuit_size); - z_lookup_expected[0] = FF::zero(); // Z_lookup_0 = 0 - - // Compute the numerator in accumulators[0]; The denominator is in accumulators[3] - for (size_t i = 0; i < circuit_size - 1; ++i) { - accumulators[0][i] *= accumulators[1][i] * accumulators[2][i]; - } - // Compute Z_lookup_i, i = [1, n-1] - for (size_t i = 0; i < circuit_size - 1; ++i) { - z_lookup_expected[i + 1] = accumulators[0][i] / accumulators[3][i]; - } - - EXPECT_EQ(prover_polynomials.z_lookup, z_lookup_expected); - }; }; using FieldTypes = testing::Types; @@ -283,8 +155,3 @@ TYPED_TEST(GrandProductTests, GrandProductPermutation) { TestFixture::template test_permutation_grand_product_construction(); } - -TYPED_TEST(GrandProductTests, GrandProductLookup) -{ - TestFixture::test_lookup_grand_product_construction(); -} diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 267c8643f4f..45467f78325 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -13,7 +13,7 @@ #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/ecc_op_queue_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/poseidon2_external_relation.hpp" #include "barretenberg/relations/poseidon2_internal_relation.hpp" @@ -39,24 +39,23 @@ class MegaFlavor { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. - // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 58; + static constexpr size_t NUM_ALL_ENTITIES = 57; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 30; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 17; + static constexpr size_t NUM_WITNESS_ENTITIES = 18; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; - using GrandProductRelations = std::tuple, bb::LookupRelation>; + using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. template using Relations_ = std::tuple, bb::UltraPermutationRelation, - bb::LookupRelation, + bb::LogDerivLookupRelation, bb::DeltaRangeConstraintRelation, bb::EllipticRelation, bb::AuxiliaryRelation, @@ -66,8 +65,6 @@ class MegaFlavor { bb::Poseidon2InternalRelation>; using Relations = Relations_; - using LogDerivLookupRelation = bb::DatabusLookupRelation; - static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); @@ -179,19 +176,20 @@ class MegaFlavor { template class DerivedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - sorted_accum, // column 4 - z_perm, // column 5 - z_lookup, // column 6 - ecc_op_wire_1, // column 7 - ecc_op_wire_2, // column 8 - ecc_op_wire_3, // column 9 - ecc_op_wire_4, // column 10 - calldata, // column 11 - calldata_read_counts, // column 12 - calldata_inverses, // column 13 - return_data, // column 14 - return_data_read_counts, // column 15 - return_data_inverses); // column 16 + z_perm, // column 4 + lookup_inverses, // column 5 + lookup_read_counts, // column 6 + lookup_read_tags, // column 7 + ecc_op_wire_1, // column 8 + ecc_op_wire_2, // column 9 + ecc_op_wire_3, // column 10 + ecc_op_wire_4, // column 11 + calldata, // column 12 + calldata_read_counts, // column 13 + calldata_inverses, // column 14 + return_data, // column 15 + return_data_read_counts, // column 16 + return_data_inverses); // column 17 }; /** @@ -214,9 +212,10 @@ class MegaFlavor { this->w_r, this->w_o, this->w_4, - this->sorted_accum, this->z_perm, - this->z_lookup, + this->lookup_inverses, + this->lookup_read_counts, + this->lookup_read_tags, this->ecc_op_wire_1, this->ecc_op_wire_2, this->ecc_op_wire_3, @@ -232,18 +231,15 @@ class MegaFlavor { template class ShiftedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - table_1_shift, // column 0 - table_2_shift, // column 1 - table_3_shift, // column 2 - table_4_shift, // column 3 - w_l_shift, // column 4 - w_r_shift, // column 5 - w_o_shift, // column 6 - w_4_shift, // column 7 - sorted_accum_shift, // column 8 - z_perm_shift, // column 9 - z_lookup_shift // column 10 - ) + table_1_shift, // column 0 + table_2_shift, // column 1 + table_3_shift, // column 2 + table_4_shift, // column 3 + w_l_shift, // column 4 + w_r_shift, // column 5 + w_o_shift, // column 6 + w_4_shift, // column 7 + z_perm_shift) // column 8 }; public: @@ -281,8 +277,8 @@ class MegaFlavor { auto get_witness() { return WitnessEntities::get_all(); }; auto get_to_be_shifted() { - return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, - this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; + return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, + this->w_r, this->w_o, this->w_4, this->z_perm }; }; auto get_precomputed() { return PrecomputedEntities::get_all(); } auto get_shifted() { return ShiftedEntities::get_all(); }; @@ -351,44 +347,8 @@ class MegaFlavor { std::vector memory_read_records; std::vector memory_write_records; - std::array sorted_polynomials; ProverPolynomials polynomials; // storage for all polynomials evaluated by the prover - void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) - { - // Compute sorted witness-table accumulator - compute_sorted_list_accumulator(eta, eta_two, eta_three); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); - } - - /** - * @brief Construct sorted list accumulator polynomial 's'. - * - * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the - * sorted concatenated witness/table polynomials - * - * @param key proving key - * @param sorted_list_polynomials sorted concatenated witness/table polynomials - * @param eta random challenge - * @return Polynomial - */ - void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) - { - - auto& sorted_list_accumulator = polynomials.sorted_accum; - - // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < this->circuit_size; ++i) { - FF T0 = sorted_polynomials[3][i] * eta_three; - T0 += sorted_polynomials[2][i] * eta_two; - T0 += sorted_polynomials[1][i] * eta; - T0 += sorted_polynomials[0][i]; - sorted_list_accumulator[i] = T0; - } - } - /** * @brief Add plookup memory records to the fourth wire polynomial * @@ -398,7 +358,7 @@ class MegaFlavor { * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) + void add_ram_rom_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; @@ -422,14 +382,18 @@ class MegaFlavor { } /** - * @brief Compute the inverse polynomial used in the databus log derivative lookup argument + * @brief Compute the inverse polynomials used in the log derivative lookup relations * * @tparam Flavor * @param beta * @param gamma */ - void compute_logderivative_inverse(const RelationParameters& relation_parameters) + void compute_logderivative_inverses(const RelationParameters& relation_parameters) { + // Compute inverses for conventional lookups + compute_logderivative_inverse>( + this->polynomials, relation_parameters, this->circuit_size); + // Compute inverses for calldata reads DatabusLookupRelation::compute_logderivative_inverse( this->polynomials, relation_parameters, this->circuit_size); @@ -440,7 +404,7 @@ class MegaFlavor { } /** - * @brief Computes public_input_delta, lookup_grand_product_delta, the z_perm and z_lookup polynomials + * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters */ @@ -677,8 +641,9 @@ class MegaFlavor { w_o = "W_O"; w_4 = "W_4"; z_perm = "Z_PERM"; - z_lookup = "Z_LOOKUP"; - sorted_accum = "SORTED_ACCUM"; + lookup_inverses = "LOOKUP_INVERSES"; + lookup_read_counts = "LOOKUP_READ_COUNTS"; + lookup_read_tags = "LOOKUP_READ_TAGS"; ecc_op_wire_1 = "ECC_OP_WIRE_1"; ecc_op_wire_2 = "ECC_OP_WIRE_2"; ecc_op_wire_3 = "ECC_OP_WIRE_3"; @@ -768,9 +733,10 @@ class MegaFlavor { this->w_r = commitments.w_r; this->w_o = commitments.w_o; this->w_4 = commitments.w_4; - this->sorted_accum = commitments.sorted_accum; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->ecc_op_wire_1 = commitments.ecc_op_wire_1; this->ecc_op_wire_2 = commitments.ecc_op_wire_2; this->ecc_op_wire_3 = commitments.ecc_op_wire_3; @@ -811,10 +777,11 @@ class MegaFlavor { Commitment return_data_comm; Commitment return_data_read_counts_comm; Commitment return_data_inverses_comm; - Commitment sorted_accum_comm; Commitment w_4_comm; Commitment z_perm_comm; - Commitment z_lookup_comm; + Commitment lookup_inverses_comm; + Commitment lookup_read_counts_comm; + Commitment lookup_read_tags_comm; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; std::vector zm_cq_comms; @@ -867,10 +834,11 @@ class MegaFlavor { return_data_comm = deserialize_from_buffer(proof_data, num_frs_read); return_data_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); return_data_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); - sorted_accum_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_tags_comm = deserialize_from_buffer(proof_data, num_frs_read); w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - z_lookup_comm = deserialize_from_buffer(proof_data, num_frs_read); for (size_t i = 0; i < log_n; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, @@ -908,10 +876,11 @@ class MegaFlavor { serialize_to_buffer(return_data_comm, proof_data); serialize_to_buffer(return_data_read_counts_comm, proof_data); serialize_to_buffer(return_data_inverses_comm, proof_data); - serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(lookup_read_counts_comm, proof_data); + serialize_to_buffer(lookup_read_tags_comm, proof_data); serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - serialize_to_buffer(z_lookup_comm, proof_data); for (size_t i = 0; i < log_n; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 5d5b3c03953..0682a8a44ab 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -58,6 +58,35 @@ class MockCircuits { } } + /** + * @brief Add lookup gates using the uint32 XOR lookup table (table size 4096) + * @brief Each iteration adds 6 lookup gates and results in a minimum circuit size of 4096 + * + * @param builder + * @param num_gates + */ + template static void add_lookup_gates(Builder& builder, size_t num_iterations = 1) + { + auto UINT32_XOR = plookup::MultiTableId::UINT32_XOR; + + // Each iteration adds 6 lookup gates (due to six 6-bit limbs); the first adds a table of size 4096 + for (size_t i = 0; i < num_iterations; ++i) { + // define some arbitrary inputs to uint32 XOR + uint32_t left_value = engine.get_random_uint32(); + uint32_t right_value = engine.get_random_uint32(); + + fr left = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); + fr right = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); + + auto left_idx = builder.add_variable(left); + auto right_idx = builder.add_variable(right); + + // perform lookups from the uint32 XOR table + auto accumulators = plookup::get_lookup_accumulators(UINT32_XOR, left, right, /*is_2_to_1_lookup*/ true); + builder.create_gates_from_plookup_accumulators(UINT32_XOR, accumulators, left_idx, right_idx); + } + } + /** * @brief Populate a builder with a specified number of arithmetic gates; includes a PI * diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp index b897fc8c309..0440eb17b9c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp @@ -143,14 +143,14 @@ const MultiTable& get_multitable(const MultiTableId id) /** * @brief Given a table ID and the key(s) for a key-value lookup, return the lookup accumulators - * @details In general the number of bits in key/value is greater than what can be efficiently supported in lookup - * tables. For this reason we actually perform lookups on the corresponding limbs. However, since we're interested in - * the full values and not the limbs, its convenient to structure the witnesses of lookup gates to store the former. - * This way we don't have to waste gates reaccumulating the limbs to compute the actual value of interest. The way to do - * this is to populate the wires with 'accumulator' values such that the first gate in the series contains the full - * accumulated values, and successive gates contain prior stages of the accumulator such that wire_i - r*wire_{i-1} = - * v_i, where r = num limb bits and v_i is a limb that explicitly appears in one of the lookup tables. See the detailed - * comment block below for more explanation. + * @details In general the number of bits in original key/value is greater than what can be efficiently supported in + * lookup tables. For this reason we actually perform lookups on the corresponding limbs. However, since we're + * interested in the original values and not the limbs, its convenient to structure the witnesses of lookup gates to + * store the former. This way we don't have to waste gates reaccumulating the limbs to compute the actual value of + * interest. The way to do this is to populate the wires with 'accumulator' values such that the first gate in the + * series contains the full accumulated values, and successive gates contain prior stages of the accumulator such that + * wire_i - r*wire_{i-1} = v_i, where r = num limb bits and v_i is a limb that explicitly appears in one of the lookup + * tables. See the detailed comment block below for more explanation. * * @param id * @param key_a @@ -176,7 +176,7 @@ ReadData get_lookup_accumulators(const MultiTableId id, std::vector column_3_raw_values; for (size_t i = 0; i < num_lookups; ++i) { - // compute the value(s) corresponding to the key(s) using on the i-th basic table query function + // compute the value(s) corresponding to the key(s) using the i-th basic table query function const auto values = multi_table.get_table_values[i]({ key_a_slices[i], key_b_slices[i] }); // store all query data in raw columns and key entry column_1_raw_values.emplace_back(key_a_slices[i]); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp index c41d4e94670..259082820eb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp @@ -122,8 +122,8 @@ enum MultiTableId { }; /** - * @brief Container for managing multiple BasicTables plus the data needed to combine basic table outputs (limbs) into - * accumulators. Does not store actual raw table data. + * @brief Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e.g. limbs) + * into accumulators. Does not store actual raw table data. * @details As a simple example, consider using lookups to compute XOR on uint32_t inputs. To do this we decompose the * inputs into 6 limbs and use a BasicTable for 6-bit XOR lookups. In this case the MultiTable simply manages 6 basic * tables, all of which are the XOR BasicTable. (In many cases all of the BasicTables managed by a MultiTable are @@ -213,7 +213,7 @@ struct MultiTable { // std::array value{ bb::fr(0), bb::fr(0) }; // bool operator<(const KeyEntry& other) const { return key < other.key; } -// std::array to_sorted_list_components(const bool use_two_keys) const +// std::array to_table_components(const bool use_two_keys) const // { // return { // key[0], @@ -248,7 +248,7 @@ struct MultiTable { // return (key.from_montgomery_form() < other.key.from_montgomery_form()); // } -// std::array to_sorted_list_components() const { return { key, values[0], values[0] }; } +// std::array to_table_components() const { return { key, values[0], values[0] }; } // } // BasicTableId id; @@ -268,6 +268,66 @@ struct MultiTable { // } +/** + * @brief A map from 'entry' to 'index' where entry is a row in a BasicTable and index is the row at which that entry + * exists in the table + * @details Such a map is needed to in order to construct read_counts (the polynomial containing the number of reads + * from each entry in a table) for the log-derivative lookup argument. A BasicTable essentially consists of 3 columns, + * and 'lookups' are recorded as rows in this table. The index at which this data exists in the table is not explicitly + * known at the time of lookup gate creation. This map can be used to construct read counts from the set of lookups that + * have been performed via an operation like read_counts[index_map[lookup_data]]++ + * + */ +struct LookupHashTable { + using FF = bb::fr; + using Key = std::array; // an entry in a lookup table + using Value = size_t; // the index of an entry in a lookup table + + // Define a simple hash on three field elements + struct HashFunction { + FF mult_const; + FF const_sqr; + + HashFunction() + : mult_const(FF(uint256_t(0x1337, 0x1336, 0x1335, 0x1334))) + , const_sqr(mult_const.sqr()) + {} + + size_t operator()(const Key& entry) const + { + FF result = entry[0] + mult_const * entry[1] + const_sqr * entry[2]; + return static_cast(result.reduce_once().data[0]); + } + }; + + std::unordered_map index_map; + + LookupHashTable() = default; + + // Initialize the entry-index map with the columns of a table + void initialize(std::vector& column_1, std::vector& column_2, std::vector& column_3) + { + for (size_t i = 0; i < column_1.size(); ++i) { + index_map[{ column_1[i], column_2[i], column_3[i] }] = i; + } + } + + // Given an entry in the table, return its index in the table + Value operator[](const Key& key) const + { + auto it = index_map.find(key); + if (it != index_map.end()) { + return it->second; + } else { + info("LookupHashTable: Key not found!"); + ASSERT(false); + return 0; + } + } + + bool operator==(const LookupHashTable& other) const = default; +}; + /** * @brief A basic table from which we can perform lookups (for example, an xor table) * @details Also stores the lookup gate data for all lookups performed on this table @@ -289,7 +349,8 @@ struct BasicTable { return key[0] < other.key[0] || ((key[0] == other.key[0]) && key[1] < other.key[1]); } - std::array to_sorted_list_components(const bool use_two_keys) const + // Express the key-value pair as the entries of a 3-column row in a table + std::array to_table_components(const bool use_two_keys) const { return { bb::fr(key[0]), @@ -313,6 +374,11 @@ struct BasicTable { std::vector column_3; std::vector lookup_gates; // wire data for all lookup gates created for lookups on this table + // Map from a table entry to its index in the table; used for constructing read counts + LookupHashTable index_map; + + void initialize_index_map() { index_map.initialize(column_1, column_2, column_3); } + std::array (*get_values_from_key)(const std::array); bool operator==(const BasicTable& other) const = default; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 4671a3cb58d..6ca68d7037e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -12,7 +12,7 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" @@ -36,23 +36,22 @@ class UltraFlavor { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. - // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 43; + static constexpr size_t NUM_ALL_ENTITIES = 42; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 7; + static constexpr size_t NUM_WITNESS_ENTITIES = 8; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; - using GrandProductRelations = std::tuple, bb::LookupRelation>; + using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. template using Relations_ = std::tuple, bb::UltraPermutationRelation, - bb::LookupRelation, + bb::LogDerivLookupRelation, bb::DeltaRangeConstraintRelation, bb::EllipticRelation, bb::AuxiliaryRelation>; @@ -144,17 +143,18 @@ class UltraFlavor { template class WitnessEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - w_l, // column 0 - w_r, // column 1 - w_o, // column 2 - w_4, // column 3 - sorted_accum, // column 4 - z_perm, // column 5 - z_lookup) // column 6 + w_l, // column 0 + w_r, // column 1 + w_o, // column 2 + w_4, // column 3 + z_perm, // column 4 + lookup_inverses, // column 5 + lookup_read_counts, // column 6 + lookup_read_tags) // column 7 auto get_wires() { return RefArray{ w_l, w_r, w_o, w_4 }; }; - MSGPACK_FIELDS(w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup); + MSGPACK_FIELDS(w_l, w_r, w_o, w_4, z_perm, lookup_inverses, lookup_read_counts, lookup_read_tags); }; /** @@ -163,22 +163,20 @@ class UltraFlavor { template class ShiftedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - table_1_shift, // column 0 - table_2_shift, // column 1 - table_3_shift, // column 2 - table_4_shift, // column 3 - w_l_shift, // column 4 - w_r_shift, // column 5 - w_o_shift, // column 6 - w_4_shift, // column 7 - sorted_accum_shift, // column 8 - z_perm_shift, // column 9 - z_lookup_shift) // column 10 + table_1_shift, // column 0 + table_2_shift, // column 1 + table_3_shift, // column 2 + table_4_shift, // column 3 + w_l_shift, // column 4 + w_r_shift, // column 5 + w_o_shift, // column 6 + w_4_shift, // column 7 + z_perm_shift) // column 10 auto get_shifted() { - return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift, - w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift }; + return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, + w_r_shift, w_o_shift, w_4_shift, z_perm_shift }; }; }; @@ -213,8 +211,8 @@ class UltraFlavor { auto get_witness() { return WitnessEntities::get_all(); }; auto get_to_be_shifted() { - return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, - this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; + return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, + this->w_r, this->w_o, this->w_4, this->z_perm }; }; auto get_shifted() { return ShiftedEntities::get_all(); }; }; @@ -239,7 +237,8 @@ class UltraFlavor { // Define all operations as default, except copy construction/assignment ProverPolynomials() = default; ProverPolynomials(size_t circuit_size) - { // Initialize all unshifted polynomials to the zero polynomial and initialize the shifted polys + { // Initialize all unshifted polynomials to the zero polynomial and initialize the + // shifted polys for (auto& poly : get_unshifted()) { poly = Polynomial{ circuit_size }; } @@ -284,57 +283,22 @@ class UltraFlavor { std::vector memory_read_records; std::vector memory_write_records; - std::array sorted_polynomials; ProverPolynomials polynomials; // storage for all polynomials evaluated by the prover - void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) - { - // Compute sorted witness-table accumulator - compute_sorted_list_accumulator(eta, eta_two, eta_three); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); - } - /** - * @brief Construct sorted list accumulator polynomial 's'. + * @brief Add RAM/ROM memory records to the fourth wire polynomial * - * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the - * sorted concatenated witness/table polynomials - * - * @param key proving key - * @param sorted_list_polynomials sorted concatenated witness/table polynomials - * @param eta random challenge - * @return Polynomial - */ - void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) - { - auto& sorted_list_accumulator = polynomials.sorted_accum; - - // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < this->circuit_size; ++i) { - FF T0 = sorted_polynomials[3][i] * eta_three; - T0 += sorted_polynomials[2][i] * eta_two; - T0 += sorted_polynomials[1][i] * eta; - T0 += sorted_polynomials[0][i]; - sorted_list_accumulator[i] = T0; - } - } - - /** - * @brief Add plookup memory records to the fourth wire polynomial - * - * @details This operation must be performed after the first three wires have been committed to, hence the - * dependence on the `eta` challenge. + * @details This operation must be performed after the first three wires have been + * committed to, hence the dependence on the `eta` challenge. * * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) + void add_ram_rom_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { - // The plookup memory record values are computed at the indicated indices as + // The memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; - // (See plookup_auxiliary_widget.hpp for details) + // (See the Auxiliary relation for details) auto wires = polynomials.get_wires(); // Compute read record values @@ -354,7 +318,21 @@ class UltraFlavor { } /** - * @brief Computes public_input_delta, lookup_grand_product_delta, the z_perm and z_lookup polynomials + * @brief Compute the inverse polynomial used in the log derivative lookup argument + * + * @tparam Flavor + * @param beta + * @param gamma + */ + void compute_logderivative_inverses(const RelationParameters& relation_parameters) + { + // Compute inverses for conventional lookups + compute_logderivative_inverse>( + this->polynomials, relation_parameters, this->circuit_size); + } + + /** + * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters */ @@ -402,7 +380,8 @@ class UltraFlavor { commitment = proving_key.commitment_key->commit(polynomial); } } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate up. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate + // up. VerificationKey(const uint64_t circuit_size, const uint64_t num_public_inputs, const uint64_t pub_inputs_offset, @@ -529,7 +508,8 @@ class UltraFlavor { PartiallyEvaluatedMultivariates() = default; PartiallyEvaluatedMultivariates(const size_t circuit_size) { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + // Storage is only needed after the first partial evaluation, hence polynomials of + // size (n / 2) for (auto& poly : this->get_all()) { poly = Polynomial(circuit_size / 2); } @@ -573,8 +553,9 @@ class UltraFlavor { w_o = "W_O"; w_4 = "W_4"; z_perm = "Z_PERM"; - z_lookup = "Z_LOOKUP"; - sorted_accum = "SORTED_ACCUM"; + lookup_inverses = "LOOKUP_INVERSES"; + lookup_read_counts = "LOOKUP_READ_COUNTS"; + lookup_read_tags = "LOOKUP_READ_TAGS"; q_c = "Q_C"; q_l = "Q_L"; @@ -646,10 +627,11 @@ class UltraFlavor { this->w_l = commitments.w_l; this->w_r = commitments.w_r; this->w_o = commitments.w_o; - this->sorted_accum = commitments.sorted_accum; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->w_4 = commitments.w_4; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; } } }; @@ -670,10 +652,11 @@ class UltraFlavor { Commitment w_l_comm; Commitment w_r_comm; Commitment w_o_comm; - Commitment sorted_accum_comm; + Commitment lookup_read_counts_comm; + Commitment lookup_read_tags_comm; Commitment w_4_comm; Commitment z_perm_comm; - Commitment z_lookup_comm; + Commitment lookup_inverses_comm; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; std::vector zm_cq_comms; @@ -703,8 +686,9 @@ class UltraFlavor { }; /** - * @brief Takes a FULL Ultra proof and deserializes it into the public member variables that compose the - * structure. Must be called in order to access the structure of the proof. + * @brief Takes a FULL Ultra proof and deserializes it into the public member variables + * that compose the structure. Must be called in order to access the structure of the + * proof. * */ void deserialize_full_transcript() @@ -722,10 +706,11 @@ class UltraFlavor { w_l_comm = deserialize_from_buffer(proof_data, num_frs_read); w_r_comm = deserialize_from_buffer(proof_data, num_frs_read); w_o_comm = deserialize_from_buffer(proof_data, num_frs_read); - sorted_accum_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_tags_comm = deserialize_from_buffer(proof_data, num_frs_read); w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - z_lookup_comm = deserialize_from_buffer(proof_data, num_frs_read); for (size_t i = 0; i < log_n; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, @@ -739,8 +724,9 @@ class UltraFlavor { kzg_w_comm = deserialize_from_buffer(proof_data, num_frs_read); } /** - * @brief Serializes the structure variables into a FULL Ultra proof. Should be called only if - * deserialize_full_transcript() was called and some transcript variable was modified. + * @brief Serializes the structure variables into a FULL Ultra proof. Should be called + * only if deserialize_full_transcript() was called and some transcript variable was + * modified. * */ void serialize_full_transcript() @@ -757,10 +743,11 @@ class UltraFlavor { serialize_to_buffer(w_l_comm, proof_data); serialize_to_buffer(w_r_comm, proof_data); serialize_to_buffer(w_o_comm, proof_data); - serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(lookup_read_counts_comm, proof_data); + serialize_to_buffer(lookup_read_tags_comm, proof_data); serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - serialize_to_buffer(z_lookup_comm, proof_data); for (size_t i = 0; i < log_n; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index a73509fe018..195097c2c7f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -11,7 +11,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" @@ -63,12 +62,12 @@ template class UltraRecursiveFlavor_ { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 43; + static constexpr size_t NUM_ALL_ENTITIES = UltraFlavor::NUM_ALL_ENTITIES; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = UltraFlavor::NUM_PRECOMPUTED_ENTITIES; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 7; + static constexpr size_t NUM_WITNESS_ENTITIES = UltraFlavor::NUM_WITNESS_ENTITIES; // define the tuple of Relations that comprise the Sumcheck relation using Relations = UltraFlavor::Relations_; @@ -238,10 +237,11 @@ template class UltraRecursiveFlavor_ { this->w_l = commitments.w_l; this->w_r = commitments.w_r; this->w_o = commitments.w_o; - this->sorted_accum = commitments.sorted_accum; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->w_4 = commitments.w_4; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; } } }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index 3a5de3c3c5e..d3a9d0bf8ee 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -81,7 +81,10 @@ template class ProverInstance_ { construct_lookup_table_polynomials(proving_key.polynomials.get_tables(), circuit, dyadic_circuit_size); - proving_key.sorted_polynomials = construct_sorted_list_polynomials(circuit, dyadic_circuit_size); + construct_lookup_read_counts(proving_key.polynomials.lookup_read_counts, + proving_key.polynomials.lookup_read_tags, + circuit, + dyadic_circuit_size); std::span public_wires_source = proving_key.polynomials.w_r; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp deleted file mode 100644 index 4a8b5d36734..00000000000 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp +++ /dev/null @@ -1,89 +0,0 @@ - -#include "prover_instance.hpp" -#include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/srs/factories/file_crs_factory.hpp" -#include -using namespace bb; - -template class InstanceTests : public testing::Test { - using FF = typename Flavor::FF; - using Polynomial = bb::Polynomial; - using Builder = typename Flavor::CircuitBuilder; - - public: - /** - * @brief Get a random polynomial - * - * @param size - * @return Polynomial - */ - static constexpr Polynomial get_random_polynomial(size_t size) - { - Polynomial random_polynomial{ size }; - for (auto& coeff : random_polynomial) { - coeff = FF::random_element(); - } - return random_polynomial; - } - - static void populate_span(auto& polynomial_view, const auto& polynomial) - { - ASSERT(polynomial_view.size() <= polynomial.size()); - for (size_t idx = 0; idx < polynomial.size(); idx++) { - polynomial_view[idx] = polynomial[idx]; - } - }; - /** - * @brief Check consistency of the computation of the sorted list accumulator - * @details This test compares a simple, unoptimized, easily readable calculation of the sorted list accumulator - * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization - * introduced into the calculation has not changed the result. - * @note This test does confirm the correctness of the sorted list accumulator, only that the two implementations - * yield an identical result. - */ - static void test_sorted_list_accumulator_construction() - { - srs::init_crs_factory("../srs_db/ignition"); - - // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - Builder builder; - - auto a = 2; - builder.add_variable(a); - - builder.add_gates_to_ensure_all_polys_are_non_zero(); - builder.finalize_circuit(); - auto instance = ProverInstance_(builder); - - // Get random challenge eta - auto eta = FF::random_element(); - auto eta_two = FF::random_element(); - auto eta_three = FF::random_element(); - - auto sorted_list_polynomials = instance.proving_key.sorted_polynomials; - - // Method 1: computed sorted list accumulator polynomial using prover library method - instance.proving_key.compute_sorted_list_accumulator(eta, eta_two, eta_three); - auto sorted_list_accumulator = instance.proving_key.polynomials.sorted_accum; - - // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 - Polynomial sorted_list_accumulator_expected{ sorted_list_polynomials[0] }; - for (size_t i = 0; i < instance.proving_key.circuit_size; ++i) { - sorted_list_accumulator_expected[i] += sorted_list_polynomials[1][i] * eta + - sorted_list_polynomials[2][i] * eta_two + - sorted_list_polynomials[3][i] * eta_three; - } - - EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); - }; -}; - -using FlavorTypes = testing::Types; -TYPED_TEST_SUITE(InstanceTests, FlavorTypes); - -TYPED_TEST(InstanceTests, SortedListAccumulator) -{ - TestFixture::test_sorted_list_accumulator_construction(); -} diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 05c0938fa10..bfc9b0facac 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -3,7 +3,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index 4b9f122c966..8dfc816e01a 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -65,15 +65,16 @@ class MegaTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; - manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_TAGS", frs_per_G); manifest_expected.add_entry(round, "W_4", frs_per_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; + manifest_expected.add_entry(round, "LOOKUP_INVERSES", frs_per_G); manifest_expected.add_entry(round, "CALLDATA_INVERSES", frs_per_G); manifest_expected.add_entry(round, "RETURN_DATA_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); - manifest_expected.add_entry(round, "Z_LOOKUP", frs_per_G); for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); @@ -242,7 +243,7 @@ TEST_F(MegaTranscriptTests, StructureTest) Flavor::Commitment one_group_val = Flavor::Commitment::one(); FF rand_val = FF::random_element(); - prover.transcript->sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + prover.transcript->z_perm_comm = one_group_val * rand_val; // choose random object to modify EXPECT_TRUE(verifier.verify_proof( prover.export_proof())); // we have not serialized it back to the proof so it should still be fine @@ -250,5 +251,5 @@ TEST_F(MegaTranscriptTests, StructureTest) EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it prover.transcript->deserialize_full_transcript(); - EXPECT_EQ(static_cast(prover.transcript->sorted_accum_comm), one_group_val * rand_val); + EXPECT_EQ(static_cast(prover.transcript->z_perm_comm), one_group_val * rand_val); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index f0c15496c95..6626b48623f 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -1,4 +1,5 @@ #include "barretenberg/ultra_honk/oink_prover.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" namespace bb { @@ -109,21 +110,25 @@ template void OinkProver::execute_wire_commitment */ template void OinkProver::execute_sorted_list_accumulator_round() { - + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - proving_key.compute_sorted_accumulator_polynomials( + proving_key.add_ram_rom_memory_records_to_wire_4( relation_parameters.eta, relation_parameters.eta_two, relation_parameters.eta_three); - // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire - // polynomial - witness_commitments.sorted_accum = commitment_key->commit(proving_key.polynomials.sorted_accum); + + // Commit to lookup argument polynomials and the finalized (i.e. with memory records) fourth wire polynomial + witness_commitments.lookup_read_counts = commitment_key->commit(proving_key.polynomials.lookup_read_counts); + witness_commitments.lookup_read_tags = commitment_key->commit(proving_key.polynomials.lookup_read_tags); witness_commitments.w_4 = commitment_key->commit(proving_key.polynomials.w_4); - transcript->send_to_verifier(domain_separator + commitment_labels.sorted_accum, witness_commitments.sorted_accum); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_read_counts, + witness_commitments.lookup_read_counts); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_read_tags, + witness_commitments.lookup_read_tags); transcript->send_to_verifier(domain_separator + commitment_labels.w_4, witness_commitments.w_4); } @@ -136,10 +141,16 @@ template void OinkProver::execute_log_derivative_ auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); relation_parameters.beta = beta; relation_parameters.gamma = gamma; - if constexpr (IsGoblinFlavor) { - // Compute and commit to the logderivative inverse used in DataBus - proving_key.compute_logderivative_inverse(relation_parameters); + // Compute the inverses used in log-derivative lookup relations + proving_key.compute_logderivative_inverses(relation_parameters); + + witness_commitments.lookup_inverses = commitment_key->commit(proving_key.polynomials.lookup_inverses); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_inverses, + witness_commitments.lookup_inverses); + + // If Mega, commit to the databus inverse polynomials and send + if constexpr (IsGoblinFlavor) { witness_commitments.calldata_inverses = commitment_key->commit(proving_key.polynomials.calldata_inverses); witness_commitments.return_data_inverses = commitment_key->commit(proving_key.polynomials.return_data_inverses); transcript->send_to_verifier(domain_separator + commitment_labels.calldata_inverses, @@ -158,10 +169,8 @@ template void OinkProver::execute_grand_product_c proving_key.compute_grand_product_polynomials(relation_parameters); witness_commitments.z_perm = commitment_key->commit(proving_key.polynomials.z_perm); - witness_commitments.z_lookup = commitment_key->commit(proving_key.polynomials.z_lookup); transcript->send_to_verifier(domain_separator + commitment_labels.z_perm, witness_commitments.z_perm); - transcript->send_to_verifier(domain_separator + commitment_labels.z_lookup, witness_commitments.z_lookup); } template typename Flavor::RelationSeparator OinkProver::generate_alphas_round() diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 69a2b20a57b..0a5a1810e4c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -87,15 +87,18 @@ template void OinkVerifier::execute_wire_commitme */ template void OinkVerifier::execute_sorted_list_accumulator_round() { - // Get challenge for sorted list batching and wire four memory records + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - // Get commitments to sorted list accumulator and fourth wire - witness_comms.sorted_accum = - transcript->template receive_from_prover(domain_separator + comm_labels.sorted_accum); + + // Get commitments to lookup argument polynomials and fourth wire + witness_comms.lookup_read_counts = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_read_counts); + witness_comms.lookup_read_tags = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_read_tags); witness_comms.w_4 = transcript->template receive_from_prover(domain_separator + comm_labels.w_4); } @@ -109,6 +112,10 @@ template void OinkVerifier::execute_log_derivativ auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); relation_parameters.beta = beta; relation_parameters.gamma = gamma; + + witness_comms.lookup_inverses = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomials if constexpr (IsGoblinFlavor) { witness_comms.calldata_inverses = @@ -137,8 +144,6 @@ template void OinkVerifier::execute_grand_product // Get commitment to permutation and lookup grand products witness_comms.z_perm = transcript->template receive_from_prover(domain_separator + comm_labels.z_perm); - witness_comms.z_lookup = - transcript->template receive_from_prover(domain_separator + comm_labels.z_lookup); } template typename Flavor::RelationSeparator OinkVerifier::generate_alphas_round() diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index b928a0bcd04..cedd1fd4bb2 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -4,7 +4,7 @@ #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/ecc_op_queue_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" @@ -29,9 +29,8 @@ void ensure_non_zero(auto& polynomial) * @brief Check that a given relation is satified for a set of polynomials * * @tparam relation_idx Index into a tuple of provided relations - * @tparam Flavor */ -template void check_relation(auto circuit_size, auto& polynomials, auto params) +template void check_relation(auto circuit_size, auto& polynomials, auto params) { for (size_t i = 0; i < circuit_size; i++) { // Define the appropriate SumcheckArrayOfValuesOverSubrelations type for this relation and initialize to zero @@ -273,9 +272,10 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution @@ -285,18 +285,15 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) ensure_non_zero(proving_key.polynomials.q_elliptic); ensure_non_zero(proving_key.polynomials.q_aux); - // Construct the round for applying sumcheck relations and results for storing computed results - using Relations = typename Flavor::Relations; - auto& prover_polynomials = instance->proving_key.polynomials; auto params = instance->relation_parameters; // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); } TEST_F(UltraRelationCorrectnessTests, Mega) @@ -328,10 +325,10 @@ TEST_F(UltraRelationCorrectnessTests, Mega) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); - instance->proving_key.compute_logderivative_inverse(instance->relation_parameters); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution @@ -351,19 +348,18 @@ TEST_F(UltraRelationCorrectnessTests, Mega) ensure_non_zero(proving_key.polynomials.return_data_read_counts); ensure_non_zero(proving_key.polynomials.return_data_inverses); - // Construct the round for applying sumcheck relations and results for storing computed results - using Relations = typename Flavor::Relations; auto& prover_polynomials = instance->proving_key.polynomials; auto params = instance->relation_parameters; // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_linearly_dependent_relation>( - circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index 5962b8ba212..665538278c1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -5,7 +5,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" @@ -157,9 +156,10 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); auto prover_transcript = Transcript::prover_init_empty(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp similarity index 88% rename from barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp index b04bd0b7fd1..31d0423fd99 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp @@ -48,7 +48,7 @@ void ensure_non_zero(auto& polynomial) ASSERT_TRUE(has_non_zero_coefficient); } -class UltraHonkComposerTests : public ::testing::Test { +class UltraHonkTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; @@ -60,7 +60,7 @@ class UltraHonkComposerTests : public ::testing::Test { * to achieve non-zero polynomials * */ -TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) +TEST_F(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial) { auto circuit_builder = UltraCircuitBuilder(); @@ -86,7 +86,7 @@ TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) * @brief Test proof construction/verification for a structured execution trace * */ -TEST_F(UltraHonkComposerTests, StructuredTrace) +TEST_F(UltraHonkTests, StructuredTrace) { auto builder = UltraCircuitBuilder(); size_t num_gates = 3; @@ -109,7 +109,7 @@ TEST_F(UltraHonkComposerTests, StructuredTrace) * @brief Test simple circuit with public inputs * */ -TEST_F(UltraHonkComposerTests, PublicInputs) +TEST_F(UltraHonkTests, PublicInputs) { auto builder = UltraCircuitBuilder(); size_t num_gates = 10; @@ -120,7 +120,7 @@ TEST_F(UltraHonkComposerTests, PublicInputs) prove_and_verify(builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, XorConstraint) +TEST_F(UltraHonkTests, XorConstraint) { auto circuit_builder = UltraCircuitBuilder(); @@ -147,7 +147,7 @@ TEST_F(UltraHonkComposerTests, XorConstraint) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) +TEST_F(UltraHonkTests, create_gates_from_plookup_accumulators) { auto circuit_builder = UltraCircuitBuilder(); @@ -207,7 +207,91 @@ TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, test_no_lookup_proof) +/** + * @brief Test various failure modes for the lookup relation via bad input polynomials + * + */ +TEST_F(UltraHonkTests, LookupFailure) +{ + // Construct a circuit with lookup and arithmetic gates + auto construct_circuit_with_lookups = []() { + UltraCircuitBuilder builder; + + MockCircuits::add_lookup_gates(builder); + MockCircuits::add_arithmetic_gates(builder); + + return builder; + }; + + auto prove_and_verify = [](auto& instance) { + UltraProver prover(instance); + auto verification_key = std::make_shared(instance->proving_key); + UltraVerifier verifier(verification_key); + auto proof = prover.construct_proof(); + return verifier.verify_proof(proof); + }; + + // Ensure the unaltered test circuit is valid + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + + EXPECT_TRUE(prove_and_verify(instance)); + } + + // Failure mode 1: bad read counts/tags + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Erroneously update the read counts/tags at an arbitrary index + // Note: updating only one or the other may not cause failure due to the design of the relation algebra. For + // example, the inverse is only computed if read tags is non-zero, otherwise the inverse at the row in question + // will be zero. So if read counts is incremented at some arbitrary index but read tags is not, the inverse will + // be 0 and the erroneous read_counts value will get multiplied by 0 in the relation. This is expected behavior. + polynomials.lookup_read_counts[25] = 1; + polynomials.lookup_read_tags[25] = 1; + + EXPECT_FALSE(prove_and_verify(instance)); + } + + // Failure mode 2: bad lookup gate wire value + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Find a lookup gate and alter one of the wire values + for (auto [q_lookup, wire_3] : zip_view(polynomials.q_lookup, polynomials.w_o)) { + if (!q_lookup.is_zero()) { + wire_3 += 1; + break; + } + } + + EXPECT_FALSE(prove_and_verify(instance)); + } + + // Failure mode 3: erroneous lookup gate + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Turn the lookup selector on for an arbitrary row where it is not already active + EXPECT_TRUE(polynomials.q_lookup[25] != 1); + polynomials.q_lookup[25] = 1; + + EXPECT_FALSE(prove_and_verify(instance)); + } +} + +TEST_F(UltraHonkTests, test_no_lookup_proof) { auto circuit_builder = UltraCircuitBuilder(); @@ -229,7 +313,7 @@ TEST_F(UltraHonkComposerTests, test_no_lookup_proof) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, test_elliptic_gate) +TEST_F(UltraHonkTests, test_elliptic_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -262,7 +346,7 @@ TEST_F(UltraHonkComposerTests, test_elliptic_gate) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation) +TEST_F(UltraHonkTests, non_trivial_tag_permutation) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -289,7 +373,7 @@ TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) +TEST_F(UltraHonkTests, non_trivial_tag_permutation_and_cycles) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -326,7 +410,7 @@ TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, bad_tag_permutation) +TEST_F(UltraHonkTests, bad_tag_permutation) { { auto circuit_builder = UltraCircuitBuilder(); @@ -369,7 +453,7 @@ TEST_F(UltraHonkComposerTests, bad_tag_permutation) } } -TEST_F(UltraHonkComposerTests, sort_widget) +TEST_F(UltraHonkTests, sort_widget) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -386,7 +470,7 @@ TEST_F(UltraHonkComposerTests, sort_widget) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, sort_with_edges_gate) +TEST_F(UltraHonkTests, sort_with_edges_gate) { fr a = fr::one(); fr b = fr(2); @@ -476,7 +560,7 @@ TEST_F(UltraHonkComposerTests, sort_with_edges_gate) } } -TEST_F(UltraHonkComposerTests, range_constraint) +TEST_F(UltraHonkTests, range_constraint) { { auto circuit_builder = UltraCircuitBuilder(); @@ -545,7 +629,7 @@ TEST_F(UltraHonkComposerTests, range_constraint) } } -TEST_F(UltraHonkComposerTests, range_with_gates) +TEST_F(UltraHonkTests, range_with_gates) { auto circuit_builder = UltraCircuitBuilder(); auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); @@ -563,7 +647,7 @@ TEST_F(UltraHonkComposerTests, range_with_gates) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, range_with_gates_where_range_is_not_a_power_of_two) +TEST_F(UltraHonkTests, range_with_gates_where_range_is_not_a_power_of_two) { auto circuit_builder = UltraCircuitBuilder(); auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); @@ -581,7 +665,7 @@ TEST_F(UltraHonkComposerTests, range_with_gates_where_range_is_not_a_power_of_tw prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, sort_widget_complex) +TEST_F(UltraHonkTests, sort_widget_complex) { { @@ -607,7 +691,7 @@ TEST_F(UltraHonkComposerTests, sort_widget_complex) } } -TEST_F(UltraHonkComposerTests, sort_widget_neg) +TEST_F(UltraHonkTests, sort_widget_neg) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -624,7 +708,7 @@ TEST_F(UltraHonkComposerTests, sort_widget_neg) prove_and_verify(circuit_builder, /*expected_result=*/false); } -TEST_F(UltraHonkComposerTests, composed_range_constraint) +TEST_F(UltraHonkTests, composed_range_constraint) { auto circuit_builder = UltraCircuitBuilder(); auto c = fr::random_element(); @@ -637,7 +721,7 @@ TEST_F(UltraHonkComposerTests, composed_range_constraint) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_native_field_multiplication) +TEST_F(UltraHonkTests, non_native_field_multiplication) { using fq = fq; auto circuit_builder = UltraCircuitBuilder(); @@ -693,7 +777,7 @@ TEST_F(UltraHonkComposerTests, non_native_field_multiplication) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, rom) +TEST_F(UltraHonkTests, rom) { auto circuit_builder = UltraCircuitBuilder(); @@ -734,7 +818,7 @@ TEST_F(UltraHonkComposerTests, rom) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, ram) +TEST_F(UltraHonkTests, ram) { auto circuit_builder = UltraCircuitBuilder(); @@ -797,7 +881,7 @@ TEST_F(UltraHonkComposerTests, ram) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, range_checks_on_duplicates) +TEST_F(UltraHonkTests, range_checks_on_duplicates) { auto circuit_builder = UltraCircuitBuilder(); @@ -836,7 +920,7 @@ TEST_F(UltraHonkComposerTests, range_checks_on_duplicates) // range constrained, do not break the set equivalence checks because of indices mismatch. // 2^14 is DEFAULT_PLOOKUP_RANGE_BITNUM i.e. the maximum size before a variable gets sliced // before range constraints are applied to it. -TEST_F(UltraHonkComposerTests, range_constraint_small_variable) +TEST_F(UltraHonkTests, range_constraint_small_variable) { auto circuit_builder = UltraCircuitBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index 952894e4a36..df541aeb2df 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -58,13 +58,14 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; - manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_TAGS", frs_per_G); manifest_expected.add_entry(round, "W_4", frs_per_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; + manifest_expected.add_entry(round, "LOOKUP_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); - manifest_expected.add_entry(round, "Z_LOOKUP", frs_per_G); for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); @@ -226,7 +227,7 @@ TEST_F(UltraTranscriptTests, StructureTest) Flavor::Commitment one_group_val = Flavor::Commitment::one(); FF rand_val = FF::random_element(); - prover.transcript->sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + prover.transcript->z_perm_comm = one_group_val * rand_val; // choose random object to modify EXPECT_TRUE(verifier.verify_proof( prover.export_proof())); // we have not serialized it back to the proof so it should still be fine @@ -234,5 +235,5 @@ TEST_F(UltraTranscriptTests, StructureTest) EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it prover.transcript->deserialize_full_transcript(); - EXPECT_EQ(static_cast(prover.transcript->sorted_accum_comm), one_group_val * rand_val); + EXPECT_EQ(static_cast(prover.transcript->z_perm_comm), one_group_val * rand_val); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index df045145c6c..e7abe6553c8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -7,7 +7,6 @@ #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 1ebc77c5a5f..4619fd298dd 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x00000000000000000000000000000044d7ca77b464f03aa44f6f8d49a0d3ada5","0x00000000000000000000000000000000002a36959f550517d82d0af666bcd7dc","0x0000000000000000000000000000000566b28c19f0b1732b95e0381bc5d6dbdd","0x00000000000000000000000000000000002511360b7a8c6a823559f0ac9eb02b","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x00000000000000000000000000000058035b1ed115023f42bf4ee93d2dc29dcb","0x00000000000000000000000000000000002de4b004225be4e68938b0db546287","0x0000000000000000000000000000003d18d72585ef033ab3663d1944abb2054a","0x0000000000000000000000000000000000149a1974c0c2b5f0639970cda1af83","0x000000000000000000000000000000bb1eb2b1fc10b55295ed6c1ae54e8a40da","0x000000000000000000000000000000000026da80059472ac8c64e437d6fe6134","0x000000000000000000000000000000d1f101b72ee710423ca44548910676a4fe","0x00000000000000000000000000000000000323378ad6b5aec67af99e522095a0","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x2622384e4b4688a3ad115007c1c09de1a141aeca06c31925898cf746038a5897","0x2f743e893a3880004db1ff3492279d89c025b9815f16e129d15f7a3687b6f833","0x03e05487307f18e3afb90cc524e56809e478039d317a3757433bfc8e06a32b73","0x099ba7011747dd2d8b5ac03ed02b93c9803d51899677409931d5b1571c3041b5","0x189ef108e334c5173619eac1067b99526a5cc6e47cbffaa3c117f0c3eb8bebd4","0x0b5f77b69ac2955ecc44a73e18b2ea8403224cf769657d53acc9a5d302d0b86e","0x1b81353a160e985e8a1fb09d3a3827fe68d03585757530dcec1b8038ac829a21","0x175e75cef1b974011de38e6e631f42bffd4dcb6fad6680930388cffaa60d940e","0x1631945a2aa39032cfa8cf379d18a983d4b5a487adab67252c6514b35bc88095","0x181b639e465a6f9842c5d75f6f5b855a065f498595146df3bd2b9c0ef66042a1","0x0c6e5af7add3e12f610c13d8066896d08882a7c50cfe33676fda8a75e250e9b9","0x28f94cd060c45a2e6b423831302deb456d0964879db5008a2be0957a2c749e2a","0x1c81fb20cea508580aa962e5b4736a43382816e7abac7e478e6c080cf896798d","0x23dea53784aa14dcf7e1cce5ee480796e67b2dd69a8e20c5c09558001640edfa","0x149c2548f8b0d96fefecab53e31aa3902341c903fa0ef863ef64610315de993b","0x16ad81b3129ccebe1682d14b726bc9b86acd0f0be8c304594ce5a87e756add27","0x2c1ef938516edccc0cd1d4d812644d72b6ead3c85e1c8500fc54e77e5652b23f","0x0eecb7fba3395b21197cb24bb9b733b1985d81f35a1ee944714ffd781a7bd136","0x06e2a96ecf1e8419198eca10133954f3560102467f40a234cf071d23c6cf411a","0x1e6bfa2adcbdc50313408ef28a77b76dd915fa372c093c4484ba662695a3eadc","0x28ccaf4d4759c1f4bb49429b961a59cdefbc445017ffa807e90c54b27e1ee657","0x22803d537311e757a146ae7a2fc396d42d67f27e73efca82e3e324dc493da4de","0x196255f687cede05f326204bfaead7a54f8d48b67ce8522cb8af6a7fffaffcb6","0x147ea42988386b944f006be242ccc6b099fadd7f450955d252768667bbaee4f9","0x1f9ccb05e508b1d08c79c11acbc0677fdc18d5d40827e2e1eaae60fee51b940f","0x28ea76870d22eea72821da25f9b7a89341347afcd6c077387986a82dc8afa833","0x0e6ef82d3e5a318a9c6233dffbb00d130599f4ac979a89b034ce9d930b11165a","0x2e97fa9299a218c982504199ada3278270b9cb566bf46fe1ecc1d151e06b8745","0x1a41ac9b1032ac24c11720407c253a866e9c75a4ec233f15f968b206ea1e5d0e","0x0b31b541bb044c1bc2428c2a57ba29438f620050d1628389ff1fa90c494d7c58","0x050fec8d69f182768a9b34eca8c3f4695dad8bc20a10904090cfe18777d44d25","0x069283ac40daaafff76c3679f54a0aa773c8d71152fbb9c3219906113fc4f683","0x25c3ec4e8b90214aafe3b5416abf11a98bd34b8acb449df8424f159ddf858bc1","0x1a3884f3a922d0da758cb7ed9a5ddc3c3c2132dde8d913753fa3e6b766be5697","0x222d05a0fce0565bf9cc490f97bd4eff53858f2ca6afe9d91c5c8d7de8076f39","0x054698b045b439467a3067a8dc2b4d020b2bb44df3d98a19f9cfb04c9ee5ffd1","0x0e39d66cded0f3df40e04124e36c827bcaf15fbe9fb6e9bbc3af889f8bd1ebf0","0x145aea47dc97ec35ac67f135aac37f8bc6eaf149551a2f48901529d10e25c860","0x1894877b2769ae2c288738f8aa33acfc7ca9a7d1e26a76908ca2909bf25aa59a","0x27e8c702be67be467f052abd180464a468b7d5d5d8a4961e56e8561f7863c91a","0x0326d3e4607d54a30c7fa99d1609f386aeb8c8094cabd7397246074f634dcec8","0x17eb8f62b5ba2dad391e3f81d3a6b9d03ff723a7d6a4d77b98b18ddd0debf4fd","0x1a5d3e8a27c1f69d6e4558b3c89cd9347c62182ce90fb6e34392bc4e7b7c178c","0x2293034bed3d33d5ad0d150f64d493c9be554f640103621f9ae56034a7323d84","0x13d75ffbb9d2ceb2daa6d42f3618d4ea9775befa1cf5f9df141dfebf794abc35","0x2ec339c42fbb2d50221ec907779e72be3eab2960d110a90d36cc6c0afcf5857e","0x15e9c913fa84a2657571831d5d7a90f6534ca67a1617b4063fa5bf09f46cd7a2","0x10f56fbe9fefd59d2acd49fa641fedcfb65d96d54cf47207e2c8ab34f22bbabe","0x117fa3859a400040ebe8dee4a60ddcb04484ff5cfb5294c6530354c3c8cb35f3","0x123260b824df2f8bbe6a351ba2fa94c61aa754741eb198b768a699b2d1cc2b6f","0x1e51d9a653adc6b67287d35bb60584261f57363177c6b54a56dbd39834d851ba","0x18a9b2e2fce77bdb5e41215e2caeb7e77e946dbb2f381c8e7974709e03a6c216","0x2b2640870195a40e374cfa834e37ad9a5e17cb687bd2119a63ac02c3769b0f1e","0x2da73263fef362dfc79dd1066fd7ec294b765e2533f3ac4320e8d1540f2639a8","0x0cc9f299e5291bb1bc0951ce510a634c418af9f9802a291fe6d951768c0a1b2d","0x02a940acb788df42cc9219531776d45465be19087fc3f523fe92df771e5efc10","0x2d5976cc5540e761824bdacf69a2dddabe104fdbb235985ae9080b488f642fa9","0x284c18d1574d2cb7b4ee45b3ff30176eff2ab9c7b7f60cd8a87cef599379244d","0x12a38d659bf38da09af8f445505baa16bcb036d83173f6f45a7e46cac511e5a1","0x0852ef710b2396ba5b7fd69a95b336908d3a368262ec41e0d972564f784201a4","0x240c467a31ed3bb7c4cef09407750d2d89b3750e6cebb4aaa9d0f1f92be77249","0x04edf7595087745abc11fe7780afd4754c5013725653a4cec31f039b77e7b3c7","0x080d04b50ae3acd787f33f8f4a639a58677b5c04ef8a352fd4dd9236883f0e81","0x0cd745e7540fe230038f024ab1269177599ad94e8d8099a010eb7eebd3e41ec8","0x25e2394f90f5b3e3046b8876a6b3ef19a03ef9e9aeae4813fcb14907decc0393","0x03df12a6e39c606d70d3d470aff710d9daa86dece773a6f6f057725b57d6d115","0x0f744082aecf54f55db19dfbe56a81c17b3eb48417305c129beb6c97a22c705b","0x244a80d6d82e82fc416e8e4694deb4e08b81c32bb90cb2f96ff3f687298322d1","0x251eb4d8692f49523e3972096264ee770b295fb62a970fbfdd8aa1fff661ef50","0x0c4d9200120430618493a9151d632faa95c9ae842b7d97103a4afb3330cafbed","0x09e970a55dd7335db16a3823b6489c77cb7785f674cb7c924994ee121122e514","0x19e5bd1113959463be673ee72103bfe7559f423c632fbf9701ff099e165c429b","0x071eb2916ba30652a328c98353f69f239c41a4913c34931f18e91e5414b3270a","0x2a0cd2ebac904b7ebd82b6509dfcaf9ecf32175758c691d01f4fb32dad6371c4","0x1aa43a3009417d95904ebecd4189545e52ca7e9c7dfa3bde5f255ddefed5c754","0x29fd7a93212d60af81b810dad13a240bbbe16966a4977408b1d64c5d692b50b4","0x000000000000000000000000000000bef7cad70fa62891e6329cb7c17d0c5459","0x0000000000000000000000000000000000209177f2a04609421c1f23c04b454e","0x00000000000000000000000000000060dec389686170618e2490100f3fcf39e2","0x0000000000000000000000000000000000213368873145aad5f93798c31730af","0x000000000000000000000000000000c0f21a470488d9cbe53650d941c25cd569","0x000000000000000000000000000000000016d6f88e6b319553f5948886a6bd5e","0x000000000000000000000000000000d6dbb8a54a071e01c46d648c8c555ec352","0x0000000000000000000000000000000000130a7ce06ad74eb6c83f5565e2f821","0x00000000000000000000000000000058ca3aa788bd6ff37a5da3ecefdc896601","0x00000000000000000000000000000000001381bddcf8fb976cc52fee0d920598","0x00000000000000000000000000000082bdd94acd10edf22e09b1a42be500f8f8","0x00000000000000000000000000000000002f27815e28b2bc0699336893abdc0f","0x000000000000000000000000000000eb1d6973a54f8848f4c0630370d6181e49","0x000000000000000000000000000000000000129c1889d64ab66303bf17bfc864","0x000000000000000000000000000000155918aa9f6d352b847bf860a261266282","0x0000000000000000000000000000000000216e687d2f85a811f67573cbf311ba","0x0000000000000000000000000000002d2662f79a7ba21a95f44e67ed0b5abf3b","0x00000000000000000000000000000000001351870a81dc6edff235df110fe798","0x000000000000000000000000000000b113a55b86f59b21fe419ed8518dfddfc6","0x00000000000000000000000000000000002f26cd920f79b0d72a49897acc521c","0x0000000000000000000000000000002a4e1689c65dcae73ed1a33b03c611a7fe","0x00000000000000000000000000000000001c5093a8ae791c00fdd763c95800c5","0x0000000000000000000000000000006231d049ec3683c06ec6b00348e0669c61","0x0000000000000000000000000000000000237bfd7ec06c28f22ce84db9bb17ed","0x0000000000000000000000000000008afa7fa0842467bded20491950c3c1cde0","0x00000000000000000000000000000000000194ab5c71154605b8483cb40d00b8","0x00000000000000000000000000000066709af193591e93e8be3b833f63cb8597","0x000000000000000000000000000000000008ab9091bb9225b00ca0c011dff12f"] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x0000000000000000000000000000007f36e0b4f59927ebbb2302e76cbe8bd44e","0x00000000000000000000000000000000001b95777c6c98640c80638c195909ca","0x0000000000000000000000000000006d4b1ad71244248cb2070fbbbb0ac9df88","0x00000000000000000000000000000000001abada4d5d816a67b6fc75746cb723","0x000000000000000000000000000000465811089df032ceb5269254547a101e57","0x000000000000000000000000000000000011a4a909c59776a6df9c7615e8e87d","0x000000000000000000000000000000311f6f724e7199351c9774225f15c25f20","0x00000000000000000000000000000000001ddba8eb0ab208ad3d96c70941fcbc","0x0000000000000000000000000000000dfa80bdf5be151b21ad89466b7201b63d","0x000000000000000000000000000000000015ca7dc258adab8ea406d94e00c56d","0x000000000000000000000000000000507ea3454165f92295b6e435c7d30d14f0","0x00000000000000000000000000000000002f522608db7b7d389d1df67eab104d","0x000000000000000000000000000000950102cce743fadb23965fc72e31efd36c","0x000000000000000000000000000000000018b4a7ec90df68dfe97d3c5367d1bf","0x000000000000000000000000000000118d90258b25dba8bc0f99d9f7547c6a62","0x000000000000000000000000000000000012d78638701da6322abbf325693b0f","0x000000000000000000000000000000144743e0d082f35295b51561af65f94c6b","0x00000000000000000000000000000000002322a615615e5405836374bb3c5336","0x000000000000000000000000000000e6f08dd5904ee42f826cde680919b41a96","0x00000000000000000000000000000000002d3f823ea255b68465e4b5360bf864","0x00000000000000000000000000000076d4db93683b6363ae92a5a20d8bb9922e","0x00000000000000000000000000000000002f8a7009cac72c9599b81cb9054308","0x00000000000000000000000000000085c12dd2be9f2b29e54c1a4bc3cbf9b6ce","0x000000000000000000000000000000000024e3688a1f4f50b0c6bd6c068f32b2","0x00000000000000000000000000000023a2015e7ea351e444c9405adfbd81e84d","0x00000000000000000000000000000000001fb3e4228c15dc4380db796925ec49","0x000000000000000000000000000000834ad9406b8ded7208b872373be7445e47","0x0000000000000000000000000000000000267544d6a9f5cc46d10555f2617c65"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr index d25fd804ce4..c534b07fc77 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -6,7 +6,7 @@ fn main( // This is the proof without public inputs attached. // // This means: the size of this does not change with the number of public inputs. - proof: [Field; 153], + proof: [Field; 156], public_inputs: pub [Field; 1], // This is currently not public. It is fine given that the vk is a part of the circuit definition. // I believe we want to eventually make it public too though.