diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp index aed2c22d58c..3bdf857cfa5 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp @@ -59,10 +59,11 @@ void UltraHonkComposerHelper_::compute_witness(CircuitConstructor& circu // TODO(luke): The +1 size for z_lookup is not necessary and can lead to confusion. Resolve. polynomial z_lookup(subgroup_size + 1); // Only instantiated in this function; nothing assigned. - // Save space for adding random scalars in the s polynomial later. The subtracted 1 allows us to insert a `1` at the - // end, to ensure the evaluations (and hence coefficients) aren't all 0. See ComposerBase::compute_proving_key_base - // for further explanation, as a similar trick is done there. - size_t count = subgroup_size - tables_size - lookups_size - s_randomness - 1; + // TODO(kesha): Look at this once we figure out how we do ZK (previously we had roots cut out, so just added + // randomness) + // The size of empty space in sorted polynomials + size_t count = subgroup_size - tables_size - lookups_size; + ASSERT(count > 0); // We need at least 1 row of zeroes for the permutation argument for (size_t i = 0; i < count; ++i) { s_1[i] = 0; s_2[i] = 0; @@ -115,18 +116,7 @@ void UltraHonkComposerHelper_::compute_witness(CircuitConstructor& circu } } - // Initialise the `s_randomness` positions in the s polynomials with 0. - // These will be the positions where we will be adding random scalars to add zero knowledge - // to plookup (search for `Blinding` in plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp - // ProverPlookupWidget::compute_sorted_list_polynomial()) - for (size_t i = 0; i < s_randomness; ++i) { - s_1[count] = 0; - s_2[count] = 0; - s_3[count] = 0; - s_4[count] = 0; - ++count; - } - + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing space proving_key->sorted_1 = s_1; proving_key->sorted_2 = s_2; proving_key->sorted_3 = s_3; @@ -230,7 +220,7 @@ std::shared_ptr UltraHonkComposerHelper_::c polynomial poly_q_table_column_3(subgroup_size); polynomial poly_q_table_column_4(subgroup_size); - size_t offset = subgroup_size - tables_size - s_randomness - 1; + size_t offset = subgroup_size - tables_size; // Create lookup selector polynomials which interpolate each table column. // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to @@ -259,15 +249,7 @@ std::shared_ptr UltraHonkComposerHelper_::c } } - // Initialise the last `s_randomness` positions in table polynomials with 0. We don't need to actually randomise - // the table polynomials. - for (size_t i = 0; i < s_randomness; ++i) { - poly_q_table_column_1[offset] = 0; - poly_q_table_column_2[offset] = 0; - poly_q_table_column_3[offset] = 0; - poly_q_table_column_4[offset] = 0; - ++offset; - } + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing space // // In the case of using UltraPlonkComposer for a circuit which does _not_ make use of any lookup tables, all // four diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp index a07e9c16846..2aed24e6440 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp @@ -38,12 +38,6 @@ template class UltraHonkComposerHelper_ { bool contains_recursive_proof = false; bool computed_witness = false; - // This variable controls the amount with which the lookup table and witness values need to be shifted - // above to make room for adding randomness into the permutation and witness polynomials in the plookup widget. - // This must be (num_roots_cut_out_of_the_vanishing_polynomial - 1), since the variable num_roots_cut_out_of_ - // vanishing_polynomial cannot be trivially fetched here, I am directly setting this to 4 - 1 = 3. - static constexpr size_t s_randomness = 3; - explicit UltraHonkComposerHelper_(std::shared_ptr crs_factory) : crs_factory_(std::move(crs_factory)) {} diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp index f76025bee55..a0cb4d0c22a 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp @@ -76,8 +76,7 @@ class UltraHonkComposerTests : public ::testing::Test { TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) { auto composer = UltraHonkComposer(); - - composer.add_gates_to_ensure_all_polys_are_non_zero(); + // The composer should call add_gates_to_ensure_all_polys_are_non_zero by default auto prover = composer.create_prover(); auto proof = prover.construct_proof(); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp index 3f7ce41ed1c..8edd5c7104f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp @@ -93,30 +93,24 @@ void UltraCircuitConstructor::add_gates_to_ensure_all_polys_are_non_zero() create_big_add_gate({ zero_idx, zero_idx, zero_idx, one_idx, 0, 0, 0, 1, -1 }); // Take care of all polys related to lookups (q_lookup, tables, sorted, etc) - // by doing an arbitrary xor and an "and" lookup. + // by doing a dummy lookup with a special table. // Note: the 4th table poly is the table index: this is not the value of the table // type enum but rather the index of the table in the list of all tables utilized - // in the circuit. Therefore we naively need two different tables (indices 0, 1) - // to get a non-zero value in table_4. I assume this index is arbitrary and could - // start from 1 instead of 0? + // in the circuit. Therefore we naively need two different basic tables (indices 0, 1) + // to get a non-zero value in table_4. + // The multitable operates on 2-bit values, so the maximum is 3 uint32_t left_value = 3; - uint32_t right_value = 5; + uint32_t right_value = 3; fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); uint32_t left_witness_index = add_variable(left_witness_value); uint32_t right_witness_index = add_variable(right_witness_value); - - const auto and_accumulators = plookup::get_lookup_accumulators( - plookup::MultiTableId::UINT32_AND, left_witness_value, right_witness_value, true); - const auto xor_accumulators = plookup::get_lookup_accumulators( - plookup::MultiTableId::UINT32_XOR, left_witness_value, right_witness_value, true); - - create_gates_from_plookup_accumulators( - plookup::MultiTableId::UINT32_AND, and_accumulators, left_witness_index, right_witness_index); + const auto dummy_accumulators = plookup::get_lookup_accumulators( + plookup::MultiTableId::HONK_DUMMY_MULTI, left_witness_value, right_witness_value, true); create_gates_from_plookup_accumulators( - plookup::MultiTableId::UINT32_XOR, xor_accumulators, left_witness_index, right_witness_index); + plookup::MultiTableId::HONK_DUMMY_MULTI, dummy_accumulators, left_witness_index, right_witness_index); } /** diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/dummy.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/dummy.hpp new file mode 100644 index 00000000000..e44ea72e8fb --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/dummy.hpp @@ -0,0 +1,97 @@ +#pragma once +/** + * @file dummy.hpp + * @author Rumata888 + * @brief This file contains functions for the dummy tables that we use in UltraHonk to make table, sorted and lookup + * selector polynomials non-zero. + * + */ + +#include "types.hpp" + +namespace plookup { +namespace dummy_tables { + +/** + * @brief Lookup the value corresponding to a specific key + * + * @details We need this function for when we are constructing the circuit and want to query the table. Since we need + * two basic tables to make the table polynomial have non-zero values, we instantiate two tables with the same function, + * but change it slightly through templating + * + * @tparam id The id of the basic table used to parametrize the values for 2 fake tables + * @param key The key that we are looking up + * @return std::array + */ +template inline std::array get_value_from_key(const std::array key) +{ + return { key[0] * 3 + key[1] * 4 + id * 0x1337ULL, 0ULL }; +} + +/** + * @brief Generate the whole table + * + * @details This function is used to generate the whole table for the table polynomial. It's templated with id, since we + * generate 2 slightly different fake tables. + * + * @tparam table_id The id of the table this function is instantiated for + * @param id Table id that is the same for all circuits + * @param table_index The index for this table that is used in this circuit. 0, 1, ... + * @return A table of values + */ +template +inline BasicTable generate_honk_dummy_table(const BasicTableId id, const size_t table_index) +{ + + // We do the assertion, since this function is templated, but the general API for these functions contains the id, + // too. This helps us ensure that the correct instantion is used for a particular BasicTableId + ASSERT(table_id == static_cast(id)); + const size_t base = 1 << 1; // Probably has to be a power of 2 + BasicTable table; + table.id = id; + table.table_index = table_index; + table.size = base * base; + table.use_twin_keys = true; + for (uint64_t i = 0; i < base; ++i) { + for (uint64_t j = 0; j < base; ++j) { + table.column_1.emplace_back(i); + table.column_2.emplace_back(j); + table.column_3.emplace_back(i * 3 + j * 4 + static_cast(id) * 0x1337ULL); + } + } + + table.get_values_from_key = &get_value_from_key; + + table.column_1_step_size = base; + table.column_2_step_size = base; + table.column_3_step_size = base; + + return table; +} +/** + * @brief Create a multitable for filling UltraHonk polynomials with non-zero values + * + * @details Consists of 2 Basic tables that are almost identical. Each of those basic tables should only have 4 entries, + * so the overall overhead is just 8 + * + */ +inline MultiTable get_honk_dummy_multitable() +{ + const MultiTableId id = HONK_DUMMY_MULTI; + const size_t number_of_elements_in_argument = 1 << 1; // Probably has to be a power of 2 + const size_t number_of_lookups = 2; + MultiTable table(number_of_elements_in_argument, + number_of_elements_in_argument, + number_of_elements_in_argument, + number_of_lookups); + table.id = id; + table.slice_sizes.emplace_back(number_of_elements_in_argument); + table.lookup_ids.emplace_back(HONK_DUMMY_BASIC1); + table.get_table_values.emplace_back(&get_value_from_key); + table.slice_sizes.emplace_back(number_of_elements_in_argument); + table.lookup_ids.emplace_back(HONK_DUMMY_BASIC2); + table.get_table_values.emplace_back(&get_value_from_key); + return table; +} +} // namespace dummy_tables +} // namespace plookup \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.cpp index b0f2528224c..6580a47e8e4 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.cpp @@ -96,6 +96,7 @@ void init_multi_tables() MULTI_TABLES[(size_t)MultiTableId::KECCAK_NORMALIZE_AND_ROTATE + i] = keccak_tables::Rho<8, i>::get_rho_output_table(MultiTableId::KECCAK_NORMALIZE_AND_ROTATE); }); + MULTI_TABLES[MultiTableId::HONK_DUMMY_MULTI] = dummy_tables::get_honk_dummy_multitable(); } } // namespace diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.hpp index a6f46d3c496..2e674befa21 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/plookup_tables.hpp @@ -14,6 +14,7 @@ #include "keccak/keccak_output.hpp" #include "keccak/keccak_rho.hpp" #include "keccak/keccak_theta.hpp" +#include "dummy.hpp" namespace plookup { @@ -242,6 +243,12 @@ inline BasicTable create_basic_table(const BasicTableId id, const size_t index) case PEDERSEN_IV_BASE: { return pedersen_tables::basic::generate_pedersen_iv_table(PEDERSEN_IV_BASE); } + case HONK_DUMMY_BASIC1: { + return dummy_tables::generate_honk_dummy_table(HONK_DUMMY_BASIC1, index); + } + case HONK_DUMMY_BASIC2: { + return dummy_tables::generate_honk_dummy_table(HONK_DUMMY_BASIC2, index); + } case KECCAK_INPUT: { return keccak_tables::KeccakInput::generate_keccak_input_table(KECCAK_INPUT, index); } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp index 0337e1553a8..f6c7c0f6dff 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp @@ -83,6 +83,8 @@ enum BasicTableId { PEDERSEN_1, PEDERSEN_0, PEDERSEN_IV_BASE, + HONK_DUMMY_BASIC1, + HONK_DUMMY_BASIC2, KECCAK_INPUT, KECCAK_THETA, KECCAK_RHO, @@ -136,6 +138,7 @@ enum MultiTableId { BLAKE_XOR_ROTATE_8, BLAKE_XOR_ROTATE_7, PEDERSEN_IV, + HONK_DUMMY_MULTI, KECCAK_THETA_OUTPUT, KECCAK_CHI_OUTPUT, KECCAK_FORMAT_INPUT, @@ -145,6 +148,7 @@ enum MultiTableId { }; struct MultiTable { + // Coefficients are accumulated products of corresponding step sizes until that point std::vector column_1_coefficients; std::vector column_2_coefficients; std::vector column_3_coefficients;