From de7524e79ccb6a6d9dd2df90f5b6032ff61bdb66 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Tue, 18 Jul 2023 19:47:32 +0000 Subject: [PATCH 01/48] raw round component #183 --- .../hashes/keccak/keccak_component.hpp | 266 +++++++ .../components/hashes/keccak/keccak_round.hpp | 690 ++++++++++++++++++ test/hashes/plonk/keccak_round.cpp | 210 ++++++ 3 files changed, 1166 insertions(+) create mode 100644 include/nil/blueprint/components/hashes/keccak/keccak_component.hpp create mode 100644 include/nil/blueprint/components/hashes/keccak/keccak_round.hpp create mode 100644 test/hashes/plonk/keccak_round.cpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp new file mode 100644 index 000000000..6ae5e2c69 --- /dev/null +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -0,0 +1,266 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_HPP + +#include + +#include + +namespace nil { + namespace blueprint { + namespace components { + template + class keccak; + + template + class keccak, + WitnessesAmount> : + public plonk_component { + + using component_type = plonk_component; + using value_type = typename BlueprintFieldType::value_type; + + std::size_t calculate_normalize_chunk_size(std::size_t num_rows, std::size_t i) { + std::size_t res = 0; + std::size_t power = i; + while (power < num_rows) { + ++res; + power *= i; + } + return res; + } + + std::size_t rows() const { + return 0; + } + + public: + using var = typename component_type::var; + + using round_component_type = keccak_round, + WitnessesAmount>; + std::array rounds; + + const std::size_t lookup_rows; + const std::size_t lookup_columns; + const std::size_t normalize3_chunk_size; + const std::size_t normalize4_chunk_size; + const std::size_t normalize6_chunk_size; + + constexpr static const bool needs_bonus_row = WitnessesAmount < 5; + const std::size_t rows_amount; + constexpr static const std::size_t gates_amount = 1; + + struct input_type { + std::array inner_state; + std::array padded_message_chunk; + var round_constant; + }; + + struct result_type { + std::array final_inner_state; + + result_type(const keccak &component, std::size_t start_row_index) { + std::pair + r_address = component.get_var_address(var_address::R_, start_row_index), + q_address = component.get_var_address(var_address::Q, start_row_index); + + quotient = var(component.W(q_address.second), q_address.first); + remainder = var(component.W(r_address.second), r_address.first); + } + }; + + #define __keccak_init_macro(witness, constant, public_input, \ + lookup_rows_, lookup_columns_) \ + lookup_rows(lookup_rows_), \ + lookup_columns(lookup_columns_), \ + normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ + normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ + normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ + range_checks(range_check_amount, \ + range_check_component_type(witness, constant, public_input, bits_amount_)), \ + rows_amount(rows()) + + template + division_remainder(ContainerType witness, std::size_t bits_amount_, bool check_inputs_) : + component_type(witness, {}, {}), + __division_remainder_init_macro(witness, {}, {}, bits_amount_, check_inputs_) {}; + + + template + division_remainder(WitnessContainerType witness, ConstantContainerType constant, + PublicInputContainerType public_input, + std::size_t bits_amount_, bool check_inputs_): + component_type(witness, constant, public_input), + __division_remainder_init_macro(witness, constant, public_input, bits_amount_, check_inputs_) {}; + + division_remainder( + std::initializer_list witnesses, + std::initializer_list constants, + std::initializer_list + public_inputs, + std::size_t bits_amount_, bool check_inputs_) : + component_type(witnesses, constants, public_inputs), + __division_remainder_init_macro(witnesses, constants, public_inputs, + bits_amount_, check_inputs_) + {}; + + #undef __keccak_init_macro + }; + + template + using keccak_component = + keccak, + WitnessesAmount>; + + template= 9, bool> = true> + void generate_gates( + const keccak_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_component::input_type + &instance_input, + const std::size_t first_selector_index) { + + using component_type = keccak_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + using constraint_type = crypto3::zk::snark::plonk_constraint; + using gate_type = typename crypto3::zk::snark::plonk_gate; + using value_type = typename BlueprintFieldType::value_type; + } + + template= 9, bool> = true> + void generate_copy_constraints( + const keccak_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + std::uint32_t row = start_row_index; + } + + template= 9, bool> = true> + typename keccak_component::result_type + generate_circuit( + const keccak_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + auto selector_iterator = assignment.find_selector(component); + std::size_t first_selector_index; + std::size_t row = start_row_index; + + using component_type = keccak_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + + return typename component_type::result_type(component, start_row_index); + } + + template= 9, bool> = true> + typename keccak_component::result_type + generate_assignments( + const keccak_component + &component, + assignment> + &assignment, + const typename keccak_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + std::size_t row = start_row_index; + + using component_type = keccak_component; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + return typename component_type::result_type(component, start_row_index); + } + + + } // namespace components + } // namespace blueprint +} // namespace nil + +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp new file mode 100644 index 000000000..e0d3cae2a --- /dev/null +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -0,0 +1,690 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP + +#include + + +namespace nil { + namespace blueprint { + namespace components { + template + class keccak_round; + + template + class keccak_round, + WitnessesAmount> : + public plonk_component { + + using component_type = plonk_component; + using value_type = typename BlueprintFieldType::value_type; + + std::size_t calculate_normalize_num_chunks(std::size_t num_rows, std::size_t base) { + std::size_t chunk_size = 0; + std::size_t power = base; + while (power < num_rows) { + ++chunk_size; + power *= base; + } + return chunk_size; + } + std::size_t calculate_chi_num_chunks(std::size_t num_rows) { + std::size_t chunk_size = 0; + std::size_t power = 2; + while (power < num_rows) { + ++chunk_size; + power *= 2; + } + return chunk_size; + } + + std::size_t rows() const { + std::size_t num_cells = 17 * xor2_cells + // inner_state ^ chunk + 5 * xor5_cells + // theta + 5 * rot_cells + // theta + 25 * xor3_cells + // theta + 24 * rot_cells + // rho/phi + 25 * chi_cells + // chi + xor2_cells; // iota + return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); + } + std::size_t gates() const { + // TODO: need to find the exact answer + return rows() / 3 + bool(rows() % 3); + } + + struct configuration { + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + }; + + // In constraints we use such notation: constr[0] - result, + // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates last_coordinate; + std::vector copy_from; + std::vector> constraints; + std::vector> lookups; + std::vector copy_to; + + configuration() = default; + configuration(std::pair last_coordinate_, + std::vector> copy_from_, + std::vector>> constraints_, + std::vector>> lookups_, + std::vector> copy_to_) : + last_coordinate(last_coordinate_), copy_from(copy_from_), + constraints(constraints_), lookups(lookups_), copy_to(copy_to_) {}; + }; + + public: + using var = typename component_type::var; + + const std::size_t lookup_rows; + const std::size_t lookup_columns; + + const std::size_t normalize3_chunk_size; + const std::size_t normalize4_chunk_size; + const std::size_t normalize6_chunk_size; + const std::size_t chi_chunk_size; + + const std::size_t xor2_cells; + const std::size_t xor3_cells; + const std::size_t xor5_cells; + const std::size_t rot_cells = 22; + const std::size_t chi_cells; + + // full configuration is precalculated, then used in other functions + std::array full_configuration; + + const std::size_t rows_amount; + constexpr static const std::size_t gates_amount = 1; + + struct input_type { + std::array inner_state; + std::array padded_message_chunk; + var round_constant; + }; + + struct result_type { + std::array inner_state; + + result_type(const keccak_round &component, std::size_t start_row_index) { + + } + }; + + value_type normalize(value_type value) { + integral_type result = 0; + integral_type power = 1; + integral_type integral_value = integral_type(value.data); + for (std::size_t i = 0; i < 64; ++i) { + result += (integral_value & 1) * power; + power *= 8; + integral_value >>= 3; + } + return value_type(result); + } + + configuration configure_xor(std::size_t row, std::size_t column, std::size_t num_args) { + std::size_t num_chunks = num_args == 2 ? normalize3_num_chunks + : num args == 3 ? normalize4_num_chunks + : normalize6_num_chunks; + std::size_t last_row = row, + last_column = column; + std::vector> copy_constrain_from = {{last_row, last_column++}}; + for (int i = 0; i < num_args - 1; ++i) { + copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + + std::vector>> constraints = + {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; + for (int i = 0; i < num_args; ++i) { + constraints[0].push_back(copy_constrain_from[i]); + } + constraints.push_back({constraints[0][0]}); + constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); + std::vector> copy_constrain_to = {constraints[2][0]}; + std::vector>> lookups(num_chunks, std::vector>); + for (std::size_t i = 1; i < 3; ++i) { + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); + lookups[j].push_back(constraints[i].back()); + } + } + + BOOST_ASSERT(last_column - column == xor2_cells); + last_row += last_column / WitnessesAmount; + last_column %= WitnessesAmount; + return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + } + + configuration configure_chi(std::size_t row, std::size_t column) { + std::size_t last_row = row, + last_column = column; + std::vector> copy_constrain_from; + for (int i = 0; i < 3; ++i) { + copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + + std::vector>> constraints = + {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; + for (int i = 0; i < 3; ++i) { + constraints[0].push_back(copy_constrain_from[i]); + } + constraints.push_back({constraints[0][0]}); + constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); + std::vector> copy_constrain_to = {constraints[2][0]}; + std::vector>> lookups(chi_num_chunks, std::vector>); + for (std::size_t i = 1; i < 3; ++i) { + for (std::size_t j = 0; j < chi_num_chunks; ++j) { + constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); + lookups[j].push_back(constraints[i].back()); + } + } + + BOOST_ASSERT(last_column - column == xor2_cells); + last_row += last_column / WitnessesAmount; + last_column %= WitnessesAmount; + return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + } + + configuration configure_rot(std::size_t row, std::size_t column) { + std::size_t last_row = row, + last_column = column; + std::vector> copy_constrain_from; + for (int i = 0; i < 3; ++i) { + copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + + std::vector>> constraints = + {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; + for (int i = 0; i < 3; ++i) { + constraints[0].push_back(copy_constrain_from[i]); + } + constraints.push_back({constraints[0][0]}); + constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); + std::vector> copy_constrain_to = {constraints[2][0]}; + std::vector>> lookups(chi_num_chunks, std::vector>); + for (std::size_t i = 1; i < 3; ++i) { + for (std::size_t j = 0; j < chi_num_chunks; ++j) { + constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); + lookups[j].push_back(constraints[i].back()); + } + } + + BOOST_ASSERT(last_column - column == xor2_cells); + last_row += last_column / WitnessesAmount; + last_column %= WitnessesAmount; + return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + } + + std::array configure_all() { + std::array result; + std::size_t row = 0, + column = 0; + + // inner_state ^ chunk + for (int i = 0; i < 17; ++i) { + result[i] = configure_xor(row, column, 2); + row = result[i].last_coordinate.row; + column = result[i].last_coordinate.column; + } + // theta + for (int i = 0; i < 5; ++i) { + result[17 + i] = configure_xor(row, column, 5); + row = result[17 + i].last_coordinate.row; + column = result[17 + i].last_coordinate.column; + } + for (int i = 0; i < 5; ++i) { + result[22 + i] = configure_rot(row, column); + row = result[22 + i].last_coordinate.row; + column = result[22 + i].last_coordinate.column; + } + for (int i = 0; i < 25; ++i) { + result[27 + i] = configure_xor(row, column, 3); + row = result[27 + i].last_coordinate.row; + column = result[27 + i].last_coordinate.column; + } + // rho/phi + for (int i = 0; i < 24; ++i) { + result[52 + i] = configure_rot(row, column); + row = result[52 + i].last_coordinate.row; + column = result[52 + i].last_coordinate.column; + } + // chi + for (int i = 0; i < 25; ++i) { + result[76 + i] = configure_chi(row, column); + row = result[76 + i].last_coordinate.row; + column = result[76 + i].last_coordinate.column; + } + // iota + result[101] = configure_xor(row, column, 2); + + return result; + } + + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_) \ + lookup_rows(lookup_rows_), \ + lookup_columns(lookup_columns_), \ + normalize3_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 3)), \ + normalize4_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 4)), \ + normalize6_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 6)), \ + chi_chunk_size(calculate_chi_num_chunks(lookup_rows_)), \ + xor2_cells((64 / normalize3_chunk_size + bool(64 % normalize3_chunk_size)) * 2 + 2 + 2), \ + xor3_cells((64 / normalize4_chunk_size + bool(64 % normalize4_chunk_size)) * 2 + 3 + 2), \ + xor5_cells((64 / normalize6_chunk_size + bool(64 % normalize6_chunk_size)) * 2 + 5 + 2), \ + chi_cells((64 / chi_chunk_size + bool(64 % chi_chunk_size)) * 2 + 5), \ + full_configuration(configure_all()), \ + rows_amount(rows()), \ + gates_amount(gates()) + + template + keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_) : + component_type(witness, {}, {}), + __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; + + + template + keccak_round(WitnessContainerType witness, ConstantContainerType constant, + PublicInputContainerType public_input, + std::size_t lookup_rows_, std::size_t lookup_columns_): + component_type(witness, constant, public_input), + __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; + + keccak_round( + std::initializer_list witnesses, + std::initializer_list constants, + std::initializer_list + public_inputs, + std::size_t lookup_rows_, std::size_t lookup_columns_) : + component_type(witnesses, constants, public_inputs), + __keccak_round_init_macro(lookup_rows_, lookup_columns_) + {}; + + #undef __keccak_round_init_macro + }; + + template + using keccak_round_component = + keccak_round, + WitnessesAmount>; + + template= 9, bool> = true> + void generate_gates( + const keccak_round_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_round_component::input_type + &instance_input, + const std::size_t first_selector_index) { + + using component_type = keccak_round_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + using constraint_type = crypto3::zk::snark::plonk_constraint; + using gate_type = typename crypto3::zk::snark::plonk_gate; + using value_type = typename BlueprintFieldType::value_type; + } + + template= 9, bool> = true> + void generate_copy_constraints( + const keccak_round_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_round_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_round_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + std::uint32_t row = start_row_index; + } + + template= 9, bool> = true> + typename keccak_round_component::result_type + generate_circuit( + const keccak_round_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_round_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + auto selector_iterator = assignment.find_selector(component); + std::size_t first_selector_index; + std::size_t row = start_row_index; + + using component_type = keccak_round_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + + return typename component_type::result_type(component, start_row_index); + } + + template= 9, bool> = true> + typename keccak_round_component::result_type + generate_assignments( + const keccak_round_component + &component, + assignment> + &assignment, + const typename keccak_round_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + std::size_t row = start_row_index; + + using component_type = keccak_round_component; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + int config_index = 0; + + // inner_state ^ chunk + std::array A_1; + for (int index = 0; index < 17; ++index) { + value_type state = var_value(assignment, instance_input.inner_state[index]); + value_type message = var_value(assignment, instance_input.padded_message_chunk[index]); + value_type sum = state + message; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize3_chunk_size; + std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); + std::vector chunks; + std::vector normalized_chunks; + integral_type mask = (1 << (3 * chunk_size)) - 1; + value_type power = 1; + value_type normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + chunks.push_back(value_type(integral_sum & mask)); + integral_sum >>= chunk_size; + normalized_chunks.push_back(normalize(chunks.back())); + normalized_sum += normalized_chunks.back() * power; + power *= chunk_size; + } + A_1[index] = normalized_sum; + + auto cur_config = component.full_configuration[index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = state; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = message; + assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; + for (int j = 1; j < cur_config.constraint[1].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; + } + for (int j = 1; j < cur_config.constraint[2].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + } + } + for (int i = 17; i < 25; ++i) { + A_1[i] = var_value(assignment, instance_input.inner_state[i]); + } + config_index += 17; + + // theta + std::array C; + for (int index = 0; index < 5; ++index) { + value_type sum = 0; + for (int j = 0; j < 5; ++j) { + sum += A_1[index + 5 * j]; + } + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize6_chunk_size; + std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); + std::vector chunks; + std::vector normalized_chunks; + integral_type mask = (1 << (3 * chunk_size)) - 1; + value_type power = 1; + value_type normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + chunks.push_back(value_type(integral_sum & mask)); + integral_sum >>= chunk_size; + normalized_chunks.push_back(normalize(chunks.back())); + normalized_sum += normalized_chunks.back() * power; + power *= chunk_size; + } + C[index] = normalized_sum; + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = A_1[index + 5]; + assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = A_1[index + 10]; + assignment.witness(component.W(cur_config.copy_from[3].row), cur_config.copy_from[3].column) = A_1[index + 15]; + assignment.witness(component.W(cur_config.copy_from[4].row), cur_config.copy_from[4].column) = A_1[index + 20]; + assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; + for (int j = 1; j < cur_config.constraint[1].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; + } + for (int j = 1; j < cur_config.constraint[2].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + } + } + config_index += 5; + + // TODO: rot + std::array C_rot; + for (int index = 0; index < 5; ++index) { + integral_type integral_C = integral_type(C[index].data); + integral_type smaller_part = integral_C & ((1 << 3) - 1); + integral_type bigger_part = integral_C >> 3; + integral_type integral_C_rot = (bigger_part << 3) + smaller_part; + C_rot[index] = value_type(integral_C_rot); + integral_type bound_smaller = smaller_part - (1 << 3) + + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = C[index]; + + } + config_index += 5; + + std::array A_2; + for (int index = 0; index < 25; ++index) { + value_type sum = A_1[index] + C_rot[(index + 1) % 5] + C[(index - 1) % 5]; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize4_chunk_size; + std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); + std::vector chunks; + std::vector normalized_chunks; + integral_type mask = (1 << (3 * chunk_size)) - 1; + value_type power = 1; + value_type normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + chunks.push_back(value_type(integral_sum & mask)); + integral_sum >>= chunk_size; + normalized_chunks.push_back(normalize(chunks.back())); + normalized_sum += normalized_chunks.back() * power; + power *= chunk_size; + } + A_2[index] = normalized_sum; + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = C_rot[(index + 1) % 5]; + assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = C[(index - 1) % 5]; + assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; + for (int j = 1; j < cur_config.constraint[1].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; + } + for (int j = 1; j < cur_config.constraint[2].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + } + } + config_index += 25; + + // rho/phi + std::array, 5> B; + B[0][0] = A_2[0]; + // TODO: finish rot(r) + for (int index = 1; index < 25; ++index) { + int x = index % 5; + int y = index / 5; + integral_type integral_A = integral_type(A_2[index].data); + integral_type smaller_part = integral_A & ((1 << 3) - 1); + integral_type bigger_part = integral_A >> 3; + integral_type integral_A_rot = (bigger_part << 3) + smaller_part; + B[y][2*x + 3*y] = value_type(integral_A_rot); + + } + config_index += 24; + + // chi + // TODO: chunk size need to be for sparse form so no times 3 anywhere + std::array A_3; + for (int index = 0; index < 25; ++index) { + int x = index % 5; + int y = index / 5; + value_type sum = component.sparse_3 - 2 * B[x][y] + B[(x+1)%5][y] - B[(x+2)%5][y]; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.chi_chunk_size; + std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); + std::vector chunks; + std::vector chi_chunks; + integral_type mask = (1 << (3 * chunk_size)) - 1; + value_type power = 1; + value_type chi_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + chunks.push_back(value_type(integral_sum & mask)); + integral_sum >>= chunk_size; + chi_chunks.push_back(chi(chunks.back())); + chi_sum += chi_chunks.back() * power; + power *= chunk_size; + } + A_3[index] = chi_sum; + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = B[x][y]; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = B[(x+1)%5][y]; + assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = B[(x+2)%5][y]; + assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = chi_sum; + for (int j = 1; j < cur_config.constraint[1].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; + } + for (int j = 1; j < cur_config.constraint[2].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = chi_chunks[j - 1]; + } + } + config_index += 25; + + // iota + // TODO: power and norm_sum - maybe integral type? + value_type round_constant = var_value(assignment, instance_input.round_constant); + value_type sum = A_3[0] + round_constant; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.chi_chunk_size; + std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); + std::vector chunks; + std::vector normalized_chunks; + integral_type mask = (1 << (3 * chunk_size)) - 1; + value_type power = 1; + value_type normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + chunks.push_back(value_type(integral_sum & mask)); + integral_sum >>= chunk_size; + normalized_chunks.push_back(chi(chunks.back())); + normalized_sum += normalized_chunks.back() * power; + power *= chunk_size; + } + value_type A_4 = normalized_sum; + + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_3[0]; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = round_constant; + assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; + for (int j = 1; j < cur_config.constraint[1].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; + } + for (int j = 1; j < cur_config.constraint[2].size(); ++j) { + assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = chi_chunks[j - 1]; + } + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + return typename component_type::result_type(component, start_row_index); + } + + + } // namespace components + } // namespace blueprint +} // namespace nil + +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp new file mode 100644 index 000000000..4f1dd9509 --- /dev/null +++ b/test/hashes/plonk/keccak_round.cpp @@ -0,0 +1,210 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE plonk_keccak_test + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include "../../test_plonk_component.hpp" + +const int r[5][5] = {{0, 1, 62, 28, 27}, + {36, 44, 6, 55, 20}, + {3, 10, 43, 25, 39}, + {41, 45, 15, 21, 8}, + {18, 2, 61, 56, 14}}; + +// here for level we use: +// 0 - inner ^ chunk, 1 - theta, 2 - rho/phi, 3 - chi, 4 - iota (full round, by default) +template +std::array round_function(std::array inner_state, + std::array padded_message_chunk, + typename BlueprintFieldType::value_type RC) { + #define rot(x, s) (((x) << s) | ((x) >> (64 - s))); + for (int i = 0; i < 17; ++i) { + inner_state[i] = inner_state[i] ^ padded_message_chunk[i]; + } + if (level == 0) { + return inner_state; + } + // theta + std::array C; + for (int x = 0; x < 5; ++x) { + C[x] = inner_state[5 * x] ^ inner_state[5 * x + 1] ^ inner_state[5 * x + 2] ^ inner_state[5 * x + 3] ^ + inner_state[5 * x + 4]; + for (int y = 0; y < 5; ++y) { + inner_state[5 * x + y] = inner_state[5 * x + y] ^ C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); + } + } + if (level == 1) { + return inner_state; + } + // rho and pi + std::array B; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + B[5 * y + ((2 * x + 3 * y) % 5)] = rot(inner_state[5 * x + y], r[x, y]); + } + } + if (level == 2) { + return B; + } + // chi + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state[5 * x + y] = B[5 * x + y] ^ ((~B[5 * x + ((y + 1) % 5)]) & B[5 * x + ((y + 2) % 5)]); + } + } + if (level == 3) { + return inner_state; + } + // iota + inner_state[0] = inner_state[0] ^ RC; + + return inner_state; +} + +template +auto test_keccak_round_inner(std::array inner_state, + std::array padded_message_chunk, + typename BlueprintFieldType::value_type RC) { + constexpr std::size_t PublicInputColumns = 1; + constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t SelectorColumns = 10; + using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + using AssignmentType = nil::blueprint::assignment; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; + constexpr std::size_t Lambda = 1; + + using var = nil::crypto3::zk::snark::plonk_variable; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using component_type = nil::blueprint::components::keccak_round; + + std::vector public_input; + for (int i = 0; i < 25; ++i) { + public_input.push_back(inner_state[i]); + } + for (int i = 0; i < 17; ++i) { + public_input.push_back(padded_message_chunk[i]); + } + public_input.push_back(RC); + + std::array inner_state_vars; + std::array padded_message_chunk_vars; + var RC_var; + for (int i = 0; i < 25; ++i) { + inner_state_vars[i] = var(0, i, false, var::column_type::public_input); + } + for (int i = 0; i < 17; ++i) { + padded_message_chunk_vars[i] = var(0, i + 25, false, var::column_type::public_input); + } + RC_var = var(0, 42, false, var::column_type::public_input); + typename component_type::input_type instance_input = {inner_state_vars, padded_message_chunk_vars, RC_var}; + + auto expected_result = round_function(inner_state, padded_message_chunk, RC); + + auto result_check = [expected_result] + (AssignmentType &assignment, typename component_type::result_type &real_res) { + for (int i = 0; i < 25; ++i) { + assert(expected_result[i] == var_value(assignment, real_res.inner_state[i])); + } + }; + + component_type component_instance = WitnessesAmount == 15 ? + component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, + {0}, LookupRows, LookupColumns) + : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {0}, + LookupRows, LookupColumns); + + if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { + BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; + } + + nil::crypto3::test_component( + boost::get(component_instance), public_input, result_check, instance_input); +} + +template +void test_keccak_round_random() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + nil::crypto3::random::algebraic_engine generate_random; + boost::random::mt19937 seed_seq; + generate_random.seed(seed_seq); + uint64_t range = value_type(2).pow(64) - 1; + + boost::random::uniform_int_distribution distribution(0, range); + + std::array inner_state; + std::array padded_message_chunk; + value_type RC = value_type(0); + + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(distribution(generate_random)); + } + for (int i = 0; i < 17; ++i) { + padded_message_chunk[i] = value_type(distribution(generate_random)); + } + RC = value_type(distribution(generate_random)); + + test_keccak_round_inner + (inner_state, padded_message_chunk, RC); +} + +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { + using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; + test_keccak_round(); + test_keccak_round(); +} + +// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { +// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +// } + +BOOST_AUTO_TEST_SUITE_END() From fb701f36cf1e09ce1501d04d74ee8e020b3ef9dc Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 26 Jul 2023 12:07:05 +0000 Subject: [PATCH 02/48] calculated configurations #183 --- .../hashes/keccak/keccak_component.hpp | 4 +- .../hashes/keccak/keccak_per_chunk.hpp | 330 +++++++++ .../components/hashes/keccak/keccak_round.hpp | 675 ++++++++++++------ test/CMakeLists.txt | 1 + test/hashes/plonk/keccak_round.cpp | 70 +- 5 files changed, 832 insertions(+), 248 deletions(-) create mode 100644 include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 6ae5e2c69..26e818c7a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -27,7 +27,7 @@ #include -#include +#include namespace nil { namespace blueprint { @@ -62,7 +62,7 @@ namespace nil { public: using var = typename component_type::var; - using round_component_type = keccak_round, WitnessesAmount>; std::array rounds; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp new file mode 100644 index 000000000..27a8829a4 --- /dev/null +++ b/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp @@ -0,0 +1,330 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP + +#include + +#include + +namespace nil { + namespace blueprint { + namespace components { + template + class keccak_per_chunk; + + template + class keccak_per_chunk, + WitnessesAmount> : + public plonk_component { + + using component_type = plonk_component; + using value_type = typename BlueprintFieldType::value_type; + + std::size_t rows() const { + return 0; + } + + public: + using var = typename component_type::var; + + using round_component_type = keccak_round, + WitnessesAmount>; + std::array rounds; + + using configuration = round_component_type::configuration; + + const std::size_t rows_amount; + constexpr static const std::size_t gates_amount = 17 * round_component_type::gates_amount; + + struct input_type { + std::array inner_state; + std::array padded_message_chunk; + }; + + struct result_type { + std::array final_inner_state; + + result_type(const keccak_per_chunk &component, std::size_t start_row_index) { + + } + }; + + configuration configure_pack_unpack(std::size_t row, std::size_t column) { + // regular constraints: + // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) + // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) + + std::size_t last_row = row, + last_column = column; + + std::vector> copy_from; + std::vector>> constraints; + + if (1 + column > limit) { + copy_from.push_back({last_row + 1, 0}); + } else { + copy_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + + std::pair cell_copy_to; + std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + if (final_row == copy_from[0].first) { + cell_copy_to = {final_row, copy_from.back().second + 1}; + } else { + cell_copy_to = {final_row, 0}; + } + + std::vector> cells; + if (1 + column > limit) { + for (int i = column; i < WitnessesAmount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cur_row = row + 1, + cur_column = 1; + while (cur_column < cells_left) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } else { + std::size_t cur_row = row, + cur_column = column + 1; + while (cur_column - column < num_cells) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } + std::size_t cell_index = 0; + + std::vector>> lookups(num_chunks, std::vector>()); + + constraints.push_back({copy_from[0]}); + constraints.push_back({cell_copy_to}); + for (std::size_t i = 0; i < 2; ++i) { + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[i].push_back(cells[cell_index++]); + lookups[j].push_back(constraints[i].back()); + } + } + + last_column = cells.back().second + 1; + last_row = cells.back().first + (last_column / WitnessesAmount); + last_column %= WitnessesAmount; + + + return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + } + + // std::array configure_all() { + // std::array result; + // std::size_t row = 0, + // column = 0; + // for (std::size_t i = 0; i < 17; ++i) { + // result[i] = configure_pack_unpack(row, column); + // row = result[i].last_row; + // column = result[i].last_column; + // } + // return result; + // } + + #define __keccak_per_chunk_init_macro(witness, constant, public_input, \ + lookup_rows_, lookup_columns_) \ + lookup_rows(lookup_rows_), \ + lookup_columns(lookup_columns_), \ + normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ + normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ + normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ + range_checks(range_check_amount, \ + range_check_component_type(witness, constant, public_input, bits_amount_)), \ + rows_amount(rows()) + + template + keccak_per_chunk(ContainerType witness, std::size_t bits_amount_, bool check_inputs_) : + component_type(witness, {}, {}), + __keccak_per_chunk_init_macro(witness, {}, {}, bits_amount_, check_inputs_) {}; + + + template + keccak_per_chunk(WitnessContainerType witness, ConstantContainerType constant, + PublicInputContainerType public_input, + std::size_t bits_amount_, bool check_inputs_): + component_type(witness, constant, public_input), + __keccak_per_chunk_init_macro(witness, constant, public_input, bits_amount_, check_inputs_) {}; + + keccak_per_chunk( + std::initializer_list witnesses, + std::initializer_list constants, + std::initializer_list + public_inputs, + std::size_t bits_amount_, bool check_inputs_) : + component_type(witnesses, constants, public_inputs), + __keccak_per_chunk_init_macro(witnesses, constants, public_inputs, + bits_amount_, check_inputs_) + {}; + + #undef __keccak_per_chunk_init_macro + }; + + template + using keccak_pc_component = + keccak_per_chunk, + WitnessesAmount>; + + template= 9, bool> = true> + void generate_gates( + const keccak_pc_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_pc_component::input_type + &instance_input, + const std::size_t first_selector_index) { + + using component_type = keccak_pc_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + using constraint_type = crypto3::zk::snark::plonk_constraint; + using gate_type = typename crypto3::zk::snark::plonk_gate; + using value_type = typename BlueprintFieldType::value_type; + } + + template= 9, bool> = true> + void generate_copy_constraints( + const keccak_pc_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_pc_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_pc_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + std::uint32_t row = start_row_index; + } + + template= 9, bool> = true> + typename keccak_pc_component::result_type + generate_circuit( + const keccak_pc_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_pc_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + auto selector_iterator = assignment.find_selector(component); + std::size_t first_selector_index; + std::size_t row = start_row_index; + + using component_type = keccak_pc_component; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + + return typename component_type::result_type(component, start_row_index); + } + + template= 9, bool> = true> + typename keccak_pc_component::result_type + generate_assignments( + const keccak_pc_component + &component, + assignment> + &assignment, + const typename keccak_pc_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + std::size_t row = start_row_index; + + using component_type = keccak_pc_component; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using var = typename component_type::var; + using var_address = typename component_type::var_address; + + + BOOST_ASSERT(row == start_row_index + component.rows_amount); + + return typename component_type::result_type(component, start_row_index); + } + + + } // namespace components + } // namespace blueprint +} // namespace nil + +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP \ No newline at end of file diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index e0d3cae2a..8e9803706 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -27,6 +27,10 @@ #include +#include +#include +#include + namespace nil { namespace blueprint { @@ -43,24 +47,28 @@ namespace nil { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; - std::size_t calculate_normalize_num_chunks(std::size_t num_rows, std::size_t base) { + std::size_t calculate_normalize_chunk_size(std::size_t num_rows, std::size_t base) { std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { ++chunk_size; power *= base; } - return chunk_size; + return chunk_size * 3; } - std::size_t calculate_chi_num_chunks(std::size_t num_rows) { + std::size_t calculate_chi_chunk_size(std::size_t num_rows) { std::size_t chunk_size = 0; std::size_t power = 2; while (power < num_rows) { ++chunk_size; power *= 2; } - return chunk_size; + return chunk_size * 3; + } + std::size_t calculate_num_chunks(std::size_t chunk_size) { + return word_size / chunk_size + bool(word_size % chunk_size); } std::size_t rows() const { @@ -78,34 +86,6 @@ namespace nil { return rows() / 3 + bool(rows() % 3); } - struct configuration { - struct coordinates { - std::size_t row; - std::size_t column; - - coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - }; - - // In constraints we use such notation: constr[0] - result, - // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. - coordinates last_coordinate; - std::vector copy_from; - std::vector> constraints; - std::vector> lookups; - std::vector copy_to; - - configuration() = default; - configuration(std::pair last_coordinate_, - std::vector> copy_from_, - std::vector>> constraints_, - std::vector>> lookups_, - std::vector> copy_to_) : - last_coordinate(last_coordinate_), copy_from(copy_from_), - constraints(constraints_), lookups(lookups_), copy_to(copy_to_) {}; - }; - public: using var = typename component_type::var; @@ -116,6 +96,13 @@ namespace nil { const std::size_t normalize4_chunk_size; const std::size_t normalize6_chunk_size; const std::size_t chi_chunk_size; + const std::size_t rotate_chunk_size = 24; + + const std::size_t normalize3_num_chunks; + const std::size_t normalize4_num_chunks; + const std::size_t normalize6_num_chunks; + const std::size_t chi_num_chunks; + const std::size_t rotate_num_chunks = 8; const std::size_t xor2_cells; const std::size_t xor3_cells; @@ -123,11 +110,30 @@ namespace nil { const std::size_t rot_cells = 22; const std::size_t chi_cells; + constexpr static const int r[5][5] = {{0, 3, 186, 84, 81}, + {108, 132, 18, 165, 60}, + {9, 30, 129, 75, 117}, + {123, 135, 45, 63, 24}, + {54, 6, 183, 168, 42}}; + + // all words in sparse form + const std::size_t word_size = 192; + const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui192; + + const std::size_t limit_permutation_column = 7; + + constexpr static const std::array + r_constants = {0, 36, 3, 41, 18, + 1, 44, 10, 45, 2, + 62, 6, 43, 15, 61, + 28, 55, 25, 21, 56, + 27, 20, 39, 8, 14}; + // full configuration is precalculated, then used in other functions std::array full_configuration; const std::size_t rows_amount; - constexpr static const std::size_t gates_amount = 1; + const std::size_t gates_amount = 1; struct input_type { std::array inner_state; @@ -139,116 +145,267 @@ namespace nil { std::array inner_state; result_type(const keccak_round &component, std::size_t start_row_index) { - + std::size_t num_config = 102; + std::size_t ind = 25; + inner_state[0] = var(component.W(component.full_configuration[num_config].copy_to[0].row), + component.full_configuration[num_config].copy_to[0].column); + for (int i = 1; i < 25; ++i) { + inner_state[ind - i] = var(component.W(component.full_configuration[num_config - i].copy_to[0].row), + component.full_configuration[num_config - i].copy_to[0].column); + } } }; - value_type normalize(value_type value) { + integral_type normalize(const integral_type& integral_value) const { integral_type result = 0; + integral_type value = integral_value; integral_type power = 1; - integral_type integral_value = integral_type(value.data); for (std::size_t i = 0; i < 64; ++i) { - result += (integral_value & 1) * power; + result += (value & 1) * power; power *= 8; - integral_value >>= 3; + value >>= 3; } - return value_type(result); + return result; } - configuration configure_xor(std::size_t row, std::size_t column, std::size_t num_args) { - std::size_t num_chunks = num_args == 2 ? normalize3_num_chunks - : num args == 3 ? normalize4_num_chunks - : normalize6_num_chunks; + integral_type chi(const integral_type& integral_value) const { + integral_type result = 0; + integral_type value = integral_value; + integral_type power = 1; + integral_type mask = 7; + int table[5] = {0, 1, 1, 0, 0}; + for (std::size_t i = 0; i < 64; ++i) { + int bit = table[int(value & mask)]; + result += bit * power; + power *= 8; + value >>= 8; + } + return result; + } + + struct configuration { + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + }; + + // In constraints we use such notation: constr[0] - result, + // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates last_coordinate; + std::vector copy_from; + std::vector> constraints; + std::vector> lookups; + coordinates copy_to; + + configuration() = default; + configuration(std::pair last_coordinate_, + std::vector> copy_from_, + std::vector>> constraints_, + std::vector>> lookups_, + std::pair copy_to_) { + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_from_.size(); ++i) { + copy_from[i] = coordinates(copy_from_[i]); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + for (std::size_t j = 0; j < constraints[i].size(); ++j) { + constraints[i][j] = coordinates(constraints_[i][j]); + } + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + for (std::size_t j = 0; j < lookups[i].size(); ++j) { + lookups[i][j] = coordinates(lookups_[i][j]); + } + } + copy_to = coordinates(copy_to_); + }; + }; + + configuration configure_inner(std::size_t row, std::size_t column, std::size_t num_args, + std::size_t num_chunks, std::size_t num_cells) { + std::size_t last_row = row, last_column = column; - std::vector> copy_constrain_from = {{last_row, last_column++}}; - for (int i = 0; i < num_args - 1; ++i) { - copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); - } + + std::vector> copy_from; - std::vector>> constraints = - {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; + if (num_args + column > limit_permutation_column) { + for (int i = 0; i < num_args; ++i) { + copy_from.push_back({last_row + 1, i}); + } + } else { + for (int i = 0; i < num_args; ++i) { + copy_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + } + + std::pair cell_copy_to; + std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + if (final_row == copy_from[0].first) { + cell_copy_to = {final_row, copy_from.back().second + 1}; + } else { + cell_copy_to = {final_row, 0}; + } + + std::vector> cells; + std::pair cell_copy_to; + if (num_args + column > limit_permutation_column) { + for (int i = column; i < WitnessesAmount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cur_row = row + 1, + cur_column = num_args; + while (cur_column < cells_left) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } else { + std::size_t cur_row = row, + cur_column = column + num_args; + while (cur_column - column < num_cells) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } + std::size_t cell_index = 0; + + std::vector>> constraints; + constraints.push_back({cells[cell_index++]}); for (int i = 0; i < num_args; ++i) { - constraints[0].push_back(copy_constrain_from[i]); + constraints[0].push_back(copy_from[i]); } + constraints.push_back({constraints[0][0]}); - constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); - std::vector> copy_constrain_to = {constraints[2][0]}; - std::vector>> lookups(num_chunks, std::vector>); + constraints.push_back({cell_copy_to}); + std::vector>> lookups(num_chunks, std::vector>()); for (std::size_t i = 1; i < 3; ++i) { for (std::size_t j = 0; j < num_chunks; ++j) { - constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); + constraints[i].push_back(cells[cell_index++]); lookups[j].push_back(constraints[i].back()); } } - BOOST_ASSERT(last_column - column == xor2_cells); - last_row += last_column / WitnessesAmount; + last_column = cells.back().second + 1; + last_row = cells.back().first + (last_column > WitnessesAmount); last_column %= WitnessesAmount; - return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + } + + configuration configure_xor(std::size_t row, std::size_t column, int num_args) { + // regular constraints: + // sum = arg1 + arg2 + ... + argn + // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) + // norm_sum = norm_sum_chunk0 + norm_sum_chunk1 * 2^chunk_size + ... + norm_sum_chunkk * 2^(k*chunk_size) + + std::size_t num_chunks = num_args == 2 ? normalize3_num_chunks + : num_args == 3 ? normalize4_num_chunks + : normalize6_num_chunks; + std::size_t num_cells = num_chunks * 2 + num_args + 2; + + return configure_inner(row, column, num_args, num_chunks, num_cells); } configuration configure_chi(std::size_t row, std::size_t column) { - std::size_t last_row = row, - last_column = column; - std::vector> copy_constrain_from; - for (int i = 0; i < 3; ++i) { - copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); - } + // regular constraints: + // sum = sparse_3 - 2 * a + b - c; + // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) + // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * 2^(k*chunk_size) - std::vector>> constraints = - {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; - for (int i = 0; i < 3; ++i) { - constraints[0].push_back(copy_constrain_from[i]); - } - constraints.push_back({constraints[0][0]}); - constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); - std::vector> copy_constrain_to = {constraints[2][0]}; - std::vector>> lookups(chi_num_chunks, std::vector>); - for (std::size_t i = 1; i < 3; ++i) { - for (std::size_t j = 0; j < chi_num_chunks; ++j) { - constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); - lookups[j].push_back(constraints[i].back()); - } - } + std::size_t num_args = 3; + std::size_t num_cells = num_chunks * 2 + num_args + 2; - BOOST_ASSERT(last_column - column == xor2_cells); - last_row += last_column / WitnessesAmount; - last_column %= WitnessesAmount; - return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + return configure_inner(row, column, num_args, chi_num_chunks, num_cells); } configuration configure_rot(std::size_t row, std::size_t column) { + // regular constraints: + // a = big_part << r + small_part; + // a_rot = small_part << (192 - r) + big_part; + // bound_big = big_part - (1 << (192 - r)) + (1 << 192); + // bound_small = small_part - (1 << r) + (1 << 192); + // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) + // bound_small = small_chunk0 + small_chunk1 * 2^chunk_size + ... + small_chunkk * 2^(k*chunk_size) + std::size_t last_row = row, last_column = column; - std::vector> copy_constrain_from; - for (int i = 0; i < 3; ++i) { - copy_constrain_from.push_back({last_row + (last_column / WitnessesAmount), + + std::vector> copy_from; + std::pair cell_copy_to; + std::vector>> constraints; + + if (2 + column > limit_permutation_column) { + copy_from.push_back({last_row + 1, 0}); + cell_copy_to = {last_row + 1, 1}; + } else { + copy_from.push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); + cell_copy_to = {last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}; } - - std::vector>> constraints = - {{{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}}; - for (int i = 0; i < 3; ++i) { - constraints[0].push_back(copy_constrain_from[i]); - } - constraints.push_back({constraints[0][0]}); - constraints.push_back({{last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}}); - std::vector> copy_constrain_to = {constraints[2][0]}; - std::vector>> lookups(chi_num_chunks, std::vector>); - for (std::size_t i = 1; i < 3; ++i) { - for (std::size_t j = 0; j < chi_num_chunks; ++j) { - constraints[i].push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); - lookups[j].push_back(constraints[i].back()); + + std::vector> cells; + if (2 + column > limit_permutation_column) { + for (int i = column; i < WitnessesAmount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cur_row = row + 1, + cur_column = 2; + while (cur_column < cells_left) { + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); } + } else { + std::size_t cur_row = row, + cur_column = column + 2; + while (cur_column - column < num_cells) { + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } + std::size_t cell_index = 0; + + constraints.push_back({copy_from[0]}); + constraints[0].push_back(cells[cell_index++]); + constraints[0].push_back(cells[cell_index++]); + + constraints.push_back({cell_copy_to}); + constraints[1].push_back(constraints[0][2]); + constraints[1].push_back(constraints[0][1]); + + std::vector>> lookups(2, std::vector>()); + + constraints.push_back({cells[cell_index++]}); + constraints[2].push_back(constraints[0][1]); + constraints.push_back({constraints[2][0]}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[3].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[3].back()); } - - BOOST_ASSERT(last_column - column == xor2_cells); - last_row += last_column / WitnessesAmount; + + constraints.push_back({cells[cell_index++]}); + constraints[4].push_back(constraints[0][2]); + constraints.push_back({constraints[4][0]}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[5].push_back(cells[cell_index++]); + lookups[1].push_back(constraints[5].back()); + } + + last_column = cells.back().second + 1; + last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - return configuration({last_row, last_column}, copy_constrain_from, constraints, lookups, copy_constrain_to); + + return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } std::array configure_all() { @@ -299,14 +456,18 @@ namespace nil { #define __keccak_round_init_macro(lookup_rows_, lookup_columns_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ - normalize3_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 3)), \ - normalize4_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 4)), \ - normalize6_chunk_size(calculate_normalize_num_chunks(lookup_rows_, 6)), \ - chi_chunk_size(calculate_chi_num_chunks(lookup_rows_)), \ - xor2_cells((64 / normalize3_chunk_size + bool(64 % normalize3_chunk_size)) * 2 + 2 + 2), \ - xor3_cells((64 / normalize4_chunk_size + bool(64 % normalize4_chunk_size)) * 2 + 3 + 2), \ - xor5_cells((64 / normalize6_chunk_size + bool(64 % normalize6_chunk_size)) * 2 + 5 + 2), \ - chi_cells((64 / chi_chunk_size + bool(64 % chi_chunk_size)) * 2 + 5), \ + normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ + normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ + normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ + chi_chunk_size(calculate_chi_chunk_size(lookup_rows_)), \ + normalize3_num_chunks(calculate_num_chunks(normalize3_chunk_size)), \ + normalize4_num_chunks(calculate_num_chunks(normalize4_chunk_size)), \ + normalize6_num_chunks(calculate_num_chunks(normalize6_chunk_size)), \ + chi_num_chunks(calculate_num_chunks(chi_chunk_size)), \ + xor2_cells(normalize3_num_chunks * 2 + 2 + 2), \ + xor3_cells(normalize4_num_chunks * 2 + 3 + 2), \ + xor5_cells(normalize6_num_chunks * 2 + 5 + 2), \ + chi_cells(chi_num_chunks * 2 + 5), \ full_configuration(configure_all()), \ rows_amount(rows()), \ gates_amount(gates()) @@ -364,7 +525,6 @@ namespace nil { using component_type = keccak_round_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; @@ -390,8 +550,41 @@ namespace nil { using component_type = keccak_round_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; - std::uint32_t row = start_row_index; + + std::size_t config_index = 0; + auto config = component.full_configuration; + + // TODO: finish copy_constraints + for (int i = 0; i < 17; ++i) { + bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_from[0].row), config[i].copy_from[0].column, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_from[1].row), config[i].copy_from[1].column, false)}); + } + } + + template= 9, bool> = true> + void generate_assignments_constant( + const keccak_round_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_round_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_round_component; + // TODO: need to find the exact answer + std::size_t row = start_row_index + 242 + 3; + for (std::size_t i = 0; i < 25; i++) { + assignment.constant(component.C(0), row + i * 8) = component_type::r_constants[i]; + } } template; using var = typename component_type::var; - using var_address = typename component_type::var_address; BOOST_ASSERT(row == start_row_index + component.rows_amount); @@ -446,14 +638,12 @@ namespace nil { &instance_input, const std::uint32_t start_row_index) { - std::size_t row = start_row_index; - using component_type = keccak_round_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - using var_address = typename component_type::var_address; + std::size_t word_size = component.word_size; int config_index = 0; @@ -465,31 +655,29 @@ namespace nil { value_type sum = state + message; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize3_chunk_size; - std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); - std::vector chunks; - std::vector normalized_chunks; - integral_type mask = (1 << (3 * chunk_size)) - 1; - value_type power = 1; - value_type normalized_sum = 0; + auto num_chunks = component.normalize3_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (1 << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { - chunks.push_back(value_type(integral_sum & mask)); + integral_chunks.push_back(integral_sum & mask); integral_sum >>= chunk_size; - normalized_chunks.push_back(normalize(chunks.back())); - normalized_sum += normalized_chunks.back() * power; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; power *= chunk_size; } - A_1[index] = normalized_sum; + A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = state; assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = message; - assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; - for (int j = 1; j < cur_config.constraint[1].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; - } - for (int j = 1; j < cur_config.constraint[2].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } } for (int i = 17; i < 25; ++i) { @@ -502,55 +690,72 @@ namespace nil { for (int index = 0; index < 5; ++index) { value_type sum = 0; for (int j = 0; j < 5; ++j) { - sum += A_1[index + 5 * j]; + sum += A_1[5 * index + j]; } integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize6_chunk_size; - std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); - std::vector chunks; - std::vector normalized_chunks; - integral_type mask = (1 << (3 * chunk_size)) - 1; - value_type power = 1; - value_type normalized_sum = 0; + auto num_chunks = component.normalize6_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (1 << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { - chunks.push_back(value_type(integral_sum & mask)); + integral_chunks.push_back(integral_sum & mask); integral_sum >>= chunk_size; - normalized_chunks.push_back(normalize(chunks.back())); - normalized_sum += normalized_chunks.back() * power; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; power *= chunk_size; } - C[index] = normalized_sum; + C[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = A_1[index + 5]; - assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = A_1[index + 10]; - assignment.witness(component.W(cur_config.copy_from[3].row), cur_config.copy_from[3].column) = A_1[index + 15]; - assignment.witness(component.W(cur_config.copy_from[4].row), cur_config.copy_from[4].column) = A_1[index + 20]; - assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; - for (int j = 1; j < cur_config.constraint[1].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; - } - for (int j = 1; j < cur_config.constraint[2].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = A_1[index + 1]; + assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = A_1[index + 2]; + assignment.witness(component.W(cur_config.copy_from[3].row), cur_config.copy_from[3].column) = A_1[index + 3]; + assignment.witness(component.W(cur_config.copy_from[4].row), cur_config.copy_from[4].column) = A_1[index + 4]; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } } config_index += 5; - // TODO: rot std::array C_rot; for (int index = 0; index < 5; ++index) { integral_type integral_C = integral_type(C[index].data); integral_type smaller_part = integral_C & ((1 << 3) - 1); integral_type bigger_part = integral_C >> 3; - integral_type integral_C_rot = (bigger_part << 3) + smaller_part; + integral_type integral_C_rot = (smaller_part << 189) + bigger_part; C_rot[index] = value_type(integral_C_rot); - integral_type bound_smaller = smaller_part - (1 << 3) + + integral_type bound_smaller = smaller_part - (1 << 3) + (integral_type(1) << 192); + integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); + auto chunk_size = component.rotate_chunk_size; + auto num_chunks = component.rotate_num_chunks; + std::vector integral_small_chunks; + std::vector integral_big_chunks; + integral_type mask = (1 << chunk_size) - 1; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_small_chunks.push_back(bound_smaller & mask); + bound_smaller >>= chunk_size; + integral_big_chunks.push_back(bound_bigger & mask); + bound_bigger >>= chunk_size; + } auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = C[index]; - + assignment.witness(component.W(cur_config.copy_to.row), cur_config.copy_to.column) = C_rot[index]; + assignment.witness(component.W(cur_config.constraints[0][1].row), cur_config.constraints[0][1].column) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].row), cur_config.constraints[0][2].column) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].row), cur_config.constraints[3][0].column) = value_type(bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].row), cur_config.constraints[5][0].column) = value_type(bound_bigger); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[3][j].row), cur_config.constraints[3][j].column) = value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].row), cur_config.constraints[5][j].column) = value_type(integral_big_chunks[j - 1]); + } } config_index += 5; @@ -559,32 +764,30 @@ namespace nil { value_type sum = A_1[index] + C_rot[(index + 1) % 5] + C[(index - 1) % 5]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; - std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); - std::vector chunks; - std::vector normalized_chunks; - integral_type mask = (1 << (3 * chunk_size)) - 1; - value_type power = 1; - value_type normalized_sum = 0; + auto num_chunks = component.normalize4_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (1 << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { - chunks.push_back(value_type(integral_sum & mask)); + integral_chunks.push_back(integral_sum & mask); integral_sum >>= chunk_size; - normalized_chunks.push_back(normalize(chunks.back())); - normalized_sum += normalized_chunks.back() * power; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; power *= chunk_size; } - A_2[index] = normalized_sum; + A_2[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = C_rot[(index + 1) % 5]; assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = C[(index - 1) % 5]; - assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; - for (int j = 1; j < cur_config.constraint[1].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; - } - for (int j = 1; j < cur_config.constraint[2].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = normalized_chunks[j - 1]; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } } config_index += 25; @@ -592,93 +795,111 @@ namespace nil { // rho/phi std::array, 5> B; B[0][0] = A_2[0]; - // TODO: finish rot(r) for (int index = 1; index < 25; ++index) { - int x = index % 5; - int y = index / 5; + int x = index / 5; + int y = index % 5; + int r = r_constants[x][y]; + int minus_r = 192 - r_constants[x][y]; integral_type integral_A = integral_type(A_2[index].data); - integral_type smaller_part = integral_A & ((1 << 3) - 1); - integral_type bigger_part = integral_A >> 3; - integral_type integral_A_rot = (bigger_part << 3) + smaller_part; + integral_type smaller_part = integral_A & ((1 << r) - 1); + integral_type bigger_part = integral_A >> r; + integral_type integral_A_rot = (smaller_part << minus_r) + bigger_part; B[y][2*x + 3*y] = value_type(integral_A_rot); + integral_type bound_smaller = smaller_part - (1 << r) + (integral_type(1) << 192); + integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); + auto chunk_size = component.rotate_chunk_size; + auto num_chunks = component.rotate_num_chunks; + std::vector integral_small_chunks; + std::vector integral_big_chunks; + integral_type mask = (1 << chunk_size) - 1; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_small_chunks.push_back(bound_smaller & mask); + bound_smaller >>= chunk_size; + integral_big_chunks.push_back(bound_bigger & mask); + bound_bigger >>= chunk_size; + } + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_2[index]; + assignment.witness(component.W(cur_config.copy_to.row), cur_config.copy_to.column) = B[y][2*x + 3*y]; + assignment.witness(component.W(cur_config.constraints[0][1].row), cur_config.constraints[0][1].column) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].row), cur_config.constraints[0][2].column) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].row), cur_config.constraints[3][0].column) = value_type(bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].row), cur_config.constraints[5][0].column) = value_type(bound_bigger); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[3][j].row), cur_config.constraints[3][j].column) = value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].row), cur_config.constraints[5][j].column) = value_type(integral_big_chunks[j - 1]); + } } config_index += 24; // chi - // TODO: chunk size need to be for sparse form so no times 3 anywhere std::array A_3; for (int index = 0; index < 25; ++index) { - int x = index % 5; - int y = index / 5; + int x = index / 5; + int y = index % 5; value_type sum = component.sparse_3 - 2 * B[x][y] + B[(x+1)%5][y] - B[(x+2)%5][y]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.chi_chunk_size; - std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); - std::vector chunks; - std::vector chi_chunks; - integral_type mask = (1 << (3 * chunk_size)) - 1; - value_type power = 1; - value_type chi_sum = 0; + auto num_chunks = component.chi_num_chunks; + std::vector integral_chunks; + std::vector integral_chi_chunks; + integral_type mask = (1 << chunk_size) - 1; + integral_type power = 1; + integral_type integral_chi_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { - chunks.push_back(value_type(integral_sum & mask)); + integral_chunks.push_back(integral_sum & mask); integral_sum >>= chunk_size; - chi_chunks.push_back(chi(chunks.back())); - chi_sum += chi_chunks.back() * power; + integral_chi_chunks.push_back(component.chi(integral_chunks.back())); + integral_chi_sum += integral_chi_chunks.back() * power; power *= chunk_size; } - A_3[index] = chi_sum; + A_3[index] = value_type(integral_chi_sum); auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = B[x][y]; assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = B[(x+1)%5][y]; assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = B[(x+2)%5][y]; - assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = chi_sum; - for (int j = 1; j < cur_config.constraint[1].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; - } - for (int j = 1; j < cur_config.constraint[2].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = chi_chunks[j - 1]; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_chi_sum); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_chi_chunks[j - 1]); } } config_index += 25; // iota - // TODO: power and norm_sum - maybe integral type? value_type round_constant = var_value(assignment, instance_input.round_constant); value_type sum = A_3[0] + round_constant; integral_type integral_sum = integral_type(sum.data); - auto chunk_size = component.chi_chunk_size; - std::size_t num_chunks = 64 / chunk_size + bool(64 % chunk_size); - std::vector chunks; - std::vector normalized_chunks; - integral_type mask = (1 << (3 * chunk_size)) - 1; - value_type power = 1; - value_type normalized_sum = 0; + auto chunk_size = component.normalize3_chunk_size; + auto num_chunks = component.normalize3_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (1 << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { - chunks.push_back(value_type(integral_sum & mask)); + integral_chunks.push_back(integral_sum & mask); integral_sum >>= chunk_size; - normalized_chunks.push_back(chi(chunks.back())); - normalized_sum += normalized_chunks.back() * power; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; power *= chunk_size; } - value_type A_4 = normalized_sum; + value_type A_4 = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_3[0]; assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = round_constant; - assignment.witness(component.W(cur_config.constraint[1][0].row), cur_config.constraint[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraint[2][0].row), cur_config.constraint[2][0].column) = normalized_sum; - for (int j = 1; j < cur_config.constraint[1].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[1][j].row), cur_config.constraint[1][j].column) = chunks[j - 1]; - } - for (int j = 1; j < cur_config.constraint[2].size(); ++j) { - assignment.witness(component.W(cur_config.constraint[2][j].row), cur_config.constraint[2][j].column) = chi_chunks[j - 1]; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } - BOOST_ASSERT(row == start_row_index + component.rows_amount); - return typename component_type::result_type(component, start_row_index); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 23fc015d1..bff01142e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,6 +95,7 @@ set(PLONK_TESTS_FILES "hashes/plonk/sha512" "hashes/plonk/sha256_process" "hashes/plonk/sha512_process" + "hashes/plonk/keccak_round" "hashes/plonk/decomposition" "hashes/plonk/detail/sha_table_generators_base4" "hashes/plonk/detail/sha_table_generators_base7" diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 4f1dd9509..cd0558774 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -41,6 +41,7 @@ #include #include + #include #include "../../test_plonk_component.hpp" @@ -54,50 +55,81 @@ const int r[5][5] = {{0, 1, 62, 28, 27}, // here for level we use: // 0 - inner ^ chunk, 1 - theta, 2 - rho/phi, 3 - chi, 4 - iota (full round, by default) template -std::array round_function(std::array inner_state, - std::array padded_message_chunk, +std::array round_function(std::array inner_state, + std::array padded_message_chunk, typename BlueprintFieldType::value_type RC) { - #define rot(x, s) (((x) << s) | ((x) >> (64 - s))); + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::array inner_state_integral; + std::array padded_message_chunk_integral; + integral_type RC_integral = integral_type(RC.data); + for (int i = 0; i < 25; ++i) { + inner_state_integral[i] = integral_type(inner_state[i].data); + } + for (int i = 0; i < 17; ++i) { + padded_message_chunk_integral[i] = integral_type(padded_message_chunk[i].data); + } + + auto rot = [](integral_type x, const int s) { + return ((x << s) | (x >> (64 - s))); + }; + for (int i = 0; i < 17; ++i) { - inner_state[i] = inner_state[i] ^ padded_message_chunk[i]; + inner_state_integral[i] = inner_state_integral[i] ^ padded_message_chunk_integral[i]; } if (level == 0) { + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(inner_state_integral[i]); + } return inner_state; } // theta - std::array C; + std::array C; for (int x = 0; x < 5; ++x) { - C[x] = inner_state[5 * x] ^ inner_state[5 * x + 1] ^ inner_state[5 * x + 2] ^ inner_state[5 * x + 3] ^ - inner_state[5 * x + 4]; + C[x] = inner_state_integral[5 * x] ^ inner_state_integral[5 * x + 1] ^ inner_state_integral[5 * x + 2] ^ inner_state_integral[5 * x + 3] ^ + inner_state_integral[5 * x + 4]; for (int y = 0; y < 5; ++y) { - inner_state[5 * x + y] = inner_state[5 * x + y] ^ C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); + inner_state_integral[5 * x + y] = inner_state_integral[5 * x + y] ^ C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); } } if (level == 1) { + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(inner_state_integral[i]); + } return inner_state; } // rho and pi - std::array B; + std::array B; for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { - B[5 * y + ((2 * x + 3 * y) % 5)] = rot(inner_state[5 * x + y], r[x, y]); + B[5 * y + ((2 * x + 3 * y) % 5)] = rot(inner_state_integral[5 * x + y], r[x][y]); } } if (level == 2) { - return B; + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(B[i]); + } + return inner_state; } // chi for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { - inner_state[5 * x + y] = B[5 * x + y] ^ ((~B[5 * x + ((y + 1) % 5)]) & B[5 * x + ((y + 2) % 5)]); + inner_state_integral[5 * x + y] = B[5 * x + y] ^ ((~B[5 * x + ((y + 1) % 5)]) & B[5 * x + ((y + 2) % 5)]); } } if (level == 3) { + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(inner_state_integral[i]); + } return inner_state; } // iota - inner_state[0] = inner_state[0] ^ RC; + inner_state_integral[0] = inner_state_integral[0] ^ RC_integral; + for (int i = 0; i < 25; ++i) { + inner_state[i] = value_type(inner_state_integral[i]); + } return inner_state; } @@ -175,7 +207,7 @@ void test_keccak_round_random() { nil::crypto3::random::algebraic_engine generate_random; boost::random::mt19937 seed_seq; generate_random.seed(seed_seq); - uint64_t range = value_type(2).pow(64) - 1; + uint64_t range = 18446744073709551615U; //2^64 - 1 boost::random::uniform_int_distribution distribution(0, range); @@ -184,12 +216,12 @@ void test_keccak_round_random() { value_type RC = value_type(0); for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(distribution(generate_random)); + inner_state[i] = generate_random(); } for (int i = 0; i < 17; ++i) { - padded_message_chunk[i] = value_type(distribution(generate_random)); + padded_message_chunk[i] = generate_random(); } - RC = value_type(distribution(generate_random)); + RC = generate_random(); test_keccak_round_inner (inner_state, padded_message_chunk, RC); @@ -199,8 +231,8 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - test_keccak_round(); - test_keccak_round(); + test_keccak_round_random(); + test_keccak_round_random(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { From 75d015503a18464b56999bcc5e916181887f7fa0 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 27 Jul 2023 20:08:14 +0000 Subject: [PATCH 03/48] gates calculation #183 --- .../hashes/keccak/keccak_component.hpp | 211 +++++++++--- .../hashes/keccak/keccak_per_chunk.hpp | 62 +++- .../components/hashes/keccak/keccak_round.hpp | 301 +++++++++++++----- 3 files changed, 437 insertions(+), 137 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 26e818c7a..abaa5a474 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -44,16 +44,7 @@ namespace nil { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; - - std::size_t calculate_normalize_chunk_size(std::size_t num_rows, std::size_t i) { - std::size_t res = 0; - std::size_t power = i; - while (power < num_rows) { - ++res; - power *= i; - } - return res; - } + using integral_type = typename BlueprintFieldType::integral_type; std::size_t rows() const { return 0; @@ -62,74 +53,212 @@ namespace nil { public: using var = typename component_type::var; - using per_chunk_component_type = keccak_per_chunk, WitnessesAmount>; - std::array rounds; + std::vector rounds; + + using configuration = round_component_type::configuration; + std::vector full_configuration; const std::size_t lookup_rows; const std::size_t lookup_columns; - const std::size_t normalize3_chunk_size; - const std::size_t normalize4_chunk_size; - const std::size_t normalize6_chunk_size; + + const std::size_t num_blocks; + const std::size_t num_round_calls; + const std::size_t num_configs; + + const std::size_t pack_chunk_size; + const std::size_t pack_num_chunks; + const std::size_t pack_num_cells; - constexpr static const bool needs_bonus_row = WitnessesAmount < 5; const std::size_t rows_amount; constexpr static const std::size_t gates_amount = 1; struct input_type { - std::array inner_state; - std::array padded_message_chunk; - var round_constant; + std::vector message; }; struct result_type { std::array final_inner_state; result_type(const keccak &component, std::size_t start_row_index) { - std::pair - r_address = component.get_var_address(var_address::R_, start_row_index), - q_address = component.get_var_address(var_address::Q, start_row_index); - - quotient = var(component.W(q_address.second), q_address.first); - remainder = var(component.W(r_address.second), r_address.first); + } }; + integral_type pack(const integral_type& const_input) const { + integral_type input = const_input; + integral_type sparse_res = 0; + integral_type power = 1; + while (input > 0) { + auto bit = input % 2; + sparse_res += bit * power; + power *= 8; + input /= 2; + } + return sparse_res; + } + + integral_type unpack(const integral_type& const_sparse_input) const { + integral_type sparse_input = const_sparse_input; + integral_type res = 0; + integral_type power = 1; + while (sparse_input > 0) { + auto bit = sparse_input % 8; + BOOST_ASSERT(bit * (1 - bit) == 0); + res += bit * power; + power *= 2; + sparse_input /= 8; + } + return res; + } + + configuration configure_pack_unpack(std::size_t row, std::size_t column) { + // regular constraints: + // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) + // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) + + std::size_t last_row = row, + last_column = column; + + std::vector> copy_from; + std::vector>> constraints; + + if (1 + column > limit) { + copy_from.push_back({last_row + 1, 0}); + } else { + copy_from.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + + std::pair cell_copy_to; + std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + if (final_row == copy_from[0].first) { + cell_copy_to = {final_row, copy_from.back().second + 1}; + } else { + cell_copy_to = {final_row, 0}; + } + + std::vector> cells; + if (1 + column > limit) { + for (int i = column; i < WitnessesAmount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cur_row = row + 1, + cur_column = 1; + while (cur_column < cells_left) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } else { + std::size_t cur_row = row, + cur_column = column + 1; + while (cur_column - column < num_cells) { + if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } + std::size_t cell_index = 0; + + std::vector>> lookups(num_chunks, std::vector>()); + + constraints.push_back({copy_from[0]}); + constraints.push_back({cell_copy_to}); + for (std::size_t i = 0; i < 2; ++i) { + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[i].push_back(cells[cell_index++]); + lookups[j].push_back(constraints[i].back()); + } + } + + last_column = cells.back().second + 1; + last_row = cells.back().first + (last_column / WitnessesAmount); + last_column %= WitnessesAmount; + + + return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + } + + std::vector configure_all(const std::size_t num_configs, + const std::size_t num_round_calls) { + std::vector result; + std::size_t round_rows = round_component_type::rows_amount; + + std::size_t row = 0, + column = 0; + // padding + + // rounds + for (std::size_t index = 0; index < num_round_calls; ++index) { + for (std::size_t i = 0; i < 17; ++i) { + result.push_back(configure_pack_unpack(row, column)); + row = result[i].last_row; + column = result[i].last_column; + } + if (column > 0) { + column = 0; + row += 1 + 24 * round_rows; + } else { + row += 24 * round_rows; + } + } + + // finalization + for (std::size_t i = 0; i < 5; ++i) { + result.push_back(configure_pack_unpack(row, column)); + row = result[i].last_row; + column = result[i].last_column; + } + + return result; + } + #define __keccak_init_macro(witness, constant, public_input, \ - lookup_rows_, lookup_columns_) \ + lookup_rows_, lookup_columns_, num_blocks_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ - normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ - normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ - normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ - range_checks(range_check_amount, \ - range_check_component_type(witness, constant, public_input, bits_amount_)), \ + num_blocks(num_blocks_), \ + num_round_calls(), \ + rounds(num_round_calls * 24, \ + round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ + num_configs(), \ + full_configuration(configure_all(num_configs, num_round_calls)), \ rows_amount(rows()) template - division_remainder(ContainerType witness, std::size_t bits_amount_, bool check_inputs_) : + keccak(ContainerType witness, std::size_t lookup_rows_, + std::size_t lookup_columns_, std::size_t num_blocks_) : component_type(witness, {}, {}), - __division_remainder_init_macro(witness, {}, {}, bits_amount_, check_inputs_) {}; + __keccak_init_macro(witness, {}, {}, lookup_rows_, lookup_columns_, num_blocks_) {}; template - division_remainder(WitnessContainerType witness, ConstantContainerType constant, + keccak(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t bits_amount_, bool check_inputs_): + std::size_t lookup_rows_, + std::size_t lookup_columns_, + std::size_t num_blocks_): component_type(witness, constant, public_input), - __division_remainder_init_macro(witness, constant, public_input, bits_amount_, check_inputs_) {}; + __keccak_init_macro(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_) {}; - division_remainder( + keccak( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t bits_amount_, bool check_inputs_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : component_type(witnesses, constants, public_inputs), - __division_remainder_init_macro(witnesses, constants, public_inputs, - bits_amount_, check_inputs_) + __keccak_init_macro(witnesses, constants, public_inputs, + lookup_rows_, lookup_columns_, num_blocks_) {}; #undef __keccak_init_macro @@ -161,7 +290,6 @@ namespace nil { using component_type = keccak_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; @@ -187,7 +315,6 @@ namespace nil { using component_type = keccak_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; std::uint32_t row = start_row_index; } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp index 27a8829a4..40aa0f62e 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp @@ -58,6 +58,7 @@ namespace nil { std::array rounds; using configuration = round_component_type::configuration; + std::array full_configuration; const std::size_t rows_amount; constexpr static const std::size_t gates_amount = 17 * round_component_type::gates_amount; @@ -75,6 +76,33 @@ namespace nil { } }; + integral_type pack(const integral_type& const_input) const { + integral_type input = const_input; + integral_type sparse_res = 0; + integral_type power = 1; + while (input > 0) { + auto bit = input % 2; + sparse_res += bit * power; + power *= 8; + input /= 2; + } + return sparse_res; + } + + integral_type unpack(const integral_type& const_sparse_input) const { + integral_type sparse_input = const_sparse_input; + integral_type res = 0; + integral_type power = 1; + while (sparse_input > 0) { + auto bit = sparse_input % 8; + BOOST_ASSERT(bit * (1 - bit) == 0); + res += bit * power; + power *= 2; + sparse_input /= 8; + } + return res; + } + configuration configure_pack_unpack(std::size_t row, std::size_t column) { // regular constraints: // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) @@ -148,28 +176,28 @@ namespace nil { return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } - // std::array configure_all() { - // std::array result; - // std::size_t row = 0, - // column = 0; - // for (std::size_t i = 0; i < 17; ++i) { - // result[i] = configure_pack_unpack(row, column); - // row = result[i].last_row; - // column = result[i].last_column; - // } - // return result; - // } + std::array configure_all() { + std::array result; + std::size_t row = 0, + column = 0; + for (std::size_t i = 0; i < 17; ++i) { + result[i] = configure_pack_unpack(row, column); + row = result[i].last_row; + column = result[i].last_column; + } + return result; + } #define __keccak_per_chunk_init_macro(witness, constant, public_input, \ lookup_rows_, lookup_columns_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ - normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ - normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ - normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ - range_checks(range_check_amount, \ - range_check_component_type(witness, constant, public_input, bits_amount_)), \ - rows_amount(rows()) + pack_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ + pack_num_chunks(calculate_num_chunks(normalize3_chunk_size)), \ + pack_cells(normalize3_num_chunks * 2 + 2 + 2), \ + full_configuration(configure_all()), \ + rows_amount(rows()), \ + gates_amount(gates()) template keccak_per_chunk(ContainerType witness, std::size_t bits_amount_, bool check_inputs_) : diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 8e9803706..908690bda 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -82,8 +82,15 @@ namespace nil { return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } std::size_t gates() const { - // TODO: need to find the exact answer - return rows() / 3 + bool(rows() % 3); + std::size_t res = 1; + auto cur_selector = gates_configuration[0]; + for (std::size_t i = 1; i < gates_configuration.size(); ++i) { + if (gates_configuration[i] != cur_selector) { + res++; + cur_selector = gates_configuration[i]; + } + } + return res; } public: @@ -131,9 +138,12 @@ namespace nil { // full configuration is precalculated, then used in other functions std::array full_configuration; + // number represents relative selector index for each constraint + std::vector gates_configuration; + std::vector lookup_gates_configuration; const std::size_t rows_amount; - const std::size_t gates_amount = 1; + const std::size_t gates_amount; struct input_type { std::array inner_state; @@ -145,13 +155,12 @@ namespace nil { std::array inner_state; result_type(const keccak_round &component, std::size_t start_row_index) { - std::size_t num_config = 102; - std::size_t ind = 25; - inner_state[0] = var(component.W(component.full_configuration[num_config].copy_to[0].row), - component.full_configuration[num_config].copy_to[0].column); + std::size_t num_config = 101; + inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from[0].row), + component.full_configuration[num_config].copy_from[0].column); for (int i = 1; i < 25; ++i) { - inner_state[ind - i] = var(component.W(component.full_configuration[num_config - i].copy_to[0].row), - component.full_configuration[num_config - i].copy_to[0].column); + inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from[0].row), + component.full_configuration[num_config - i].copy_from[0].column); } } }; @@ -196,20 +205,20 @@ namespace nil { // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. coordinates last_coordinate; - std::vector copy_from; + std::vector copy_to; std::vector> constraints; std::vector> lookups; - coordinates copy_to; + coordinates copy_from; configuration() = default; configuration(std::pair last_coordinate_, - std::vector> copy_from_, + std::vector> copy_to_, std::vector>> constraints_, std::vector>> lookups_, - std::pair copy_to_) { + std::pair copy_from_) { last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_from_.size(); ++i) { - copy_from[i] = coordinates(copy_from_[i]); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to[i] = coordinates(copy_to_[i]); } for (std::size_t i = 0; i < constraints_.size(); ++i) { for (std::size_t j = 0; j < constraints[i].size(); ++j) { @@ -221,7 +230,7 @@ namespace nil { lookups[i][j] = coordinates(lookups_[i][j]); } } - copy_to = coordinates(copy_to_); + copy_from = coordinates(copy_from_); }; }; @@ -231,29 +240,29 @@ namespace nil { std::size_t last_row = row, last_column = column; - std::vector> copy_from; + std::vector> copy_to; if (num_args + column > limit_permutation_column) { for (int i = 0; i < num_args; ++i) { - copy_from.push_back({last_row + 1, i}); + copy_to.push_back({last_row + 1, i}); } } else { for (int i = 0; i < num_args; ++i) { - copy_from.push_back({last_row + (last_column / WitnessesAmount), + copy_to.push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); } } - std::pair cell_copy_to; + std::pair cell_copy_from; std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; - if (final_row == copy_from[0].first) { - cell_copy_to = {final_row, copy_from.back().second + 1}; + if (final_row == copy_to[0].first) { + cell_copy_from = {final_row, copy_to.back().second + 1}; } else { - cell_copy_to = {final_row, 0}; + cell_copy_from = {final_row, 0}; } std::vector> cells; - std::pair cell_copy_to; + std::pair cell_copy_from; if (num_args + column > limit_permutation_column) { for (int i = column; i < WitnessesAmount; ++i) { cells.push_back({row, i}); @@ -262,7 +271,7 @@ namespace nil { std::size_t cur_row = row + 1, cur_column = num_args; while (cur_column < cells_left) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { cur_column++; continue; } @@ -272,7 +281,7 @@ namespace nil { std::size_t cur_row = row, cur_column = column + num_args; while (cur_column - column < num_cells) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { cur_column++; continue; } @@ -284,11 +293,11 @@ namespace nil { std::vector>> constraints; constraints.push_back({cells[cell_index++]}); for (int i = 0; i < num_args; ++i) { - constraints[0].push_back(copy_from[i]); + constraints[0].push_back(copy_to[i]); } constraints.push_back({constraints[0][0]}); - constraints.push_back({cell_copy_to}); + constraints.push_back({cell_copy_from}); std::vector>> lookups(num_chunks, std::vector>()); for (std::size_t i = 1; i < 3; ++i) { for (std::size_t j = 0; j < num_chunks; ++j) { @@ -300,7 +309,7 @@ namespace nil { last_column = cells.back().second + 1; last_row = cells.back().first + (last_column > WitnessesAmount); last_column %= WitnessesAmount; - return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } configuration configure_xor(std::size_t row, std::size_t column, int num_args) { @@ -341,17 +350,17 @@ namespace nil { std::size_t last_row = row, last_column = column; - std::vector> copy_from; - std::pair cell_copy_to; + std::vector> copy_to; + std::pair cell_copy_from; std::vector>> constraints; if (2 + column > limit_permutation_column) { - copy_from.push_back({last_row + 1, 0}); - cell_copy_to = {last_row + 1, 1}; + copy_to.push_back({last_row + 1, 0}); + cell_copy_from = {last_row + 1, 1}; } else { - copy_from.push_back({last_row + (last_column / WitnessesAmount), + copy_to.push_back({last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}); - cell_copy_to = {last_row + (last_column / WitnessesAmount), + cell_copy_from = {last_row + (last_column / WitnessesAmount), (last_column++) % WitnessesAmount}; } @@ -375,11 +384,11 @@ namespace nil { } std::size_t cell_index = 0; - constraints.push_back({copy_from[0]}); + constraints.push_back({copy_to[0]}); constraints[0].push_back(cells[cell_index++]); constraints[0].push_back(cells[cell_index++]); - constraints.push_back({cell_copy_to}); + constraints.push_back({cell_copy_from}); constraints[1].push_back(constraints[0][2]); constraints[1].push_back(constraints[0][1]); @@ -405,7 +414,7 @@ namespace nil { last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } std::array configure_all() { @@ -453,6 +462,58 @@ namespace nil { return result; } + std::vector configure_gates() { + std::vector> pairs; + for (std::size_t i = 0; i < 102; ++i) { + for (auto constr : full_configuration[i].constraints) { + std::size_t min = std::min(constr[0].row, constr[1].row); + std::size_t max = constr.back().row; + BOOST_ASSERT(max - min <= 2); + pairs.push_back({min, max}); + } + } + std::vector result; + std::size_t cur_row = 0; + while (cur_row < rows_amount) { + std::size_t cur_constr = 0; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + result.push_back(cur_row + 1); + ++cur_constr; + } + if (cur_constr == pairs.size()) { + break; + } + cur_row = pairs[cur_constr].first; + } + return result; + } + + std::vector configure_lookup_gates() { + std::vector> pairs; + for (std::size_t i = 0; i < 102; ++i) { + for (auto constr : full_configuration[i].lookups) { + std::size_t min = std::min(constr[0].row, constr[1].row); + std::size_t max = constr.back().row; + BOOST_ASSERT(max - min <= 2); + pairs.push_back({min, max}); + } + } + std::vector result; + std::size_t cur_row = 0; + while (cur_row < rows_amount) { + std::size_t cur_constr = 0; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + result.push_back(cur_row + 1); + ++cur_constr; + } + if (cur_constr == pairs.size()) { + break; + } + cur_row = pairs[cur_constr].first; + } + return result; + } + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ @@ -468,8 +529,10 @@ namespace nil { xor3_cells(normalize4_num_chunks * 2 + 3 + 2), \ xor5_cells(normalize6_num_chunks * 2 + 5 + 2), \ chi_cells(chi_num_chunks * 2 + 5), \ - full_configuration(configure_all()), \ rows_amount(rows()), \ + full_configuration(configure_all()), \ + gates_configuration(configure_gates()), \ + lookup_gates_configuration(configure_lookup_gates()), \ gates_amount(gates()) template @@ -528,6 +591,17 @@ namespace nil { using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; + + auto config = component.full_configuration; + auto gate_config = component.gates_configuration; + std::size_t config_index = 0; + std::size_t gate_index = 0; + + // inner_state ^ chunk + for (int i = 0; i < 17; ++i) { + auto cur_config = config[config_index + i]; + + } } template perm_index = {14,4,19,9, 5,20,10,0,15, 11,1,16,6,21, 17,7,22,12,2, 23,13,3,18,8}; + std::vector B = {var(component.W(config[prev_index].copy_from.row, config[prev_index].copy_from.column, false))}; + for (auto i : perm_index) { + B.push_back(var(component.W(config[config_index + i].copy_from.row, config[config_index + i].copy_from.column, false))); + } + config_index += 24; + prev_index += 25; + for (int i = 0; i < 25; ++i) { + int x = index / 5; + int y = index % 5; + bp.add_copy_constraint({B[x * 5 + y], + var(component.W(config[config_index + i].copy_to[0].row, config[config_index + i].copy_to[0].column, false))}); + bp.add_copy_constraint({B[((x + 1) % 5) * 5 + y], + var(component.W(config[config_index + i].copy_to[1].row, config[config_index + i].copy_to[1].column, false))}); + bp.add_copy_constraint({B[((x + 2) % 5) * 5 + y], + var(component.W(config[config_index + i].copy_to[2].row, config[config_index + i].copy_to[2].column, false))}); + } + config_index += 25; + prev_index += 24; + + // iota + bp.add_copy_constraint({var(component.W(config[prev_index].copy_from.row, config[prev_index].copy_from.column, false)), + var(component.W(config[config_index].copy_to[0].row, config[config_index].copy_to[0].column, false))}); + bp.add_copy_constraint({instance_input.round_constant, + var(component.W(config[config_index].copy_to[1].row, config[config_index].copy_to[1].column, false))}); } template; // TODO: need to find the exact answer - std::size_t row = start_row_index + 242 + 3; - for (std::size_t i = 0; i < 25; i++) { - assignment.constant(component.C(0), row + i * 8) = component_type::r_constants[i]; - } + // std::size_t row = start_row_index + 242 + 3; + // for (std::size_t i = 0; i < 25; i++) { + // assignment.constant(component.C(0), row + i * 8) = component_type::r_constants[i]; + // } } template; + + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); + auto selector_iterator = assignment.find_selector(component); std::size_t first_selector_index; - std::size_t row = start_row_index; - using component_type = keccak_round_component; - using var = typename component_type::var; + if (selector_iterator == assignment.selectors_end()) { + first_selector_index = assignment.allocate_selector(component, component.gates_amount); + generate_gates(component, bp, assignment, instance_input, first_selector_index); + } else { + first_selector_index = selector_iterator->second; + } BOOST_ASSERT(row == start_row_index + component.rows_amount); @@ -671,11 +816,11 @@ namespace nil { A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = state; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = message; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = state; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = message; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } @@ -710,14 +855,14 @@ namespace nil { C[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = A_1[index + 1]; - assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = A_1[index + 2]; - assignment.witness(component.W(cur_config.copy_from[3].row), cur_config.copy_from[3].column) = A_1[index + 3]; - assignment.witness(component.W(cur_config.copy_from[4].row), cur_config.copy_from[4].column) = A_1[index + 4]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_1[5 * index]; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = A_1[5 * index + 1]; + assignment.witness(component.W(cur_config.copy_to[2].row), cur_config.copy_to[2].column) = A_1[5 * index + 2]; + assignment.witness(component.W(cur_config.copy_to[3].row), cur_config.copy_to[3].column) = A_1[5 * index + 3]; + assignment.witness(component.W(cur_config.copy_to[4].row), cur_config.copy_to[4].column) = A_1[5 * index + 4]; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } @@ -746,13 +891,13 @@ namespace nil { } auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = C[index]; - assignment.witness(component.W(cur_config.copy_to.row), cur_config.copy_to.column) = C_rot[index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = C[index]; + assignment.witness(component.W(cur_config.copy_from.row), cur_config.copy_from.column) = C_rot[index]; assignment.witness(component.W(cur_config.constraints[0][1].row), cur_config.constraints[0][1].column) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].row), cur_config.constraints[0][2].column) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].row), cur_config.constraints[3][0].column) = value_type(bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].row), cur_config.constraints[5][0].column) = value_type(bound_bigger); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].row), cur_config.constraints[3][j].column) = value_type(integral_small_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[5][j].row), cur_config.constraints[5][j].column) = value_type(integral_big_chunks[j - 1]); } @@ -780,12 +925,12 @@ namespace nil { A_2[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_1[index]; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = C_rot[(index + 1) % 5]; - assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = C[(index - 1) % 5]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_1[index]; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = C_rot[(index + 1) % 5]; + assignment.witness(component.W(cur_config.copy_to[2].row), cur_config.copy_to[2].column) = C[(index + 4) % 5]; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks; ++j) { + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = A_2[index]; + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } @@ -820,14 +965,14 @@ namespace nil { bound_bigger >>= chunk_size; } - auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_2[index]; - assignment.witness(component.W(cur_config.copy_to.row), cur_config.copy_to.column) = B[y][2*x + 3*y]; + auto cur_config = component.full_configuration[index - 1 + config_index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_2[index]; + assignment.witness(component.W(cur_config.copy_from.row), cur_config.copy_from.column) = B[y][2*x + 3*y]; assignment.witness(component.W(cur_config.constraints[0][1].row), cur_config.constraints[0][1].column) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].row), cur_config.constraints[0][2].column) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].row), cur_config.constraints[3][0].column) = value_type(bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].row), cur_config.constraints[5][0].column) = value_type(bound_bigger); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].row), cur_config.constraints[3][j].column) = value_type(integral_small_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[5][j].row), cur_config.constraints[5][j].column) = value_type(integral_big_chunks[j - 1]); } @@ -858,12 +1003,12 @@ namespace nil { A_3[index] = value_type(integral_chi_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = B[x][y]; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = B[(x+1)%5][y]; - assignment.witness(component.W(cur_config.copy_from[2].row), cur_config.copy_from[2].column) = B[(x+2)%5][y]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = B[x][y]; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = B[(x+1)%5][y]; + assignment.witness(component.W(cur_config.copy_to[2].row), cur_config.copy_to[2].column) = B[(x+2)%5][y]; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_chi_sum); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_chi_chunks[j - 1]); } @@ -891,11 +1036,11 @@ namespace nil { value_type A_4 = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_from[0].row), cur_config.copy_from[0].column) = A_3[0]; - assignment.witness(component.W(cur_config.copy_from[1].row), cur_config.copy_from[1].column) = round_constant; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_3[0]; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = round_constant; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks; ++j) { + for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } From 7991a453cc010a984a08fd2b8c76355c319c156e Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Fri, 28 Jul 2023 11:21:54 +0000 Subject: [PATCH 04/48] gates added #183 --- .../components/hashes/keccak/keccak_round.hpp | 396 ++++++++++++++---- 1 file changed, 313 insertions(+), 83 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 908690bda..c6d7655a7 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -74,9 +74,9 @@ namespace nil { std::size_t rows() const { std::size_t num_cells = 17 * xor2_cells + // inner_state ^ chunk 5 * xor5_cells + // theta - 5 * rot_cells + // theta + 5 * rotate_cells + // theta 25 * xor3_cells + // theta - 24 * rot_cells + // rho/phi + 24 * rotate_cells + // rho/phi 25 * chi_cells + // chi xor2_cells; // iota return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); @@ -94,6 +94,49 @@ namespace nil { } public: + + struct configuration { + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + }; + + // In constraints we use such notation: constr[0] - result, + // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates last_coordinate; + std::vector copy_to; + std::vector> constraints; + std::vector> lookups; + coordinates copy_from; + + configuration() = default; + configuration(std::pair last_coordinate_, + std::vector> copy_to_, + std::vector>> constraints_, + std::vector>> lookups_, + std::pair copy_from_) { + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to[i] = coordinates(copy_to_[i]); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + for (std::size_t j = 0; j < constraints[i].size(); ++j) { + constraints[i][j] = coordinates(constraints_[i][j]); + } + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + for (std::size_t j = 0; j < lookups[i].size(); ++j) { + lookups[i][j] = coordinates(lookups_[i][j]); + } + } + copy_from = coordinates(copy_from_); + }; + }; + using var = typename component_type::var; const std::size_t lookup_rows; @@ -114,7 +157,7 @@ namespace nil { const std::size_t xor2_cells; const std::size_t xor3_cells; const std::size_t xor5_cells; - const std::size_t rot_cells = 22; + const std::size_t rotate_cells = 22; const std::size_t chi_cells; constexpr static const int r[5][5] = {{0, 3, 186, 84, 81}, @@ -130,7 +173,7 @@ namespace nil { const std::size_t limit_permutation_column = 7; constexpr static const std::array - r_constants = {0, 36, 3, 41, 18, + rho_offsets = {0, 36, 3, 41, 18, 1, 44, 10, 45, 2, 62, 6, 43, 15, 61, 28, 55, 25, 21, 56, @@ -156,11 +199,11 @@ namespace nil { result_type(const keccak_round &component, std::size_t start_row_index) { std::size_t num_config = 101; - inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from[0].row), - component.full_configuration[num_config].copy_from[0].column); + inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.row), + component.full_configuration[num_config].copy_from.column); for (int i = 1; i < 25; ++i) { - inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from[0].row), - component.full_configuration[num_config - i].copy_from[0].column); + inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from.row), + component.full_configuration[num_config - i].copy_from.column); } } }; @@ -192,48 +235,6 @@ namespace nil { return result; } - struct configuration { - struct coordinates { - std::size_t row; - std::size_t column; - - coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - }; - - // In constraints we use such notation: constr[0] - result, - // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. - coordinates last_coordinate; - std::vector copy_to; - std::vector> constraints; - std::vector> lookups; - coordinates copy_from; - - configuration() = default; - configuration(std::pair last_coordinate_, - std::vector> copy_to_, - std::vector>> constraints_, - std::vector>> lookups_, - std::pair copy_from_) { - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to[i] = coordinates(copy_to_[i]); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - for (std::size_t j = 0; j < constraints[i].size(); ++j) { - constraints[i][j] = coordinates(constraints_[i][j]); - } - } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - for (std::size_t j = 0; j < lookups[i].size(); ++j) { - lookups[i][j] = coordinates(lookups_[i][j]); - } - } - copy_from = coordinates(copy_from_); - }; - }; - configuration configure_inner(std::size_t row, std::size_t column, std::size_t num_args, std::size_t num_chunks, std::size_t num_cells) { @@ -262,7 +263,6 @@ namespace nil { } std::vector> cells; - std::pair cell_copy_from; if (num_args + column > limit_permutation_column) { for (int i = column; i < WitnessesAmount; ++i) { cells.push_back({row, i}); @@ -333,22 +333,24 @@ namespace nil { // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * 2^(k*chunk_size) std::size_t num_args = 3; - std::size_t num_cells = num_chunks * 2 + num_args + 2; + std::size_t num_cells = chi_num_chunks * 2 + num_args + 2; return configure_inner(row, column, num_args, chi_num_chunks, num_cells); } configuration configure_rot(std::size_t row, std::size_t column) { // regular constraints: - // a = big_part << r + small_part; - // a_rot = small_part << (192 - r) + big_part; - // bound_big = big_part - (1 << (192 - r)) + (1 << 192); + // a = small_part << (192 - r) + big_part; + // a_rot = big_part << r + small_part; // bound_small = small_part - (1 << r) + (1 << 192); - // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) // bound_small = small_chunk0 + small_chunk1 * 2^chunk_size + ... + small_chunkk * 2^(k*chunk_size) + // bound_big = big_part - (1 << (192 - r)) + (1 << 192); + // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) std::size_t last_row = row, last_column = column; + std::size_t num_chunks = rotate_num_chunks; + std::size_t num_cells = rotate_cells; std::vector> copy_to; std::pair cell_copy_from; @@ -590,17 +592,245 @@ namespace nil { using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; + // using lookup_constraint_type = typename crypto3::zk::snark::lookup_constraint; + // using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; auto config = component.full_configuration; auto gate_config = component.gates_configuration; + // auto lookup_gate_config = component.lookup_gates_configuration; std::size_t config_index = 0; std::size_t gate_index = 0; + // std::size_t lookup_gate_index = 0; + + std::vector constraints; + // std::vector lookup_constraints; // inner_state ^ chunk for (int i = 0; i < 17; ++i) { - auto cur_config = config[config_index + i]; + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + // theta + for (int i = 0; i < 5; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + + var(cur_config.constraints[0][4].column, cur_config.constraints[0][4].row - gate_config[gate_index]) + + var(cur_config.constraints[0][5].column, cur_config.constraints[0][5].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize6_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize6_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize6_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize6_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + for (int i = 0; i < 5; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (1ull << 189) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (1ull << 3) + + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) + - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) + - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) + - (1ull << 3) + + (1ull << 192))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) + - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) + - (1ull << 189) + + (1ull << 192))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); + for (int j = 0; j < component.rotate_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); + for (int j = 0; j < component.rotate_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + for (int i = 0; i < 5; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize4_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize4_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize4_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize4_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + // rho/phi + for (int i = 1; i < 25; ++i) { + auto r = component.rho_offsets[i]; + + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (1ull << (192 - r)) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (1ull << r) + + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) + - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) + - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) + - (1ull << r) + + (1ull << 192))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) + - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) + - (1ull << (192 - r)) + + (1ull << 192))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); + for (int j = 0; j < component.rotate_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); + for (int j = 0; j < component.rotate_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + // chi + for (int i = 0; i < 5; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(component.sparse_3 + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * 2 + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.chi_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.chi_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.chi_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.chi_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + // iota + { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (1ull << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + + BOOST_ASSERT(config_index == 102); + BOOST_ASSERT(constraints.size() == gate_config.size()); + + std::size_t prev_selector = gate_config[0]; + std::vector cur_constraints = {constraints[0]}; + gate_index = 1; + while (gate_index < gate_config.size()) { + while (gate_index < gate_config.size() && gate_config[gate_index] == prev_selector) { + cur_constraints.push_back(constraints[gate_index]); + ++gate_index; + } + if (gate_index == gate_config.size()) { + break; + } + gate_type gate(first_selector_index + prev_selector, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + prev_selector = gate_config[gate_index]; + } + if (!cur_constraints.empty()) { + gate_type gate(first_selector_index + prev_selector, cur_constraints); + bp.add_gate(gate); } } @@ -638,65 +868,65 @@ namespace nil { // theta for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({var(component.W(config[prev_index + i].copy_from.row, config[prev_index + i].copy_from.column, false)), - var(component.W(config[config_index + i / 5].copy_to[i % 5].row, config[config_index + i / 5].copy_to[i % 5].column, false))}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, + {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - var(component.W(config[config_index + i / 5].copy_to[i % 5].row, config[config_index + i / 5].copy_to[i % 5].column, false))}); + {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); } config_index += 5; prev_index += 17; for (int i = 0; i < 5; ++i) { - bp.add_copy_constraint({var(component.W(config[prev_index + i].copy_from.row, config[prev_index + i].copy_from.column, false)), - var(component.W(config[config_index + i].copy_to[0].row, config[config_index + i].copy_to[0].column, false))}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, + {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); } config_index += 5; prev_index += 5; for (int i = 0; i < 25; ++i) { - bp.add_copy_constraint({var(component.W(config[17 + i / 5].copy_to[i % 5].row, config[17 + i / 5].copy_to[i % 5].column, false)), - var(component.W(config[config_index + i].copy_to[0].row, config[config_index + i].copy_to[0].column, false))}); - bp.add_copy_constraint({var(component.W(config[prev_index + (i + 1) % 5].copy_from.row, config[prev_index + (i + 1) % 5].copy_from.column, false)), - var(component.W(config[config_index + i].copy_to[1].row, config[config_index + i].copy_to[1].column, false))}); - bp.add_copy_constraint({var(component.W(config[prev_index + (i + 4) % 5].copy_to[0].row, config[prev_index + (i + 4) % 5].copy_to[0].column, false)), - var(component.W(config[config_index + i].copy_to[2].row, config[config_index + i].copy_to[2].column, false))}); + bp.add_copy_constraint({{component.W(config[17 + i / 5].copy_to[i % 5].row), static_cast(config[17 + i / 5].copy_to[i % 5].column), false}, + {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.row), static_cast(config[prev_index + (i + 1) % 5].copy_from.column), false}, + {component.W(config[config_index + i].copy_to[1].row), static_cast(config[config_index + i].copy_to[1].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].row), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].column), false}, + {component.W(config[config_index + i].copy_to[2].row), static_cast(config[config_index + i].copy_to[2].column), false}}); } config_index += 25; prev_index += 5; // rho/phi for (int i = 0; i < 24; ++i) { - bp.add_copy_constraint({var(component.W(config[prev_index + i + 1].copy_from.row, config[prev_index + i + 1].copy_from.column, false)), - var(component.W(config[config_index + i].copy_to[0].row, config[config_index + i].copy_to[0].column, false))}); + bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.row), static_cast(config[prev_index + i + 1].copy_from.column), false}, + {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); } // chi std::vector perm_index = {14,4,19,9, 5,20,10,0,15, 11,1,16,6,21, 17,7,22,12,2, 23,13,3,18,8}; - std::vector B = {var(component.W(config[prev_index].copy_from.row, config[prev_index].copy_from.column, false))}; + std::vector B = {{component.W(config[prev_index].copy_from.row), static_cast(config[prev_index].copy_from.column), false}}; for (auto i : perm_index) { - B.push_back(var(component.W(config[config_index + i].copy_from.row, config[config_index + i].copy_from.column, false))); + B.push_back({component.W(config[config_index + i].copy_from.row), static_cast(config[config_index + i].copy_from.column), false}); } config_index += 24; prev_index += 25; for (int i = 0; i < 25; ++i) { - int x = index / 5; - int y = index % 5; + int x = i / 5; + int y = i % 5; bp.add_copy_constraint({B[x * 5 + y], - var(component.W(config[config_index + i].copy_to[0].row, config[config_index + i].copy_to[0].column, false))}); + {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); bp.add_copy_constraint({B[((x + 1) % 5) * 5 + y], - var(component.W(config[config_index + i].copy_to[1].row, config[config_index + i].copy_to[1].column, false))}); + {component.W(config[config_index + i].copy_to[1].row), static_cast(config[config_index + i].copy_to[1].column), false}}); bp.add_copy_constraint({B[((x + 2) % 5) * 5 + y], - var(component.W(config[config_index + i].copy_to[2].row, config[config_index + i].copy_to[2].column, false))}); + {component.W(config[config_index + i].copy_to[2].row), static_cast(config[config_index + i].copy_to[2].column), false}}); } config_index += 25; prev_index += 24; // iota - bp.add_copy_constraint({var(component.W(config[prev_index].copy_from.row, config[prev_index].copy_from.column, false)), - var(component.W(config[config_index].copy_to[0].row, config[config_index].copy_to[0].column, false))}); + bp.add_copy_constraint({{component.W(config[prev_index].copy_from.row), static_cast(config[prev_index].copy_from.column), false}, + {component.W(config[config_index].copy_to[0].row), static_cast(config[config_index].copy_to[0].column), false}}); bp.add_copy_constraint({instance_input.round_constant, - var(component.W(config[config_index].copy_to[1].row, config[config_index].copy_to[1].column, false))}); + {component.W(config[config_index].copy_to[1].row), static_cast(config[config_index].copy_to[1].column), false}}); } template> r; From 4a9c312031aac0902d910d0978b834ad01a00c4a Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Sun, 6 Aug 2023 19:32:24 +0000 Subject: [PATCH 05/48] fixed some computation bugs #183 --- .../components/hashes/keccak/keccak_round.hpp | 287 +++++++++++------- test/hashes/plonk/data_for_keccak_round.hpp | 121 ++++++++ test/hashes/plonk/keccak_round.cpp | 157 ++++++++-- 3 files changed, 438 insertions(+), 127 deletions(-) create mode 100644 test/hashes/plonk/data_for_keccak_round.hpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index c6d7655a7..0a0bff97b 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -29,7 +29,7 @@ #include #include -#include +#include namespace nil { @@ -49,7 +49,7 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::size_t calculate_normalize_chunk_size(std::size_t num_rows, std::size_t base) { + std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base) { std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -58,20 +58,23 @@ namespace nil { } return chunk_size * 3; } - std::size_t calculate_chi_chunk_size(std::size_t num_rows) { - std::size_t chunk_size = 0; - std::size_t power = 2; - while (power < num_rows) { - ++chunk_size; - power *= 2; - } - return chunk_size * 3; + std::size_t calculate_num_chunks(std::size_t base = 0) { + std::size_t chunk_size = base == 3 ? normalize3_chunk_size + : base == 4 ? normalize4_chunk_size + : base == 6 ? normalize6_chunk_size + : chi_chunk_size; + std::size_t res = 192 / chunk_size + bool(192 % chunk_size); + return res; } - std::size_t calculate_num_chunks(std::size_t chunk_size) { - return word_size / chunk_size + bool(word_size % chunk_size); + std::size_t calculate_num_cells(std::size_t base = 0) { + std::size_t res = base == 3 ? normalize3_num_chunks * 2 + 2 + 2 + : base == 4 ? normalize4_num_chunks * 2 + 3 + 2 + : base == 6 ? normalize6_num_chunks * 2 + 5 + 2 + : chi_chunk_size * 2 + 5; + return res; } - std::size_t rows() const { + std::size_t calculate_rows() const { std::size_t num_cells = 17 * xor2_cells + // inner_state ^ chunk 5 * xor5_cells + // theta 5 * rotate_cells + // theta @@ -81,6 +84,18 @@ namespace nil { xor2_cells; // iota return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } + std::vector calculate_gates_rows() const { + std::vector res; + auto cur_selector = gates_configuration[0]; + res.push_back(cur_selector); + for (std::size_t i = 1; i < gates_configuration.size(); ++i) { + if (gates_configuration[i] != cur_selector) { + cur_selector = gates_configuration[i]; + res.push_back(cur_selector); + } + } + return res; + } std::size_t gates() const { std::size_t res = 1; auto cur_selector = gates_configuration[0]; @@ -121,17 +136,21 @@ namespace nil { std::pair copy_from_) { last_coordinate = coordinates(last_coordinate_); for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to[i] = coordinates(copy_to_[i]); + copy_to.push_back(coordinates(copy_to_[i])); } for (std::size_t i = 0; i < constraints_.size(); ++i) { - for (std::size_t j = 0; j < constraints[i].size(); ++j) { - constraints[i][j] = coordinates(constraints_[i][j]); + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); } + constraints.push_back(constr); } for (std::size_t i = 0; i < lookups_.size(); ++i) { - for (std::size_t j = 0; j < lookups[i].size(); ++j) { - lookups[i][j] = coordinates(lookups_[i][j]); + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); } + lookups.push_back(lookup); } copy_from = coordinates(copy_from_); }; @@ -160,6 +179,17 @@ namespace nil { const std::size_t rotate_cells = 22; const std::size_t chi_cells; + const std::size_t rows_amount; + + // full configuration is precalculated, then used in other functions + std::array full_configuration; + // number represents relative selector index for each constraint + std::vector gates_configuration; + std::vector lookup_gates_configuration; + std::vector gates_rows; + + const std::size_t gates_amount; + constexpr static const int r[5][5] = {{0, 3, 186, 84, 81}, {108, 132, 18, 165, 60}, {9, 30, 129, 75, 117}, @@ -168,7 +198,7 @@ namespace nil { // all words in sparse form const std::size_t word_size = 192; - const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui192; + const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; const std::size_t limit_permutation_column = 7; @@ -179,15 +209,6 @@ namespace nil { 28, 55, 25, 21, 56, 27, 20, 39, 8, 14}; - // full configuration is precalculated, then used in other functions - std::array full_configuration; - // number represents relative selector index for each constraint - std::vector gates_configuration; - std::vector lookup_gates_configuration; - - const std::size_t rows_amount; - const std::size_t gates_amount; - struct input_type { std::array inner_state; std::array padded_message_chunk; @@ -212,9 +233,9 @@ namespace nil { integral_type result = 0; integral_type value = integral_value; integral_type power = 1; - for (std::size_t i = 0; i < 64; ++i) { + while (value > 0) { result += (value & 1) * power; - power *= 8; + power <<= 3; value >>= 3; } return result; @@ -226,11 +247,11 @@ namespace nil { integral_type power = 1; integral_type mask = 7; int table[5] = {0, 1, 1, 0, 0}; - for (std::size_t i = 0; i < 64; ++i) { + while (value > 0) { int bit = table[int(value & mask)]; result += bit * power; - power *= 8; - value >>= 8; + power <<= 3; + value >>= 3; } return result; } @@ -468,16 +489,20 @@ namespace nil { std::vector> pairs; for (std::size_t i = 0; i < 102; ++i) { for (auto constr : full_configuration[i].constraints) { - std::size_t min = std::min(constr[0].row, constr[1].row); + std::size_t min = constr[0].row; std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } BOOST_ASSERT(max - min <= 2); pairs.push_back({min, max}); } } std::vector result; std::size_t cur_row = 0; + std::size_t cur_constr = 0; while (cur_row < rows_amount) { - std::size_t cur_constr = 0; while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { result.push_back(cur_row + 1); ++cur_constr; @@ -494,16 +519,20 @@ namespace nil { std::vector> pairs; for (std::size_t i = 0; i < 102; ++i) { for (auto constr : full_configuration[i].lookups) { - std::size_t min = std::min(constr[0].row, constr[1].row); + std::size_t min = constr[0].row; std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } BOOST_ASSERT(max - min <= 2); pairs.push_back({min, max}); } } std::vector result; std::size_t cur_row = 0; + std::size_t cur_constr = 0; while (cur_row < rows_amount) { - std::size_t cur_constr = 0; while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { result.push_back(cur_row + 1); ++cur_constr; @@ -519,30 +548,31 @@ namespace nil { #define __keccak_round_init_macro(lookup_rows_, lookup_columns_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ - normalize3_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ - normalize4_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 4)), \ - normalize6_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 6)), \ - chi_chunk_size(calculate_chi_chunk_size(lookup_rows_)), \ - normalize3_num_chunks(calculate_num_chunks(normalize3_chunk_size)), \ - normalize4_num_chunks(calculate_num_chunks(normalize4_chunk_size)), \ - normalize6_num_chunks(calculate_num_chunks(normalize6_chunk_size)), \ - chi_num_chunks(calculate_num_chunks(chi_chunk_size)), \ - xor2_cells(normalize3_num_chunks * 2 + 2 + 2), \ - xor3_cells(normalize4_num_chunks * 2 + 3 + 2), \ - xor5_cells(normalize6_num_chunks * 2 + 5 + 2), \ - chi_cells(chi_num_chunks * 2 + 5), \ - rows_amount(rows()), \ + normalize3_chunk_size(calculate_chunk_size(lookup_rows_, 3)), \ + normalize4_chunk_size(calculate_chunk_size(lookup_rows_, 4)), \ + normalize6_chunk_size(calculate_chunk_size(lookup_rows_, 6)), \ + chi_chunk_size(calculate_chunk_size(lookup_rows_, 2)), \ + word_size(192), \ + normalize3_num_chunks(calculate_num_chunks(3)), \ + normalize4_num_chunks(calculate_num_chunks(4)), \ + normalize6_num_chunks(calculate_num_chunks(6)), \ + chi_num_chunks(calculate_num_chunks()), \ + xor2_cells(calculate_num_cells(3)), \ + xor3_cells(calculate_num_cells(4)), \ + xor5_cells(calculate_num_cells(6)), \ + chi_cells(calculate_num_cells()), \ + rows_amount(calculate_rows()), \ full_configuration(configure_all()), \ gates_configuration(configure_gates()), \ lookup_gates_configuration(configure_lookup_gates()), \ - gates_amount(gates()) + gates_amount(gates()), \ + gates_rows(calculate_gates_rows()) template keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_) : component_type(witness, {}, {}), __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; - template keccak_round(WitnessContainerType witness, ConstantContainerType constant, @@ -558,8 +588,7 @@ namespace nil { public_inputs, std::size_t lookup_rows_, std::size_t lookup_columns_) : component_type(witnesses, constants, public_inputs), - __keccak_round_init_macro(lookup_rows_, lookup_columns_) - {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; #undef __keccak_round_init_macro }; @@ -617,14 +646,14 @@ namespace nil { constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize3_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize3_chunk_size)); + * (integral_type(1) << (j * component.normalize3_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize3_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize3_chunk_size)); + * (integral_type(1) << (j * component.normalize3_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -644,14 +673,14 @@ namespace nil { constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize6_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize6_chunk_size)); + * (integral_type(1) << (j * component.normalize6_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize6_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize6_chunk_size)); + * (integral_type(1) << (j * component.normalize6_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -660,42 +689,42 @@ namespace nil { for (int i = 0; i < 5; ++i) { auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (1ull << 189) + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << 189) + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (1ull << 3) + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << 3) + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); gate_index++; constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - - (1ull << 3) - + (1ull << 192))); + - (integral_type(1) << 3) + + (integral_type(1) << 192))); gate_index++; constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) - - (1ull << 189) - + (1ull << 192))); + - (integral_type(1) << 189) + + (integral_type(1) << 192))); gate_index++; constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.rotate_chunk_size)); + * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.rotate_chunk_size)); + * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; config_index++; } - for (int i = 0; i < 5; ++i) { + for (int i = 0; i < 25; ++i) { auto cur_config = config[config_index]; constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) @@ -705,14 +734,14 @@ namespace nil { constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize4_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize4_chunk_size)); + * (integral_type(1) << (j * component.normalize4_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize4_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize4_chunk_size)); + * (integral_type(1) << (j * component.normalize4_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -721,38 +750,38 @@ namespace nil { // rho/phi for (int i = 1; i < 25; ++i) { - auto r = component.rho_offsets[i]; + auto r = 3 * component.rho_offsets[i]; auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (1ull << (192 - r)) + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << (192 - r)) + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (1ull << r) + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << r) + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); gate_index++; constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - - (1ull << r) - + (1ull << 192))); + - (integral_type(1) << r) + + (integral_type(1) << 192))); gate_index++; constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) - - (1ull << (192 - r)) - + (1ull << 192))); + - (integral_type(1) << (192 - r)) + + (integral_type(1) << 192))); gate_index++; constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.rotate_chunk_size)); + * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.rotate_chunk_size)); + * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -760,7 +789,7 @@ namespace nil { } // chi - for (int i = 0; i < 5; ++i) { + for (int i = 0; i < 25; ++i) { auto cur_config = config[config_index]; constraints.push_back(bp.add_constraint(component.sparse_3 - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * 2 @@ -771,14 +800,14 @@ namespace nil { constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); for (int j = 0; j < component.chi_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.chi_chunk_size)); + * (integral_type(1) << (j * component.chi_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); for (int j = 0; j < component.chi_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.chi_chunk_size)); + * (integral_type(1) << (j * component.chi_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -795,14 +824,14 @@ namespace nil { constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize3_num_chunks; ++j) { constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize3_chunk_size)); + * (integral_type(1) << (j * component.normalize3_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); for (int j = 0; j < component.normalize3_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (1ull << (j * component.normalize3_chunk_size)); + * (integral_type(1) << (j * component.normalize3_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_2)); gate_index++; @@ -989,8 +1018,9 @@ namespace nil { first_selector_index = selector_iterator->second; } - - BOOST_ASSERT(row == start_row_index + component.rows_amount); + for (std::size_t i = 0; i < component.gates_amount; ++i) { + assignment.enable_selector(first_selector_index + i, component.gates_rows[i]); + } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -1033,7 +1063,7 @@ namespace nil { auto num_chunks = component.normalize3_num_chunks; std::vector integral_chunks; std::vector integral_normalized_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type power = 1; integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1041,8 +1071,16 @@ namespace nil { integral_sum >>= chunk_size; integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); integral_normalized_sum += integral_normalized_chunks.back() * power; - power *= chunk_size; + power <<= chunk_size; } + // std::cout << "chunks:\n"; + // for (int j = 0; j < num_chunks; ++j) { + // std::cout << integral_chunks[j] << "\n"; + // } + // std::cout << "normalized chunks:\n"; + // for (int j = 0; j < num_chunks; ++j) { + // std::cout << integral_normalized_chunks[j] << "\n"; + // } A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; @@ -1059,6 +1097,10 @@ namespace nil { A_1[i] = var_value(assignment, instance_input.inner_state[i]); } config_index += 17; + std::cout << "inner_state ^ chunk:\n"; + for (int i = 0; i < 25; ++i) { + std::cout << A_1[i] << "\n"; + } // theta std::array C; @@ -1072,7 +1114,7 @@ namespace nil { auto num_chunks = component.normalize6_num_chunks; std::vector integral_chunks; std::vector integral_normalized_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type power = 1; integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1080,7 +1122,7 @@ namespace nil { integral_sum >>= chunk_size; integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); integral_normalized_sum += integral_normalized_chunks.back() * power; - power *= chunk_size; + power <<= chunk_size; } C[index] = value_type(integral_normalized_sum); @@ -1098,21 +1140,25 @@ namespace nil { } } config_index += 5; + std::cout << "theta 0:\n"; + for (int i = 0; i < 5; ++i) { + std::cout << C[i] << "\n"; + } std::array C_rot; for (int index = 0; index < 5; ++index) { integral_type integral_C = integral_type(C[index].data); - integral_type smaller_part = integral_C & ((1 << 3) - 1); - integral_type bigger_part = integral_C >> 3; - integral_type integral_C_rot = (smaller_part << 189) + bigger_part; + integral_type smaller_part = integral_C >> 189; + integral_type bigger_part = integral_C & ((integral_type(1) << 189) - 1); + integral_type integral_C_rot = (bigger_part << 3) + smaller_part; C_rot[index] = value_type(integral_C_rot); - integral_type bound_smaller = smaller_part - (1 << 3) + (integral_type(1) << 192); + integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); auto chunk_size = component.rotate_chunk_size; auto num_chunks = component.rotate_num_chunks; std::vector integral_small_chunks; std::vector integral_big_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; for (std::size_t j = 0; j < num_chunks; ++j) { integral_small_chunks.push_back(bound_smaller & mask); bound_smaller >>= chunk_size; @@ -1133,16 +1179,20 @@ namespace nil { } } config_index += 5; + std::cout << "theta 1:\n"; + for (int i = 0; i < 5; ++i) { + std::cout << C_rot[i] << "\n"; + } std::array A_2; for (int index = 0; index < 25; ++index) { - value_type sum = A_1[index] + C_rot[(index + 1) % 5] + C[(index - 1) % 5]; + value_type sum = A_1[index] + C_rot[(index + 1) % 5] + C[(index + 4) % 5]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; auto num_chunks = component.normalize4_num_chunks; std::vector integral_chunks; std::vector integral_normalized_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type power = 1; integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1150,7 +1200,7 @@ namespace nil { integral_sum >>= chunk_size; integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); integral_normalized_sum += integral_normalized_chunks.back() * power; - power *= chunk_size; + power <<= chunk_size; } A_2[index] = value_type(integral_normalized_sum); @@ -1166,28 +1216,33 @@ namespace nil { } } config_index += 25; + std::cout << "theta 2:\n"; + for (int i = 0; i < 25; ++i) { + std::cout << A_2[i] << "\n"; + } // rho/phi - std::array, 5> B; + value_type B[5][5]; B[0][0] = A_2[0]; for (int index = 1; index < 25; ++index) { int x = index / 5; int y = index % 5; - int r = component.rho_offsets[index]; + int r = 3 * component.rho_offsets[index]; int minus_r = 192 - r; integral_type integral_A = integral_type(A_2[index].data); - integral_type smaller_part = integral_A & ((1 << r) - 1); - integral_type bigger_part = integral_A >> r; - integral_type integral_A_rot = (smaller_part << minus_r) + bigger_part; - B[y][2*x + 3*y] = value_type(integral_A_rot); + integral_type smaller_part = integral_A >> minus_r; + integral_type bigger_part = integral_A & ((integral_type(1) << minus_r) - 1); + integral_type integral_A_rot = (bigger_part << r) + smaller_part; + B[y][(2*x + 3*y) % 5] = value_type(integral_A_rot); + // std::cout << "parts: " << smaller_part << " " << bigger_part << ' ' << integral_A_rot << "\n"; - integral_type bound_smaller = smaller_part - (1 << r) + (integral_type(1) << 192); + integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); auto chunk_size = component.rotate_chunk_size; auto num_chunks = component.rotate_num_chunks; std::vector integral_small_chunks; std::vector integral_big_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; for (std::size_t j = 0; j < num_chunks; ++j) { integral_small_chunks.push_back(bound_smaller & mask); bound_smaller >>= chunk_size; @@ -1197,7 +1252,7 @@ namespace nil { auto cur_config = component.full_configuration[index - 1 + config_index]; assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_2[index]; - assignment.witness(component.W(cur_config.copy_from.row), cur_config.copy_from.column) = B[y][2*x + 3*y]; + assignment.witness(component.W(cur_config.copy_from.row), cur_config.copy_from.column) = B[y][(2*x + 3*y) % 5]; assignment.witness(component.W(cur_config.constraints[0][1].row), cur_config.constraints[0][1].column) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].row), cur_config.constraints[0][2].column) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].row), cur_config.constraints[3][0].column) = value_type(bound_smaller); @@ -1208,6 +1263,12 @@ namespace nil { } } config_index += 24; + std::cout << "rho/phi:\n"; + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 5; ++j) { + std::cout << B[i][j] << "\n"; + } + } // chi std::array A_3; @@ -1220,7 +1281,7 @@ namespace nil { auto num_chunks = component.chi_num_chunks; std::vector integral_chunks; std::vector integral_chi_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type power = 1; integral_type integral_chi_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1228,7 +1289,7 @@ namespace nil { integral_sum >>= chunk_size; integral_chi_chunks.push_back(component.chi(integral_chunks.back())); integral_chi_sum += integral_chi_chunks.back() * power; - power *= chunk_size; + power <<= chunk_size; } A_3[index] = value_type(integral_chi_sum); @@ -1244,6 +1305,10 @@ namespace nil { } } config_index += 25; + std::cout << "chi:\n"; + for (int i = 0; i < 25; ++i) { + std::cout << A_3[i] << "\n"; + } // iota value_type round_constant = var_value(assignment, instance_input.round_constant); @@ -1253,7 +1318,7 @@ namespace nil { auto num_chunks = component.normalize3_num_chunks; std::vector integral_chunks; std::vector integral_normalized_chunks; - integral_type mask = (1 << chunk_size) - 1; + integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type power = 1; integral_type integral_normalized_sum = 0; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1261,7 +1326,7 @@ namespace nil { integral_sum >>= chunk_size; integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); integral_normalized_sum += integral_normalized_chunks.back() * power; - power *= chunk_size; + power <<= chunk_size; } value_type A_4 = value_type(integral_normalized_sum); @@ -1274,6 +1339,8 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } + std::cout << "iota:\n"; + std::cout << A_4 << "\n"; return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/data_for_keccak_round.hpp b/test/hashes/plonk/data_for_keccak_round.hpp new file mode 100644 index 000000000..be8b442e6 --- /dev/null +++ b/test/hashes/plonk/data_for_keccak_round.hpp @@ -0,0 +1,121 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2021-2022 Mikhail Komarov +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_DATA_KECCAK_ROUND_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_DATA_KECCAK_ROUND_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +using namespace nil::crypto3; + +const uint64_t RC[25] = {0, 1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + +const std::vector> inner_states = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { + 32899, 17592186044416, 32768, 1, 17592186077184, + 0, 35184374185984, 0, 35184372088832, 2097152, + 2, 512, 0, 514, 0, + 268436480, 0, 1024, 268435456, 0, + 1099511627776, 0, 1099511627780, 0, 4 + }, + { + 9236970796698600460, 4092250545529553158, 626057523912327425, 2306538108895626371, 1173341635645358336, + 1293304092434976, 1266393375296193026, 4612686711565066480, 3572814934320349200, 6918386853474468034, + 181437471070544, 17451689225912448, 14123431978033217603, 9612137362626578, 14131171423402623105, + 109225863298950544, 4469910934709993472, 291608492588557700, 4143342752895270928, 722898250671538564, + 9260980282462904729, 14339470011802853602, 37581858268459548, 4683770000893804961, 432358761588732518 + }, + { + 592319258926211651, 14940587067404002452, 6163873250186209783, 9133172271835791495, 13983250434949586883, + 10037245043040796116, 14625807227073111006, 9517639169617348992, 10802803781493464979, 1170967630360556906, + 4833658608200494670, 14411270558251773425, 10413092914151648788, 6324505867985343017, 15456637871614865798, + 15961727220218474669, 12219779720573097889, 13453918774002596887, 11249665490274026413, 16763947842887530834, + 9348458261315236693, 11269932799224724130, 5725669273397430228, 16793563075160212879, 7296601056617420707 + }, + { + 7638250137956199023, 17990125325728205105, 7906499215270811140, 10861036725959346835, 11195520138696188958, + 8358174899797462070, 8135952663530915624, 1143978644753002443, 15662404937588594201, 16535557756827863490, + 2821756897662528488, 12114361851460063201, 8845673958919045506, 13942698502943567537, 11656387723772272466, + 13322614738909770079, 2086432298574777049, 17543636310180418713, 1178364895537752846, 10832164025006223835, + 2030143342952750111, 12360607886846421348, 10479039689777663018, 16563260862735374768, 7279885679800479721 + }, + { + 4891766363406797400, 15439122233753343804, 13823342620960621853, 11746433691194652646, 4017314498112237324, + 815207819430446539, 4967747420293129338, 3818588911347179217, 12982395987346120149, 8831006501622048216, + 3273200702990303769, 11925911941096385939, 11818410238024184151, 6855937196075990472, 6813782227838587502, + 5749709705375199086, 198532287281302992, 3986921420170929948, 2084732521627207926, 3955984847012879536, + 17540298648724239738, 14973796877054370773, 9207394463793105740, 13336242423054526618, 2223831538796077986 + }, + { + 898454936699210940, 8026835929569667841, 7594412717710188589, 17691297879001667639, 12039682773981733750, + 4806751406901749727, 11830785691895369039, 6215100860000502273, 3084694277248389144, 16700214332683074198, + 1701067029580549681, 2935021215067160996, 10064659787097191500, 7604822824502759976, 1494105689337672248, + 12626178481354463734, 2395136601172298592, 4068135589652482799, 15567196270789777948, 4732526861918809121, + 2821496240805205513, 5710775155925759758, 9794593245826189275, 17281148776925903127, 7447477925633355381 + } + //8 +}; + +template +auto inner_states_data(int num_round) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::array prev_inner_state; + for (std::size_t i = 0; i < 25; i++) { + prev_inner_state[i] = value_type(integral_type(inner_states[num_round - 1][i])); + } + std::array inner_state; + for (std::size_t i = 0; i < 25; i++) { + inner_state[i] = value_type(integral_type(inner_states[num_round][i])); + } + value_type rc = value_type(integral_type(RC[num_round])); + return std::make_tuple(prev_inner_state, inner_state, rc); +} + +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_DATA_KECCAK_ROUND_HPP \ No newline at end of file diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index cd0558774..4f274ae70 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -52,10 +52,41 @@ const int r[5][5] = {{0, 1, 62, 28, 27}, {41, 45, 15, 21, 8}, {18, 2, 61, 56, 14}}; +template +typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 1; + power = power << 3; + } + return value_type(result_integral); +} +template +bool check_sparse(typename BlueprintFieldType::value_type value, typename BlueprintFieldType::value_type sparse_value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type sparse_value_integral = integral_type(sparse_value.data); + bool result = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + integral_type sparse_bit = sparse_value_integral & 7; + result *= (bit == sparse_bit); + } + return result; +} + + // here for level we use: // 0 - inner ^ chunk, 1 - theta, 2 - rho/phi, 3 - chi, 4 - iota (full round, by default) template -std::array round_function(std::array inner_state, +std::array sparse_round_function(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC) { using value_type = typename BlueprintFieldType::value_type; @@ -72,7 +103,7 @@ std::array round_function(std::arra } auto rot = [](integral_type x, const int s) { - return ((x << s) | (x >> (64 - s))); + return ((x << s) | (x >> (192 - 3 * s))); }; for (int i = 0; i < 17; ++i) { @@ -137,10 +168,11 @@ template auto test_keccak_round_inner(std::array inner_state, std::array padded_message_chunk, - typename BlueprintFieldType::value_type RC) { + typename BlueprintFieldType::value_type RC, + std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 10; + constexpr std::size_t SelectorColumns = 150; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; constexpr std::size_t Lambda = 1; - using var = nil::crypto3::zk::snark::plonk_variable; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using component_type = nil::blueprint::components::keccak_round; + using var = typename component_type::var; std::vector public_input; + std::cout << "inner state:\n"; for (int i = 0; i < 25; ++i) { public_input.push_back(inner_state[i]); + std::cout << inner_state[i].data << std::endl; } + std::cout << "padded message chunk:\n"; for (int i = 0; i < 17; ++i) { public_input.push_back(padded_message_chunk[i]); + std::cout << padded_message_chunk[i].data << std::endl; } public_input.push_back(RC); + std::cout << "RC: " << RC.data << std::endl; std::array inner_state_vars; std::array padded_message_chunk_vars; @@ -175,19 +212,18 @@ auto test_keccak_round_inner(std::array(inner_state, padded_message_chunk, RC); - auto result_check = [expected_result] (AssignmentType &assignment, typename component_type::result_type &real_res) { for (int i = 0; i < 25; ++i) { - assert(expected_result[i] == var_value(assignment, real_res.inner_state[i])); + std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.inner_state[i]).data << std::endl; + // assert(expected_result[i] == var_value(assignment, real_res.inner_state[i])); } }; component_type component_instance = WitnessesAmount == 15 ? component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, - {0}, LookupRows, LookupColumns) - : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {0}, + {1}, LookupRows, LookupColumns) + : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {1}, LookupRows, LookupColumns); if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { @@ -198,6 +234,90 @@ auto test_keccak_round_inner(std::array(component_instance), public_input, result_check, instance_input); } +// works +template +void test_keccak_round_0() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + + std::array inner_state = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + value_type RC = to_sparse(value_type(1)); + + std::array expected_result = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); +} + +template +void test_keccak_round_1() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::array inner_state = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + value_type RC = to_sparse(value_type(0x8082ULL)); + + std::array expected_result = { + 32899, 17592186044416, 32768, 1, 17592186077184, + 0, 35184374185984, 0, 35184372088832, 2097152, + 2, 512, 0, 514, 0, + 268436480, 0, 1024, 268435456, 0, + 1099511627776, 0, 1099511627780, 0, 4}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); +} + +template +void test_keccak_round_7() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + + std::array inner_state = { + 4891766363406797400, 15439122233753343804, 13823342620960621853, 11746433691194652646, 4017314498112237324, + 815207819430446539, 4967747420293129338, 3818588911347179217, 12982395987346120149, 8831006501622048216, + 3273200702990303769, 11925911941096385939, 11818410238024184151, 6855937196075990472, 6813782227838587502, + 5749709705375199086, 198532287281302992, 3986921420170929948, 2084732521627207926, 3955984847012879536, + 17540298648724239738, 14973796877054370773, 9207394463793105740, 13336242423054526618, 2223831538796077986 + }; + for (int i = 0; i < 25; ++i) { + inner_state[i] = to_sparse(inner_state[i]); + } + std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + for (int i = 0; i < 17; ++i) { + padded_message_chunk[i] = to_sparse(padded_message_chunk[i]); + } + value_type RC = to_sparse(value_type(0x8000000080008081ULL)); + + std::array expected_result = { + 898454936699210940, 8026835929569667841, 7594412717710188589, 17691297879001667639, 12039682773981733750, + 4806751406901749727, 11830785691895369039, 6215100860000502273, 3084694277248389144, 16700214332683074198, + 1701067029580549681, 2935021215067160996, 10064659787097191500, 7604822824502759976, 1494105689337672248, + 12626178481354463734, 2395136601172298592, 4068135589652482799, 15567196270789777948, 4732526861918809121, + 2821496240805205513, 5710775155925759758, 9794593245826189275, 17281148776925903127, 7447477925633355381 + }; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + + auto check_expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); + + // BOOST_ASSERT_MSG(check_expected_result == expected_result, "Wrong expected result!") ; + + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); +} + template void test_keccak_round_random() { @@ -208,6 +328,7 @@ void test_keccak_round_random() { boost::random::mt19937 seed_seq; generate_random.seed(seed_seq); uint64_t range = 18446744073709551615U; //2^64 - 1 + integral_type mask = integral_type(1) << 64 - 1; boost::random::uniform_int_distribution distribution(0, range); @@ -216,23 +337,25 @@ void test_keccak_round_random() { value_type RC = value_type(0); for (int i = 0; i < 25; ++i) { - inner_state[i] = generate_random(); + inner_state[i] = to_sparse(value_type(integral_type(generate_random().data) & mask)); } for (int i = 0; i < 17; ++i) { - padded_message_chunk[i] = generate_random(); + padded_message_chunk[i] = 0; //to_sparse(value_type(integral_type(generate_random().data) & mask)); } - RC = generate_random(); + RC = to_sparse(value_type(integral_type(generate_random().data) & mask)); + + auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); test_keccak_round_inner - (inner_state, padded_message_chunk, RC); + (inner_state, padded_message_chunk, RC, expected_result); } BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { - using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - test_keccak_round_random(); - test_keccak_round_random(); + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + test_keccak_round_1(); + test_keccak_round_1(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { From 97a220498cce6b0df971cf8a3e1821656d8a2370 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 9 Aug 2023 18:08:56 +0000 Subject: [PATCH 06/48] fixed calculations #183 --- .../components/hashes/keccak/keccak_round.hpp | 124 +++++++++-------- test/hashes/plonk/keccak_round.cpp | 127 ++++++++++-------- 2 files changed, 130 insertions(+), 121 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 0a0bff97b..01c0952ab 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -1073,14 +1073,6 @@ namespace nil { integral_normalized_sum += integral_normalized_chunks.back() * power; power <<= chunk_size; } - // std::cout << "chunks:\n"; - // for (int j = 0; j < num_chunks; ++j) { - // std::cout << integral_chunks[j] << "\n"; - // } - // std::cout << "normalized chunks:\n"; - // for (int j = 0; j < num_chunks; ++j) { - // std::cout << integral_normalized_chunks[j] << "\n"; - // } A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; @@ -1097,10 +1089,10 @@ namespace nil { A_1[i] = var_value(assignment, instance_input.inner_state[i]); } config_index += 17; - std::cout << "inner_state ^ chunk:\n"; - for (int i = 0; i < 25; ++i) { - std::cout << A_1[i] << "\n"; - } + // std::cout << "inner_state ^ chunk:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << A_1[i] << "\n"; + // } // theta std::array C; @@ -1140,10 +1132,10 @@ namespace nil { } } config_index += 5; - std::cout << "theta 0:\n"; - for (int i = 0; i < 5; ++i) { - std::cout << C[i] << "\n"; - } + // std::cout << "theta 0:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C[i] << "\n"; + // } std::array C_rot; for (int index = 0; index < 5; ++index) { @@ -1179,14 +1171,16 @@ namespace nil { } } config_index += 5; - std::cout << "theta 1:\n"; - for (int i = 0; i < 5; ++i) { - std::cout << C_rot[i] << "\n"; - } + // std::cout << "theta 1:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C_rot[i] << "\n"; + // } std::array A_2; for (int index = 0; index < 25; ++index) { - value_type sum = A_1[index] + C_rot[(index + 1) % 5] + C[(index + 4) % 5]; + int x = index / 5; + int y = index % 5; + value_type sum = A_1[index] + C_rot[(x + 1) % 5] + C[(x + 4) % 5]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; auto num_chunks = component.normalize4_num_chunks; @@ -1216,10 +1210,10 @@ namespace nil { } } config_index += 25; - std::cout << "theta 2:\n"; - for (int i = 0; i < 25; ++i) { - std::cout << A_2[i] << "\n"; - } + // std::cout << "theta 2:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << A_2[i] << "\n"; + // } // rho/phi value_type B[5][5]; @@ -1263,12 +1257,12 @@ namespace nil { } } config_index += 24; - std::cout << "rho/phi:\n"; - for (int i = 0; i < 5; ++i) { - for (int j = 0; j < 5; ++j) { - std::cout << B[i][j] << "\n"; - } - } + // std::cout << "rho/phi:\n"; + // for (int i = 0; i < 5; ++i) { + // for (int j = 0; j < 5; ++j) { + // std::cout << B[i][j] << "\n"; + // } + // } // chi std::array A_3; @@ -1305,42 +1299,44 @@ namespace nil { } } config_index += 25; - std::cout << "chi:\n"; - for (int i = 0; i < 25; ++i) { - std::cout << A_3[i] << "\n"; - } + // std::cout << "chi:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << A_3[i] << "\n"; + // } // iota - value_type round_constant = var_value(assignment, instance_input.round_constant); - value_type sum = A_3[0] + round_constant; - integral_type integral_sum = integral_type(sum.data); - auto chunk_size = component.normalize3_chunk_size; - auto num_chunks = component.normalize3_num_chunks; - std::vector integral_chunks; - std::vector integral_normalized_chunks; - integral_type mask = (integral_type(1) << chunk_size) - 1; - integral_type power = 1; - integral_type integral_normalized_sum = 0; - for (std::size_t j = 0; j < num_chunks; ++j) { - integral_chunks.push_back(integral_sum & mask); - integral_sum >>= chunk_size; - integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); - integral_normalized_sum += integral_normalized_chunks.back() * power; - power <<= chunk_size; - } - value_type A_4 = value_type(integral_normalized_sum); - - auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_3[0]; - assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = round_constant; - assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); + { + value_type round_constant = var_value(assignment, instance_input.round_constant); + value_type sum = A_3[0] + round_constant; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize3_chunk_size; + auto num_chunks = component.normalize3_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_chunks.push_back(integral_sum & mask); + integral_sum >>= chunk_size; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; + power <<= chunk_size; + } + value_type A_4 = value_type(integral_normalized_sum); + + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_3[0]; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = round_constant; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum) + for (int j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); + } } - std::cout << "iota:\n"; - std::cout << A_4 << "\n"; + // std::cout << "iota:\n"; + // std::cout << A_4 << "\n"; return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 4f274ae70..bf8b4186a 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -25,6 +25,9 @@ #define BOOST_TEST_MODULE plonk_keccak_test #include +#include +#include +#include #include @@ -46,11 +49,11 @@ #include "../../test_plonk_component.hpp" -const int r[5][5] = {{0, 1, 62, 28, 27}, - {36, 44, 6, 55, 20}, - {3, 10, 43, 25, 39}, - {41, 45, 15, 21, 8}, - {18, 2, 61, 56, 14}}; +const int r[5][5] = {{0, 36, 3, 41, 18}, + {1, 44, 10, 45, 2}, + {62, 6, 43, 15, 61}, + {28, 55, 25, 21, 56}, + {27, 20, 39, 8, 14}}; template typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { @@ -103,61 +106,72 @@ std::array sparse_round_function(st } auto rot = [](integral_type x, const int s) { - return ((x << s) | (x >> (192 - 3 * s))); + return ((x << (3 * s)) | (x >> (192 - 3 * s))) & ((integral_type(1) << 192) - 1); }; for (int i = 0; i < 17; ++i) { inner_state_integral[i] = inner_state_integral[i] ^ padded_message_chunk_integral[i]; } - if (level == 0) { - for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(inner_state_integral[i]); - } - return inner_state; - } + // std::cout << "expected inner_state ^ chunk:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << inner_state_integral[i] << "\n"; + // } + // theta std::array C; for (int x = 0; x < 5; ++x) { C[x] = inner_state_integral[5 * x] ^ inner_state_integral[5 * x + 1] ^ inner_state_integral[5 * x + 2] ^ inner_state_integral[5 * x + 3] ^ inner_state_integral[5 * x + 4]; - for (int y = 0; y < 5; ++y) { - inner_state_integral[5 * x + y] = inner_state_integral[5 * x + y] ^ C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); - } } - if (level == 1) { - for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(inner_state_integral[i]); - } - return inner_state; + // std::cout << "expected theta 0:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C[i] << "\n"; + // } + std::array C_rot; + for (int x = 0; x < 5; ++x) { + C_rot[x] = rot(C[x], 1); } - // rho and pi - std::array B; + // std::cout << "expected theta 1:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C_rot[i] << "\n"; + // } for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { - B[5 * y + ((2 * x + 3 * y) % 5)] = rot(inner_state_integral[5 * x + y], r[x][y]); + inner_state_integral[5 * x + y] = inner_state_integral[5 * x + y] ^ C[(x + 4) % 5] ^ C_rot[(x + 1) % 5]; } } - if (level == 2) { - for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(B[i]); - } - return inner_state; + // std::cout << "expected theta 2:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << inner_state_integral[i] << "\n"; + // } + + // rho and pi + std::array, 5> B; + for (int i = 0; i < 25; ++i) { + int x = i / 5; + int y = i % 5; + B[y][(2 * x + 3 * y) % 5] = rot(inner_state_integral[i], r[x][y]); } + // std::cout << "expected rho/pi:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << B[i / 5][i % 5] << "\n"; + // } + // chi - for (int x = 0; x < 5; ++x) { - for (int y = 0; y < 5; ++y) { - inner_state_integral[5 * x + y] = B[5 * x + y] ^ ((~B[5 * x + ((y + 1) % 5)]) & B[5 * x + ((y + 2) % 5)]); - } - } - if (level == 3) { - for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(inner_state_integral[i]); - } - return inner_state; + for (int i = 0; i < 25; ++i) { + int x = i / 5; + int y = i % 5; + inner_state_integral[i] = B[x][y] ^ ((~B[(x + 1) % 5][y]) & B[(x + 2) % 5][y]); } + // std::cout << "expected chi:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << inner_state_integral[i] << "\n"; + // } + // iota inner_state_integral[0] = inner_state_integral[0] ^ RC_integral; - + // std::cout << "expected iota:\n"; + // std::cout << inner_state_integral[0] << "\n"; for (int i = 0; i < 25; ++i) { inner_state[i] = value_type(inner_state_integral[i]); } @@ -187,18 +201,18 @@ auto test_keccak_round_inner(std::array public_input; - std::cout << "inner state:\n"; + // std::cout << "inner state:\n"; for (int i = 0; i < 25; ++i) { public_input.push_back(inner_state[i]); - std::cout << inner_state[i].data << std::endl; + // std::cout << inner_state[i].data << std::endl; } - std::cout << "padded message chunk:\n"; + // std::cout << "padded message chunk:\n"; for (int i = 0; i < 17; ++i) { public_input.push_back(padded_message_chunk[i]); - std::cout << padded_message_chunk[i].data << std::endl; + // std::cout << padded_message_chunk[i].data << std::endl; } public_input.push_back(RC); - std::cout << "RC: " << RC.data << std::endl; + // std::cout << "RC: " << RC.data << std::endl; std::array inner_state_vars; std::array padded_message_chunk_vars; @@ -215,7 +229,7 @@ auto test_keccak_round_inner(std::array generate_random; - boost::random::mt19937 seed_seq; - generate_random.seed(seed_seq); - uint64_t range = 18446744073709551615U; //2^64 - 1 - integral_type mask = integral_type(1) << 64 - 1; - - boost::random::uniform_int_distribution distribution(0, range); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; std::array inner_state; std::array padded_message_chunk; value_type RC = value_type(0); for (int i = 0; i < 25; ++i) { - inner_state[i] = to_sparse(value_type(integral_type(generate_random().data) & mask)); + auto random_value = integral_type(dis(gen)); + inner_state[i] = to_sparse(value_type(random_value)); } for (int i = 0; i < 17; ++i) { - padded_message_chunk[i] = 0; //to_sparse(value_type(integral_type(generate_random().data) & mask)); + auto random_value = integral_type(dis(gen)); + padded_message_chunk[i] = to_sparse(value_type(random_value)); } - RC = to_sparse(value_type(integral_type(generate_random().data) & mask)); + auto random_value = integral_type(dis(gen)); + RC = to_sparse(value_type(random_value)); auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); @@ -354,8 +367,8 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_round_1(); - test_keccak_round_1(); + test_keccak_round_random(); + test_keccak_round_random(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { From 62a49fc84b48cf87b1385dba1a959140e5e9fbae Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 16 Aug 2023 19:23:24 +0000 Subject: [PATCH 07/48] padding component #183 --- .../hashes/keccak/keccak_component.hpp | 26 +- ...eccak_per_chunk.hpp => keccak_padding.hpp} | 268 +++++------ .../components/hashes/keccak/keccak_round.hpp | 438 ++++++++++++------ test/hashes/plonk/keccak_round.cpp | 28 +- 4 files changed, 466 insertions(+), 294 deletions(-) rename include/nil/blueprint/components/hashes/keccak/{keccak_per_chunk.hpp => keccak_padding.hpp} (55%) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index abaa5a474..cc8655ec6 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -27,7 +27,8 @@ #include -#include +#include < +#include namespace nil { namespace blueprint { @@ -54,10 +55,13 @@ namespace nil { using var = typename component_type::var; using round_component_type = keccak_round, - WitnessesAmount>; + ArithmetizationParams>, WitnessesAmount>; std::vector rounds; + using padding_component_type = keccak_padding, WitnessesAmount>; + padding_component_type padding; + using configuration = round_component_type::configuration; std::vector full_configuration; @@ -191,18 +195,22 @@ namespace nil { const std::size_t num_round_calls) { std::vector result; std::size_t round_rows = round_component_type::rows_amount; + std::size_t padding_rows = padding_component_type::rows_amount; std::size_t row = 0, column = 0; // padding + row += padding_rows; - // rounds + //rounds for (std::size_t index = 0; index < num_round_calls; ++index) { + // to sparse representation for (std::size_t i = 0; i < 17; ++i) { result.push_back(configure_pack_unpack(row, column)); row = result[i].last_row; column = result[i].last_column; } + // round if (column > 0) { column = 0; row += 1 + 24 * round_rows; @@ -211,7 +219,7 @@ namespace nil { } } - // finalization + // from sparse representation for (std::size_t i = 0; i < 5; ++i) { result.push_back(configure_pack_unpack(row, column)); row = result[i].last_row; @@ -229,6 +237,7 @@ namespace nil { num_round_calls(), \ rounds(num_round_calls * 24, \ round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ + padding(padding_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ num_configs(), \ full_configuration(configure_all(num_configs, num_round_calls)), \ rows_amount(rows()) @@ -344,7 +353,6 @@ namespace nil { using component_type = keccak_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; BOOST_ASSERT(row == start_row_index + component.rows_amount); @@ -377,8 +385,12 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - using var_address = typename component_type::var_address; + std::vector> padded_message = generate_assignments(component.padding, assignment, + {instance_input.message}, row).output; + row += component.padding.rows_amount; + + BOOST_ASSERT(row == start_row_index + component.rows_amount); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp similarity index 55% rename from include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp rename to include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 40aa0f62e..4a9898660 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_per_chunk.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -52,191 +52,140 @@ namespace nil { public: using var = typename component_type::var; - using round_component_type = keccak_round, - WitnessesAmount>; - std::array rounds; - - using configuration = round_component_type::configuration; - std::array full_configuration; - const std::size_t rows_amount; - constexpr static const std::size_t gates_amount = 17 * round_component_type::gates_amount; + constexpr static const std::size_t gates_amount; + + const std::size_t num_blocks; + const std::size_t num_bits_first; + const std::size_t bits_per_block = 255; + std::vector shifts; struct input_type { - std::array inner_state; - std::array padded_message_chunk; + std::vector message; }; struct result_type { - std::array final_inner_state; + std::vector padded_message; result_type(const keccak_per_chunk &component, std::size_t start_row_index) { } }; - integral_type pack(const integral_type& const_input) const { - integral_type input = const_input; - integral_type sparse_res = 0; - integral_type power = 1; - while (input > 0) { - auto bit = input % 2; - sparse_res += bit * power; - power *= 8; - input /= 2; + configuration configure_batching(std::size_t row, std::size_t column, + std::size_t prev_bits, std::size_t &next_bits, + std::size_t total_bits = bits_per_block) { + if (prev_bits > 64) { + next_bits = prev_bits - 64; + } else { + next_bits = bits_per_block - 64 + prev_bits; } - return sparse_res; - } - integral_type unpack(const integral_type& const_sparse_input) const { - integral_type sparse_input = const_sparse_input; - integral_type res = 0; - integral_type power = 1; - while (sparse_input > 0) { - auto bit = sparse_input % 8; - BOOST_ASSERT(bit * (1 - bit) == 0); - res += bit * power; - power *= 2; - sparse_input /= 8; - } - return res; + std::size_t num_chunks = total_bits / 64 + bool(total_bits % 64); + + + // return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - configuration configure_pack_unpack(std::size_t row, std::size_t column) { - // regular constraints: - // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) - // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) - - std::size_t last_row = row, - last_column = column; - - std::vector> copy_from; - std::vector>> constraints; - - if (1 + column > limit) { - copy_from.push_back({last_row + 1, 0}); - } else { - copy_from.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); - } - - std::pair cell_copy_to; - std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; - if (final_row == copy_from[0].first) { - cell_copy_to = {final_row, copy_from.back().second + 1}; - } else { - cell_copy_to = {final_row, 0}; - } - - std::vector> cells; - if (1 + column > limit) { - for (int i = column; i < WitnessesAmount; ++i) { - cells.push_back({row, i}); - } - std::size_t cells_left = num_cells - WitnessesAmount + column; - std::size_t cur_row = row + 1, - cur_column = 1; - while (cur_column < cells_left) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { - cur_column++; - continue; - } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); - } - } else { - std::size_t cur_row = row, - cur_column = column + 1; - while (cur_column - column < num_cells) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { - cur_column++; - continue; - } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); - } - } - std::size_t cell_index = 0; - - std::vector>> lookups(num_chunks, std::vector>()); - - constraints.push_back({copy_from[0]}); - constraints.push_back({cell_copy_to}); - for (std::size_t i = 0; i < 2; ++i) { - for (std::size_t j = 0; j < num_chunks; ++j) { - constraints[i].push_back(cells[cell_index++]); - lookups[j].push_back(constraints[i].back()); - } + configuration configure_padding(std::size_t row, std::size_t column, + std::size_t prev_bits = 0) { + if (prev_bits == 0) { + // costraint with 0 + auto last_column = column + 1; + auto last_row = row + (last_column / WitnessesAmount); + last_column %= WitnessesAmount; + return configuration({last_row, last_column}, {{row, column}}, {}, {}, {row, column}); } - - last_column = cells.back().second + 1; - last_row = cells.back().first + (last_column / WitnessesAmount); + auto other_column = column + 1; + auto other_row = row + (other_column / WitnessesAmount); + other_column %= WitnessesAmount; + auto last_column = column + 2; + auto last_row = row + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - - return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + return configuration({last_row, last_column}, {{row, column}}, {{{other_row, other_column}, {row, column}}}, {{other_row, other_column}}, {other_row, other_column}); } - std::array configure_all() { - std::array result; + std::vector configure_all() { + std::vector result; std::size_t row = 0, column = 0; - for (std::size_t i = 0; i < 17; ++i) { - result[i] = configure_pack_unpack(row, column); + std::size_t next_bits = 0; + + //batching + result.push_back(configure_batching(row, column, 0, next_bits, num_bits_first)); + row = result.back().last_row; + column = result.back().last_column; + for (std::size_t i = 1; i < num_blocks; ++i) { + result.push_back(configure_batching(row, column, next_bits, next_bits)); row = result[i].last_row; column = result[i].last_column; } + + //counting number of chunks + std::size_t total_bits = num_bits_first + (num_blocks - 1) * bits_per_block; + std::size_t padding_bits = 1088 - (total_bits % 1088); + std::size_t padding_chunks = (total_bits + padding_bits) / 64 - total_bits / 64; + + //padding with zeros + result.push_back(configure_padding(row, column, next_bits)); + row = result.back().last_row; + column = result.back().last_column; + for (std::size_t i = 1; i < padding_chunks; ++i) { + result.push_back(configure_padding(row, column)); + row = result.back().last_row; + column = result.back().last_column; + } + return result; } - #define __keccak_per_chunk_init_macro(witness, constant, public_input, \ - lookup_rows_, lookup_columns_) \ + #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_first_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ - pack_chunk_size(calculate_normalize_chunk_size(lookup_rows_, 3)), \ - pack_num_chunks(calculate_num_chunks(normalize3_chunk_size)), \ - pack_cells(normalize3_num_chunks * 2 + 2 + 2), \ + num_blocks(num_blocks_), \ + num_bits_first(num_bits_first_), \ full_configuration(configure_all()), \ rows_amount(rows()), \ gates_amount(gates()) template - keccak_per_chunk(ContainerType witness, std::size_t bits_amount_, bool check_inputs_) : + keccak_per_chunk(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : component_type(witness, {}, {}), - __keccak_per_chunk_init_macro(witness, {}, {}, bits_amount_, check_inputs_) {}; + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) {}; template keccak_per_chunk(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t bits_amount_, bool check_inputs_): + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_): component_type(witness, constant, public_input), - __keccak_per_chunk_init_macro(witness, constant, public_input, bits_amount_, check_inputs_) {}; + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) {}; keccak_per_chunk( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t bits_amount_, bool check_inputs_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : component_type(witnesses, constants, public_inputs), - __keccak_per_chunk_init_macro(witnesses, constants, public_inputs, - bits_amount_, check_inputs_) + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) {}; - #undef __keccak_per_chunk_init_macro + #undef __keccak_padding_init_macro }; template - using keccak_pc_component = - keccak_per_chunk, WitnessesAmount>; template= 9, bool> = true> void generate_gates( - const keccak_pc_component &component, circuit> &assignment, - const typename keccak_pc_component::input_type &instance_input, const std::size_t first_selector_index) { - using component_type = keccak_pc_component; using var = typename component_type::var; using var_address = typename component_type::var_address; @@ -262,7 +211,7 @@ namespace nil { template= 9, bool> = true> void generate_copy_constraints( - const keccak_pc_component &component, circuit> &assignment, - const typename keccak_pc_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_pc_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; std::uint32_t row = start_row_index; } template= 9, bool> = true> - typename keccak_pc_component::result_type generate_circuit( - const keccak_pc_component &component, circuit> &assignment, - const typename keccak_pc_component::input_type &instance_input, const std::uint32_t start_row_index) { @@ -306,50 +254,88 @@ namespace nil { std::size_t first_selector_index; std::size_t row = start_row_index; - using component_type = keccak_pc_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; BOOST_ASSERT(row == start_row_index + component.rows_amount); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + generate_assignments_constants(component, bp, assignment, instance_input, start_row_index); return typename component_type::result_type(component, start_row_index); } template= 9, bool> = true> - typename keccak_pc_component::result_type generate_assignments( - const keccak_pc_component &component, assignment> &assignment, - const typename keccak_pc_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t row = start_row_index; - using component_type = keccak_pc_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - using var_address = typename component_type::var_address; - - BOOST_ASSERT(row == start_row_index + component.rows_amount); + std::size_t config_index = 0; + + // batching + value_type relay_chunk = 0; + std::size_t relay_bits = 0; + for (std::size_t index = 0; index < component.num_blocks; ++index) { + value_type chunk = var_value(assignment, instance_input.message[index]); + std::size_t bit_size = index == 0 ? component.num_bits_first : component.bits_per_block; + std::size_t shift = component.shifts[index]; + std::vector chunk_parts; + while (chunk > 0) { + integral_type mask = (integral_type(1) << shift) - 1; + chunk_parts.push_back(chunk & mask); + chunk >>= shift; + shift = 64; + } + value_type first_chunk = (relay_chunk << relay_bits) + chunk_parts.back(); + } return typename component_type::result_type(component, start_row_index); } + template= 9, bool> = true> + void generate_assignments_constant( + const keccak_pad_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_pad_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_pad_component; + + assignment.constant(component.C(0), start_row_index) = 0; + } + } // namespace components } // namespace blueprint diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 01c0952ab..c8a40218d 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -75,13 +75,15 @@ namespace nil { } std::size_t calculate_rows() const { - std::size_t num_cells = 17 * xor2_cells + // inner_state ^ chunk - 5 * xor5_cells + // theta - 5 * rotate_cells + // theta - 25 * xor3_cells + // theta - 24 * rotate_cells + // rho/phi - 25 * chi_cells + // chi - xor2_cells; // iota + std::size_t num_cells = xor3_cells * last_round_call + // xor with last message chunk + ((17 - last_round_call) * xor2_cells) + * xor_with_mes + // inner_state ^ chunk + 5 * xor5_cells + // theta + 5 * rotate_cells + // theta + 25 * xor3_cells + // theta + 24 * rotate_cells + // rho/phi + 25 * chi_cells + // chi + xor2_cells; // iota return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } std::vector calculate_gates_rows() const { @@ -94,6 +96,9 @@ namespace nil { res.push_back(cur_selector); } } + // for (int i = 0; i < res.size(); ++i) { + // std::cout << res[i] << " "; + // } return res; } std::size_t gates() const { @@ -118,6 +123,9 @@ namespace nil { coordinates() = default; coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + bool operator== (const coordinates& other) const { + return row == other.row && column == other.column; + } }; // In constraints we use such notation: constr[0] - result, @@ -161,6 +169,13 @@ namespace nil { const std::size_t lookup_rows; const std::size_t lookup_columns; + // need to xor inner state with message only on the first round + const bool xor_with_mes; + // need to xor last message chunk with 0x80 or 1 only on the last round + const bool last_round_call; + // change permutation on rho/phi step + const bool eth_perm; + const std::size_t normalize3_chunk_size; const std::size_t normalize4_chunk_size; const std::size_t normalize6_chunk_size; @@ -182,7 +197,8 @@ namespace nil { const std::size_t rows_amount; // full configuration is precalculated, then used in other functions - std::array full_configuration; + const std::size_t full_configuration_size = 17 * xor_with_mes + 85; + std::vector full_configuration = std::vector(full_configuration_size); // number represents relative selector index for each constraint std::vector gates_configuration; std::vector lookup_gates_configuration; @@ -219,7 +235,7 @@ namespace nil { std::array inner_state; result_type(const keccak_round &component, std::size_t start_row_index) { - std::size_t num_config = 101; + std::size_t num_config = component.full_configuration.size() - 1; inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.row), component.full_configuration[num_config].copy_from.column); for (int i = 1; i < 25; ++i) { @@ -328,8 +344,24 @@ namespace nil { } last_column = cells.back().second + 1; - last_row = cells.back().first + (last_column > WitnessesAmount); + last_row = cells.back().first + (last_column >= WitnessesAmount); last_column %= WitnessesAmount; + + // std::cout << "normalize " << num_args << ": " << row << ' ' << column << std::endl; + // std::cout << "last coordinate: " << last_row << " " << last_column << std::endl; + // std::cout << "copy from: " << cell_copy_from.first << " " << cell_copy_from.second << std::endl; + // std::cout << "copy to:\n"; + // for (auto cell : copy_to) { + // std::cout << cell.first << " " << cell.second << "\n"; + // } + // std::cout << "constraints:\n"; + // for (auto constr : constraints) { + // std::cout << "constraint:\n"; + // for (auto cell : constr) { + // std::cout << cell.first << " " << cell.second << "\n"; + // } + // } + return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } @@ -436,58 +468,105 @@ namespace nil { last_column = cells.back().second + 1; last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; + + // std::cout << "ROT: " << row << ' ' << column << std::endl; + // std::cout << "last coordinate: " << last_row << " " << last_column << std::endl; + // std::cout << "copy from: " << cell_copy_from.first << " " << cell_copy_from.second << std::endl; + // std::cout << "copy to:\n"; + // for (auto cell : copy_to) { + // std::cout << cell.first << " " << cell.second << "\n"; + // } + // std::cout << "constraints:\n"; + // for (auto constr : constraints) { + // std::cout << "constraint:\n"; + // for (auto cell : constr) { + // std::cout << cell.first << " " << cell.second << "\n"; + // } + // } return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - std::array configure_all() { - std::array result; + std::vector configure_all() { + auto result = std::vector(full_configuration_size); std::size_t row = 0, column = 0; + std::size_t cur_config = 0; // inner_state ^ chunk - for (int i = 0; i < 17; ++i) { - result[i] = configure_xor(row, column, 2); - row = result[i].last_coordinate.row; - column = result[i].last_coordinate.column; + if (xor_with_mes) { + for (int i = 0; i < 17 - last_round_call; ++i) { + result[i] = configure_xor(row, column, 2); + row = result[i].last_coordinate.row; + column = result[i].last_coordinate.column; + cur_config++; + } + // xor with last message chunk + if (last_round_call) { + result[cur_config] = configure_xor(row, column, 3); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; + } } // theta for (int i = 0; i < 5; ++i) { - result[17 + i] = configure_xor(row, column, 5); - row = result[17 + i].last_coordinate.row; - column = result[17 + i].last_coordinate.column; + result[cur_config] = configure_xor(row, column, 5); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; } for (int i = 0; i < 5; ++i) { - result[22 + i] = configure_rot(row, column); - row = result[22 + i].last_coordinate.row; - column = result[22 + i].last_coordinate.column; + result[cur_config] = configure_rot(row, column); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; } for (int i = 0; i < 25; ++i) { - result[27 + i] = configure_xor(row, column, 3); - row = result[27 + i].last_coordinate.row; - column = result[27 + i].last_coordinate.column; + result[cur_config] = configure_xor(row, column, 3); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; } // rho/phi for (int i = 0; i < 24; ++i) { - result[52 + i] = configure_rot(row, column); - row = result[52 + i].last_coordinate.row; - column = result[52 + i].last_coordinate.column; + result[cur_config] = configure_rot(row, column); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; } // chi for (int i = 0; i < 25; ++i) { - result[76 + i] = configure_chi(row, column); - row = result[76 + i].last_coordinate.row; - column = result[76 + i].last_coordinate.column; + result[cur_config] = configure_chi(row, column); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; } // iota - result[101] = configure_xor(row, column, 2); - + result[cur_config] = configure_xor(row, column, 2); + + // for (int i = 0; i < 50; ++i) { + // std::cout << "configuration " << i << std::endl; + // std::cout << "last coordinate: " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; + // std::cout << "copy from: " << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; + // std::cout << "copy to:\n"; + // for (auto cell : result[i].copy_to) { + // std::cout << cell.row << " " << cell.column << "\n"; + // } + // std::cout << "constraints:\n"; + // for (auto constr : result[i].constraints) { + // std::cout << "constraint:\n"; + // for (auto cell : constr) { + // std::cout << cell.row << " " << cell.column << "\n"; + // } + // } + // } return result; } std::vector configure_gates() { std::vector> pairs; - for (std::size_t i = 0; i < 102; ++i) { + for (std::size_t i = 0; i < full_configuration_size; ++i) { for (auto constr : full_configuration[i].constraints) { std::size_t min = constr[0].row; std::size_t max = constr.back().row; @@ -517,7 +596,7 @@ namespace nil { std::vector configure_lookup_gates() { std::vector> pairs; - for (std::size_t i = 0; i < 102; ++i) { + for (std::size_t i = 0; i < full_configuration_size; ++i) { for (auto constr : full_configuration[i].lookups) { std::size_t min = constr[0].row; std::size_t max = constr.back().row; @@ -545,9 +624,12 @@ namespace nil { return result; } - #define __keccak_round_init_macro(lookup_rows_, lookup_columns_) \ + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ + xor_with_mes(xor_with_mes_), \ + last_round_call(last_round_call_),\ + eth_perm(eth_perm_), \ normalize3_chunk_size(calculate_chunk_size(lookup_rows_, 3)), \ normalize4_chunk_size(calculate_chunk_size(lookup_rows_, 4)), \ normalize6_chunk_size(calculate_chunk_size(lookup_rows_, 6)), \ @@ -569,26 +651,35 @@ namespace nil { gates_rows(calculate_gates_rows()) template - keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_) : + keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, + bool xor_with_mes_ = false, + bool last_round_call_ = false, + bool eth_perm_ = false) : component_type(witness, {}, {}), - __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; template keccak_round(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t lookup_rows_, std::size_t lookup_columns_): + std::size_t lookup_rows_, std::size_t lookup_columns_, + bool xor_with_mes_ = false, + bool last_round_call_ = false, + bool eth_perm_ = false) : component_type(witness, constant, public_input), - __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; keccak_round( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, + bool xor_with_mes_ = false, + bool last_round_call_ = false, + bool eth_perm_ = false) : component_type(witnesses, constants, public_inputs), - __keccak_round_init_macro(lookup_rows_, lookup_columns_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; #undef __keccak_round_init_macro }; @@ -637,27 +728,52 @@ namespace nil { // std::vector lookup_constraints; // inner_state ^ chunk - for (int i = 0; i < 17; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); + if (component.xor_with_mes) { + for (int i = 0; i < 17 - component.last_round_call; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (integral_type(1) << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize3_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (integral_type(1) << (j * component.normalize3_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; + } + if (component.last_round_call) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + gate_index++; + constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize4_num_chunks; ++j) { + constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + * (integral_type(1) << (j * component.normalize4_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + gate_index++; + constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + for (int j = 0; j < component.normalize4_num_chunks; ++j) { + constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + * (integral_type(1) << (j * component.normalize4_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + gate_index++; + config_index++; } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; } // theta @@ -702,18 +818,18 @@ namespace nil { - (integral_type(1) << 3) + (integral_type(1) << 192))); gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) - - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) - - (integral_type(1) << 189) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); + constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) + constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) + - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) + - (integral_type(1) << 189) + + (integral_type(1) << 192))); + gate_index++; constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) @@ -766,18 +882,18 @@ namespace nil { - (integral_type(1) << r) + (integral_type(1) << 192))); gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]) - - var(cur_config.constraints[3][1].column, cur_config.constraints[3][1].row - gate_config[gate_index]) - - (integral_type(1) << (192 - r)) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]); + constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[4][j + 1].column, cur_config.constraints[4][j + 1].row - gate_config[gate_index]) + constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) * (integral_type(1) << (j * component.rotate_chunk_size)); } constraints.push_back(bp.add_constraint(constraint_1)); gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) + - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) + - (integral_type(1) << (192 - r)) + + (integral_type(1) << 192))); + gate_index++; constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); for (int j = 0; j < component.rotate_num_chunks; ++j) { constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) @@ -838,7 +954,7 @@ namespace nil { config_index++; } - BOOST_ASSERT(config_index == 102); + BOOST_ASSERT(config_index == component.full_configuration_size); BOOST_ASSERT(constraints.size() == gate_config.size()); std::size_t prev_selector = gate_config[0]; @@ -885,27 +1001,40 @@ namespace nil { using var = typename component_type::var; std::size_t config_index = 0; + std::size_t prev_index = 0; auto config = component.full_configuration; - // inner_state ^ chunk - for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].row), config[i].copy_to[0].column, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].row), config[i].copy_to[1].column, false)}); - } - config_index += 17; - std::size_t prev_index = 0; + if (component.xor_with_mes) { + // inner_state ^ chunk + for (int i = 0; i < 17 - component.last_round_call; ++i) { + bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].row), config[i].copy_to[0].column, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].row), config[i].copy_to[1].column, false)}); + } + config_index += 16; + if (component.last_round_call) { + bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].row), config[config_index].copy_to[0].column, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].row), config[config_index].copy_to[1].column, false)}); + } + config_index += 1; - // theta - for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, - {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); - } - for (int i = 17; i < 25; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + // theta + for (int i = 0; i < 17; ++i) { + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, + {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + } + for (int i = 17; i < 25; ++i) { + bp.add_copy_constraint({instance_input.inner_state[i], + {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + } + config_index += 5; + prev_index += 17; + } else { + for (int i = 0; i < 25; ++i) { + bp.add_copy_constraint({instance_input.inner_state[i], + {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + } + config_index += 5; } - config_index += 5; - prev_index += 17; for (int i = 0; i < 5; ++i) { bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); @@ -914,7 +1043,7 @@ namespace nil { prev_index += 5; for (int i = 0; i < 25; ++i) { - bp.add_copy_constraint({{component.W(config[17 + i / 5].copy_to[i % 5].row), static_cast(config[17 + i / 5].copy_to[i % 5].column), false}, + bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].row), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].column), false}, {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.row), static_cast(config[prev_index + (i + 1) % 5].copy_from.column), false}, {component.W(config[config_index + i].copy_to[1].row), static_cast(config[config_index + i].copy_to[1].column), false}}); @@ -977,8 +1106,11 @@ namespace nil { using component_type = keccak_round_component; - // TODO: need to find the exact answer - // std::size_t row = start_row_index + 242 + 3; + + std::size_t row = start_row_index; + assignment.constant(component.C(0), row) = 2097152; // sparse 0x80 + assignment.constant(component.C(0), row + 1) = 1; // sparse 1 + // for (std::size_t i = 0; i < 25; i++) { // assignment.constant(component.C(0), row + i * 8) = component_type::rho_offsets[i]; // } @@ -1054,41 +1186,79 @@ namespace nil { // inner_state ^ chunk std::array A_1; - for (int index = 0; index < 17; ++index) { - value_type state = var_value(assignment, instance_input.inner_state[index]); - value_type message = var_value(assignment, instance_input.padded_message_chunk[index]); - value_type sum = state + message; - integral_type integral_sum = integral_type(sum.data); - auto chunk_size = component.normalize3_chunk_size; - auto num_chunks = component.normalize3_num_chunks; - std::vector integral_chunks; - std::vector integral_normalized_chunks; - integral_type mask = (integral_type(1) << chunk_size) - 1; - integral_type power = 1; - integral_type integral_normalized_sum = 0; - for (std::size_t j = 0; j < num_chunks; ++j) { - integral_chunks.push_back(integral_sum & mask); - integral_sum >>= chunk_size; - integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); - integral_normalized_sum += integral_normalized_chunks.back() * power; - power <<= chunk_size; + if (component.xor_with_mes) { + for (int index = 0; index < 17 - component.last_round_call; ++index) { + value_type state = var_value(assignment, instance_input.inner_state[index]); + value_type message = var_value(assignment, instance_input.padded_message_chunk[index]); + value_type sum = state + message; + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize3_chunk_size; + auto num_chunks = component.normalize3_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_chunks.push_back(integral_sum & mask); + integral_sum >>= chunk_size; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; + power <<= chunk_size; + } + A_1[index] = value_type(integral_normalized_sum); + + auto cur_config = component.full_configuration[index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = state; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = message; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); + } } - A_1[index] = value_type(integral_normalized_sum); - - auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = state; - assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = message; - assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); + // last round call + if (component.last_round_call) { + value_type state = var_value(assignment, instance_input.inner_state[16]); + value_type message = var_value(assignment, instance_input.padded_message_chunk[16]); + value_type sum = state + message + value_type(component.C(0)); + integral_type integral_sum = integral_type(sum.data); + auto chunk_size = component.normalize4_chunk_size; + auto num_chunks = component.normalize4_num_chunks; + std::vector integral_chunks; + std::vector integral_normalized_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + integral_type power = 1; + integral_type integral_normalized_sum = 0; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_chunks.push_back(integral_sum & mask); + integral_sum >>= chunk_size; + integral_normalized_chunks.push_back(component.normalize(integral_chunks.back())); + integral_normalized_sum += integral_normalized_chunks.back() * power; + power <<= chunk_size; + } + A_1[16] = value_type(integral_normalized_sum); + + auto cur_config = component.full_configuration[16]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = state; + assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = message; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); + for (int j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); + } + } + for (int i = 17; i < 25; ++i) { + A_1[i] = var_value(assignment, instance_input.inner_state[i]); + } + config_index += 17; + } else { + for (int i = 0; i < 25; ++i) { + A_1[i] = var_value(assignment, instance_input.inner_state[i]); } } - for (int i = 17; i < 25; ++i) { - A_1[i] = var_value(assignment, instance_input.inner_state[i]); - } - config_index += 17; // std::cout << "inner_state ^ chunk:\n"; // for (int i = 0; i < 25; ++i) { // std::cout << A_1[i] << "\n"; @@ -1305,6 +1475,7 @@ namespace nil { // } // iota + value_type A_4; { value_type round_constant = var_value(assignment, instance_input.round_constant); value_type sum = A_3[0] + round_constant; @@ -1323,20 +1494,23 @@ namespace nil { integral_normalized_sum += integral_normalized_chunks.back() * power; power <<= chunk_size; } - value_type A_4 = value_type(integral_normalized_sum); + A_4 = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = A_3[0]; assignment.witness(component.W(cur_config.copy_to[1].row), cur_config.copy_to[1].column) = round_constant; assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum) + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].row), cur_config.constraints[1][j].column) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].row), cur_config.constraints[2][j].column) = value_type(integral_normalized_chunks[j - 1]); } } - // std::cout << "iota:\n"; + // std::cout << "result:\n"; // std::cout << A_4 << "\n"; + // for (int i = 1; i < 25; ++i) { + // std::cout << A_3[i] << "\n"; + // } return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index bf8b4186a..89aa05024 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -85,10 +85,7 @@ bool check_sparse(typename BlueprintFieldType::value_type value, typename Bluepr return result; } - -// here for level we use: -// 0 - inner ^ chunk, 1 - theta, 2 - rho/phi, 3 - chi, 4 - iota (full round, by default) -template +template std::array sparse_round_function(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC) { @@ -109,8 +106,10 @@ std::array sparse_round_function(st return ((x << (3 * s)) | (x >> (192 - 3 * s))) & ((integral_type(1) << 192) - 1); }; - for (int i = 0; i < 17; ++i) { - inner_state_integral[i] = inner_state_integral[i] ^ padded_message_chunk_integral[i]; + if (xor_with_mes) { + for (int i = 0; i < 17; ++i) { + inner_state_integral[i] = inner_state_integral[i] ^ padded_message_chunk_integral[i]; + } } // std::cout << "expected inner_state ^ chunk:\n"; // for (int i = 0; i < 25; ++i) { @@ -179,7 +178,7 @@ std::array sparse_round_function(st } template + std::size_t LookupColumns, bool xor_with_mes, bool eth_perm> auto test_keccak_round_inner(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC, @@ -236,9 +235,9 @@ auto test_keccak_round_inner(std::array + std::size_t LookupColumns, bool xor_with_mes, bool eth_perm> void test_keccak_round_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -357,9 +356,9 @@ void test_keccak_round_random() { auto random_value = integral_type(dis(gen)); RC = to_sparse(value_type(random_value)); - auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); + auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } @@ -367,8 +366,9 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); + test_keccak_round_random(); + // test_keccak_round_random(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { From 0da0733de227f64a1fdf890695bcbae42fe20ad0 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Tue, 29 Aug 2023 21:59:01 +0000 Subject: [PATCH 08/48] less constraints update #183 --- .../hashes/keccak/keccak_padding.hpp | 214 ++- .../components/hashes/keccak/keccak_round.hpp | 1311 ++++++++++++----- test/hashes/plonk/keccak_padding.cpp | 222 +++ test/hashes/plonk/keccak_round.cpp | 26 +- 4 files changed, 1374 insertions(+), 399 deletions(-) create mode 100644 test/hashes/plonk/keccak_padding.cpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 4a9898660..47473f2e4 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -56,11 +56,16 @@ namespace nil { constexpr static const std::size_t gates_amount; const std::size_t num_blocks; - const std::size_t num_bits_first; - const std::size_t bits_per_block = 255; - std::vector shifts; + const std::size_t num_bits; + const std::size_t bits_per_block = 64; + std::size_t shift; + + const std::size_t limit_permutation_column = 7; struct input_type { + // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + message[num_blocks - 1] + // all message[i] are 64-bit for i > 0 + // message[0] is <= 64-bit std::vector message; }; @@ -72,6 +77,10 @@ namespace nil { } }; + std::size_t get_shift() { + return num_blocks * 64 - num_bits; + } + configuration configure_batching(std::size_t row, std::size_t column, std::size_t prev_bits, std::size_t &next_bits, std::size_t total_bits = bits_per_block) { @@ -83,6 +92,77 @@ namespace nil { std::size_t num_chunks = total_bits / 64 + bool(total_bits % 64); + std::size_t last_row = row, + last_column = column; + + std::vector> copy_to; + + if (num_args + column > limit_permutation_column) { + for (int i = 0; i < num_args; ++i) { + copy_to.push_back({last_row + 1, i}); + } + } else { + for (int i = 0; i < num_args; ++i) { + copy_to.push_back({last_row + (last_column / WitnessesAmount), + (last_column++) % WitnessesAmount}); + } + } + + std::pair cell_copy_from; + std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + if (final_row == copy_to[0].first) { + cell_copy_from = {final_row, copy_to.back().second + 1}; + } else { + cell_copy_from = {final_row, 0}; + } + + std::vector> cells; + if (num_args + column > limit_permutation_column) { + for (int i = column; i < WitnessesAmount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cur_row = row + 1, + cur_column = num_args; + while (cur_column < cells_left) { + if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } else { + std::size_t cur_row = row, + cur_column = column + num_args; + while (cur_column - column < num_cells) { + if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { + cur_column++; + continue; + } + cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + } + } + std::size_t cell_index = 0; + + std::vector>> constraints; + constraints.push_back({cells[cell_index++]}); + for (int i = 0; i < num_args; ++i) { + constraints[0].push_back(copy_to[i]); + } + + constraints.push_back({constraints[0][0]}); + constraints.push_back({cell_copy_from}); + std::vector>> lookups(num_chunks, std::vector>()); + for (std::size_t i = 1; i < 3; ++i) { + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[i].push_back(cells[cell_index++]); + lookups[j].push_back(constraints[i].back()); + } + } + + last_column = cells.back().second + 1; + last_row = cells.back().first + (last_column >= WitnessesAmount); + last_column %= WitnessesAmount; // return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } @@ -91,6 +171,11 @@ namespace nil { std::size_t prev_bits = 0) { if (prev_bits == 0) { // costraint with 0 + if (column >= limit_permutation_column) { + row = row + 1; + column = 0; + return configuration({row + 1, 1}, {{row + 1, 0}}, {}, {}, {row + 1, 0}); + } auto last_column = column + 1; auto last_row = row + (last_column / WitnessesAmount); last_column %= WitnessesAmount; @@ -140,37 +225,41 @@ namespace nil { return result; } - #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_first_) \ + #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ num_blocks(num_blocks_), \ - num_bits_first(num_bits_first_), \ + num_bits(num_bits_), \ + shift(get_shift()), \ full_configuration(configure_all()), \ rows_amount(rows()), \ gates_amount(gates()) template - keccak_per_chunk(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : + keccak_per_chunk(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, + std::size_t num_blocks_, std::size_t num_bits_) : component_type(witness, {}, {}), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) {}; + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; template keccak_per_chunk(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_): + std::size_t lookup_rows_, std::size_t lookup_columns_, + std::size_t num_blocks_ std::size_t num_bits_): component_type(witness, constant, public_input), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) {}; + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; keccak_per_chunk( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, + std::size_t num_blocks_, std::size_t num_bits_) : component_type(witnesses, constants, public_inputs), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_) + __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; #undef __keccak_padding_init_macro @@ -202,10 +291,51 @@ namespace nil { using component_type = keccak_pad_component; using var = typename component_type::var; - using var_address = typename component_type::var_address; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + + auto config = component.full_configuration; + auto gate_config = component.gates_configuration; + // auto lookup_gate_config = component.lookup_gates_configuration; + std::size_t config_index = 0; + std::size_t gate_index = 0; + // std::size_t lookup_gate_index = 0; + + std::vector constraints; + // std::vector lookup_constraints; + + // batching + if (component.shift > 0) { + for (int i = 0; i < component.num_block; ++i) { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]))); + gate_index++; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + gate_index++; + if (i > 0) { + constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) + + var(cur_config.constraints[2][2].column, cur_config.constraints[2][2].row - gate_config[gate_index]) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]))); + gate_index++; + } + config_index++; + } + + // padding + { + auto cur_config = config[config_index]; + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << component.shift))); + } + } } template; using var = typename component_type::var; - std::uint32_t row = start_row_index; + + std::size_t config_index = 0; + if (component.shift > 0) { + config_index += component.num_blocks + 1; + } + + while (congif_index < component.full_configuration.size()) { + bp.add_copy_constraint({component.C(0), var(component.W(config[i].copy_to[0].row), config[i].copy_to[0].column, false)}); + config_index++; + } } template chunk_parts; - while (chunk > 0) { - integral_type mask = (integral_type(1) << shift) - 1; - chunk_parts.push_back(chunk & mask); - chunk >>= shift; - shift = 64; + if (component.shift != 0) { + // TODO where to put first relay chunk? + value_type relay_chunk = var_value(assignment, instance_input.message[0]); + for (std::size_t index = 1; index < component.num_blocks; ++index) { + value_type chunk = var_value(assignment, instance_input.message[index]); + integral_type integral_chunk = integral_type(chunk); + integral_type mask = (integral_type(1) << component.shift) - 1; + std::array chunk_parts = {value_type(integral_chunk >> component.shift), value_type(integral_chunk & mask)}; + value_type first_chunk = (relay_chunk << (64 - component.shift)) + chunk_parts[0]; + value_type relay_range_check = chunk_parts[1] - (1 << component.shift) + (1 << 64); + + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = chunk; + for (int j = 1; j < 3; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].row), cur_config.constraints[0][j].column) = value_type(chunk_parts[j - 1]); + } + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = relay_range_check; + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = first_chunk; + + relay_chunk = chunk_parts[1]; + config_index++; + } + // padding + { + value_type last_chunk = relay_chunk << (64 - component.shift); + + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = relay_chunk; + assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = last_chunk; + config_index++; } - value_type first_chunk = (relay_chunk << relay_bits) + chunk_parts.back(); + } + + while (congif_index < component.full_configuration.size()) { + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = component.C(0); + config_index++; } return typename component_type::result_type(component, start_row_index); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index c8a40218d..33f4b215a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -29,6 +29,7 @@ #include #include +#include #include @@ -70,19 +71,43 @@ namespace nil { std::size_t res = base == 3 ? normalize3_num_chunks * 2 + 2 + 2 : base == 4 ? normalize4_num_chunks * 2 + 3 + 2 : base == 6 ? normalize6_num_chunks * 2 + 5 + 2 - : chi_chunk_size * 2 + 5; + : chi_num_chunks * 2 + 5; return res; } + std::size_t calculate_buff(std::size_t base = 0) { + std::size_t buff = 0; + std::size_t cells = base == 3 ? xor2_cells + : base == 4 ? xor3_cells + : base == 6 ? xor5_cells + : base == 7 ? chi_cells + : rotate_cells; + if (base == 6) { + return WitnessesAmount * ((cells - 1) / WitnessesAmount + 1) - cells; + } + if (WitnessesAmount % 9 == 0) { + while (cells % 3 != 0) { + cells++; + buff++; + } + } else if (WitnessesAmount % 15 == 0) { + while (cells % 5 != 0) { + cells++; + buff++; + } + } + return buff; + } std::size_t calculate_rows() const { - std::size_t num_cells = xor3_cells * last_round_call + // xor with last message chunk - ((17 - last_round_call) * xor2_cells) + std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call + * xor_with_mes + // xor with last message chunk + ((17 - last_round_call) * (xor2_cells + xor2_buff)) * xor_with_mes + // inner_state ^ chunk - 5 * xor5_cells + // theta - 5 * rotate_cells + // theta - 25 * xor3_cells + // theta - 24 * rotate_cells + // rho/phi - 25 * chi_cells + // chi + 5 * (xor5_cells + xor5_buff) + // theta + 5 * (rotate_cells + rotate_buff) + // theta + 25 * (xor3_cells + xor3_buff) + // theta + 24 * (rotate_cells + rotate_buff) + // rho/phi + 25 * (chi_cells + chi_buff) + // chi xor2_cells; // iota return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } @@ -126,10 +151,14 @@ namespace nil { bool operator== (const coordinates& other) const { return row == other.row && column == other.column; } + bool operator< (const coordinates& other) const { + return row < other.row || (row == other.row && column < other.column); + } }; // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates first_coordinate; coordinates last_coordinate; std::vector copy_to; std::vector> constraints; @@ -137,11 +166,13 @@ namespace nil { coordinates copy_from; configuration() = default; - configuration(std::pair last_coordinate_, + configuration(std::pair first_coordinate_, + std::pair last_coordinate_, std::vector> copy_to_, std::vector>> constraints_, std::vector>> lookups_, std::pair copy_from_) { + first_coordinate = coordinates(first_coordinate_); last_coordinate = coordinates(last_coordinate_); for (std::size_t i = 0; i < copy_to_.size(); ++i) { copy_to.push_back(coordinates(copy_to_[i])); @@ -162,6 +193,18 @@ namespace nil { } copy_from = coordinates(copy_from_); }; + bool operator== (const configuration& other) const { + return first_coordinate == other.first_coordinate && + last_coordinate == other.last_coordinate && + copy_to == other.copy_to && + constraints == other.constraints && + lookups == other.lookups && + copy_from == other.copy_from; + } + bool operator< (const configuration& other) const { + return first_coordinate < other.first_coordinate || + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + } }; using var = typename component_type::var; @@ -194,24 +237,25 @@ namespace nil { const std::size_t rotate_cells = 22; const std::size_t chi_cells; + const std::size_t xor2_buff; + const std::size_t xor3_buff; + const std::size_t xor5_buff; + const std::size_t rotate_buff; + const std::size_t chi_buff; + const std::size_t rows_amount; // full configuration is precalculated, then used in other functions const std::size_t full_configuration_size = 17 * xor_with_mes + 85; std::vector full_configuration = std::vector(full_configuration_size); // number represents relative selector index for each constraint - std::vector gates_configuration; + std::map, std::vector> gates_configuration_map; + std::vector> gates_configuration; std::vector lookup_gates_configuration; std::vector gates_rows; const std::size_t gates_amount; - constexpr static const int r[5][5] = {{0, 3, 186, 84, 81}, - {108, 132, 18, 165, 60}, - {9, 30, 129, 75, 117}, - {123, 135, 45, 63, 24}, - {54, 6, 183, 168, 42}}; - // all words in sparse form const std::size_t word_size = 192; const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; @@ -236,11 +280,11 @@ namespace nil { result_type(const keccak_round &component, std::size_t start_row_index) { std::size_t num_config = component.full_configuration.size() - 1; - inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.row), - component.full_configuration[num_config].copy_from.column); + inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.column), + component.full_configuration[num_config].copy_from.row); for (int i = 1; i < 25; ++i) { - inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from.row), - component.full_configuration[num_config - i].copy_from.column); + inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from.column), + component.full_configuration[num_config - i].copy_from.row); } } }; @@ -273,7 +317,11 @@ namespace nil { } configuration configure_inner(std::size_t row, std::size_t column, std::size_t num_args, - std::size_t num_chunks, std::size_t num_cells) { + std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { + + std::cout << "finding similar configs: " << column << ' ' << num_cells << ' ' << buff << std::endl; + + std::pair first_coordinate = {row, column}; std::size_t last_row = row, last_column = column; @@ -343,7 +391,11 @@ namespace nil { } } - last_column = cells.back().second + 1; + if (cell_copy_from.first > cells.back().first) { + cells.back() = cell_copy_from; + } + + last_column = cells.back().second + 1 + buff; last_row = cells.back().first + (last_column >= WitnessesAmount); last_column %= WitnessesAmount; @@ -362,7 +414,7 @@ namespace nil { // } // } - return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } configuration configure_xor(std::size_t row, std::size_t column, int num_args) { @@ -375,8 +427,11 @@ namespace nil { : num_args == 3 ? normalize4_num_chunks : normalize6_num_chunks; std::size_t num_cells = num_chunks * 2 + num_args + 2; + std::size_t buff = num_args == 2 ? xor2_buff + : num_args == 3 ? xor3_buff + : xor5_buff; - return configure_inner(row, column, num_args, num_chunks, num_cells); + return configure_inner(row, column, num_args, num_chunks, num_cells, buff); } configuration configure_chi(std::size_t row, std::size_t column) { @@ -388,7 +443,7 @@ namespace nil { std::size_t num_args = 3; std::size_t num_cells = chi_num_chunks * 2 + num_args + 2; - return configure_inner(row, column, num_args, chi_num_chunks, num_cells); + return configure_inner(row, column, num_args, chi_num_chunks, num_cells, chi_buff); } configuration configure_rot(std::size_t row, std::size_t column) { @@ -400,6 +455,9 @@ namespace nil { // bound_big = big_part - (1 << (192 - r)) + (1 << 192); // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) + std::pair first_coordinate = {row, column}; + + std::cout << "finding similar configs: " << column << ' ' << rotate_cells << std::endl; std::size_t last_row = row, last_column = column; std::size_t num_chunks = rotate_num_chunks; @@ -465,7 +523,7 @@ namespace nil { lookups[1].push_back(constraints[5].back()); } - last_column = cells.back().second + 1; + last_column = cells.back().second + 1 + rotate_buff; last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; @@ -484,7 +542,7 @@ namespace nil { // } // } - return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } std::vector configure_all() { @@ -564,10 +622,142 @@ namespace nil { return result; } - std::vector configure_gates() { - std::vector> pairs; - for (std::size_t i = 0; i < full_configuration_size; ++i) { - for (auto constr : full_configuration[i].constraints) { + std::map, std::vector> configure_map() { + auto config = full_configuration; + std::size_t row = 0, + column = 0; + std::size_t cur_config = 0; + + std::map, std::vector> config_map; + + // inner_state ^ chunk + if (xor_with_mes) { + for (int i = 0; i < 17 - last_round_call; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {2, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + // xor with last message chunk + if (last_round_call) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {3, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + } + // theta + for (int i = 0; i < 5; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {5, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + for (int i = 0; i < 5; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {7, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + for (int i = 0; i < 25; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {3, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + // rho/phi + for (int i = 0; i < 24; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {7, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + // chi + for (int i = 0; i < 25; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {0, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } + // iota + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {2, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + + for (auto config : config_map) { + std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; + for (auto c : config.second) { + std::cout << c << ' '; + } + std::cout << std::endl; + } + return config_map; + } + + std::vector> configure_gates() { + std::vector> result; + for (auto config: gates_configuration_map) { + configuration cur_config; + switch (config.first.first) { + case 2: + cur_config = configure_xor(0, config.first.second, 2); + break; + case 3: + cur_config = configure_xor(0, config.first.second, 3); + break; + case 5: + cur_config = configure_rot(0, config.first.second); + break; + case 7: + cur_config = configure_rot(0, config.first.second); + break; + case 0: + cur_config = configure_chi(0, config.first.second); + break; + } + + std::vector> pairs; + for (auto constr : cur_config.constraints) { std::size_t min = constr[0].row; std::size_t max = constr.back().row; for (std::size_t j = 0; j < constr.size(); ++j) { @@ -577,23 +767,54 @@ namespace nil { BOOST_ASSERT(max - min <= 2); pairs.push_back({min, max}); } - } - std::vector result; - std::size_t cur_row = 0; - std::size_t cur_constr = 0; - while (cur_row < rows_amount) { - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { - result.push_back(cur_row + 1); - ++cur_constr; - } - if (cur_constr == pairs.size()) { - break; + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + cur_row = pairs[cur_constr].first; + cur_result.push_back(c); } - cur_row = pairs[cur_constr].first; + result.push_back(cur_result); } return result; } + // std::vector configure_gates() { + // std::vector> pairs; + // for (std::size_t i = 0; i < full_configuration_size; ++i) { + // for (auto constr : full_configuration[i].constraints) { + // std::size_t min = constr[0].row; + // std::size_t max = constr.back().row; + // for (std::size_t j = 0; j < constr.size(); ++j) { + // min = std::min(min, constr[j].row); + // max = std::max(max, constr[j].row); + // } + // BOOST_ASSERT(max - min <= 2); + // pairs.push_back({min, max}); + // } + // } + // std::vector result; + // std::size_t cur_row = 0; + // std::size_t cur_constr = 0; + // while (cur_row < rows_amount) { + // while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + // result.push_back(cur_row + 1); + // ++cur_constr; + // } + // if (cur_constr == pairs.size()) { + // break; + // } + // cur_row = pairs[cur_constr].first; + // } + // return result; + // } + std::vector configure_lookup_gates() { std::vector> pairs; for (std::size_t i = 0; i < full_configuration_size; ++i) { @@ -643,8 +864,14 @@ namespace nil { xor3_cells(calculate_num_cells(4)), \ xor5_cells(calculate_num_cells(6)), \ chi_cells(calculate_num_cells()), \ + xor2_buff(calculate_buff(3)), \ + xor3_buff(calculate_buff(4)), \ + xor5_buff(calculate_buff(6)), \ + chi_buff(calculate_buff(7)), \ + rotate_buff(calculate_buff()), \ rows_amount(calculate_rows()), \ full_configuration(configure_all()), \ + gates_configuration_map(configure_map()), \ gates_configuration(configure_gates()), \ lookup_gates_configuration(configure_lookup_gates()), \ gates_amount(gates()), \ @@ -684,6 +911,301 @@ namespace nil { #undef __keccak_round_init_macro }; + // template + // using keccak_round_component = + // keccak_round, + // WitnessesAmount>; + + // template= 9, bool> = true> + // void generate_gates( + // const keccak_round_component + // &component, + // circuit> + // &bp, + // assignment> + // &assignment, + // const typename keccak_round_component::input_type + // &instance_input, + // const std::size_t first_selector_index) { + + // using component_type = keccak_round_component; + // using var = typename component_type::var; + // using constraint_type = crypto3::zk::snark::plonk_constraint; + // using gate_type = typename crypto3::zk::snark::plonk_gate; + // // using lookup_constraint_type = typename crypto3::zk::snark::lookup_constraint; + // // using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; + // using value_type = typename BlueprintFieldType::value_type; + // using integral_type = typename BlueprintFieldType::integral_type; + + // auto config = component.full_configuration; + // auto gate_config = component.gates_configuration; + // // auto lookup_gate_config = component.lookup_gates_configuration; + // std::size_t config_index = 0; + // std::size_t gate_index = 0; + // // std::size_t lookup_gate_index = 0; + + // std::vector constraints; + // // std::vector lookup_constraints; + + // // inner_state ^ chunk + // if (component.xor_with_mes) { + // for (int i = 0; i < 17 - component.last_round_call; ++i) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize3_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize3_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize3_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize3_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + // if (component.last_round_call) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize4_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize4_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize4_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize4_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + // } + + // // theta + // for (int i = 0; i < 5; ++i) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][4].column, cur_config.constraints[0][4].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][5].column, cur_config.constraints[0][5].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize6_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize6_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize6_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize6_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // for (int i = 0; i < 5; ++i) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << 189) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << 3) + // + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) + // - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) + // - (integral_type(1) << 3) + // + (integral_type(1) << 192))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.rotate_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.rotate_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) + // - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) + // - (integral_type(1) << 189) + // + (integral_type(1) << 192))); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.rotate_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.rotate_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // for (int i = 0; i < 25; ++i) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize4_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize4_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize4_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize4_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // // rho/phi + // for (int i = 1; i < 25; ++i) { + // auto r = 3 * component.rho_offsets[i]; + + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << (192 - r)) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << r) + // + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) + // - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) + // - (integral_type(1) << r) + // + (integral_type(1) << 192))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.rotate_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.rotate_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) + // - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) + // - (integral_type(1) << (192 - r)) + // + (integral_type(1) << 192))); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.rotate_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.rotate_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // // chi + // for (int i = 0; i < 25; ++i) { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(component.sparse_3 + // - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * 2 + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.chi_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.chi_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.chi_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.chi_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // // iota + // { + // auto cur_config = config[config_index]; + // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) + // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) + // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); + // gate_index++; + // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize3_num_chunks; ++j) { + // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize3_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_1)); + // gate_index++; + // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); + // for (int j = 0; j < component.normalize3_num_chunks; ++j) { + // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) + // * (integral_type(1) << (j * component.normalize3_chunk_size)); + // } + // constraints.push_back(bp.add_constraint(constraint_2)); + // gate_index++; + // config_index++; + // } + + // BOOST_ASSERT(config_index == component.full_configuration_size); + // // BOOST_ASSERT(constraints.size() == gate_config.size()); + + // std::size_t prev_selector = gate_config[0]; + // std::vector cur_constraints = {constraints[0]}; + // gate_index = 1; + // while (gate_index < gate_config.size()) { + // while (gate_index < gate_config.size() && gate_config[gate_index] == prev_selector) { + // cur_constraints.push_back(constraints[gate_index]); + // ++gate_index; + // } + // if (gate_index == gate_config.size()) { + // break; + // } + // gate_type gate(first_selector_index + prev_selector, cur_constraints); + // bp.add_gate(gate); + // cur_constraints.clear(); + // prev_selector = gate_config[gate_index]; + // } + // if (!cur_constraints.empty()) { + // gate_type gate(first_selector_index + prev_selector, cur_constraints); + // bp.add_gate(gate); + // } + // } + template using keccak_round_component = keccak_round constraints; // std::vector lookup_constraints; - // inner_state ^ chunk - if (component.xor_with_mes) { - for (int i = 0; i < 17 - component.last_round_call; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } - if (component.last_round_call) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize4_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize4_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize4_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize4_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } - } + std::size_t index = 0; + for (auto gm: gate_map) { + configuration cur_config_vec = gate_config[index]; + std::size_t i = 0, j = 0, cur_len = 0; + std::vector cur_constraints; + switch (gm.first.first) { + case 2: + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.normalize3_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize3_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_1)); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; - // theta - for (int i = 0; i < 5; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - + var(cur_config.constraints[0][4].column, cur_config.constraints[0][4].row - gate_config[gate_index]) - + var(cur_config.constraints[0][5].column, cur_config.constraints[0][5].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize6_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize6_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize6_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize6_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + for (int k = 0; k < component.normalize3_num_chunks; ++k) { + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize3_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_2)); + + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); - for (int i = 0; i < 5; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << 189) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << 3) - + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - - (integral_type(1) << 3) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); - for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.rotate_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) - - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) - - (integral_type(1) << 189) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); - for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.rotate_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + index++; + break; + case 3: + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.normalize4_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize4_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_1)); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; - for (int i = 0; i < 25; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize4_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize4_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize4_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize4_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + for (int k = 0; k < component.normalize4_num_chunks; ++k) { + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize4_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_2)); + + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); - // rho/phi - for (int i = 1; i < 25; ++i) { - auto r = 3 * component.rho_offsets[i]; - - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << (192 - r)) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << r) - + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - - (integral_type(1) << r) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); - for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.rotate_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) - - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) - - (integral_type(1) << (192 - r)) - + (integral_type(1) << 192))); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); - for (int j = 0; j < component.rotate_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.rotate_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + index++; + break; + case 5: + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.normalize6_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize6_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_1)); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; - // chi - for (int i = 0; i < 25; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(component.sparse_3 - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * 2 - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.chi_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.chi_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.chi_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.chi_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + for (int k = 0; k < component.normalize6_num_chunks; ++k) { + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.normalize6_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_2)); + + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); - // iota - { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - gate_index++; - constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_1)); - gate_index++; - constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - for (int j = 0; j < component.normalize3_num_chunks; ++j) { - constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - * (integral_type(1) << (j * component.normalize3_chunk_size)); - } - constraints.push_back(bp.add_constraint(constraint_2)); - gate_index++; - config_index++; - } + index++; + break; + case 7: + auto r = component.var(component.C(0), 0, false, var::column_type::constant); + + constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (192 - r)) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << r) + + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1))); + g + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << r) + + (integral_type(1) << 192))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; - BOOST_ASSERT(config_index == component.full_configuration_size); - BOOST_ASSERT(constraints.size() == gate_config.size()); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.rotate_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_1)); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << (192 - r)) + + (integral_type(1) << 192))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; - std::size_t prev_selector = gate_config[0]; - std::vector cur_constraints = {constraints[0]}; - gate_index = 1; - while (gate_index < gate_config.size()) { - while (gate_index < gate_config.size() && gate_config[gate_index] == prev_selector) { - cur_constraints.push_back(constraints[gate_index]); - ++gate_index; - } - if (gate_index == gate_config.size()) { - break; + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.rotate_num_chunks; ++k) { + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.rotate_chunk_size)); + } + constraints.push_back(bp.add_constraint(constraint_2)); + + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + + index++; + break; + case 0: + cur_constraints.push_back(bp.add_constraint(component.sparse_3 + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + for (int k = 0; k < component.chi_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.chi_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_1)); + + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + for (int k = 0; k < component.chi_num_chunks; ++k) { + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) + * (integral_type(1) << (k * component.chi_chunk_size)); + } + cur_constraints.push_back(bp.add_constraint(constraint_2)); + + gate_type gate(first_selector_index++, cur_constraints); + bp.add_gate(gate); + + index++; + break; } - gate_type gate(first_selector_index + prev_selector, cur_constraints); - bp.add_gate(gate); - cur_constraints.clear(); - prev_selector = gate_config[gate_index]; - } - if (!cur_constraints.empty()) { - gate_type gate(first_selector_index + prev_selector, cur_constraints); - bp.add_gate(gate); + index++; } } @@ -1007,63 +1559,63 @@ namespace nil { if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].row), config[i].copy_to[0].column, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].row), config[i].copy_to[1].column, false)}); + bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), config[i].copy_to[0].row, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), config[i].copy_to[1].row, false)}); } config_index += 16; if (component.last_round_call) { - bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].row), config[config_index].copy_to[0].column, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].row), config[config_index].copy_to[1].column, false)}); + bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row, false)}); } config_index += 1; // theta for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, - {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row), false}, + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); } config_index += 5; prev_index += 17; } else { for (int i = 0; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].row), static_cast(config[config_index + i / 5].copy_to[i % 5].column), false}}); + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); } config_index += 5; } for (int i = 0; i < 5; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.row), static_cast(config[prev_index + i].copy_from.column), false}, - {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); } config_index += 5; prev_index += 5; for (int i = 0; i < 25; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].row), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].column), false}, - {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.row), static_cast(config[prev_index + (i + 1) % 5].copy_from.column), false}, - {component.W(config[config_index + i].copy_to[1].row), static_cast(config[config_index + i].copy_to[1].column), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].row), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].column), false}, - {component.W(config[config_index + i].copy_to[2].row), static_cast(config[config_index + i].copy_to[2].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].column), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].row), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.column), static_cast(config[prev_index + (i + 1) % 5].copy_from.row), false}, + {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].row), false}, + {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row), false}}); } config_index += 25; prev_index += 5; // rho/phi for (int i = 0; i < 24; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.row), static_cast(config[prev_index + i + 1].copy_from.column), false}, - {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.column), static_cast(config[prev_index + i + 1].copy_from.row), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); } // chi std::vector perm_index = {14,4,19,9, 5,20,10,0,15, 11,1,16,6,21, 17,7,22,12,2, 23,13,3,18,8}; - std::vector B = {{component.W(config[prev_index].copy_from.row), static_cast(config[prev_index].copy_from.column), false}}; + std::vector B = {{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row), false}}; for (auto i : perm_index) { - B.push_back({component.W(config[config_index + i].copy_from.row), static_cast(config[config_index + i].copy_from.column), false}); + B.push_back({component.W(config[config_index + i].copy_from.column), static_cast(config[config_index + i].copy_from.row), false}); } config_index += 24; prev_index += 25; @@ -1071,20 +1623,20 @@ namespace nil { int x = i / 5; int y = i % 5; bp.add_copy_constraint({B[x * 5 + y], - {component.W(config[config_index + i].copy_to[0].row), static_cast(config[config_index + i].copy_to[0].column), false}}); + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); bp.add_copy_constraint({B[((x + 1) % 5) * 5 + y], - {component.W(config[config_index + i].copy_to[1].row), static_cast(config[config_index + i].copy_to[1].column), false}}); + {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row), false}}); bp.add_copy_constraint({B[((x + 2) % 5) * 5 + y], - {component.W(config[config_index + i].copy_to[2].row), static_cast(config[config_index + i].copy_to[2].column), false}}); + {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row), false}}); } config_index += 25; prev_index += 24; // iota - bp.add_copy_constraint({{component.W(config[prev_index].copy_from.row), static_cast(config[prev_index].copy_from.column), false}, - {component.W(config[config_index].copy_to[0].row), static_cast(config[config_index].copy_to[0].column), false}}); + bp.add_copy_constraint({{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row), false}, + {component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row), false}}); bp.add_copy_constraint({instance_input.round_constant, - {component.W(config[config_index].copy_to[1].row), static_cast(config[config_index].copy_to[1].column), false}}); + {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row), false}}); } template rotate_rows; + for (auto g : gate_map) { + if (g.first.first == 7) { + rotate_rows.emplace_back(g.second); + } + } + std::sort(rotate_rows.begin(), rotate_rows.end()); + for (std::size_t i = 0; i < 5; i++) { + assignment.constant(component.C(0), start_row_index + rotate_rows[i]) = 3; + } + for (std::size_t i = 5; i < 29; i++) { + assignment.constant(component.C(0), start_row_index + rotate_rows[i]) = 3 * component_type::rho_offsets[i]; + } } template +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE plonk_keccak_test + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include "../../test_plonk_component.hpp" + +template +std::vector padding_function(std::vector message) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector result; + std::size_t shift = 64 * message.size() - num_bits + + if (shift > 0) { + integral_type relay_value = message[0]; + for (int i = 1; i < message.size(); ++i) { + integral_type mask = (integral_type(1) << shift) - 1; + integral_type left_part = message[i].data >> shift; + integral_type right_part = message[i].data & mask; + result.push_back(value_type((relay_value << (64 - shift)) | left_part)); + relay_value = right_part; + } + result.push_back(value_type(relay_value << (64 - shift))); + } else { + for (int i = 0; i < message.size(); ++i) { + result.push_back(message[i]); + } + } + while (result.size() % 17 != 0) { + result.push_back(value_type(0)); + } + return result; +} + +template +auto test_keccak_padding_inner(std::vector message, + std::vector expected_result) { + constexpr std::size_t PublicInputColumns = 1; + constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t SelectorColumns = 150; + using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + using AssignmentType = nil::blueprint::assignment; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; + constexpr std::size_t Lambda = 1; + + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using component_type = nil::blueprint::components::keccak_padding; + using var = typename component_type::var; + + auto mes_size = message.size(); + + std::vector public_input; + // std::cout << "message:\n"; + for (int i = 0; i < mes_size; ++i) { + public_input.push_back(message[i]); + // std::cout << message[i].data << std::endl; + } + public_input.push_back(first_bits); + // std::cout << "first_bits: " << first_bits.data << std::endl; + + std::vector message_vars; + var first_bits_var; + for (int i = 0; i < mes_size; ++i) { + message_vars[i] = var(0, i, false, var::column_type::public_input); + } + first_bits_var = var(0, mes_size, false, var::column_type::public_input); + typename component_type::input_type instance_input = {message_vars, first_bits_var}; + + auto result_check = [expected_result] + (AssignmentType &assignment, typename component_type::result_type &real_res) { + for (int i = 0; i < expected_result.size(); ++i) { + // std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.inner_state[i]).data << std::endl; + // assert(expected_result[i] == var_value(assignment, real_res.inner_state[i])); + } + }; + + component_type component_instance = WitnessesAmount == 15 ? + component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, + {1}, LookupRows, LookupColumns, num_blocks, first_bits) + : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {1}, + LookupRows, LookupColumns, num_blocks, first_bits); + + if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { + BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; + } + + nil::crypto3::test_component( + boost::get(component_instance), public_input, result_check, instance_input); +} + +// works +template +void test_keccak_round_0() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + + std::vector message = {0}; + std::size_t first_bits = 0; + + std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + test_keccak_round_inner + (message, first_bits, expected_result); +} + +// template +// void test_keccak_round_1() { +// using value_type = typename BlueprintFieldType::value_type; +// using integral_type = typename BlueprintFieldType::integral_type; + +// std::vector message = {0}; +// std::size_t first_bits = 0; + +// std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +// std::array expected_result = { +// 32899, 17592186044416, 32768, 1, 17592186077184, +// 0, 35184374185984, 0, 35184372088832, 2097152, +// 2, 512, 0, 514, 0, +// 268436480, 0, 1024, 268435456, 0, +// 1099511627776, 0, 1099511627780, 0, 4}; +// for (int i = 0; i < 25; ++i) { +// expected_result[i] = to_sparse(expected_result[i]); +// } + +// test_keccak_round_inner +// (inner_state, padded_message_chunk, RC, expected_result); +// } + +template +void test_keccak_round_random() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; + + std::size_t num_bits = 62; + integral_type mask = (integral_type(1) << num_bits) - 1; + std::vector message = {value_type(integral_type(dis(gen)) & mask)}; + + // for (int i = 0; i < 25; ++i) { + // auto random_value = integral_type(dis(gen)); + // inner_state[i] = to_sparse(value_type(random_value)); + // } + + auto expected_result = padding_function(message); + + test_keccak_round_inner + (message, expected_result); +} + +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + // test_keccak_round_random(); + test_keccak_round_random(); + // test_keccak_round_random(); +} + +// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { +// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +// } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 89aa05024..d64baecc5 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -362,12 +362,36 @@ void test_keccak_round_random() { (inner_state, padded_message_chunk, RC, expected_result); } +template +void test_keccak_round_not_random() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::array inner_state; + std::array padded_message_chunk; + value_type RC = value_type(0); + + for (int i = 0; i < 25; ++i) { + inner_state[i] = to_sparse(i + 1); + } + for (int i = 0; i < 17; ++i) { + padded_message_chunk[i] = 1; + } + RC = to_sparse(0x1000); + + auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); + + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); +} + BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_random(); - test_keccak_round_random(); + test_keccak_round_not_random(); // test_keccak_round_random(); } From b3db4fb8b61c1642321889e83ee4763aef3fdc5c Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 4 Sep 2023 21:02:01 +0000 Subject: [PATCH 09/48] some round constr fized, code to padding added #183 --- .../hashes/keccak/keccak_component.hpp | 13 +- .../hashes/keccak/keccak_padding.hpp | 327 +++++++----- .../components/hashes/keccak/keccak_round.hpp | 485 ++++++++++-------- test/hashes/plonk/keccak_round.cpp | 4 +- 4 files changed, 484 insertions(+), 345 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index cc8655ec6..802e57c3d 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -69,6 +69,7 @@ namespace nil { const std::size_t lookup_columns; const std::size_t num_blocks; + const std::size_t num_bits; const std::size_t num_round_calls; const std::size_t num_configs; @@ -230,10 +231,11 @@ namespace nil { } #define __keccak_init_macro(witness, constant, public_input, \ - lookup_rows_, lookup_columns_, num_blocks_) \ + lookup_rows_, lookup_columns_, num_blocks_, num_bits_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ num_blocks(num_blocks_), \ + num_bits(num_bits_), \ num_round_calls(), \ rounds(num_round_calls * 24, \ round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ @@ -255,19 +257,20 @@ namespace nil { PublicInputContainerType public_input, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_): + std::size_t num_blocks_, + std::size_t num_bits_) : component_type(witness, constant, public_input), - __keccak_init_macro(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_) {}; + __keccak_init_macro(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; keccak( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_) : component_type(witnesses, constants, public_inputs), __keccak_init_macro(witnesses, constants, public_inputs, - lookup_rows_, lookup_columns_, num_blocks_) + lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; {}; #undef __keccak_init_macro diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 47473f2e4..5426d6379 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -46,14 +46,94 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; std::size_t rows() const { - return 0; + return full_configuration.back().last_coordinate.row + 1; } public: - using var = typename component_type::var; - const std::size_t rows_amount; - constexpr static const std::size_t gates_amount; + struct configuration { + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + bool operator== (const coordinates& other) const { + return row == other.row && column == other.column; + } + bool operator< (const coordinates& other) const { + return row < other.row || (row == other.row && column < other.column); + } + }; + + // In constraints we use such notation: constr[0] - result, + // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates first_coordinate; + coordinates last_coordinate; + std::vector copy_to; + std::vector> constraints; + std::vector> lookups; + coordinates copy_from; + + configuration() = default; + configuration(std::pair first_coordinate_, + std::pair last_coordinate_, + std::vector> copy_to_, + std::vector>> constraints_, + std::vector>> lookups_, + std::pair copy_from_) { + first_coordinate = coordinates(first_coordinate_); + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to.push_back(coordinates(copy_to_[i])); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); + } + constraints.push_back(constr); + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); + } + lookups.push_back(lookup); + } + copy_from = coordinates(copy_from_); + }; + bool operator== (const configuration& other) const { + return first_coordinate == other.first_coordinate && + last_coordinate == other.last_coordinate && + copy_to == other.copy_to && + constraints == other.constraints && + lookups == other.lookups && + copy_from == other.copy_from; + } + bool operator< (const configuration& other) const { + return first_coordinate < other.first_coordinate || + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + } + }; + + struct padding_gate { + coordinates relay; + std::vector value; + std::vector sum; + std::vector range_check; + std::vector first; + std::vector second; + + padding_gate() = default; + padding_gate(coordinates relay_, std::vector value_, std::vector sum_, + std::vector range_check_, std::vector first_, + std::vector second_) : + relay(relay_), value(value_), sum(sum_), range_check(range_check_), first(first_), second(second_) {}; + } + + using var = typename component_type::var; const std::size_t num_blocks; const std::size_t num_bits; @@ -62,6 +142,11 @@ namespace nil { const std::size_t limit_permutation_column = 7; + const std::size_t rows_amount; + std::vector gates_rows; + padding_gate last_gate; + constexpr static const std::size_t gates_amount; + struct input_type { // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + message[num_blocks - 1] // all message[i] are 64-bit for i > 0 @@ -81,147 +166,117 @@ namespace nil { return num_blocks * 64 - num_bits; } - configuration configure_batching(std::size_t row, std::size_t column, - std::size_t prev_bits, std::size_t &next_bits, - std::size_t total_bits = bits_per_block) { - if (prev_bits > 64) { - next_bits = prev_bits - 64; - } else { - next_bits = bits_per_block - 64 + prev_bits; - } - - std::size_t num_chunks = total_bits / 64 + bool(total_bits % 64); + template + padding_gate padding() { + throw std::runtime_error("Unsupported number of witnesses"); + return padding_gate(); + } + template<9> + padding_gate padding(std::size_t row = 0) { + padding_gate res; + res.relay = {-1 + row, 0}; + res.value = {{-1 + row, 1}, {-1 + row, 3}, {0 + row, 0}, {0 + row, 2}, {1 + row, 0}}; + res.sum = {{-1 + row, 2}, {-1 + row, 4}, {0 + row, 1}, {0 + row, 3}, {1 + row, 1}}; + res.first = {{-1 + row, 5}, {-1 + row, 7}, {0 + row, 4}, {0 + row, 6}, {1 + row, 2}}; + res.second = {{-1 + row, 6}, {-1 + row, 8}, {0 + row, 5}, {0 + row, 7}, {1 + row, 3}}; + res.range_check = {{1 + row, 4}, {1 + row, 5}, {1 + row, 6}, {1 + row, 7}, {1 + row, 8}}; + return res; + } + template<15> + padding_gate padding(std::size_t row = 0) { + padding_gate res; + res.relay = {-1 + row, 11}; + res.value = {{0 + row,0}, {0 + row,1}, {0 + row,2}, {1 + row,0}, {1 + row,1}, {1 + row,2}}; + res.sum = {{0 + row,3}, {0 + row,4}, {0 + row,5}, {1 + row,3}, {1 + row,4}, {1 + row,5}}; + res.first = {{0 + row,6}, {0 + row,7}, {0 + row,8}, {1 + row,6}, {1 + row,7}, {1 + row,8}}; + res.second = {{0 + row,9}, {0 + row,10}, {0 + row,11}, {1 + row,9}, {1 + row,10}, {1 + row,11}}; + res.range_check = {{0 + row,12}, {0 + row,13}, {0 + row,14}, {1 + row,12}, {1 + row,13}, {1 + row,14}}; + return res; + } - std::size_t last_row = row, - last_column = column; - - std::vector> copy_to; + std::vector configure_batching() { + std::vector result; - if (num_args + column > limit_permutation_column) { - for (int i = 0; i < num_args; ++i) { - copy_to.push_back({last_row + 1, i}); - } - } else { - for (int i = 0; i < num_args; ++i) { - copy_to.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); - } - } - - std::pair cell_copy_from; - std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; - if (final_row == copy_to[0].first) { - cell_copy_from = {final_row, copy_to.back().second + 1}; - } else { - cell_copy_from = {final_row, 0}; - } - - std::vector> cells; - if (num_args + column > limit_permutation_column) { - for (int i = column; i < WitnessesAmount; ++i) { - cells.push_back({row, i}); - } - std::size_t cells_left = num_cells - WitnessesAmount + column; - std::size_t cur_row = row + 1, - cur_column = num_args; - while (cur_column < cells_left) { - if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { - cur_column++; - continue; - } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + std::size_t i = 0; + std::size_t row = 1; + for (std::size_t j = 0; j < num_blocks; ++j) { + auto pg = padding(row); + congifuration conf; + if (i == 0) { + conf.last_coordinate = pg.second[0]; + conf.copy_to = {pg.relay, pg.value[0]}; + conf.constraints = {{pg.value[0], pg.first[0], pg.second[0]}, + {pg.sum[0], pg.relay, pg.first[0]}, + {pg.range_check[0], pg.relay}}; + conf.lookups = {pg.range_check[0]}; + conf.copy_from = pg.sum[0]; + result.push_back(conf); + continue; } - } else { - std::size_t cur_row = row, - cur_column = column + num_args; - while (cur_column - column < num_cells) { - if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { - cur_column++; - continue; - } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); - } - } - std::size_t cell_index = 0; - - std::vector>> constraints; - constraints.push_back({cells[cell_index++]}); - for (int i = 0; i < num_args; ++i) { - constraints[0].push_back(copy_to[i]); - } - - constraints.push_back({constraints[0][0]}); - constraints.push_back({cell_copy_from}); - std::vector>> lookups(num_chunks, std::vector>()); - for (std::size_t i = 1; i < 3; ++i) { - for (std::size_t j = 0; j < num_chunks; ++j) { - constraints[i].push_back(cells[cell_index++]); - lookups[j].push_back(constraints[i].back()); + conf.last_coordinate = pg.second[i]; + conf.copy_to = {pg.value[i]}; + conf.constraints = {{pg.value[i], pg.first[i], pg.second[i]}, + {pg.sum[i], pg.second[i-1], pg.first[i]}, + {pg.range_check[i], pg.second[i-1]}}; + conf.lookups = {pg.range_check[i]}; + conf.copy_from = pg.sum[i]; + result.push_back(conf); + i = (i + 1) % 5; + if (i == 0) { + if (WitnessesAmount == 9) row += 3; + if (WitnessesAmount == 15) row += 2; } } - last_column = cells.back().second + 1; - last_row = cells.back().first + (last_column >= WitnessesAmount); - last_column %= WitnessesAmount; - - // return configuration({last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + return result; } - configuration configure_padding(std::size_t row, std::size_t column, - std::size_t prev_bits = 0) { - if (prev_bits == 0) { - // costraint with 0 - if (column >= limit_permutation_column) { - row = row + 1; - column = 0; - return configuration({row + 1, 1}, {{row + 1, 0}}, {}, {}, {row + 1, 0}); - } - auto last_column = column + 1; - auto last_row = row + (last_column / WitnessesAmount); - last_column %= WitnessesAmount; - return configuration({last_row, last_column}, {{row, column}}, {}, {}, {row, column}); + configuration configure_padding(std::size_t row, std::size_t column) { + // costraint with 0 + if (column >= limit_permutation_column) { + return configuration({row + 1, 1}, {{row + 1, 0}}, {}, {}, {row + 1, 0}); } - auto other_column = column + 1; - auto other_row = row + (other_column / WitnessesAmount); - other_column %= WitnessesAmount; - auto last_column = column + 2; + auto last_column = column + 1; auto last_row = row + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - - return configuration({last_row, last_column}, {{row, column}}, {{{other_row, other_column}, {row, column}}}, {{other_row, other_column}}, {other_row, other_column}); + return configuration({last_row, last_column}, {{row, column}}, {}, {}, {row, column}); } std::vector configure_all() { std::vector result; - std::size_t row = 0, - column = 0; - std::size_t next_bits = 0; - - //batching - result.push_back(configure_batching(row, column, 0, next_bits, num_bits_first)); - row = result.back().last_row; - column = result.back().last_column; - for (std::size_t i = 1; i < num_blocks; ++i) { - result.push_back(configure_batching(row, column, next_bits, next_bits)); - row = result[i].last_row; - column = result[i].last_column; + + if (WitnessesAmount % 15 == 0) { + configuration conf0; + conf0.copy_to = {{0, 0}, {0, 1}}; + conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, + {{0, 3}, {0, 0}, {0, 5}}, + {{0, 8}, {0, 0}}}; + conf0.lookups = {{0, 8}}; + conf0.copy_from = {0, 3}; + result.push_back(conf0); + configuration conf1; + conf1.copy_to = {{0, 2}}; + conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, + {{0, 4}, {0, 7}, {0, 6}}, + {{0, 9}, {0, 7}}}; + conf1.lookups = {{0, 9}}; + conf1.copy_from = {0, 4}; + result.push_back(conf1); } - //counting number of chunks - std::size_t total_bits = num_bits_first + (num_blocks - 1) * bits_per_block; - std::size_t padding_bits = 1088 - (total_bits % 1088); - std::size_t padding_chunks = (total_bits + padding_bits) / 64 - total_bits / 64; + auto batch_configs = configure_batching(); + result.insert(result.end(), batch_configs.begin(), batch_configs.end()); - //padding with zeros - result.push_back(configure_padding(row, column, next_bits)); - row = result.back().last_row; - column = result.back().last_column; - for (std::size_t i = 1; i < padding_chunks; ++i) { + auto row = result.back().last_coordinate.row + 1; + std::size_t column = 0; + std::size_t size = result.size(); + + while (size % 17 != 0) { result.push_back(configure_padding(row, column)); row = result.back().last_row; column = result.back().last_column; + size++; } - return result; } @@ -233,6 +288,8 @@ namespace nil { shift(get_shift()), \ full_configuration(configure_all()), \ rows_amount(rows()), \ + gates_rows(calculate_gates_rows()), \ + last_gate(calculate_last_gate()), \ gates_amount(gates()) template @@ -428,47 +485,47 @@ namespace nil { WitnessesAmount>; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - using var = typename component_type::var; std::size_t config_index = 0; // batching if (component.shift != 0) { - // TODO where to put first relay chunk? - value_type relay_chunk = var_value(assignment, instance_input.message[0]); + integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0])); for (std::size_t index = 1; index < component.num_blocks; ++index) { value_type chunk = var_value(assignment, instance_input.message[index]); integral_type integral_chunk = integral_type(chunk); integral_type mask = (integral_type(1) << component.shift) - 1; - std::array chunk_parts = {value_type(integral_chunk >> component.shift), value_type(integral_chunk & mask)}; - value_type first_chunk = (relay_chunk << (64 - component.shift)) + chunk_parts[0]; - value_type relay_range_check = chunk_parts[1] - (1 << component.shift) + (1 << 64); + std::array chunk_parts = {integral_chunk >> component.shift, integral_chunk & mask}; + integral_type first_chunk = (relay_chunk << (64 - component.shift)) + chunk_parts[0]; + integral_type relay_range_check = relay_chunk - (1 << component.shift) + (1 << 64); auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = chunk; for (int j = 1; j < 3; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].row), cur_config.constraints[0][j].column) = value_type(chunk_parts[j - 1]); } - assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = relay_range_check; - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = first_chunk; + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = value_type(relay_range_check); + assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(first_chunk); relay_chunk = chunk_parts[1]; config_index++; } // padding { - value_type last_chunk = relay_chunk << (64 - component.shift); + integral_type last_chunk = relay_chunk << (64 - component.shift); + integral_type relay_range_check = relay_chunk - (1 << component.shift) + (1 << 64); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = relay_chunk; - assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = last_chunk; + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = value_type(relay_chunk); + assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = value_type(last_chunk); + assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = value_type(relay_range_check); config_index++; } } while (congif_index < component.full_configuration.size()) { auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = component.C(0); + assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = 0; config_index++; } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 33f4b215a..f6d164981 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -109,32 +109,65 @@ namespace nil { 24 * (rotate_cells + rotate_buff) + // rho/phi 25 * (chi_cells + chi_buff) + // chi xor2_cells; // iota + std::size_t num_cells_before = (xor3_cells) * last_round_call + * xor_with_mes + // xor with last message chunk + ((17 - last_round_call) * (xor2_cells)) + * xor_with_mes + // inner_state ^ chunk + 5 * (xor5_cells) + // theta + 5 * (rotate_cells) + // theta + 25 * (xor3_cells) + // theta + 24 * (rotate_cells) + // rho/phi + 25 * (chi_cells) + // chi + xor2_cells; // iota + std::size_t num_cells_buff = (0 + xor3_buff) * last_round_call + * xor_with_mes + // xor with last message chunk + ((17 - last_round_call) * (0 + xor2_buff)) + * xor_with_mes + // inner_state ^ chunk + 5 * (0 + xor5_buff) + // theta + 5 * (0 + rotate_buff) + // theta + 25 * (0 + xor3_buff) + // theta + 24 * (0 + rotate_buff) + // rho/phi + 25 * (0 + chi_buff) + // chi + xor2_cells; // iota + std::cout << "rows: " << num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount) << std::endl; + std::cout << "rows before: " << num_cells_before / WitnessesAmount + bool(num_cells_before % WitnessesAmount) << std::endl; + std::cout << "empty cells: " << num_cells_buff + num_cells % WitnessesAmount << std::endl; + std::cout << "empty cells before: " << num_cells_before % WitnessesAmount << std::endl; return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } - std::vector calculate_gates_rows() const { - std::vector res; - auto cur_selector = gates_configuration[0]; - res.push_back(cur_selector); - for (std::size_t i = 1; i < gates_configuration.size(); ++i) { - if (gates_configuration[i] != cur_selector) { - cur_selector = gates_configuration[i]; - res.push_back(cur_selector); + // std::vector calculate_gates_rows() const { + // std::vector res; + // auto cur_selector = gates_configuration[0]; + // res.push_back(cur_selector); + // for (std::size_t i = 1; i < gates_configuration.size(); ++i) { + // if (gates_configuration[i] != cur_selector) { + // cur_selector = gates_configuration[i]; + // res.push_back(cur_selector); + // } + // } + // // for (int i = 0; i < res.size(); ++i) { + // // std::cout << res[i] << " "; + // // } + // return res; + // } + std::size_t calculate_last_round_call_row() const { + if (!last_round_call) { + return 0; + } + std::size_t res = 0; + for (auto g : gates_configuration_map) { + if (g.first.first == 3) { + res = g.second[0]; } } - // for (int i = 0; i < res.size(); ++i) { - // std::cout << res[i] << " "; - // } return res; } std::size_t gates() const { - std::size_t res = 1; - auto cur_selector = gates_configuration[0]; + std::size_t res = 0; for (std::size_t i = 1; i < gates_configuration.size(); ++i) { - if (gates_configuration[i] != cur_selector) { - res++; - cur_selector = gates_configuration[i]; - } + res += gates_configuration[i].size(); } + std::cout << "gates num: " << res << std::endl; return res; } @@ -250,10 +283,11 @@ namespace nil { std::vector full_configuration = std::vector(full_configuration_size); // number represents relative selector index for each constraint std::map, std::vector> gates_configuration_map; - std::vector> gates_configuration; + std::vector> gates_configuration; std::vector lookup_gates_configuration; std::vector gates_rows; + const std::size_t last_round_call_row; const std::size_t gates_amount; // all words in sparse form @@ -319,8 +353,6 @@ namespace nil { configuration configure_inner(std::size_t row, std::size_t column, std::size_t num_args, std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { - std::cout << "finding similar configs: " << column << ' ' << num_cells << ' ' << buff << std::endl; - std::pair first_coordinate = {row, column}; std::size_t last_row = row, @@ -457,7 +489,6 @@ namespace nil { std::pair first_coordinate = {row, column}; - std::cout << "finding similar configs: " << column << ' ' << rotate_cells << std::endl; std::size_t last_row = row, last_column = column; std::size_t num_chunks = rotate_num_chunks; @@ -724,17 +755,59 @@ namespace nil { config_map[zero_config] = {row}; } - for (auto config : config_map) { - std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; - for (auto c : config.second) { - std::cout << c << ' '; + // for (auto config : config_map) { + // std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; + // for (auto c : config.second) { + // std::cout << c << ' '; + // } + // std::cout << std::endl; + // } + return config_map; + } + + std::vector configure_gates_before() { + std::vector> pairs; + for (std::size_t i = 0; i < full_configuration_size; ++i) { + for (auto constr : full_configuration[i].constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max - min <= 2); + pairs.push_back({min, max}); } - std::cout << std::endl; } - return config_map; + std::vector result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_row < rows_amount) { + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + result.push_back(cur_row + 1); + ++cur_constr; + } + if (cur_constr == pairs.size()) { + break; + } + cur_row = pairs[cur_constr].first; + } + return result; } std::vector> configure_gates() { + + auto gates_before = configure_gates_before(); + std::size_t num_before = 1; + std::size_t cur_before = gates_before[0]; + for (int i = 1; i < gates_before.size(); ++i) { + if (gates_before[i] != cur_before) { + cur_before = gates_before[i]; + num_before++; + } + } + std::cout << "gates num before: " << num_before << std::endl; + std::vector> result; for (auto config: gates_configuration_map) { configuration cur_config; @@ -746,7 +819,7 @@ namespace nil { cur_config = configure_xor(0, config.first.second, 3); break; case 5: - cur_config = configure_rot(0, config.first.second); + cur_config = configure_xor(0, config.first.second, 5); break; case 7: cur_config = configure_rot(0, config.first.second); @@ -782,39 +855,24 @@ namespace nil { } result.push_back(cur_result); } + + // for (int i = 0; i < result.size(); ++i) { + // std::cout << "gate " << i << std::endl; + // for (int j = 0; j < result[i].size(); ++j) { + // std::cout << "configuration " << j << std::endl; + // std::cout << "type: " << " " << result[i][j].first_coordinate.column << std::endl; + // std::cout << "constraints:\n"; + // for (auto constr : result[i][j].constraints) { + // std::cout << "constraint:\n"; + // for (auto cell : constr) { + // std::cout << cell.row << " " << cell.column << "\n"; + // } + // } + // } + // } return result; } - // std::vector configure_gates() { - // std::vector> pairs; - // for (std::size_t i = 0; i < full_configuration_size; ++i) { - // for (auto constr : full_configuration[i].constraints) { - // std::size_t min = constr[0].row; - // std::size_t max = constr.back().row; - // for (std::size_t j = 0; j < constr.size(); ++j) { - // min = std::min(min, constr[j].row); - // max = std::max(max, constr[j].row); - // } - // BOOST_ASSERT(max - min <= 2); - // pairs.push_back({min, max}); - // } - // } - // std::vector result; - // std::size_t cur_row = 0; - // std::size_t cur_constr = 0; - // while (cur_row < rows_amount) { - // while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { - // result.push_back(cur_row + 1); - // ++cur_constr; - // } - // if (cur_constr == pairs.size()) { - // break; - // } - // cur_row = pairs[cur_constr].first; - // } - // return result; - // } - std::vector configure_lookup_gates() { std::vector> pairs; for (std::size_t i = 0; i < full_configuration_size; ++i) { @@ -874,8 +932,8 @@ namespace nil { gates_configuration_map(configure_map()), \ gates_configuration(configure_gates()), \ lookup_gates_configuration(configure_lookup_gates()), \ - gates_amount(gates()), \ - gates_rows(calculate_gates_rows()) + last_round_call_row(calculate_last_round_call_row()), \ + gates_amount(gates()) template keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, @@ -1238,6 +1296,7 @@ namespace nil { // using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + using configuration = typename component_type::configuration; auto gate_config = component.gates_configuration; auto gate_map = component.gates_configuration_map; @@ -1249,12 +1308,14 @@ namespace nil { // std::vector lookup_constraints; std::size_t index = 0; + std::size_t selector_index = first_selector_index; for (auto gm: gate_map) { - configuration cur_config_vec = gate_config[index]; + std::vector cur_config_vec = gate_config[index]; std::size_t i = 0, j = 0, cur_len = 0; std::vector cur_constraints; switch (gm.first.first) { - case 2: + case 2: + { cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); @@ -1262,14 +1323,14 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize3_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize3_chunk_size)); @@ -1279,26 +1340,27 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize3_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize3_chunk_size)); } cur_constraints.push_back(bp.add_constraint(constraint_2)); - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); - index++; break; + } case 3: + { cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) @@ -1307,14 +1369,14 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize4_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize4_chunk_size)); @@ -1324,26 +1386,27 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize4_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize4_chunk_size)); } cur_constraints.push_back(bp.add_constraint(constraint_2)); - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); - index++; break; + } case 5: + { cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) @@ -1354,14 +1417,14 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize6_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize6_chunk_size)); @@ -1371,65 +1434,67 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize6_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize6_chunk_size)); } cur_constraints.push_back(bp.add_constraint(constraint_2)); - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); - index++; break; + } case 7: - auto r = component.var(component.C(0), 0, false, var::column_type::constant); + { + auto r = var(component.C(0), -1, true, var::column_type::constant); + auto minus_r = var(component.C(0), 0, true, var::column_type::constant); - constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (192 - r)) + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * minus_r + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << r) + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) * r + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1))); - g + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << r) - + (integral_type(1) << 192))); + + r + - (integral_type(1) << 192))); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } @@ -1441,27 +1506,27 @@ namespace nil { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - constraints.push_back(bp.add_constraint(constraint_1)); + cur_constraints.push_back(bp.add_constraint(constraint_1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << (192 - r)) - + (integral_type(1) << 192))); + + minus_r + - (integral_type(1) << 192))); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } @@ -1473,14 +1538,15 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - constraints.push_back(bp.add_constraint(constraint_2)); + cur_constraints.push_back(bp.add_constraint(constraint_2)); - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); - index++; break; + } case 0: + { cur_constraints.push_back(bp.add_constraint(component.sparse_3 - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) @@ -1490,14 +1556,14 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config.constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.chi_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.chi_chunk_size)); @@ -1507,25 +1573,27 @@ namespace nil { j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(first_selector_index++, cur_constraints); + gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1; + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.chi_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.chi_chunk_size)); } cur_constraints.push_back(bp.add_constraint(constraint_2)); - gate_type gate(first_selector_index++, cur_constraints); - bp.add_gate(gate); + { + gate_type gate(selector_index++, cur_constraints); + bp.add_gate(gate); + } - index++; break; + } } index++; } @@ -1559,63 +1627,64 @@ namespace nil { if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), config[i].copy_to[0].row, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), config[i].copy_to[1].row, false)}); + bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), config[i].copy_to[0].row + start_row_index, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), config[i].copy_to[1].row + start_row_index, false)}); } config_index += 16; if (component.last_round_call) { - bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row, false)}); + bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row + start_row_index, false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row + start_row_index, false)}); + bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index), var(component.W(config[config_index].copy_to[2].column), config[config_index].copy_to[2].row + start_row_index, false)}); } config_index += 1; // theta for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row), false}, - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); } config_index += 5; prev_index += 17; } else { for (int i = 0; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row), false}}); + {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); } config_index += 5; } for (int i = 0; i < 5; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); } config_index += 5; prev_index += 5; for (int i = 0; i < 25; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].column), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].row), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.column), static_cast(config[prev_index + (i + 1) % 5].copy_from.row), false}, - {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].row), false}, - {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].column), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.column), static_cast(config[prev_index + (i + 1) % 5].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); } config_index += 25; prev_index += 5; // rho/phi for (int i = 0; i < 24; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.column), static_cast(config[prev_index + i + 1].copy_from.row), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.column), static_cast(config[prev_index + i + 1].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); } // chi std::vector perm_index = {14,4,19,9, 5,20,10,0,15, 11,1,16,6,21, 17,7,22,12,2, 23,13,3,18,8}; - std::vector B = {{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row), false}}; + std::vector B = {{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row + start_row_index), false}}; for (auto i : perm_index) { - B.push_back({component.W(config[config_index + i].copy_from.column), static_cast(config[config_index + i].copy_from.row), false}); + B.push_back({component.W(config[config_index + i].copy_from.column), static_cast(config[config_index + i].copy_from.row + start_row_index), false}); } config_index += 24; prev_index += 25; @@ -1623,20 +1692,20 @@ namespace nil { int x = i / 5; int y = i % 5; bp.add_copy_constraint({B[x * 5 + y], - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row), false}}); + {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); bp.add_copy_constraint({B[((x + 1) % 5) * 5 + y], - {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row), false}}); + {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); bp.add_copy_constraint({B[((x + 2) % 5) * 5 + y], - {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row), false}}); + {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); } config_index += 25; prev_index += 24; // iota - bp.add_copy_constraint({{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row), false}, - {component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row), false}}); + bp.add_copy_constraint({{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row + start_row_index), false}, + {component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + start_row_index), false}}); bp.add_copy_constraint({instance_input.round_constant, - {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row), false}}); + {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); } template; + using integral_type = typename BlueprintFieldType::integral_type; std::size_t row = start_row_index; - assignment.constant(component.C(0), row) = 2097152; // sparse 0x80 + if (component.last_round_call) { + assignment.constant(component.C(0), row + component.last_round_call_row) = 2097152; // sparse 0x80 + } auto gate_map = component.gates_configuration_map; std::vector rotate_rows; for (auto g : gate_map) { if (g.first.first == 7) { - rotate_rows.emplace_back(g.second); + rotate_rows.insert(rotate_rows.end(), g.second.begin(), g.second.end()); } } std::sort(rotate_rows.begin(), rotate_rows.end()); for (std::size_t i = 0; i < 5; i++) { - assignment.constant(component.C(0), start_row_index + rotate_rows[i]) = 3; + assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << 3; + assignment.constant(component.C(0), row + rotate_rows[i] + 1) = integral_type(1) << 189; } for (std::size_t i = 5; i < 29; i++) { - assignment.constant(component.C(0), start_row_index + rotate_rows[i]) = 3 * component_type::rho_offsets[i]; + assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i]); + assignment.constant(component.C(0), row + rotate_rows[i] + 1) = integral_type(1) << (192 - 3 * component_type::rho_offsets[i]); } } @@ -1711,13 +1785,17 @@ namespace nil { } else { first_selector_index = selector_iterator->second; } - - for (std::size_t i = 0; i < component.gates_amount; ++i) { - assignment.enable_selector(first_selector_index + i, component.gates_rows[i]); - } std::size_t index = 0; - for (auto g : component.gates_configuration_map) + for (auto g : component.gates_configuration_map) { + for (std::size_t i = 0; i < component.gates_configuration[index].size(); ++i) { + for (auto j : g.second) { + assignment.enable_selector(first_selector_index + i, + start_row_index + j + 1 + component.gates_configuration[index][i].first_coordinate.row); + } + } + first_selector_index += component.gates_configuration[index++].size(); + } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -1745,7 +1823,7 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - std::size_t word_size = component.word_size; + std::size_t strow = start_row_index; int config_index = 0; @@ -1774,13 +1852,13 @@ namespace nil { A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = state; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = message; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = state; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = message; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } // last round call @@ -1806,13 +1884,13 @@ namespace nil { A_1[16] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[16]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = state; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = message; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = state; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = message; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } for (int i = 17; i < 25; ++i) { @@ -1854,16 +1932,16 @@ namespace nil { C[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = A_1[5 * index]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = A_1[5 * index + 1]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row) = A_1[5 * index + 2]; - assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row) = A_1[5 * index + 3]; - assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row) = A_1[5 * index + 4]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[5 * index]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = A_1[5 * index + 1]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = A_1[5 * index + 2]; + assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row + strow) = A_1[5 * index + 3]; + assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row + strow) = A_1[5 * index + 4]; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } config_index += 5; @@ -1881,6 +1959,8 @@ namespace nil { C_rot[index] = value_type(integral_C_rot); integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); + auto copy_bound_smaller = bound_smaller; + auto copy_bound_bigger = bound_bigger; auto chunk_size = component.rotate_chunk_size; auto num_chunks = component.rotate_num_chunks; std::vector integral_small_chunks; @@ -1894,15 +1974,15 @@ namespace nil { } auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = C[index]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row) = C_rot[index]; - assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row) = value_type(smaller_part); - assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row) = value_type(bigger_part); - assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row) = value_type(bound_smaller); - assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row) = value_type(bound_bigger); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = C[index]; + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = C_rot[index]; + assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row) = value_type(integral_small_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row) = value_type(integral_big_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); } } config_index += 5; @@ -1934,14 +2014,14 @@ namespace nil { A_2[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = A_1[index]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = C_rot[(index + 1) % 5]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row) = C[(index + 4) % 5]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = A_2[index]; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = C_rot[(x + 1) % 5]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = C[(x + 4) % 5]; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = A_2[index]; for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } config_index += 25; @@ -1963,10 +2043,10 @@ namespace nil { integral_type bigger_part = integral_A & ((integral_type(1) << minus_r) - 1); integral_type integral_A_rot = (bigger_part << r) + smaller_part; B[y][(2*x + 3*y) % 5] = value_type(integral_A_rot); - // std::cout << "parts: " << smaller_part << " " << bigger_part << ' ' << integral_A_rot << "\n"; - integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); + auto copy_bound_smaller = bound_smaller; + auto copy_bound_bigger = bound_bigger; auto chunk_size = component.rotate_chunk_size; auto num_chunks = component.rotate_num_chunks; std::vector integral_small_chunks; @@ -1980,17 +2060,16 @@ namespace nil { } auto cur_config = component.full_configuration[index - 1 + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = A_2[index]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row) = B[y][(2*x + 3*y) % 5]; - assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row) = value_type(smaller_part); - assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row) = value_type(bigger_part); - assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row) = value_type(bound_smaller); - assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row) = value_type(bound_bigger); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_2[index]; + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = value_type(integral_A_rot); + assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row) = value_type(integral_small_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row) = value_type(integral_big_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); } - std::cout << "valuess: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row << ' ' << var_value(assignment, var(cur_config.copy_from.column, cur_config.copy_from.row)) << "\n"; } config_index += 24; // std::cout << "rho/phi:\n"; @@ -2024,14 +2103,14 @@ namespace nil { A_3[index] = value_type(integral_chi_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = B[x][y]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = B[(x+1)%5][y]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row) = B[(x+2)%5][y]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(integral_chi_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = B[x][y]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = B[(x+1)%5][y]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = B[(x+2)%5][y]; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_chi_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_chi_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_chi_chunks[j - 1]); } } config_index += 25; @@ -2063,15 +2142,15 @@ namespace nil { A_4 = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = A_3[0]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row) = round_constant; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_3[0]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = round_constant; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } - std::cout << "valuess: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row << ' ' << var_value(assignment, var(cur_config.copy_from.column, cur_config.copy_from.row)) << "\n"; + std::cout << "valuess: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row + strow << ' ' << var_value(assignment, var(cur_config.copy_from.column, cur_config.copy_from.row + strow)) << "\n"; } // std::cout << "result:\n"; // std::cout << A_4 << "\n"; diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index d64baecc5..f6c156507 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -185,7 +185,7 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 150; + constexpr std::size_t SelectorColumns = 20; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system(); - test_keccak_round_not_random(); + test_keccak_round_not_random(); // test_keccak_round_random(); } From b5f2c916c99b5e8654092ea5fb85c174f5b3760c Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 11 Sep 2023 00:57:22 +0000 Subject: [PATCH 10/48] fixed some constraints #183 --- .../components/hashes/keccak/keccak_round.hpp | 109 +++++++++++++----- test/hashes/plonk/keccak_round.cpp | 2 +- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index f6d164981..2b7f74f85 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -95,6 +95,9 @@ namespace nil { buff++; } } + // if (base == 0 && buff < 2 * WitnessesAmount) { + // buff = 2 * WitnessesAmount - rotate_cells; + // } return buff; } @@ -164,7 +167,7 @@ namespace nil { } std::size_t gates() const { std::size_t res = 0; - for (std::size_t i = 1; i < gates_configuration.size(); ++i) { + for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); } std::cout << "gates num: " << res << std::endl; @@ -251,6 +254,8 @@ namespace nil { const bool last_round_call; // change permutation on rho/phi step const bool eth_perm; + // num columns for the permutation argument + const std::size_t limit_permutation_column; const std::size_t normalize3_chunk_size; const std::size_t normalize4_chunk_size; @@ -267,7 +272,7 @@ namespace nil { const std::size_t xor2_cells; const std::size_t xor3_cells; const std::size_t xor5_cells; - const std::size_t rotate_cells = 22; + const std::size_t rotate_cells = 24; const std::size_t chi_cells; const std::size_t xor2_buff; @@ -290,12 +295,8 @@ namespace nil { const std::size_t last_round_call_row; const std::size_t gates_amount; - // all words in sparse form - const std::size_t word_size = 192; const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; - const std::size_t limit_permutation_column = 7; - constexpr static const std::array rho_offsets = {0, 36, 3, 41, 18, 1, 44, 10, 45, 2, @@ -497,8 +498,9 @@ namespace nil { std::vector> copy_to; std::pair cell_copy_from; std::vector>> constraints; - - if (2 + column > limit_permutation_column) { + + std::size_t lpc = 7; + if (2 + column > lpc) { copy_to.push_back({last_row + 1, 0}); cell_copy_from = {last_row + 1, 1}; } else { @@ -509,7 +511,7 @@ namespace nil { } std::vector> cells; - if (2 + column > limit_permutation_column) { + if (2 + column > lpc) { for (int i = column; i < WitnessesAmount; ++i) { cells.push_back({row, i}); } @@ -553,6 +555,12 @@ namespace nil { constraints[5].push_back(cells[cell_index++]); lookups[1].push_back(constraints[5].back()); } + constraints.push_back({cells[cell_index++], cells[cell_index++]}); + + constraints[0].push_back(constraints[6][1]); + constraints[1].push_back(constraints[6][0]); + constraints[2].push_back(constraints[6][0]); + constraints[4].push_back(constraints[6][1]); last_column = cells.back().second + 1 + rotate_buff; last_row = cells.back().first + (last_column / WitnessesAmount); @@ -755,13 +763,13 @@ namespace nil { config_map[zero_config] = {row}; } - // for (auto config : config_map) { - // std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; - // for (auto c : config.second) { - // std::cout << c << ' '; - // } - // std::cout << std::endl; - // } + for (auto config : config_map) { + std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; + for (auto c : config.second) { + std::cout << c << ' '; + } + std::cout << std::endl; + } return config_map; } @@ -806,7 +814,7 @@ namespace nil { num_before++; } } - std::cout << "gates num before: " << num_before << std::endl; + // std::cout << "gates num before: " << num_before << std::endl; std::vector> result; for (auto config: gates_configuration_map) { @@ -903,17 +911,17 @@ namespace nil { return result; } - #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) \ + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ xor_with_mes(xor_with_mes_), \ last_round_call(last_round_call_),\ eth_perm(eth_perm_), \ + limit_permutation_column(lpc_), \ normalize3_chunk_size(calculate_chunk_size(lookup_rows_, 3)), \ normalize4_chunk_size(calculate_chunk_size(lookup_rows_, 4)), \ normalize6_chunk_size(calculate_chunk_size(lookup_rows_, 6)), \ chi_chunk_size(calculate_chunk_size(lookup_rows_, 2)), \ - word_size(192), \ normalize3_num_chunks(calculate_num_chunks(3)), \ normalize4_num_chunks(calculate_num_chunks(4)), \ normalize6_num_chunks(calculate_num_chunks(6)), \ @@ -939,9 +947,10 @@ namespace nil { keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false) : + bool eth_perm_ = false, + std::size_t lpc_ = 7) : component_type(witness, {}, {}), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; template @@ -950,9 +959,10 @@ namespace nil { std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false) : + bool eth_perm_ = false, + std::size_t lpc_ = 7) : component_type(witness, constant, public_input), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; keccak_round( std::initializer_list witnesses, @@ -962,9 +972,10 @@ namespace nil { std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false) : + bool eth_perm_ = false, + std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; #undef __keccak_round_init_macro }; @@ -1455,8 +1466,8 @@ namespace nil { } case 7: { - auto r = var(component.C(0), -1, true, var::column_type::constant); - auto minus_r = var(component.C(0), 0, true, var::column_type::constant); + auto r = var(cur_config_vec[i].constraints.back()[0].column, cur_config_vec[i].constraints.back()[0].row - cur_config_vec[i].first_coordinate.row - 1, true); + auto minus_r = var(cur_config_vec[i].constraints.back()[1].column, cur_config_vec[i].constraints.back()[1].row - cur_config_vec[i].first_coordinate.row - 1, true); cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * minus_r + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) @@ -1538,7 +1549,19 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + gate_type gate(selector_index++, cur_constraints); + bp.add_gate(gate); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << 192))); gate_type gate(selector_index++, cur_constraints); bp.add_gate(gate); @@ -1624,17 +1647,21 @@ namespace nil { std::size_t prev_index = 0; auto config = component.full_configuration; + std::size_t num_copy_constr = 0; + if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), config[i].copy_to[0].row + start_row_index, false)}); bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), config[i].copy_to[1].row + start_row_index, false)}); + num_copy_constr += 2; } config_index += 16; if (component.last_round_call) { bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row + start_row_index, false)}); bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row + start_row_index, false)}); bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index), var(component.W(config[config_index].copy_to[2].column), config[config_index].copy_to[2].row + start_row_index, false)}); + num_copy_constr += 3; } config_index += 1; @@ -1642,10 +1669,12 @@ namespace nil { for (int i = 0; i < 17; ++i) { bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + num_copy_constr += 1; } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + num_copy_constr += 1; } config_index += 5; prev_index += 17; @@ -1653,23 +1682,30 @@ namespace nil { for (int i = 0; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + num_copy_constr += 1; } config_index += 5; } for (int i = 0; i < 5; ++i) { bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint({{component.W(config[config_index + i].constraints[6][0].column), static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, + var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); + num_copy_constr += 2; } config_index += 5; prev_index += 5; for (int i = 0; i < 25; ++i) { + std::size_t x = i / 5; bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].column), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].row + start_row_index), false}, {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 1) % 5].copy_from.column), static_cast(config[prev_index + (i + 1) % 5].copy_from.row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + (x + 1) % 5].copy_from.column), static_cast(config[prev_index + (x + 1) / 5].copy_from.row + start_row_index), false}, {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (i + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (i + 4) % 5].copy_to[0].row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + (x + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (x + 4) / 5].copy_to[0].row + start_row_index), false}, {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); + num_copy_constr += 3; + std::cout << "num_constr: " << num_copy_constr << std::endl; } config_index += 25; prev_index += 5; @@ -1678,6 +1714,8 @@ namespace nil { for (int i = 0; i < 24; ++i) { bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.column), static_cast(config[prev_index + i + 1].copy_from.row + start_row_index), false}, {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint({{component.W(config[config_index + i].constraints[6][0].column), static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, + var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); } // chi @@ -1744,11 +1782,9 @@ namespace nil { std::sort(rotate_rows.begin(), rotate_rows.end()); for (std::size_t i = 0; i < 5; i++) { assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << 3; - assignment.constant(component.C(0), row + rotate_rows[i] + 1) = integral_type(1) << 189; } for (std::size_t i = 5; i < 29; i++) { assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i]); - assignment.constant(component.C(0), row + rotate_rows[i] + 1) = integral_type(1) << (192 - 3 * component_type::rho_offsets[i]); } } @@ -1976,6 +2012,8 @@ namespace nil { auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = C[index]; assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = C_rot[index]; + std::cout << "C: " << index << ' ' << cur_config.copy_to[0].column << ' ' << cur_config.copy_to[0].row << "; " << C[index] << '\n'; + std::cout << "C_rot: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row << "; " << C_rot[index] << '\n'; assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); @@ -1984,6 +2022,8 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); } + assignment.witness(component.W(cur_config.constraints[6][0].column), cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << 3); + assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); } config_index += 5; // std::cout << "theta 1:\n"; @@ -2017,6 +2057,9 @@ namespace nil { assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = C_rot[(x + 1) % 5]; assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = C[(x + 4) % 5]; + std::cout << '\n'; + std::cout << "C: " << (x + 4) % 5 << ' ' << C[(x + 4) % 5] << '\n'; + std::cout << "C_rot: " << (x + 1) % 5 << ' ' << C_rot[(x + 1) % 5] << '\n'; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = A_2[index]; for (int j = 1; j < num_chunks + 1; ++j) { @@ -2070,6 +2113,8 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); } + assignment.witness(component.W(cur_config.constraints[6][0].column), cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << r); + assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << minus_r); } config_index += 24; // std::cout << "rho/phi:\n"; diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index f6c156507..22ff25318 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -185,7 +185,7 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 20; + constexpr std::size_t SelectorColumns = 25; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system Date: Mon, 2 Oct 2023 20:43:32 +0000 Subject: [PATCH 11/48] finished round (no lookups) #183 --- .../components/hashes/keccak/keccak_round.hpp | 632 +++--------------- test/hashes/plonk/keccak_round.cpp | 350 +++++----- 2 files changed, 264 insertions(+), 718 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 2b7f74f85..81c748c1f 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -103,56 +103,17 @@ namespace nil { std::size_t calculate_rows() const { std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call - * xor_with_mes + // xor with last message chunk + * xor_with_mes + // xor with last message chunk ((17 - last_round_call) * (xor2_cells + xor2_buff)) - * xor_with_mes + // inner_state ^ chunk - 5 * (xor5_cells + xor5_buff) + // theta + * xor_with_mes + // inner_state ^ chunk + 5 * (xor5_cells + xor5_buff) + // theta 5 * (rotate_cells + rotate_buff) + // theta - 25 * (xor3_cells + xor3_buff) + // theta + 25 * (xor3_cells + xor3_buff) + // theta 24 * (rotate_cells + rotate_buff) + // rho/phi - 25 * (chi_cells + chi_buff) + // chi - xor2_cells; // iota - std::size_t num_cells_before = (xor3_cells) * last_round_call - * xor_with_mes + // xor with last message chunk - ((17 - last_round_call) * (xor2_cells)) - * xor_with_mes + // inner_state ^ chunk - 5 * (xor5_cells) + // theta - 5 * (rotate_cells) + // theta - 25 * (xor3_cells) + // theta - 24 * (rotate_cells) + // rho/phi - 25 * (chi_cells) + // chi - xor2_cells; // iota - std::size_t num_cells_buff = (0 + xor3_buff) * last_round_call - * xor_with_mes + // xor with last message chunk - ((17 - last_round_call) * (0 + xor2_buff)) - * xor_with_mes + // inner_state ^ chunk - 5 * (0 + xor5_buff) + // theta - 5 * (0 + rotate_buff) + // theta - 25 * (0 + xor3_buff) + // theta - 24 * (0 + rotate_buff) + // rho/phi - 25 * (0 + chi_buff) + // chi - xor2_cells; // iota - std::cout << "rows: " << num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount) << std::endl; - std::cout << "rows before: " << num_cells_before / WitnessesAmount + bool(num_cells_before % WitnessesAmount) << std::endl; - std::cout << "empty cells: " << num_cells_buff + num_cells % WitnessesAmount << std::endl; - std::cout << "empty cells before: " << num_cells_before % WitnessesAmount << std::endl; + 25 * (chi_cells + chi_buff) + // chi + xor2_cells; // iota return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); } - // std::vector calculate_gates_rows() const { - // std::vector res; - // auto cur_selector = gates_configuration[0]; - // res.push_back(cur_selector); - // for (std::size_t i = 1; i < gates_configuration.size(); ++i) { - // if (gates_configuration[i] != cur_selector) { - // cur_selector = gates_configuration[i]; - // res.push_back(cur_selector); - // } - // } - // // for (int i = 0; i < res.size(); ++i) { - // // std::cout << res[i] << " "; - // // } - // return res; - // } std::size_t calculate_last_round_call_row() const { if (!last_round_call) { return 0; @@ -170,7 +131,6 @@ namespace nil { for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); } - std::cout << "gates num: " << res << std::endl; return res; } @@ -252,8 +212,6 @@ namespace nil { const bool xor_with_mes; // need to xor last message chunk with 0x80 or 1 only on the last round const bool last_round_call; - // change permutation on rho/phi step - const bool eth_perm; // num columns for the permutation argument const std::size_t limit_permutation_column; @@ -298,11 +256,10 @@ namespace nil { const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; constexpr static const std::array - rho_offsets = {0, 36, 3, 41, 18, - 1, 44, 10, 45, 2, - 62, 6, 43, 15, 61, - 28, 55, 25, 21, 56, - 27, 20, 39, 8, 14}; + rho_offsets = {0, 1, 3, 6, 10, 15, 21, + 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, + 62, 18, 39, 61, 20, 44}; struct input_type { std::array inner_state; @@ -432,21 +389,6 @@ namespace nil { last_row = cells.back().first + (last_column >= WitnessesAmount); last_column %= WitnessesAmount; - // std::cout << "normalize " << num_args << ": " << row << ' ' << column << std::endl; - // std::cout << "last coordinate: " << last_row << " " << last_column << std::endl; - // std::cout << "copy from: " << cell_copy_from.first << " " << cell_copy_from.second << std::endl; - // std::cout << "copy to:\n"; - // for (auto cell : copy_to) { - // std::cout << cell.first << " " << cell.second << "\n"; - // } - // std::cout << "constraints:\n"; - // for (auto constr : constraints) { - // std::cout << "constraint:\n"; - // for (auto cell : constr) { - // std::cout << cell.first << " " << cell.second << "\n"; - // } - // } - return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } @@ -499,8 +441,7 @@ namespace nil { std::pair cell_copy_from; std::vector>> constraints; - std::size_t lpc = 7; - if (2 + column > lpc) { + if (2 + column > limit_permutation_column) { copy_to.push_back({last_row + 1, 0}); cell_copy_from = {last_row + 1, 1}; } else { @@ -511,7 +452,7 @@ namespace nil { } std::vector> cells; - if (2 + column > lpc) { + if (2 + column > limit_permutation_column) { for (int i = column; i < WitnessesAmount; ++i) { cells.push_back({row, i}); } @@ -529,6 +470,8 @@ namespace nil { } } std::size_t cell_index = 0; + auto rot_const = cells[cell_index++]; + auto minus_rot_const = cells[cell_index++]; constraints.push_back({copy_to[0]}); constraints[0].push_back(cells[cell_index++]); @@ -555,7 +498,7 @@ namespace nil { constraints[5].push_back(cells[cell_index++]); lookups[1].push_back(constraints[5].back()); } - constraints.push_back({cells[cell_index++], cells[cell_index++]}); + constraints.push_back({rot_const, minus_rot_const}); constraints[0].push_back(constraints[6][1]); constraints[1].push_back(constraints[6][0]); @@ -565,21 +508,6 @@ namespace nil { last_column = cells.back().second + 1 + rotate_buff; last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - - // std::cout << "ROT: " << row << ' ' << column << std::endl; - // std::cout << "last coordinate: " << last_row << " " << last_column << std::endl; - // std::cout << "copy from: " << cell_copy_from.first << " " << cell_copy_from.second << std::endl; - // std::cout << "copy to:\n"; - // for (auto cell : copy_to) { - // std::cout << cell.first << " " << cell.second << "\n"; - // } - // std::cout << "constraints:\n"; - // for (auto constr : constraints) { - // std::cout << "constraint:\n"; - // for (auto cell : constr) { - // std::cout << cell.first << " " << cell.second << "\n"; - // } - // } return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } @@ -642,22 +570,6 @@ namespace nil { // iota result[cur_config] = configure_xor(row, column, 2); - // for (int i = 0; i < 50; ++i) { - // std::cout << "configuration " << i << std::endl; - // std::cout << "last coordinate: " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; - // std::cout << "copy from: " << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; - // std::cout << "copy to:\n"; - // for (auto cell : result[i].copy_to) { - // std::cout << cell.row << " " << cell.column << "\n"; - // } - // std::cout << "constraints:\n"; - // for (auto constr : result[i].constraints) { - // std::cout << "constraint:\n"; - // for (auto cell : constr) { - // std::cout << cell.row << " " << cell.column << "\n"; - // } - // } - // } return result; } @@ -763,59 +675,11 @@ namespace nil { config_map[zero_config] = {row}; } - for (auto config : config_map) { - std::cout << "config: " << config.first.first << ' ' << config.first.second << ": "; - for (auto c : config.second) { - std::cout << c << ' '; - } - std::cout << std::endl; - } return config_map; } - std::vector configure_gates_before() { - std::vector> pairs; - for (std::size_t i = 0; i < full_configuration_size; ++i) { - for (auto constr : full_configuration[i].constraints) { - std::size_t min = constr[0].row; - std::size_t max = constr.back().row; - for (std::size_t j = 0; j < constr.size(); ++j) { - min = std::min(min, constr[j].row); - max = std::max(max, constr[j].row); - } - BOOST_ASSERT(max - min <= 2); - pairs.push_back({min, max}); - } - } - std::vector result; - std::size_t cur_row = 0; - std::size_t cur_constr = 0; - while (cur_row < rows_amount) { - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { - result.push_back(cur_row + 1); - ++cur_constr; - } - if (cur_constr == pairs.size()) { - break; - } - cur_row = pairs[cur_constr].first; - } - return result; - } - std::vector> configure_gates() { - auto gates_before = configure_gates_before(); - std::size_t num_before = 1; - std::size_t cur_before = gates_before[0]; - for (int i = 1; i < gates_before.size(); ++i) { - if (gates_before[i] != cur_before) { - cur_before = gates_before[i]; - num_before++; - } - } - // std::cout << "gates num before: " << num_before << std::endl; - std::vector> result; for (auto config: gates_configuration_map) { configuration cur_config; @@ -864,20 +728,6 @@ namespace nil { result.push_back(cur_result); } - // for (int i = 0; i < result.size(); ++i) { - // std::cout << "gate " << i << std::endl; - // for (int j = 0; j < result[i].size(); ++j) { - // std::cout << "configuration " << j << std::endl; - // std::cout << "type: " << " " << result[i][j].first_coordinate.column << std::endl; - // std::cout << "constraints:\n"; - // for (auto constr : result[i][j].constraints) { - // std::cout << "constraint:\n"; - // for (auto cell : constr) { - // std::cout << cell.row << " " << cell.column << "\n"; - // } - // } - // } - // } return result; } @@ -911,12 +761,11 @@ namespace nil { return result; } - #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) \ + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ xor_with_mes(xor_with_mes_), \ last_round_call(last_round_call_),\ - eth_perm(eth_perm_), \ limit_permutation_column(lpc_), \ normalize3_chunk_size(calculate_chunk_size(lookup_rows_, 3)), \ normalize4_chunk_size(calculate_chunk_size(lookup_rows_, 4)), \ @@ -947,10 +796,9 @@ namespace nil { keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false, std::size_t lpc_ = 7) : component_type(witness, {}, {}), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; template @@ -959,10 +807,9 @@ namespace nil { std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false, std::size_t lpc_ = 7) : component_type(witness, constant, public_input), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; keccak_round( std::initializer_list witnesses, @@ -972,309 +819,13 @@ namespace nil { std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, - bool eth_perm_ = false, std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, eth_perm_, lpc_) {}; + __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; #undef __keccak_round_init_macro }; - // template - // using keccak_round_component = - // keccak_round, - // WitnessesAmount>; - - // template= 9, bool> = true> - // void generate_gates( - // const keccak_round_component - // &component, - // circuit> - // &bp, - // assignment> - // &assignment, - // const typename keccak_round_component::input_type - // &instance_input, - // const std::size_t first_selector_index) { - - // using component_type = keccak_round_component; - // using var = typename component_type::var; - // using constraint_type = crypto3::zk::snark::plonk_constraint; - // using gate_type = typename crypto3::zk::snark::plonk_gate; - // // using lookup_constraint_type = typename crypto3::zk::snark::lookup_constraint; - // // using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; - // using value_type = typename BlueprintFieldType::value_type; - // using integral_type = typename BlueprintFieldType::integral_type; - - // auto config = component.full_configuration; - // auto gate_config = component.gates_configuration; - // // auto lookup_gate_config = component.lookup_gates_configuration; - // std::size_t config_index = 0; - // std::size_t gate_index = 0; - // // std::size_t lookup_gate_index = 0; - - // std::vector constraints; - // // std::vector lookup_constraints; - - // // inner_state ^ chunk - // if (component.xor_with_mes) { - // for (int i = 0; i < 17 - component.last_round_call; ++i) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize3_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize3_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize3_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize3_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - // if (component.last_round_call) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize4_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize4_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize4_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize4_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - // } - - // // theta - // for (int i = 0; i < 5; ++i) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][4].column, cur_config.constraints[0][4].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][5].column, cur_config.constraints[0][5].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize6_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize6_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize6_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize6_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // for (int i = 0; i < 5; ++i) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << 189) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << 3) - // + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - // - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - // - (integral_type(1) << 3) - // + (integral_type(1) << 192))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.rotate_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.rotate_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) - // - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) - // - (integral_type(1) << 189) - // + (integral_type(1) << 192))); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.rotate_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.rotate_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // for (int i = 0; i < 25; ++i) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize4_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize4_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize4_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize4_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // // rho/phi - // for (int i = 1; i < 25; ++i) { - // auto r = 3 * component.rho_offsets[i]; - - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << (192 - r)) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) * (integral_type(1) << r) - // + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]) - // - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - // - (integral_type(1) << r) - // + (integral_type(1) << 192))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[3][0].column, cur_config.constraints[3][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.rotate_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[3][j + 1].column, cur_config.constraints[3][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.rotate_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[4][0].column, cur_config.constraints[4][0].row - gate_config[gate_index]) - // - var(cur_config.constraints[4][1].column, cur_config.constraints[4][1].row - gate_config[gate_index]) - // - (integral_type(1) << (192 - r)) - // + (integral_type(1) << 192))); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[5][0].column, cur_config.constraints[5][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.rotate_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[5][j + 1].column, cur_config.constraints[5][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.rotate_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // // chi - // for (int i = 0; i < 25; ++i) { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(component.sparse_3 - // - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * 2 - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][3].column, cur_config.constraints[0][3].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.chi_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.chi_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.chi_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.chi_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // // iota - // { - // auto cur_config = config[config_index]; - // constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) - // + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]) - // - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]))); - // gate_index++; - // constraint_type constraint_1 = var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize3_num_chunks; ++j) { - // constraint_1 -= var(cur_config.constraints[1][j + 1].column, cur_config.constraints[1][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize3_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_1)); - // gate_index++; - // constraint_type constraint_2 = var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]); - // for (int j = 0; j < component.normalize3_num_chunks; ++j) { - // constraint_2 -= var(cur_config.constraints[2][j + 1].column, cur_config.constraints[2][j + 1].row - gate_config[gate_index]) - // * (integral_type(1) << (j * component.normalize3_chunk_size)); - // } - // constraints.push_back(bp.add_constraint(constraint_2)); - // gate_index++; - // config_index++; - // } - - // BOOST_ASSERT(config_index == component.full_configuration_size); - // // BOOST_ASSERT(constraints.size() == gate_config.size()); - - // std::size_t prev_selector = gate_config[0]; - // std::vector cur_constraints = {constraints[0]}; - // gate_index = 1; - // while (gate_index < gate_config.size()) { - // while (gate_index < gate_config.size() && gate_config[gate_index] == prev_selector) { - // cur_constraints.push_back(constraints[gate_index]); - // ++gate_index; - // } - // if (gate_index == gate_config.size()) { - // break; - // } - // gate_type gate(first_selector_index + prev_selector, cur_constraints); - // bp.add_gate(gate); - // cur_constraints.clear(); - // prev_selector = gate_config[gate_index]; - // } - // if (!cur_constraints.empty()) { - // gate_type gate(first_selector_index + prev_selector, cur_constraints); - // bp.add_gate(gate); - // } - // } - template using keccak_round_component = keccak_round= cur_len) { @@ -1660,7 +1212,8 @@ namespace nil { if (component.last_round_call) { bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row + start_row_index, false)}); bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row + start_row_index, false)}); - bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index), var(component.W(config[config_index].copy_to[2].column), config[config_index].copy_to[2].row + start_row_index, false)}); + bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index, false, var::column_type::constant), + var(component.W(config[config_index].copy_to[2].column), config[config_index].copy_to[2].row + start_row_index, false)}); num_copy_constr += 3; } config_index += 1; @@ -1668,12 +1221,12 @@ namespace nil { // theta for (int i = 0; i < 17; ++i) { bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); num_copy_constr += 1; } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); num_copy_constr += 1; } config_index += 5; @@ -1681,7 +1234,7 @@ namespace nil { } else { for (int i = 0; i < 25; ++i) { bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i / 5].copy_to[i % 5].column), static_cast(config[config_index + i / 5].copy_to[i % 5].row + start_row_index), false}}); + {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); num_copy_constr += 1; } config_index += 5; @@ -1697,43 +1250,49 @@ namespace nil { prev_index += 5; for (int i = 0; i < 25; ++i) { - std::size_t x = i / 5; - bp.add_copy_constraint({{component.W(config[prev_index - 5 + i / 5].copy_to[i % 5].column), static_cast(config[prev_index - 5 + i / 5].copy_to[i % 5].row + start_row_index), false}, + std::size_t x = i % 5; + bp.add_copy_constraint({{component.W(config[prev_index - 5 + i % 5].copy_to[i / 5].column), static_cast(config[prev_index - 5 + i % 5].copy_to[i / 5].row + start_row_index), false}, {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (x + 1) % 5].copy_from.column), static_cast(config[prev_index + (x + 1) / 5].copy_from.row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + (x + 1) % 5].copy_from.column), static_cast(config[prev_index + (x + 1) % 5].copy_from.row + start_row_index), false}, {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (x + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (x + 4) / 5].copy_to[0].row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + (x + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (x + 4) % 5].copy_to[0].row + start_row_index), false}, {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); num_copy_constr += 3; - std::cout << "num_constr: " << num_copy_constr << std::endl; } config_index += 25; prev_index += 5; // rho/phi + std::size_t perm_rho[24] = {1, 10, 7, 11, 17, 18, 3, + 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6}; for (int i = 0; i < 24; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i + 1].copy_from.column), static_cast(config[prev_index + i + 1].copy_from.row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + perm_rho[i]].copy_from.column), static_cast(config[prev_index + perm_rho[i]].copy_from.row + start_row_index), false}, {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); bp.add_copy_constraint({{component.W(config[config_index + i].constraints[6][0].column), static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); } // chi - std::vector perm_index = {14,4,19,9, 5,20,10,0,15, 11,1,16,6,21, 17,7,22,12,2, 23,13,3,18,8}; + std::size_t perm_chi[24] = {23, 17, 5, 11, 6, 22, + 1, 8, 21, 0, 2, 16, + 15, 19, 12, 7, 3, 4, + 14, 18, 9, 20, 13, 10}; std::vector B = {{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row + start_row_index), false}}; - for (auto i : perm_index) { + for (auto i : perm_chi) { B.push_back({component.W(config[config_index + i].copy_from.column), static_cast(config[config_index + i].copy_from.row + start_row_index), false}); } config_index += 24; prev_index += 25; for (int i = 0; i < 25; ++i) { - int x = i / 5; - int y = i % 5; - bp.add_copy_constraint({B[x * 5 + y], + int x = i % 5; + int y = i / 5; + bp.add_copy_constraint({B[x + 5 * y], {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({B[((x + 1) % 5) * 5 + y], + bp.add_copy_constraint({B[(x + 1) % 5 + 5 * y], {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); - bp.add_copy_constraint({B[((x + 2) % 5) * 5 + y], + bp.add_copy_constraint({B[(x + 2) % 5 + 5 * y], {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); } config_index += 25; @@ -1784,7 +1343,7 @@ namespace nil { assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << 3; } for (std::size_t i = 5; i < 29; i++) { - assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i]); + assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i - 4]); } } @@ -1901,7 +1460,7 @@ namespace nil { if (component.last_round_call) { value_type state = var_value(assignment, instance_input.inner_state[16]); value_type message = var_value(assignment, instance_input.padded_message_chunk[16]); - value_type sum = state + message + value_type(component.C(0)); + value_type sum = state + message + value_type(2097152); integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; auto num_chunks = component.normalize4_num_chunks; @@ -1922,6 +1481,7 @@ namespace nil { auto cur_config = component.full_configuration[16]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = state; assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = message; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = value_type(2097152); assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { @@ -1938,17 +1498,13 @@ namespace nil { A_1[i] = var_value(assignment, instance_input.inner_state[i]); } } - // std::cout << "inner_state ^ chunk:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << A_1[i] << "\n"; - // } // theta std::array C; for (int index = 0; index < 5; ++index) { value_type sum = 0; for (int j = 0; j < 5; ++j) { - sum += A_1[5 * index + j]; + sum += A_1[index + 5 * j]; } integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize6_chunk_size; @@ -1968,11 +1524,11 @@ namespace nil { C[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[5 * index]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = A_1[5 * index + 1]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = A_1[5 * index + 2]; - assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row + strow) = A_1[5 * index + 3]; - assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row + strow) = A_1[5 * index + 4]; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = A_1[index + 5]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = A_1[index + 10]; + assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row + strow) = A_1[index + 15]; + assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row + strow) = A_1[index + 20]; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { @@ -1981,10 +1537,6 @@ namespace nil { } } config_index += 5; - // std::cout << "theta 0:\n"; - // for (int i = 0; i < 5; ++i) { - // std::cout << C[i] << "\n"; - // } std::array C_rot; for (int index = 0; index < 5; ++index) { @@ -2012,8 +1564,6 @@ namespace nil { auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = C[index]; assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = C_rot[index]; - std::cout << "C: " << index << ' ' << cur_config.copy_to[0].column << ' ' << cur_config.copy_to[0].row << "; " << C[index] << '\n'; - std::cout << "C_rot: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row << "; " << C_rot[index] << '\n'; assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); @@ -2026,15 +1576,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); } config_index += 5; - // std::cout << "theta 1:\n"; - // for (int i = 0; i < 5; ++i) { - // std::cout << C_rot[i] << "\n"; - // } std::array A_2; for (int index = 0; index < 25; ++index) { - int x = index / 5; - int y = index % 5; + int x = index % 5; + int y = index / 5; value_type sum = A_1[index] + C_rot[(x + 1) % 5] + C[(x + 4) % 5]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; @@ -2057,9 +1603,6 @@ namespace nil { assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = C_rot[(x + 1) % 5]; assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = C[(x + 4) % 5]; - std::cout << '\n'; - std::cout << "C: " << (x + 4) % 5 << ' ' << C[(x + 4) % 5] << '\n'; - std::cout << "C_rot: " << (x + 1) % 5 << ' ' << C_rot[(x + 1) % 5] << '\n'; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = A_2[index]; for (int j = 1; j < num_chunks + 1; ++j) { @@ -2068,24 +1611,24 @@ namespace nil { } } config_index += 25; - // std::cout << "theta 2:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << A_2[i] << "\n"; - // } // rho/phi - value_type B[5][5]; - B[0][0] = A_2[0]; + value_type B[25]; + std::size_t perm[25] = {1, 10, 7, 11, 17, 18, 3, + 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1}; + B[0] = A_2[0]; for (int index = 1; index < 25; ++index) { - int x = index / 5; - int y = index % 5; + int x = index % 5; + int y = index / 5; int r = 3 * component.rho_offsets[index]; int minus_r = 192 - r; - integral_type integral_A = integral_type(A_2[index].data); + integral_type integral_A = integral_type(A_2[perm[index - 1]].data); integral_type smaller_part = integral_A >> minus_r; integral_type bigger_part = integral_A & ((integral_type(1) << minus_r) - 1); integral_type integral_A_rot = (bigger_part << r) + smaller_part; - B[y][(2*x + 3*y) % 5] = value_type(integral_A_rot); + B[perm[index]] = value_type(integral_A_rot); integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); auto copy_bound_smaller = bound_smaller; @@ -2103,7 +1646,7 @@ namespace nil { } auto cur_config = component.full_configuration[index - 1 + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_2[index]; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_2[perm[index - 1]]; assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = value_type(integral_A_rot); assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); @@ -2117,19 +1660,13 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << minus_r); } config_index += 24; - // std::cout << "rho/phi:\n"; - // for (int i = 0; i < 5; ++i) { - // for (int j = 0; j < 5; ++j) { - // std::cout << B[i][j] << "\n"; - // } - // } // chi std::array A_3; for (int index = 0; index < 25; ++index) { - int x = index / 5; - int y = index % 5; - value_type sum = component.sparse_3 - 2 * B[x][y] + B[(x+1)%5][y] - B[(x+2)%5][y]; + int x = index % 5; + int y = index / 5; + value_type sum = component.sparse_3 - 2 * B[x + 5 * y] + B[(x+1)%5 + 5 * y] - B[(x+2)%5 + 5 * y]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.chi_chunk_size; auto num_chunks = component.chi_num_chunks; @@ -2148,9 +1685,9 @@ namespace nil { A_3[index] = value_type(integral_chi_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = B[x][y]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = B[(x+1)%5][y]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = B[(x+2)%5][y]; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = B[x + 5 * y]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = B[(x+1)%5 + 5 * y]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = B[(x+2)%5 + 5 * y]; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_chi_sum); for (int j = 1; j < num_chunks + 1; ++j) { @@ -2159,10 +1696,6 @@ namespace nil { } } config_index += 25; - // std::cout << "chi:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << A_3[i] << "\n"; - // } // iota value_type A_4; @@ -2195,18 +1728,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } - std::cout << "valuess: " << cur_config.copy_from.column << ' ' << cur_config.copy_from.row + strow << ' ' << var_value(assignment, var(cur_config.copy_from.column, cur_config.copy_from.row + strow)) << "\n"; } - // std::cout << "result:\n"; - // std::cout << A_4 << "\n"; - // for (int i = 1; i < 25; ++i) { - // std::cout << A_3[i] << "\n"; - // } return typename component_type::result_type(component, start_row_index); } - } // namespace components } // namespace blueprint } // namespace nil diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 22ff25318..4db6c193e 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -70,33 +70,20 @@ typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::v } return value_type(result_integral); } -template -bool check_sparse(typename BlueprintFieldType::value_type value, typename BlueprintFieldType::value_type sparse_value) { - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; - integral_type value_integral = integral_type(value.data); - integral_type sparse_value_integral = integral_type(sparse_value.data); - bool result = 1; - for (int i = 0; i < 64; ++i) { - integral_type bit = value_integral & 1; - integral_type sparse_bit = sparse_value_integral & 7; - result *= (bit == sparse_bit); - } - return result; -} - -template +template std::array sparse_round_function(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::array inner_state_integral; + std::array, 5> inner_state_integral; std::array padded_message_chunk_integral; integral_type RC_integral = integral_type(RC.data); - for (int i = 0; i < 25; ++i) { - inner_state_integral[i] = integral_type(inner_state[i].data); + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state_integral[x][y] = integral_type(inner_state[x + 5 * y].data); + } } for (int i = 0; i < 17; ++i) { padded_message_chunk_integral[i] = integral_type(padded_message_chunk[i].data); @@ -107,78 +94,67 @@ std::array sparse_round_function(st }; if (xor_with_mes) { - for (int i = 0; i < 17; ++i) { - inner_state_integral[i] = inner_state_integral[i] ^ padded_message_chunk_integral[i]; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + if (last_round_call && (x + 5 * y == 16)) { + continue; + } + if (x + 5 * y < 17) { + inner_state_integral[x][y] = inner_state_integral[x][y] ^ padded_message_chunk_integral[x + 5 * y]; + } + } + } + if (last_round_call) { + value_type last_round_const = to_sparse(value_type(0x80)); + integral_type last_round_const_integral = integral_type(last_round_const.data); + inner_state_integral[1][3] = inner_state_integral[1][3] ^ padded_message_chunk_integral[16] ^ last_round_const_integral; } } - // std::cout << "expected inner_state ^ chunk:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << inner_state_integral[i] << "\n"; - // } // theta std::array C; for (int x = 0; x < 5; ++x) { - C[x] = inner_state_integral[5 * x] ^ inner_state_integral[5 * x + 1] ^ inner_state_integral[5 * x + 2] ^ inner_state_integral[5 * x + 3] ^ - inner_state_integral[5 * x + 4]; + for (int y = 0; y < 5; ++y) { + C[x] ^= inner_state_integral[x][y]; + } } - // std::cout << "expected theta 0:\n"; - // for (int i = 0; i < 5; ++i) { - // std::cout << C[i] << "\n"; - // } - std::array C_rot; + std::array D; for (int x = 0; x < 5; ++x) { - C_rot[x] = rot(C[x], 1); + D[x] = C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); } - // std::cout << "expected theta 1:\n"; - // for (int i = 0; i < 5; ++i) { - // std::cout << C_rot[i] << "\n"; - // } for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { - inner_state_integral[5 * x + y] = inner_state_integral[5 * x + y] ^ C[(x + 4) % 5] ^ C_rot[(x + 1) % 5]; + inner_state_integral[x][y] ^= D[x]; } } - // std::cout << "expected theta 2:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << inner_state_integral[i] << "\n"; - // } // rho and pi std::array, 5> B; - for (int i = 0; i < 25; ++i) { - int x = i / 5; - int y = i % 5; - B[y][(2 * x + 3 * y) % 5] = rot(inner_state_integral[i], r[x][y]); + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + B[y][(2 * x + 3 * y) % 5] = rot(inner_state_integral[x][y], r[x][y]); + } } - // std::cout << "expected rho/pi:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << B[i / 5][i % 5] << "\n"; - // } // chi - for (int i = 0; i < 25; ++i) { - int x = i / 5; - int y = i % 5; - inner_state_integral[i] = B[x][y] ^ ((~B[(x + 1) % 5][y]) & B[(x + 2) % 5][y]); + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state_integral[x][y] = B[x][y] ^ ((~B[(x + 1) % 5][y]) & B[(x + 2) % 5][y]); + } } - // std::cout << "expected chi:\n"; - // for (int i = 0; i < 25; ++i) { - // std::cout << inner_state_integral[i] << "\n"; - // } // iota - inner_state_integral[0] = inner_state_integral[0] ^ RC_integral; - // std::cout << "expected iota:\n"; - // std::cout << inner_state_integral[0] << "\n"; - for (int i = 0; i < 25; ++i) { - inner_state[i] = value_type(inner_state_integral[i]); + inner_state_integral[0][0] = inner_state_integral[0][0] ^ RC_integral; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state[x + 5 * y] = value_type(inner_state_integral[x][y]); + } } return inner_state; } template + std::size_t LookupColumns, bool xor_with_mes, bool last_round_call, std::size_t last_prem_col = 7> auto test_keccak_round_inner(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC, @@ -200,18 +176,13 @@ auto test_keccak_round_inner(std::array public_input; - // std::cout << "inner state:\n"; for (int i = 0; i < 25; ++i) { public_input.push_back(inner_state[i]); - // std::cout << inner_state[i].data << std::endl; } - // std::cout << "padded message chunk:\n"; for (int i = 0; i < 17; ++i) { public_input.push_back(padded_message_chunk[i]); - // std::cout << padded_message_chunk[i].data << std::endl; } public_input.push_back(RC); - // std::cout << "RC: " << RC.data << std::endl; std::array inner_state_vars; std::array padded_message_chunk_vars; @@ -228,16 +199,15 @@ auto test_keccak_round_inner(std::array(component_instance), public_input, result_check, instance_input); } -// works template -void test_keccak_round_0() { + std::size_t LookupColumns> +void test_keccak_round_not_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - + //call 1 std::array inner_state = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; value_type RC = to_sparse(value_type(1)); - std::array expected_result = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); -} -template -void test_keccak_round_1() { - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; + //call 2 + inner_state = expected_result; + RC = to_sparse(value_type(0x8082)); + expected_result = {32899, 17592186044416, 32768, 1, 17592186077184, 0, 35184374185984, 0, 35184372088832, 2097152, + 2, 512, 0, 514, 0, 268436480, 0, 1024, 268435456, 0, 1099511627776, 0, 1099511627780, 0, 4}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); - std::array inner_state = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - value_type RC = to_sparse(value_type(0x8082ULL)); - - std::array expected_result = { - 32899, 17592186044416, 32768, 1, 17592186077184, - 0, 35184374185984, 0, 35184372088832, 2097152, - 2, 512, 0, 514, 0, - 268436480, 0, 1024, 268435456, 0, - 1099511627776, 0, 1099511627780, 0, 4}; + //call 3 + inner_state = expected_result; + RC = to_sparse(value_type(0x800000000000808a)); + expected_result = {9236970796698600460, 4092250545529553158, 626057523912327425, 2306538108895626371, 1173341635645358336, + 1293304092434976, 1266393375296193026, 4612686711565066480, 3572814934320349200, 6918386853474468034, + 181437471070544, 17451689225912448, 14123431978033217603, 9612137362626578, 14131171423402623105, + 109225863298950544, 4469910934709993472, 291608492588557700, 4143342752895270928, 722898250671538564, + 9260980282462904729, 14339470011802853602, 37581858268459548, 4683770000893804961, 432358761588732518}; for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); - test_keccak_round_inner + //call 4 + inner_state = expected_result; + RC = to_sparse(value_type(0x8000000080008000)); + expected_result = {592319258926211651, 14940587067404002452, 6163873250186209783, 9133172271835791495, 13983250434949586883, + 10037245043040796116, 14625807227073111006, 9517639169617348992, 10802803781493464979, 1170967630360556906, + 4833658608200494670, 14411270558251773425, 10413092914151648788, 6324505867985343017, 15456637871614865798, + 15961727220218474669, 12219779720573097889, 13453918774002596887, 11249665490274026413, 16763947842887530834, + 9348458261315236693, 11269932799224724130, 5725669273397430228, 16793563075160212879, 7296601056617420707}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); -} -template -void test_keccak_round_7() { - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; + //call 5 + inner_state = expected_result; + RC = to_sparse(value_type(0x808b)); + expected_result = {7638250137956199023, 17990125325728205105, 7906499215270811140, 10861036725959346835, 11195520138696188958, + 8358174899797462070, 8135952663530915624, 1143978644753002443, 15662404937588594201, 16535557756827863490, + 2821756897662528488, 12114361851460063201, 8845673958919045506, 13942698502943567537, 11656387723772272466, + 13322614738909770079, 2086432298574777049, 17543636310180418713, 1178364895537752846, 10832164025006223835, + 2030143342952750111, 12360607886846421348, 10479039689777663018, 16563260862735374768, 7279885679800479721}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); + //call 6 + inner_state = expected_result; + RC = to_sparse(value_type(0x80000001)); + expected_result = {4891766363406797400, 15439122233753343804, 13823342620960621853, 11746433691194652646, 4017314498112237324, + 815207819430446539, 4967747420293129338, 3818588911347179217, 12982395987346120149, 8831006501622048216, + 3273200702990303769, 11925911941096385939, 11818410238024184151, 6855937196075990472, 6813782227838587502, + 5749709705375199086, 198532287281302992, 3986921420170929948, 2084732521627207926, 3955984847012879536, + 17540298648724239738, 14973796877054370773, 9207394463793105740, 13336242423054526618, 2223831538796077986}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); - std::array inner_state = { - 4891766363406797400, 15439122233753343804, 13823342620960621853, 11746433691194652646, 4017314498112237324, - 815207819430446539, 4967747420293129338, 3818588911347179217, 12982395987346120149, 8831006501622048216, - 3273200702990303769, 11925911941096385939, 11818410238024184151, 6855937196075990472, 6813782227838587502, - 5749709705375199086, 198532287281302992, 3986921420170929948, 2084732521627207926, 3955984847012879536, - 17540298648724239738, 14973796877054370773, 9207394463793105740, 13336242423054526618, 2223831538796077986 - }; + // call 12 + inner_state = {8317352591327817587, 3347101423491892088, 13812284588227636790, 6672945709382097013, 14828349229463845968, + 17723229868831098326, 17401130588186959855, 16478565068789518457, 6492452647977334912, 11881899180789479218, + 16234817029224417455, 15219752985751753243, 7353976000907867650, 14188031598247865105, 15212311666827251122, + 11629652489896499652, 9435989968869629838, 3918343313233240239, 7628695717460153542, 12309003921403265649, + 345338872853187944, 12040357248728011954, 3576113714317971609, 6768822272106030756, 5816751084285246094}; for (int i = 0; i < 25; ++i) { inner_state[i] = to_sparse(inner_state[i]); } - std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0; i < 17; ++i) { - padded_message_chunk[i] = to_sparse(padded_message_chunk[i]); - } - value_type RC = to_sparse(value_type(0x8000000080008081ULL)); - - std::array expected_result = { - 898454936699210940, 8026835929569667841, 7594412717710188589, 17691297879001667639, 12039682773981733750, - 4806751406901749727, 11830785691895369039, 6215100860000502273, 3084694277248389144, 16700214332683074198, - 1701067029580549681, 2935021215067160996, 10064659787097191500, 7604822824502759976, 1494105689337672248, - 12626178481354463734, 2395136601172298592, 4068135589652482799, 15567196270789777948, 4732526861918809121, - 2821496240805205513, 5710775155925759758, 9794593245826189275, 17281148776925903127, 7447477925633355381 - }; + RC = to_sparse(value_type(0x8000000a)); + expected_result = {4650443609753860646, 9514407034135748299, 1325603491995511509, 5593257647634540243, 4316689694591141959, + 7056436588513633967, 3922974518795920519, 9361284003398536963, 12348570714043139801, 9410505497913992340, + 3614675582850630850, 6265106893083717952, 15812212848177019826, 5971330993120196744, 10998285978683370913, + 11166777828240479175, 7385351289822635840, 13873470266315090419, 6746683412968993695, 16204117485081817578, + 8627448812002334210, 5809981248579074143, 17919282347891220598, 3921880343594863541, 4864618403575458388}; for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } + test_keccak_round_inner + (inner_state, padded_message_chunk, RC, expected_result); - auto check_expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); - - // BOOST_ASSERT_MSG(check_expected_result == expected_result, "Wrong expected result!") ; - - test_keccak_round_inner + // call 24 + inner_state = {1021834983209491063, 271587765569717919, 4776059245685303294, 6929972956618907976, 15632760037079799599, + 335373011243745427, 4458191160998101431, 1054086133152375554, 2747216341432570284, 16716089959809353091, + 18427037088977732910, 8502882582543089190, 15262916258997799331, 1649067881221390653, 16305756012321036251, + 6396788823285448910, 16280709970257755463, 968684198036765735, 17453107891981340679, 14208300252181521039, + 8344225276973693085, 15466940913106191879, 9691424745450112199, 11326521537916162858, 14617465633943149704}; + for (int i = 0; i < 25; ++i) { + inner_state[i] = to_sparse(inner_state[i]); + } + RC = to_sparse(value_type(0x8000000080008008)); + expected_result = {17376452488221285863, 9571781953733019530, 15391093639620504046, 13624874521033984333, 10027350355371872343, + 18417369716475457492, 10448040663659726788, 10113917136857017974, 12479658147685402012, 3500241080921619556, + 16959053435453822517, 12224711289652453635, 9342009439668884831, 4879704952849025062, 140226327413610143, + 424854978622500449, 7259519967065370866, 7004910057750291985, 13293599522548616907, 10105770293752443592, + 10668034807192757780, 1747952066141424100, 1654286879329379778, 8500057116360352059, 16929593379567477321}; + for (int i = 0; i < 25; ++i) { + expected_result[i] = to_sparse(expected_result[i]); + } + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } template + std::size_t LookupColumns, bool xor_with_mes, bool last_round_call, std::size_t last_prem_col = 7> void test_keccak_round_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -343,60 +353,70 @@ void test_keccak_round_random() { std::array inner_state; std::array padded_message_chunk; - value_type RC = value_type(0); + value_type RC; + integral_type mask = (integral_type(1) << 64) - 1; for (int i = 0; i < 25; ++i) { - auto random_value = integral_type(dis(gen)); + auto random_value = integral_type(dis(gen)) & mask; inner_state[i] = to_sparse(value_type(random_value)); } for (int i = 0; i < 17; ++i) { - auto random_value = integral_type(dis(gen)); + auto random_value = integral_type(dis(gen)) & mask; padded_message_chunk[i] = to_sparse(value_type(random_value)); } - auto random_value = integral_type(dis(gen)); + auto random_value = integral_type(dis(gen)) & mask; RC = to_sparse(value_type(random_value)); - auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); + auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } -template -void test_keccak_round_not_random() { - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; - - std::array inner_state; - std::array padded_message_chunk; - value_type RC = value_type(0); - - for (int i = 0; i < 25; ++i) { - inner_state[i] = to_sparse(i + 1); - } - for (int i = 0; i < 17; ++i) { - padded_message_chunk[i] = 1; - } - RC = to_sparse(0x1000); - - auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) - test_keccak_round_inner - (inner_state, padded_message_chunk, RC, expected_result); +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + test_keccak_round_not_random(); + // xor_with_mes, last_round_call + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); } -BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + test_keccak_round_not_random(); + test_keccak_round_not_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); +} -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_random(); - test_keccak_round_not_random(); - // test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); } -// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { -// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; -// } +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows_to_fail) { + // these test need to fail because with small numbers for lookup rows, + // the chunks for normalization will be smaller, so more cells per operation - + // +-1 row for constraints won't be fullfilled: Assertion `max - min <= 2' failed. + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); +} BOOST_AUTO_TEST_SUITE_END() From 956b66ecc8841cd97b4566ee9d533e1bd7b8d13e Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 12 Oct 2023 00:49:07 +0000 Subject: [PATCH 12/48] added code to main component #183 --- .../hashes/keccak/keccak_component.hpp | 181 ++++++-- .../hashes/keccak/keccak_padding.hpp | 427 ++++++++++++------ test/CMakeLists.txt | 2 + test/hashes/plonk/keccak.cpp | 181 ++++++++ test/hashes/plonk/keccak_padding.cpp | 120 +++-- 5 files changed, 651 insertions(+), 260 deletions(-) create mode 100644 test/hashes/plonk/keccak.cpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 802e57c3d..cf5521c0c 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -27,7 +27,7 @@ #include -#include < +#include #include namespace nil { @@ -47,6 +47,28 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + // TODO check if it is correct + std::size_t calculate_chunk_size(std::size_t lookup_rows) const { + std::size_t chunk_size = 0; + while ((1 << chunk_size) < lookup_rows) { + chunk_size++; + } + return 0;//chunk_size; + } + std::size_t calculate_num_chunks() const { + return 0;//(num_bits + pack_chunk_size - 1) / pack_chunk_size; + } + std::size_t calculate_num_cells() const { + return 0;//(num_bits + pack_chunk_size * WitnessesAmount - 1) / (pack_chunk_size * WitnessesAmount); + } + std::size_t calculate_buff() const { + return 0;//(num_bits + pack_chunk_size * WitnessesAmount - 1) / pack_chunk_size; + } + + std::size_t calculate_num_round_calls(std::size_t num_blocks) const { + return (num_blocks + (17 - num_blocks % 17)) / 17; + } + std::size_t rows() const { return 0; } @@ -56,13 +78,16 @@ namespace nil { using round_component_type = keccak_round, WitnessesAmount>; + round_component_type round_true_true; + std::vector rounds_true_false; + std::vector rounds_false_false; std::vector rounds; - using padding_component_type = keccak_padding, WitnessesAmount>; - padding_component_type padding; + // using padding_component_type = keccak_padding, WitnessesAmount>; + // padding_component_type padding; - using configuration = round_component_type::configuration; + using configuration = typename round_component_type::configuration; std::vector full_configuration; const std::size_t lookup_rows; @@ -70,16 +95,26 @@ namespace nil { const std::size_t num_blocks; const std::size_t num_bits; + const std::size_t limit_permutation_column; + const std::size_t num_round_calls; const std::size_t num_configs; const std::size_t pack_chunk_size; const std::size_t pack_num_chunks; - const std::size_t pack_num_cells; + const std::size_t pack_cells; + const std::size_t pack_buff; const std::size_t rows_amount; constexpr static const std::size_t gates_amount = 1; + const std::size_t round_constant[24] = {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + struct input_type { std::vector message; }; @@ -92,6 +127,17 @@ namespace nil { } }; + std::vector create_rounds() { + std::vector rounds; + rounds.push_back(round_true_true); + rounds.insert(rounds.end(), rounds_false_false.begin(), rounds_false_false.begin() + 23); + for (std::size_t i = 1; i < num_round_calls; ++i) { + rounds.push_back(rounds_true_false[i - 1]); + rounds.insert(rounds.end(), rounds_false_false.begin() + i * 23, rounds_false_false.begin() + (i + 1) * 23); + } + return rounds; + } + integral_type pack(const integral_type& const_input) const { integral_type input = const_input; integral_type sparse_res = 0; @@ -126,11 +172,12 @@ namespace nil { std::size_t last_row = row, last_column = column; + std::pair first_coordinate = {row, column}; std::vector> copy_from; std::vector>> constraints; - if (1 + column > limit) { + if (1 + column > limit_permutation_column) { copy_from.push_back({last_row + 1, 0}); } else { copy_from.push_back({last_row + (last_column / WitnessesAmount), @@ -138,7 +185,7 @@ namespace nil { } std::pair cell_copy_to; - std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + std::size_t final_row = (column + pack_cells - 1) / WitnessesAmount + row; if (final_row == copy_from[0].first) { cell_copy_to = {final_row, copy_from.back().second + 1}; } else { @@ -146,11 +193,11 @@ namespace nil { } std::vector> cells; - if (1 + column > limit) { + if (1 + column > limit_permutation_column) { for (int i = column; i < WitnessesAmount; ++i) { cells.push_back({row, i}); } - std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cells_left = pack_cells - WitnessesAmount + column; std::size_t cur_row = row + 1, cur_column = 1; while (cur_column < cells_left) { @@ -163,7 +210,7 @@ namespace nil { } else { std::size_t cur_row = row, cur_column = column + 1; - while (cur_column - column < num_cells) { + while (cur_column - column < pack_cells) { if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { cur_column++; continue; @@ -173,12 +220,13 @@ namespace nil { } std::size_t cell_index = 0; - std::vector>> lookups(num_chunks, std::vector>()); + std::vector>> + lookups(pack_num_chunks, std::vector>()); constraints.push_back({copy_from[0]}); constraints.push_back({cell_copy_to}); for (std::size_t i = 0; i < 2; ++i) { - for (std::size_t j = 0; j < num_chunks; ++j) { + for (std::size_t j = 0; j < pack_num_chunks; ++j) { constraints[i].push_back(cells[cell_index++]); lookups[j].push_back(constraints[i].back()); } @@ -188,67 +236,73 @@ namespace nil { last_row = cells.back().first + (last_column / WitnessesAmount); last_column %= WitnessesAmount; - - return configuration({last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } std::vector configure_all(const std::size_t num_configs, const std::size_t num_round_calls) { std::vector result; - std::size_t round_rows = round_component_type::rows_amount; - std::size_t padding_rows = padding_component_type::rows_amount; std::size_t row = 0, column = 0; // padding - row += padding_rows; + // row += padding_component.rows_amount; //rounds for (std::size_t index = 0; index < num_round_calls; ++index) { // to sparse representation for (std::size_t i = 0; i < 17; ++i) { result.push_back(configure_pack_unpack(row, column)); - row = result[i].last_row; - column = result[i].last_column; + row = result[i].last_coordinate.row; + column = result[i].last_coordinate.column; } // round if (column > 0) { column = 0; - row += 1 + 24 * round_rows; - } else { - row += 24 * round_rows; + row++; + } + for (std::size_t i = 0; i < 24; ++i) { + row += rounds[index * 24 + i].rows_amount; } } // from sparse representation for (std::size_t i = 0; i < 5; ++i) { result.push_back(configure_pack_unpack(row, column)); - row = result[i].last_row; - column = result[i].last_column; + row = result[i].last_coordinate.row; + column = result[i].last_coordinate.column; } return result; } #define __keccak_init_macro(witness, constant, public_input, \ - lookup_rows_, lookup_columns_, num_blocks_, num_bits_) \ + lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ + pack_chunk_size(calculate_chunk_size(lookup_rows_)), \ + pack_num_chunks(calculate_num_chunks()), \ + pack_cells(calculate_num_cells()), \ + pack_buff(calculate_buff()), \ num_blocks(num_blocks_), \ num_bits(num_bits_), \ - num_round_calls(), \ - rounds(num_round_calls * 24, \ - round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ - padding(padding_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_)), \ + limit_permutation_column(lpc_), \ + num_round_calls(calculate_num_round_calls(num_blocks_)), \ + round_true_true(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_)), \ + rounds_true_false(num_round_calls - 1, \ + round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)), \ + rounds_false_false(num_round_calls * 23, \ + round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)), \ + rounds(create_rounds()), \ num_configs(), \ full_configuration(configure_all(num_configs, num_round_calls)), \ rows_amount(rows()) template keccak(ContainerType witness, std::size_t lookup_rows_, - std::size_t lookup_columns_, std::size_t num_blocks_) : + std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : component_type(witness, {}, {}), - __keccak_init_macro(witness, {}, {}, lookup_rows_, lookup_columns_, num_blocks_) {}; + __keccak_init_macro(witness, {}, {}, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; template witnesses, std::initializer_list constants, - std::initializer_list - public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_) : + std::initializer_list public_inputs, + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : component_type(witnesses, constants, public_inputs), __keccak_init_macro(witnesses, constants, public_inputs, - lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; - {}; + lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; #undef __keccak_init_macro }; @@ -356,9 +409,6 @@ namespace nil { using component_type = keccak_component; using var = typename component_type::var; - - - BOOST_ASSERT(row == start_row_index + component.rows_amount); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -389,17 +439,54 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - std::vector> padded_message = generate_assignments(component.padding, assignment, - {instance_input.message}, row).output; - row += component.padding.rows_amount; - - + // std::vector> padded_message = generate_assignments(component.padding, assignment, + // {instance_input.message}, row).output; + // row += component.padding.rows_amount; + + std::array inner_state; + for (std::size_t i = 0; i < component.num_round_calls; ++i) { + for (std::size_t j = 0; j < 24; ++j) { + auto round_input = typename component_type::round_component_type::input_type(); + round_input.padded_message_chunk;// = instance_input.message; + round_input.inner_state = inner_state; + round_input.round_constant = var(component.C(0), row + i, false, var::column_type::constant); + inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row); + row += component.rounds[i * 24 + j].rows_amount; + } + } BOOST_ASSERT(row == start_row_index + component.rows_amount); return typename component_type::result_type(component, start_row_index); } + template= 9, bool> = true> + void generate_assignments_constant( + const keccak_component + &component, + circuit> + &bp, + assignment> + &assignment, + const typename keccak_component::input_type + &instance_input, + const std::uint32_t start_row_index) { + + using component_type = keccak_round_component; + using integral_type = typename BlueprintFieldType::integral_type; + + std::size_t row = start_row_index; + for (std::size_t i = 0; i < 24; ++i) { + assignment.constant(component.C(0), row + i) = component.round_constant[i]; + } + } + } // namespace components } // namespace blueprint diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 5426d6379..f5b0a24cc 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -22,8 +22,8 @@ // SOFTWARE. //---------------------------------------------------------------------------// -#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP -#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP #include @@ -33,10 +33,10 @@ namespace nil { namespace blueprint { namespace components { template - class keccak_per_chunk; + class keccak_padding; template - class keccak_per_chunk, WitnessesAmount> : public plonk_component { @@ -45,28 +45,24 @@ namespace nil { WitnessesAmount, 1, 0>; using value_type = typename BlueprintFieldType::value_type; - std::size_t rows() const { - return full_configuration.back().last_coordinate.row + 1; - } - public: - + + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; + bool operator== (const coordinates& other) const { + return row == other.row && column == other.column; + } + bool operator< (const coordinates& other) const { + return row < other.row || (row == other.row && column < other.column); + } + }; struct configuration { - struct coordinates { - std::size_t row; - std::size_t column; - - coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - bool operator== (const coordinates& other) const { - return row == other.row && column == other.column; - } - bool operator< (const coordinates& other) const { - return row < other.row || (row == other.row && column < other.column); - } - }; - // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. coordinates first_coordinate; @@ -117,7 +113,6 @@ namespace nil { (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); } }; - struct padding_gate { coordinates relay; std::vector value; @@ -131,21 +126,40 @@ namespace nil { std::vector range_check_, std::vector first_, std::vector second_) : relay(relay_), value(value_), sum(sum_), range_check(range_check_), first(first_), second(second_) {}; - } + + bool operator== (const padding_gate& other) const { + return relay == other.relay && + value == other.value && + sum == other.sum && + range_check == other.range_check && + first == other.first && + second == other.second; + } + }; using var = typename component_type::var; + const std::size_t lookup_rows; + const std::size_t lookup_columns; + + const std::size_t limit_permutation_column = 7; + const std::size_t num_blocks; const std::size_t num_bits; const std::size_t bits_per_block = 64; std::size_t shift; + std::size_t num_padding_zeros; - const std::size_t limit_permutation_column = 7; + padding_gate first_gate_15; + padding_gate last_gate; + bool last_gate_bool; + const std::vector full_configuration; + std::vector gates_rows; + const std::vector gates_configuration; + const std::vector lookup_gates_configuration; const std::size_t rows_amount; - std::vector gates_rows; - padding_gate last_gate; - constexpr static const std::size_t gates_amount; + const std::size_t gates_amount; struct input_type { // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + message[num_blocks - 1] @@ -157,8 +171,20 @@ namespace nil { struct result_type { std::vector padded_message; - result_type(const keccak_per_chunk &component, std::size_t start_row_index) { - + result_type(const keccak_padding &component, std::size_t start_row_index) { + if (component.shift == 0) { + // for (std::size_t i = 0; i < component.num_blocks; ++i) { + // padded_message.push_back(component.) + // } + } else { + for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + auto config = component.full_configuration[i]; + padded_message.push_back(var(component.W(config.copy_from.column), config.copy_from.row + start_row_index, false)); + } + } + for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { + padded_message.push_back(var(component.C(0), start_row_index, false)); + } } }; @@ -166,13 +192,13 @@ namespace nil { return num_blocks * 64 - num_bits; } - template - padding_gate padding() { + padding_gate padding(std::size_t row = 0, std::size_t last_gate = 0) { + if (WitnessesAmount == 9) return padding_9(row, last_gate); + if (WitnessesAmount == 15) return padding_15(row, last_gate); throw std::runtime_error("Unsupported number of witnesses"); return padding_gate(); } - template<9> - padding_gate padding(std::size_t row = 0) { + padding_gate padding_9(std::size_t row = 0, std::size_t last_gate = 0) { padding_gate res; res.relay = {-1 + row, 0}; res.value = {{-1 + row, 1}, {-1 + row, 3}, {0 + row, 0}, {0 + row, 2}, {1 + row, 0}}; @@ -180,10 +206,16 @@ namespace nil { res.first = {{-1 + row, 5}, {-1 + row, 7}, {0 + row, 4}, {0 + row, 6}, {1 + row, 2}}; res.second = {{-1 + row, 6}, {-1 + row, 8}, {0 + row, 5}, {0 + row, 7}, {1 + row, 3}}; res.range_check = {{1 + row, 4}, {1 + row, 5}, {1 + row, 6}, {1 + row, 7}, {1 + row, 8}}; + if (last_gate > 0) { + res.value.resize(last_gate); + res.sum.resize(last_gate); + res.first.resize(last_gate); + res.second.resize(last_gate); + res.range_check.resize(last_gate); + } return res; } - template<15> - padding_gate padding(std::size_t row = 0) { + padding_gate padding_15(std::size_t row = 0, std::size_t last_gate = 0) { padding_gate res; res.relay = {-1 + row, 11}; res.value = {{0 + row,0}, {0 + row,1}, {0 + row,2}, {1 + row,0}, {1 + row,1}, {1 + row,2}}; @@ -191,8 +223,46 @@ namespace nil { res.first = {{0 + row,6}, {0 + row,7}, {0 + row,8}, {1 + row,6}, {1 + row,7}, {1 + row,8}}; res.second = {{0 + row,9}, {0 + row,10}, {0 + row,11}, {1 + row,9}, {1 + row,10}, {1 + row,11}}; res.range_check = {{0 + row,12}, {0 + row,13}, {0 + row,14}, {1 + row,12}, {1 + row,13}, {1 + row,14}}; + if (last_gate > 0) { + res.value.resize(last_gate); + res.sum.resize(last_gate); + res.first.resize(last_gate); + res.second.resize(last_gate); + res.range_check.resize(last_gate); + } + return res; + } + + std::size_t calculate_num_padding_zeros() { + return 17 - num_blocks % 17; + } + padding_gate calculate_first_gate_15(std::size_t row = 0) { + padding_gate res; + res.relay = {0 + row, 0}; + res.value = {{0 + row,1}, {0 + row,2}}; + res.sum = {{0 + row,3}, {0 + row,4}}; + res.first = {{0 + row,5}, {0 + row,6}}; + res.second = {{0 + row,7}, {0 + row,11}}; + res.range_check = {{0 + row,8}, {0 + row,9}}; return res; } + padding_gate calculate_last_gate() { + if (WitnessesAmount == 9) { + return padding(0, num_blocks % 5); + } else if (WitnessesAmount == 15) { + if (num_blocks < 2) { + return first_gate_15; + } + return padding(0, (num_blocks - 2) % 6); + } + } + bool calculate_last_gate_bool() { + if (WitnessesAmount == 9) { + return num_blocks % 5 != 0; + } else if (WitnessesAmount == 15) { + return (last_gate != first_gate_15) && ((num_blocks - 2) % 6 != 0); + } + } std::vector configure_batching() { std::vector result; @@ -200,15 +270,15 @@ namespace nil { std::size_t i = 0; std::size_t row = 1; for (std::size_t j = 0; j < num_blocks; ++j) { - auto pg = padding(row); - congifuration conf; + auto pg = padding(row); + configuration conf; if (i == 0) { conf.last_coordinate = pg.second[0]; conf.copy_to = {pg.relay, pg.value[0]}; conf.constraints = {{pg.value[0], pg.first[0], pg.second[0]}, {pg.sum[0], pg.relay, pg.first[0]}, {pg.range_check[0], pg.relay}}; - conf.lookups = {pg.range_check[0]}; + conf.lookups = {{{pg.range_check[0].row, pg.range_check[0].column}}}; conf.copy_from = pg.sum[0]; result.push_back(conf); continue; @@ -218,7 +288,7 @@ namespace nil { conf.constraints = {{pg.value[i], pg.first[i], pg.second[i]}, {pg.sum[i], pg.second[i-1], pg.first[i]}, {pg.range_check[i], pg.second[i-1]}}; - conf.lookups = {pg.range_check[i]}; + conf.lookups = {{pg.range_check[i]}}; conf.copy_from = pg.sum[i]; result.push_back(conf); i = (i + 1) % 5; @@ -231,99 +301,144 @@ namespace nil { return result; } - configuration configure_padding(std::size_t row, std::size_t column) { - // costraint with 0 - if (column >= limit_permutation_column) { - return configuration({row + 1, 1}, {{row + 1, 0}}, {}, {}, {row + 1, 0}); - } - auto last_column = column + 1; - auto last_row = row + (last_column / WitnessesAmount); - last_column %= WitnessesAmount; - return configuration({last_row, last_column}, {{row, column}}, {}, {}, {row, column}); - } - std::vector configure_all() { std::vector result; - - if (WitnessesAmount % 15 == 0) { - configuration conf0; - conf0.copy_to = {{0, 0}, {0, 1}}; - conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, - {{0, 3}, {0, 0}, {0, 5}}, - {{0, 8}, {0, 0}}}; - conf0.lookups = {{0, 8}}; - conf0.copy_from = {0, 3}; - result.push_back(conf0); - configuration conf1; - conf1.copy_to = {{0, 2}}; - conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, - {{0, 4}, {0, 7}, {0, 6}}, - {{0, 9}, {0, 7}}}; - conf1.lookups = {{0, 9}}; - conf1.copy_from = {0, 4}; - result.push_back(conf1); + if (shift == 0) { + std::size_t row = 0, + column = 0; + for (std::size_t i = 0; i < num_blocks; ++i) { + configuration conf; + conf.copy_to = {{row, column}}; + column += 1; + if (column == limit_permutation_column) { + column = 0; + row += 1; + } + result.push_back(conf); + } + } else { + if (WitnessesAmount % 15 == 0) { + configuration conf0; + conf0.copy_to = {{0, 0}, {0, 1}}; + conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, + {{0, 3}, {0, 0}, {0, 5}}, + {{0, 8}, {0, 0}}}; + conf0.lookups = {{{0, 8}}}; + conf0.copy_from = {0, 3}; + result.push_back(conf0); + configuration conf1; + conf1.copy_to = {{0, 2}}; + conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, + {{0, 4}, {0, 7}, {0, 6}}, + {{0, 9}, {0, 7}}}; + conf1.lookups = {{{0, 9}}}; + conf1.copy_from = {0, 4}; + result.push_back(conf1); + } + + auto batch_configs = configure_batching(); + result.insert(result.end(), batch_configs.begin(), batch_configs.end()); } - auto batch_configs = configure_batching(); - result.insert(result.end(), batch_configs.begin(), batch_configs.end()); + return result; + } - auto row = result.back().last_coordinate.row + 1; - std::size_t column = 0; - std::size_t size = result.size(); + std::vector calculate_gates_rows() { + std::vector res; + std::size_t incr = 3; + std::size_t block_per_gate = 5; + std::size_t first_block = 0; + if (WitnessesAmount == 15) { + res.push_back(0); + incr = 2; + block_per_gate = 6; + first_block = 2; + } + std::size_t cur_row = 1; + for (std::size_t i = first_block; i < num_blocks; i += block_per_gate) { + res.push_back(cur_row); + cur_row += incr; + } + return res; + } - while (size % 17 != 0) { - result.push_back(configure_padding(row, column)); - row = result.back().last_row; - column = result.back().last_column; - size++; + std::size_t gates() { + auto pg = padding(); + if (shift == 0) { + return 0; } - return result; + if (WitnessesAmount == 9) { + if (last_gate == pg) { + return 1; + } + return 2; + } + if (WitnessesAmount == 15) { + if (last_gate == first_gate_15) { + return 1; + } + if (last_gate == pg) { + return 2; + } + return 3; + } + throw std::runtime_error("Unsupported number of witnesses"); + } + std::size_t rows() { + std::size_t res = gates_rows.back() + last_gate.range_check.back().row; + if (shift == 0) { + res = full_configuration.back().copy_to.back().row; + } + return res; } - #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) \ + #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ num_blocks(num_blocks_), \ num_bits(num_bits_), \ + limit_permutation_column(lpc_), \ shift(get_shift()), \ + num_padding_zeros(calculate_num_padding_zeros()), \ + first_gate_15(calculate_first_gate_15()), \ + last_gate(calculate_last_gate()), \ full_configuration(configure_all()), \ - rows_amount(rows()), \ gates_rows(calculate_gates_rows()), \ - last_gate(calculate_last_gate()), \ - gates_amount(gates()) + gates_amount(gates()), \ + rows_amount(rows()) template - keccak_per_chunk(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_, std::size_t num_bits_) : + keccak_padding(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, + std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : component_type(witness, {}, {}), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; + __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; template - keccak_per_chunk(WitnessContainerType witness, ConstantContainerType constant, + keccak_padding(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_ std::size_t num_bits_): + std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_): component_type(witness, constant, public_input), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) {}; + __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; - keccak_per_chunk( + keccak_padding( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_, std::size_t num_bits_) : + std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : component_type(witnesses, constants, public_inputs), - __keccak_per_chunk_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_) + __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; #undef __keccak_padding_init_macro }; template - using keccak_pad_component = + using padding_component = keccak_padding, WitnessesAmount>; @@ -331,7 +446,7 @@ namespace nil { template= 9, bool> = true> void generate_gates( - const keccak_pad_component &component, circuit> &assignment, - const typename keccak_pad_component::input_type &instance_input, const std::size_t first_selector_index) { - using component_type = keccak_pad_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; @@ -366,21 +481,21 @@ namespace nil { // batching if (component.shift > 0) { - for (int i = 0; i < component.num_block; ++i) { + for (int i = 0; i < config.size() - 1; ++i) { auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row - gate_config[gate_index]))); + constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row - gate_config[gate_index]) + constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row - gate_config[gate_index]))); + - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row))); gate_index++; if (i > 0) { - constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row - gate_config[gate_index]) - + var(cur_config.constraints[2][2].column, cur_config.constraints[2][2].row - gate_config[gate_index]) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row - gate_config[gate_index]))); + constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + + var(cur_config.constraints[2][2].column, cur_config.constraints[2][2].row) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); gate_index++; } config_index++; @@ -398,7 +513,7 @@ namespace nil { template= 9, bool> = true> void generate_copy_constraints( - const keccak_pad_component &component, circuit> &assignment, - const typename keccak_pad_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_pad_component; using var = typename component_type::var; std::size_t config_index = 0; - if (component.shift > 0) { - config_index += component.num_blocks + 1; - } - while (congif_index < component.full_configuration.size()) { - bp.add_copy_constraint({component.C(0), var(component.W(config[i].copy_to[0].row), config[i].copy_to[0].column, false)}); + while (config_index < component.full_configuration.size()) { + auto config = component.full_configuration[config_index]; + bp.add_copy_constraint({instance_input.message[config_index], + var(component.W(config.copy_to[0].column), config.copy_to[0].row, false)}); + if (config_index == 1 && component.shift != 0) { + bp.add_copy_constraint({instance_input.message[config_index], + var(component.W(config.copy_to[1].column), config.copy_to[1].row, false)}); + } config_index++; } } template= 9, bool> = true> - typename keccak_pad_component::result_type generate_circuit( - const keccak_pad_component &component, circuit> &assignment, - const typename keccak_pad_component::input_type &instance_input, const std::uint32_t start_row_index) { - auto selector_iterator = assignment.find_selector(component); - std::size_t first_selector_index; - std::size_t row = start_row_index; - - using component_type = keccak_pad_component; using var = typename component_type::var; - - BOOST_ASSERT(row == start_row_index + component.rows_amount); + auto selector_iterator = assignment.find_selector(component); + std::size_t first_selector_index; + if (selector_iterator == assignment.selectors_end()) { + first_selector_index = assignment.allocate_selector(component, component.gates_amount); + generate_gates(component, bp, assignment, instance_input, first_selector_index); + } else { + first_selector_index = selector_iterator->second; + } + + std::size_t gate_row_ind = 0; + if (WitnessesAmount == 15) { + assignment.enable_selector(first_selector_index++, component.gates_rows[gate_row_ind++]); + } + for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - component.last_gate_bool; ++i) { + assignment.enable_selector(first_selector_index, component.gates_rows[gate_row_ind++]); + } + if (component.last_gate_bool) { + assignment.enable_selector(first_selector_index + 1, component.gates_rows[gate_row_ind]); + } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); - generate_assignments_constants(component, bp, assignment, instance_input, start_row_index); + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); return typename component_type::result_type(component, start_row_index); } template= 9, bool> = true> - typename keccak_pad_component::result_type generate_assignments( - const keccak_pad_component &component, assignment> &assignment, - const typename keccak_pad_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t row = start_row_index; - using component_type = keccak_pad_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -490,22 +621,22 @@ namespace nil { // batching if (component.shift != 0) { - integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0])); + integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); for (std::size_t index = 1; index < component.num_blocks; ++index) { value_type chunk = var_value(assignment, instance_input.message[index]); - integral_type integral_chunk = integral_type(chunk); + integral_type integral_chunk = integral_type(chunk.data); integral_type mask = (integral_type(1) << component.shift) - 1; std::array chunk_parts = {integral_chunk >> component.shift, integral_chunk & mask}; integral_type first_chunk = (relay_chunk << (64 - component.shift)) + chunk_parts[0]; - integral_type relay_range_check = relay_chunk - (1 << component.shift) + (1 << 64); + integral_type relay_range_check = relay_chunk - (1 << component.shift) + (integral_type(1) << 64); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = chunk; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row) = chunk; for (int j = 1; j < 3; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].row), cur_config.constraints[0][j].column) = value_type(chunk_parts[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row) = value_type(chunk_parts[j - 1]); } - assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = value_type(relay_range_check); - assignment.witness(component.W(cur_config.constraints[2][0].row), cur_config.constraints[2][0].column) = value_type(first_chunk); + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = value_type(relay_range_check); + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(first_chunk); relay_chunk = chunk_parts[1]; config_index++; @@ -513,19 +644,19 @@ namespace nil { // padding { integral_type last_chunk = relay_chunk << (64 - component.shift); - integral_type relay_range_check = relay_chunk - (1 << component.shift) + (1 << 64); + integral_type relay_range_check = relay_chunk - (1 << component.shift) + (integral_type(1) << 64); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = value_type(relay_chunk); - assignment.witness(component.W(cur_config.constraints[0][0].row), cur_config.constraints[0][0].column) = value_type(last_chunk); - assignment.witness(component.W(cur_config.constraints[1][0].row), cur_config.constraints[1][0].column) = value_type(relay_range_check); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = value_type(relay_chunk); + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row) = value_type(last_chunk); + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = value_type(relay_range_check); config_index++; } } - while (congif_index < component.full_configuration.size()) { + while (config_index < component.full_configuration.size()) { auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].row), cur_config.copy_to[0].column) = 0; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = 0; config_index++; } @@ -535,7 +666,7 @@ namespace nil { template= 9, bool> = true> void generate_assignments_constant( - const keccak_pad_component &component, circuit> &assignment, - const typename keccak_pad_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_pad_component; assignment.constant(component.C(0), start_row_index) = 0; @@ -560,4 +691,4 @@ namespace nil { } // namespace blueprint } // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PER_CHUNK_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bff01142e..063ff2b43 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -96,6 +96,8 @@ set(PLONK_TESTS_FILES "hashes/plonk/sha256_process" "hashes/plonk/sha512_process" "hashes/plonk/keccak_round" + "hashes/plonk/keccak_padding" + "hashes/plonk/keccak" "hashes/plonk/decomposition" "hashes/plonk/detail/sha_table_generators_base4" "hashes/plonk/detail/sha_table_generators_base7" diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp new file mode 100644 index 000000000..310035132 --- /dev/null +++ b/test/hashes/plonk/keccak.cpp @@ -0,0 +1,181 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE plonk_keccak_test + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include "../../test_plonk_component.hpp" + +template +std::size_t number_bits(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + integral_type integral_value = integral_type(value.data); + std::size_t result = 0; + while (integral_value > 0) { + integral_value >>= 1; + ++result; + } + return result; +} + +template +auto test_keccak_inner(std::vector message, + std::vector expected_result) { + constexpr std::size_t PublicInputColumns = 1; + constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t SelectorColumns = 20; + using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + using AssignmentType = nil::blueprint::assignment; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; + constexpr std::size_t Lambda = 1; + + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using component_type = nil::blueprint::components::keccak; + using var = typename component_type::var; + + std::vector public_input; + // std::cout << "message:\n"; + for (int i = 0; i < num_blocks; ++i) { + public_input.push_back(message[i]); + // std::cout << message[i].data << std::endl; + } + + std::vector message_vars; + for (int i = 0; i < num_blocks; ++i) { + message_vars.push_back(var(0, i, false, var::column_type::public_input)); + } + typename component_type::input_type instance_input = {message_vars}; + + auto result_check = [expected_result] + (AssignmentType &assignment, typename component_type::result_type &real_res) { + // std::cout << "sizes: " << expected_result.size() << " " << real_res.padded_message.size() << std::endl; + // assert(expected_result.size() == real_res.padded_message.size()); + for (int i = 0; i < expected_result.size(); ++i) { + // std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.padded_message[i]).data << std::endl; + // assert(expected_result[i] == var_value(assignment, real_res.padded_message[i])); + } + }; + + component_type component_instance = WitnessesAmount == 15 ? + component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, + {1}, LookupRows, LookupColumns, num_blocks, num_bits, 7) + : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {1}, + LookupRows, LookupColumns, num_blocks, num_bits, 7); + + if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { + BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; + } + + nil::crypto3::test_component( + boost::get(component_instance), public_input, result_check, instance_input); +} + +// works +template +void test_keccak_0() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector message = {0}; + const std::size_t num_blocks = 1; + const std::size_t num_bits = 1; + + std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + test_keccak_inner(message, expected_result); +} + +// template +// void test_keccak_padding_random() { +// using value_type = typename BlueprintFieldType::value_type; +// using integral_type = typename BlueprintFieldType::integral_type; + +// std::random_device rd; +// std::mt19937 gen(rd()); +// std::uniform_int_distribution dis; + +// integral_type mask = (integral_type(1) << 64) - 1; +// integral_type mask_zero = (integral_type(1) << 60) - 1; +// std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), +// value_type(integral_type(dis(gen)) & mask), +// value_type(integral_type(dis(gen)) & mask)}; +// std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); +// std::size_t num_blocks = message.size(); + +// for (int i = 0; i < message.size(); ++i) { +// std::cout << "message: " << message[i].data << std::endl; +// } + +// auto expected_result = padding_function(message, num_bits); + +// test_keccak_padding_inner +// (message, expected_result, num_blocks, num_bits); +// } + +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_pallas) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + // test_keccak_round_random(); + test_keccak_0(); + // test_keccak_round_random(); +} + +// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { +// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +// } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 100ab77fe..23c6ea02d 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -49,20 +49,35 @@ #include "../../test_plonk_component.hpp" -template -std::vector padding_function(std::vector message) { +template +std::size_t number_bits(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + integral_type integral_value = integral_type(value.data); + std::size_t result = 0; + while (integral_value > 0) { + integral_value >>= 1; + ++result; + } + return result; +} + +template +std::vector padding_function(std::vector message, + std::size_t num_bits) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; std::vector result; - std::size_t shift = 64 * message.size() - num_bits + std::size_t shift = 64 * message.size() - num_bits; if (shift > 0) { - integral_type relay_value = message[0]; + integral_type relay_value = integral_type(message[0].data); for (int i = 1; i < message.size(); ++i) { integral_type mask = (integral_type(1) << shift) - 1; - integral_type left_part = message[i].data >> shift; - integral_type right_part = message[i].data & mask; + integral_type left_part = integral_type(message[i].data >> shift); + integral_type right_part = integral_type(message[i].data) & mask; result.push_back(value_type((relay_value << (64 - shift)) | left_part)); relay_value = right_part; } @@ -79,12 +94,13 @@ std::vector padding_function(std::vecto } template + std::size_t LookupColumns> auto test_keccak_padding_inner(std::vector message, - std::vector expected_result) { + std::vector expected_result, + const std::size_t num_blocks, const std::size_t num_bits) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 150; + constexpr std::size_t SelectorColumns = 3; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using var = typename component_type::var; - auto mes_size = message.size(); - std::vector public_input; // std::cout << "message:\n"; - for (int i = 0; i < mes_size; ++i) { + for (int i = 0; i < num_blocks; ++i) { public_input.push_back(message[i]); // std::cout << message[i].data << std::endl; } - public_input.push_back(first_bits); - // std::cout << "first_bits: " << first_bits.data << std::endl; std::vector message_vars; - var first_bits_var; - for (int i = 0; i < mes_size; ++i) { - message_vars[i] = var(0, i, false, var::column_type::public_input); + for (int i = 0; i < num_blocks; ++i) { + message_vars.push_back(var(0, i, false, var::column_type::public_input)); } - first_bits_var = var(0, mes_size, false, var::column_type::public_input); - typename component_type::input_type instance_input = {message_vars, first_bits_var}; + typename component_type::input_type instance_input = {message_vars}; auto result_check = [expected_result] (AssignmentType &assignment, typename component_type::result_type &real_res) { + // std::cout << "sizes: " << expected_result.size() << " " << real_res.padded_message.size() << std::endl; + // assert(expected_result.size() == real_res.padded_message.size()); for (int i = 0; i < expected_result.size(); ++i) { - // std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.inner_state[i]).data << std::endl; - // assert(expected_result[i] == var_value(assignment, real_res.inner_state[i])); + // std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.padded_message[i]).data << std::endl; + // assert(expected_result[i] == var_value(assignment, real_res.padded_message[i])); } }; component_type component_instance = WitnessesAmount == 15 ? component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, - {1}, LookupRows, LookupColumns, num_blocks, first_bits) + {1}, LookupRows, LookupColumns, num_blocks, num_bits, 7) : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {1}, - LookupRows, LookupColumns, num_blocks, first_bits); + LookupRows, LookupColumns, num_blocks, num_bits, 7); if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; @@ -142,48 +154,23 @@ auto test_keccak_padding_inner(std::vector -void test_keccak_round_0() { +void test_keccak_padding_0() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::vector message = {0}; - std::size_t first_bits = 0; + const std::size_t num_blocks = 1; + const std::size_t num_bits = 1; std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - test_keccak_round_inner - (message, first_bits, expected_result); + test_keccak_padding_inner + (message, expected_result, num_blocks, num_bits); } -// template -// void test_keccak_round_1() { -// using value_type = typename BlueprintFieldType::value_type; -// using integral_type = typename BlueprintFieldType::integral_type; - -// std::vector message = {0}; -// std::size_t first_bits = 0; - -// std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -// std::array expected_result = { -// 32899, 17592186044416, 32768, 1, 17592186077184, -// 0, 35184374185984, 0, 35184372088832, 2097152, -// 2, 512, 0, 514, 0, -// 268436480, 0, 1024, 268435456, 0, -// 1099511627776, 0, 1099511627780, 0, 4}; -// for (int i = 0; i < 25; ++i) { -// expected_result[i] = to_sparse(expected_result[i]); -// } - -// test_keccak_round_inner -// (inner_state, padded_message_chunk, RC, expected_result); -// } - template -void test_keccak_round_random() { +void test_keccak_padding_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -191,19 +178,22 @@ void test_keccak_round_random() { std::mt19937 gen(rd()); std::uniform_int_distribution dis; - std::size_t num_bits = 62; - integral_type mask = (integral_type(1) << num_bits) - 1; - std::vector message = {value_type(integral_type(dis(gen)) & mask)}; + integral_type mask = (integral_type(1) << 64) - 1; + integral_type mask_zero = (integral_type(1) << 60) - 1; + std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), + value_type(integral_type(dis(gen)) & mask), + value_type(integral_type(dis(gen)) & mask)}; + std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); + std::size_t num_blocks = message.size(); - // for (int i = 0; i < 25; ++i) { - // auto random_value = integral_type(dis(gen)); - // inner_state[i] = to_sparse(value_type(random_value)); - // } + for (int i = 0; i < message.size(); ++i) { + std::cout << "message: " << message[i].data << std::endl; + } - auto expected_result = padding_function(message); + auto expected_result = padding_function(message, num_bits); - test_keccak_round_inner - (message, expected_result); + test_keccak_padding_inner + (message, expected_result, num_blocks, num_bits); } BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) @@ -211,7 +201,7 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_random(); - test_keccak_round_random(); + test_keccak_padding_random(); // test_keccak_round_random(); } From a76bba397b95ac38fb1c7b061f2c5ab9caeebb2a Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 16 Oct 2023 01:02:48 +0000 Subject: [PATCH 13/48] some updates #183 --- .../hashes/keccak/keccak_component.hpp | 27 +- .../hashes/keccak/keccak_padding.hpp | 255 +++++++++--------- test/hashes/plonk/keccak_padding.cpp | 22 +- 3 files changed, 161 insertions(+), 143 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index cf5521c0c..ee33813f0 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -108,22 +108,25 @@ namespace nil { const std::size_t rows_amount; constexpr static const std::size_t gates_amount = 1; - const std::size_t round_constant[24] = {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + const std::size_t round_constant[24] = {1, 0x8082, 0x800000000000808a, 0x8000000080008000, + 0x808b, 0x80000001, 0x8000000080008081, 0x8000000000008009, + 0x8a, 0x88, 0x80008009, 0x8000000a, + 0x8000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, + 0x8000000000008002, 0x8000000000000080, 0x800a, 0x800000008000000a, + 0x8000000080008081, 0x8000000000008080, 0x80000001, 0x8000000080008008}; struct input_type { std::vector message; }; struct result_type { - std::array final_inner_state; + std::array final_inner_state; result_type(const keccak &component, std::size_t start_row_index) { - + for (std::size_t i = 0; i < 5; ++i) { + final_inner_state[i] = var(component.W(component.full_configuration[component.num_configs - 5 + i].copy_from.column), + start_row_index + component.full_configuration[component.num_configs - 5 + i].copy_from.row, false); + } } }; @@ -300,7 +303,7 @@ namespace nil { template keccak(ContainerType witness, std::size_t lookup_rows_, - std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : + std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : component_type(witness, {}, {}), __keccak_init_macro(witness, {}, {}, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; @@ -313,7 +316,7 @@ namespace nil { std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, - std::size_t lpc_) : + std::size_t lpc_ = 7) : component_type(witness, constant, public_input), __keccak_init_macro(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; @@ -321,7 +324,7 @@ namespace nil { std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : + std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs), __keccak_init_macro(witnesses, constants, public_inputs, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; @@ -450,7 +453,7 @@ namespace nil { round_input.padded_message_chunk;// = instance_input.message; round_input.inner_state = inner_state; round_input.round_constant = var(component.C(0), row + i, false, var::column_type::constant); - inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row); + inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row).inner_state; row += component.rounds[i * 24 + j].rows_amount; } } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index f5b0a24cc..2521ed4ec 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -151,8 +151,8 @@ namespace nil { std::size_t num_padding_zeros; padding_gate first_gate_15; - padding_gate last_gate; - bool last_gate_bool; + std::size_t last_gate; + std::size_t confs_per_gate; const std::vector full_configuration; std::vector gates_rows; const std::vector gates_configuration; @@ -172,15 +172,9 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { - if (component.shift == 0) { - // for (std::size_t i = 0; i < component.num_blocks; ++i) { - // padded_message.push_back(component.) - // } - } else { - for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { - auto config = component.full_configuration[i]; - padded_message.push_back(var(component.W(config.copy_from.column), config.copy_from.row + start_row_index, false)); - } + for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + auto config = component.full_configuration[i]; + padded_message.push_back(var(component.W(config.copy_from.column), config.copy_from.row + start_row_index, false)); } for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { padded_message.push_back(var(component.C(0), start_row_index, false)); @@ -192,13 +186,13 @@ namespace nil { return num_blocks * 64 - num_bits; } - padding_gate padding(std::size_t row = 0, std::size_t last_gate = 0) { - if (WitnessesAmount == 9) return padding_9(row, last_gate); - if (WitnessesAmount == 15) return padding_15(row, last_gate); + padding_gate padding(std::size_t row = 0) { + if (WitnessesAmount == 9) return padding_9(row); + if (WitnessesAmount == 15) return padding_15(row); throw std::runtime_error("Unsupported number of witnesses"); return padding_gate(); } - padding_gate padding_9(std::size_t row = 0, std::size_t last_gate = 0) { + padding_gate padding_9(std::size_t row = 0) { padding_gate res; res.relay = {-1 + row, 0}; res.value = {{-1 + row, 1}, {-1 + row, 3}, {0 + row, 0}, {0 + row, 2}, {1 + row, 0}}; @@ -206,16 +200,9 @@ namespace nil { res.first = {{-1 + row, 5}, {-1 + row, 7}, {0 + row, 4}, {0 + row, 6}, {1 + row, 2}}; res.second = {{-1 + row, 6}, {-1 + row, 8}, {0 + row, 5}, {0 + row, 7}, {1 + row, 3}}; res.range_check = {{1 + row, 4}, {1 + row, 5}, {1 + row, 6}, {1 + row, 7}, {1 + row, 8}}; - if (last_gate > 0) { - res.value.resize(last_gate); - res.sum.resize(last_gate); - res.first.resize(last_gate); - res.second.resize(last_gate); - res.range_check.resize(last_gate); - } return res; } - padding_gate padding_15(std::size_t row = 0, std::size_t last_gate = 0) { + padding_gate padding_15(std::size_t row = 0) { padding_gate res; res.relay = {-1 + row, 11}; res.value = {{0 + row,0}, {0 + row,1}, {0 + row,2}, {1 + row,0}, {1 + row,1}, {1 + row,2}}; @@ -223,13 +210,6 @@ namespace nil { res.first = {{0 + row,6}, {0 + row,7}, {0 + row,8}, {1 + row,6}, {1 + row,7}, {1 + row,8}}; res.second = {{0 + row,9}, {0 + row,10}, {0 + row,11}, {1 + row,9}, {1 + row,10}, {1 + row,11}}; res.range_check = {{0 + row,12}, {0 + row,13}, {0 + row,14}, {1 + row,12}, {1 + row,13}, {1 + row,14}}; - if (last_gate > 0) { - res.value.resize(last_gate); - res.sum.resize(last_gate); - res.first.resize(last_gate); - res.second.resize(last_gate); - res.range_check.resize(last_gate); - } return res; } @@ -246,33 +226,35 @@ namespace nil { res.range_check = {{0 + row,8}, {0 + row,9}}; return res; } - padding_gate calculate_last_gate() { + std::size_t calculate_last_gate() { if (WitnessesAmount == 9) { - return padding(0, num_blocks % 5); + return num_blocks % 5; } else if (WitnessesAmount == 15) { - if (num_blocks < 2) { - return first_gate_15; + if (num_blocks <= 2) { + return 7; } - return padding(0, (num_blocks - 2) % 6); + return (num_blocks - 2) % 6; } } - bool calculate_last_gate_bool() { + std::size_t calculate_confs_per_gate() { if (WitnessesAmount == 9) { - return num_blocks % 5 != 0; + return 5; } else if (WitnessesAmount == 15) { - return (last_gate != first_gate_15) && ((num_blocks - 2) % 6 != 0); + return 6; } } std::vector configure_batching() { std::vector result; - std::size_t i = 0; + std::size_t conf_ind = 0; std::size_t row = 1; - for (std::size_t j = 0; j < num_blocks; ++j) { + + while (conf_ind < num_blocks - 2 * (WitnessesAmount == 15)) { auto pg = padding(row); - configuration conf; - if (i == 0) { + std::size_t j = 0; + { + configuration conf; conf.last_coordinate = pg.second[0]; conf.copy_to = {pg.relay, pg.value[0]}; conf.constraints = {{pg.value[0], pg.first[0], pg.second[0]}, @@ -281,21 +263,24 @@ namespace nil { conf.lookups = {{{pg.range_check[0].row, pg.range_check[0].column}}}; conf.copy_from = pg.sum[0]; result.push_back(conf); - continue; + j++; + conf_ind++; } - conf.last_coordinate = pg.second[i]; - conf.copy_to = {pg.value[i]}; - conf.constraints = {{pg.value[i], pg.first[i], pg.second[i]}, - {pg.sum[i], pg.second[i-1], pg.first[i]}, - {pg.range_check[i], pg.second[i-1]}}; - conf.lookups = {{pg.range_check[i]}}; - conf.copy_from = pg.sum[i]; - result.push_back(conf); - i = (i + 1) % 5; - if (i == 0) { - if (WitnessesAmount == 9) row += 3; - if (WitnessesAmount == 15) row += 2; + while ((j < confs_per_gate) && (conf_ind < num_blocks - 2 * (WitnessesAmount == 15))) { + configuration conf; + conf.last_coordinate = pg.second[j]; + conf.copy_to = {pg.value[j]}; + conf.constraints = {{pg.value[j], pg.first[j], pg.second[j]}, + {pg.sum[j], pg.second[j-1], pg.first[j]}, + {pg.range_check[j], pg.second[j-1]}}; + conf.lookups = {{pg.range_check[j]}}; + conf.copy_from = pg.sum[j]; + result.push_back(conf); + j++; + conf_ind++; } + if (WitnessesAmount == 9) row += 3; + if (WitnessesAmount == 15) row += 2; } return result; @@ -308,7 +293,7 @@ namespace nil { column = 0; for (std::size_t i = 0; i < num_blocks; ++i) { configuration conf; - conf.copy_to = {{row, column}}; + conf.copy_from = {row, column}; column += 1; if (column == limit_permutation_column) { column = 0; @@ -363,21 +348,20 @@ namespace nil { } std::size_t gates() { - auto pg = padding(); if (shift == 0) { return 0; } if (WitnessesAmount == 9) { - if (last_gate == pg) { + if (last_gate == 0 || last_gate == full_configuration.size()) { return 1; } return 2; } if (WitnessesAmount == 15) { - if (last_gate == first_gate_15) { + if (last_gate == 7) { return 1; } - if (last_gate == pg) { + if (last_gate == 0 || last_gate == full_configuration.size() - 2) { return 2; } return 3; @@ -385,11 +369,7 @@ namespace nil { throw std::runtime_error("Unsupported number of witnesses"); } std::size_t rows() { - std::size_t res = gates_rows.back() + last_gate.range_check.back().row; - if (shift == 0) { - res = full_configuration.back().copy_to.back().row; - } - return res; + return full_configuration.back().copy_to.back().row; } #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) \ @@ -402,6 +382,7 @@ namespace nil { num_padding_zeros(calculate_num_padding_zeros()), \ first_gate_15(calculate_first_gate_15()), \ last_gate(calculate_last_gate()), \ + confs_per_gate(calculate_confs_per_gate()), \ full_configuration(configure_all()), \ gates_rows(calculate_gates_rows()), \ gates_amount(gates()), \ @@ -468,7 +449,7 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - + auto selector_index = first_selector_index; auto config = component.full_configuration; auto gate_config = component.gates_configuration; // auto lookup_gate_config = component.lookup_gates_configuration; @@ -479,35 +460,72 @@ namespace nil { std::vector constraints; // std::vector lookup_constraints; - // batching if (component.shift > 0) { - for (int i = 0; i < config.size() - 1; ++i) { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - gate_index++; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row))); + std::vector cur_constraints; + if (WitnessesAmount == 15) { + for (std::size_t i = 0; i < 2; ++i) { + auto cur_config = config[config_index]; + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); + config_index++; + } + gate_type gate(selector_index++, cur_constraints); + bp.add_gate(gate); gate_index++; - if (i > 0) { - constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - + var(cur_config.constraints[2][2].column, cur_config.constraints[2][2].row) + cur_constraints.clear(); + } + std::cout << "gate_index: " << gate_index << std::endl; + std::cout << "component.gates_amount: " << component.gates_amount << std::endl; + std::cout << "component.last_gate: " << component.last_gate << std::endl; + if (component.gates_amount - gate_index - (bool)(component.last_gate % 7) > 0) { + for (int i = 0; i < component.confs_per_gate; ++i) { + auto cur_config = config[config_index]; + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); - gate_index++; + config_index++; } - config_index++; + gate_type gate(selector_index++, cur_constraints); + bp.add_gate(gate); + gate_index++; + cur_constraints.clear(); } - - // padding - { - auto cur_config = config[config_index]; - constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row - gate_config[gate_index]) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row - gate_config[gate_index]) * (integral_type(1) << component.shift))); + if (component.last_gate % 7) { + for (int i = 0; i < component.last_gate; ++i) { + auto cur_config = config[config_index]; + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); + cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); + config_index++; + } + gate_type gate(selector_index, cur_constraints); + bp.add_gate(gate); + gate_index++; } } + BOOST_ASSERT(gate_index == component.gates_amount); } template; @@ -622,43 +646,34 @@ namespace nil { // batching if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); - for (std::size_t index = 1; index < component.num_blocks; ++index) { - value_type chunk = var_value(assignment, instance_input.message[index]); + for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { + value_type chunk = 0; + if (index < component.num_blocks) { + chunk = var_value(assignment, instance_input.message[index]); + } integral_type integral_chunk = integral_type(chunk.data); - integral_type mask = (integral_type(1) << component.shift) - 1; - std::array chunk_parts = {integral_chunk >> component.shift, integral_chunk & mask}; - integral_type first_chunk = (relay_chunk << (64 - component.shift)) + chunk_parts[0]; - integral_type relay_range_check = relay_chunk - (1 << component.shift) + (integral_type(1) << 64); + integral_type mask = (integral_type(1) << (64-component.shift)) - 1; + std::array chunk_parts = {integral_chunk >> (64-component.shift), integral_chunk & mask}; + integral_type first_chunk = (relay_chunk << component.shift) + chunk_parts[0]; + integral_type relay_range_check = relay_chunk - (1 << (64-component.shift)) + (integral_type(1) << 64); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row) = chunk; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + strow) = chunk; for (int j = 1; j < 3; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row) = value_type(chunk_parts[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_parts[j - 1]); } - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = value_type(relay_range_check); - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row) = value_type(first_chunk); + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = value_type(first_chunk); + assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(relay_range_check); relay_chunk = chunk_parts[1]; config_index++; } - // padding - { - integral_type last_chunk = relay_chunk << (64 - component.shift); - integral_type relay_range_check = relay_chunk - (1 << component.shift) + (integral_type(1) << 64); - - auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = value_type(relay_chunk); - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row) = value_type(last_chunk); - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row) = value_type(relay_range_check); - config_index++; + } else { + for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { + auto cur_config = component.full_configuration[index]; + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = var_value(assignment, instance_input.message[index]); } } - - while (config_index < component.full_configuration.size()) { - auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row) = 0; - config_index++; - } return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 23c6ea02d..874cb4702 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -71,17 +71,18 @@ std::vector padding_function(std::vecto std::vector result; std::size_t shift = 64 * message.size() - num_bits; + std::cout << "shift: " << shift << ' ' << num_bits << std::endl; if (shift > 0) { integral_type relay_value = integral_type(message[0].data); for (int i = 1; i < message.size(); ++i) { - integral_type mask = (integral_type(1) << shift) - 1; - integral_type left_part = integral_type(message[i].data >> shift); + integral_type mask = (integral_type(1) << (64-shift)) - 1; + integral_type left_part = integral_type(message[i].data >> (64-shift)); integral_type right_part = integral_type(message[i].data) & mask; - result.push_back(value_type((relay_value << (64 - shift)) | left_part)); + result.push_back(value_type((relay_value << shift) + left_part)); relay_value = right_part; } - result.push_back(value_type(relay_value << (64 - shift))); + result.push_back(value_type(relay_value << shift)); } else { for (int i = 0; i < message.size(); ++i) { result.push_back(message[i]); @@ -129,10 +130,10 @@ auto test_keccak_padding_inner(std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), - value_type(integral_type(dis(gen)) & mask), - value_type(integral_type(dis(gen)) & mask)}; + value_type(integral_type(dis(gen)) & mask_zero)}; std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); std::size_t num_blocks = message.size(); @@ -201,8 +201,8 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_random(); - test_keccak_padding_random(); - // test_keccak_round_random(); + // test_keccak_padding_random(); + test_keccak_padding_random(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { From 63fb978b8be04ea853eb891468c90fd6190a54a3 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 18 Oct 2023 09:54:36 +0000 Subject: [PATCH 14/48] minor changes #183 --- .../blueprint/components/hashes/keccak/keccak_padding.hpp | 6 +++--- test/hashes/plonk/keccak_padding.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 2521ed4ec..2576ab66a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -603,13 +603,13 @@ namespace nil { std::size_t gate_row_ind = 0; if (WitnessesAmount == 15) { - assignment.enable_selector(first_selector_index++, component.gates_rows[gate_row_ind++]); + assignment.enable_selector(first_selector_index++, component.gates_rows[gate_row_ind++] + start_row_index); } for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { - assignment.enable_selector(first_selector_index, component.gates_rows[gate_row_ind++]); + assignment.enable_selector(first_selector_index, component.gates_rows[gate_row_ind++] + start_row_index); } if (component.last_gate % 7) { - assignment.enable_selector(first_selector_index + 1, component.gates_rows[gate_row_ind]); + assignment.enable_selector(first_selector_index + 1, component.gates_rows[gate_row_ind] + start_row_index); } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 874cb4702..a62416923 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -130,11 +130,11 @@ auto test_keccak_padding_inner(std::vector Date: Mon, 23 Oct 2023 05:15:49 +0000 Subject: [PATCH 15/48] updates for gate_manifest #183 --- .../hashes/keccak/keccak_component.hpp | 503 +++++++++++------- .../hashes/keccak/keccak_padding.hpp | 369 ++++++------- .../components/hashes/keccak/keccak_round.hpp | 256 +++++---- test/hashes/plonk/keccak.cpp | 18 +- test/hashes/plonk/keccak_padding.cpp | 15 +- 5 files changed, 675 insertions(+), 486 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index ee33813f0..37f36c444 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -27,86 +27,127 @@ #include -#include +#include +#include +#include +#include + +#include +// #include #include namespace nil { namespace blueprint { namespace components { - template + template class keccak; - template + template class keccak, - WitnessesAmount> : - public plonk_component { + ArithmetizationParams>> : + public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - // TODO check if it is correct - std::size_t calculate_chunk_size(std::size_t lookup_rows) const { - std::size_t chunk_size = 0; - while ((1 << chunk_size) < lookup_rows) { - chunk_size++; - } - return 0;//chunk_size; - } - std::size_t calculate_num_chunks() const { - return 0;//(num_bits + pack_chunk_size - 1) / pack_chunk_size; - } - std::size_t calculate_num_cells() const { - return 0;//(num_bits + pack_chunk_size * WitnessesAmount - 1) / (pack_chunk_size * WitnessesAmount); - } - std::size_t calculate_buff() const { - return 0;//(num_bits + pack_chunk_size * WitnessesAmount - 1) / pack_chunk_size; - } - - std::size_t calculate_num_round_calls(std::size_t num_blocks) const { + static std::size_t calculate_num_round_calls(std::size_t num_blocks) { return (num_blocks + (17 - num_blocks % 17)) / 17; } - std::size_t rows() const { - return 0; - } - public: using var = typename component_type::var; - using round_component_type = keccak_round, WitnessesAmount>; - round_component_type round_true_true; - std::vector rounds_true_false; - std::vector rounds_false_false; - std::vector rounds; + // using round_component_type = keccak_round>; + // round_component_type round_true_true; + // std::vector rounds_true_false; + // std::vector rounds_false_false; + // std::vector rounds; + + using padding_component_type = keccak_padding>; + padding_component_type padding; + + using manifest_type = nil::blueprint::plonk_component_manifest; + class gate_manifest_type : public component_gate_manifest { + public: + static const constexpr std::size_t clamp = 15; + std::size_t witness_amount; + std::size_t num_blocks; + std::size_t num_bits; + + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_) + : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_) {} + + std::uint32_t gates_amount() const override { + return get_gates_amount(witness_amount); + } + }; - // using padding_component_type = keccak_padding, WitnessesAmount>; - // padding_component_type padding; + static gate_manifest get_gate_manifest(std::size_t witness_amount, + std::size_t lookup_column_amount, + std::size_t num_blocks, + std::size_t num_bits) { + std::size_t num_round_calls = calculate_num_round_calls(num_blocks); + gate_manifest manifest = + gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits)) + .merge_with( + padding_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + num_blocks, num_bits)); + // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + // true, true)); + // for (std::size_t i = 1; i < num_round_calls; ++i) { + // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + // true, false)); + // } + // for (std::size_t i = 0; i < num_round_calls; ++i) { + // for (std::size_t j = 0; j < 23; ++j) { + // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + // false, false)); + // } + // } + + return manifest; + } + + static manifest_type get_manifest() { + static manifest_type manifest = manifest_type( + std::shared_ptr( + new manifest_range_param(9, 15)), + false + ).merge_with(padding_component_type::get_manifest()); + return manifest; + } - using configuration = typename round_component_type::configuration; - std::vector full_configuration; + using configuration = typename padding_component_type::configuration; const std::size_t lookup_rows; const std::size_t lookup_columns; const std::size_t num_blocks; const std::size_t num_bits; - const std::size_t limit_permutation_column; - - const std::size_t num_round_calls; - const std::size_t num_configs; - - const std::size_t pack_chunk_size; - const std::size_t pack_num_chunks; - const std::size_t pack_cells; - const std::size_t pack_buff; + const std::size_t limit_permutation_column = 7; + + const std::size_t round_tt_rows = 0; + const std::size_t round_tf_rows = 0; + const std::size_t round_ff_rows = 0; + const std::size_t round_tt_gates = 0; + const std::size_t round_tf_gates = 0; + const std::size_t round_ff_gates = 0; + + const std::size_t num_round_calls = calculate_num_round_calls(num_blocks); + const std::size_t num_configs = 5 + num_blocks + (17 - num_blocks % 17); + + const std::size_t pack_chunk_size = 8; + const std::size_t pack_num_chunks = 8; + const std::size_t pack_cells = 2 * (pack_num_chunks + 1); + const std::size_t pack_buff = (this->witness_amount() == 15) * 2; + + std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls); - const std::size_t rows_amount; - constexpr static const std::size_t gates_amount = 1; + const std::size_t rows_amount = get_rows_amount(num_round_calls); + const std::size_t gates_amount = get_gates_amount(this->witness_amount()); const std::size_t round_constant[24] = {1, 0x8082, 0x800000000000808a, 0x8000000080008000, 0x808b, 0x80000001, 0x8000000080008081, 0x8000000000008009, @@ -117,6 +158,10 @@ namespace nil { struct input_type { std::vector message; + + std::vector all_vars() const { + return message; + } }; struct result_type { @@ -128,18 +173,21 @@ namespace nil { start_row_index + component.full_configuration[component.num_configs - 5 + i].copy_from.row, false); } } + std::vector all_vars() const { + return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], final_inner_state[4]}; + } }; - std::vector create_rounds() { - std::vector rounds; - rounds.push_back(round_true_true); - rounds.insert(rounds.end(), rounds_false_false.begin(), rounds_false_false.begin() + 23); - for (std::size_t i = 1; i < num_round_calls; ++i) { - rounds.push_back(rounds_true_false[i - 1]); - rounds.insert(rounds.end(), rounds_false_false.begin() + i * 23, rounds_false_false.begin() + (i + 1) * 23); - } - return rounds; - } + // std::vector create_rounds() { + // std::vector rounds; + // rounds.push_back(round_true_true); + // rounds.insert(rounds.end(), rounds_false_false.begin(), rounds_false_false.begin() + 23); + // for (std::size_t i = 1; i < num_round_calls; ++i) { + // rounds.push_back(rounds_true_false[i - 1]); + // rounds.insert(rounds.end(), rounds_false_false.begin() + i * 23, rounds_false_false.begin() + (i + 1) * 23); + // } + // return rounds; + // } integral_type pack(const integral_type& const_input) const { integral_type input = const_input; @@ -168,7 +216,7 @@ namespace nil { return res; } - configuration configure_pack_unpack(std::size_t row, std::size_t column) { + configuration configure_pack_unpack(std::size_t witness_amount, std::size_t row, std::size_t column) { // regular constraints: // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) @@ -183,12 +231,12 @@ namespace nil { if (1 + column > limit_permutation_column) { copy_from.push_back({last_row + 1, 0}); } else { - copy_from.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); + copy_from.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); } std::pair cell_copy_to; - std::size_t final_row = (column + pack_cells - 1) / WitnessesAmount + row; + std::size_t final_row = (column + pack_cells - 1) / witness_amount + row; if (final_row == copy_from[0].first) { cell_copy_to = {final_row, copy_from.back().second + 1}; } else { @@ -197,28 +245,28 @@ namespace nil { std::vector> cells; if (1 + column > limit_permutation_column) { - for (int i = column; i < WitnessesAmount; ++i) { + for (int i = column; i < witness_amount; ++i) { cells.push_back({row, i}); } - std::size_t cells_left = pack_cells - WitnessesAmount + column; + std::size_t cells_left = pack_cells - witness_amount + column; std::size_t cur_row = row + 1, cur_column = 1; while (cur_column < cells_left) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + if (cur_column % witness_amount == cell_copy_to.second && (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { cur_column++; continue; } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { std::size_t cur_row = row, cur_column = column + 1; while (cur_column - column < pack_cells) { - if (cur_column % WitnessesAmount == cell_copy_to.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_to.first)) { + if (cur_column % witness_amount == cell_copy_to.second && (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { cur_column++; continue; } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } std::size_t cell_index = 0; @@ -236,13 +284,13 @@ namespace nil { } last_column = cells.back().second + 1; - last_row = cells.back().first + (last_column / WitnessesAmount); - last_column %= WitnessesAmount; + last_row = cells.back().first + (last_column / witness_amount); + last_column %= witness_amount; return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } - std::vector configure_all(const std::size_t num_configs, + std::vector configure_all(std::size_t witness_amount, const std::size_t num_configs, const std::size_t num_round_calls) { std::vector result; @@ -255,7 +303,7 @@ namespace nil { for (std::size_t index = 0; index < num_round_calls; ++index) { // to sparse representation for (std::size_t i = 0; i < 17; ++i) { - result.push_back(configure_pack_unpack(row, column)); + result.push_back(configure_pack_unpack(witness_amount, row, column)); row = result[i].last_coordinate.row; column = result[i].last_coordinate.column; } @@ -264,14 +312,14 @@ namespace nil { column = 0; row++; } - for (std::size_t i = 0; i < 24; ++i) { - row += rounds[index * 24 + i].rows_amount; - } + // for (std::size_t i = 0; i < 24; ++i) { + // row += rounds[index * 24 + i].rows_amount; + // } } // from sparse representation for (std::size_t i = 0; i < 5; ++i) { - result.push_back(configure_pack_unpack(row, column)); + result.push_back(configure_pack_unpack(witness_amount, row, column)); row = result[i].last_coordinate.row; column = result[i].last_coordinate.column; } @@ -279,34 +327,21 @@ namespace nil { return result; } - #define __keccak_init_macro(witness, constant, public_input, \ - lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) \ - lookup_rows(lookup_rows_), \ - lookup_columns(lookup_columns_), \ - pack_chunk_size(calculate_chunk_size(lookup_rows_)), \ - pack_num_chunks(calculate_num_chunks()), \ - pack_cells(calculate_num_cells()), \ - pack_buff(calculate_buff()), \ - num_blocks(num_blocks_), \ - num_bits(num_bits_), \ - limit_permutation_column(lpc_), \ - num_round_calls(calculate_num_round_calls(num_blocks_)), \ - round_true_true(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_)), \ - rounds_true_false(num_round_calls - 1, \ - round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)), \ - rounds_false_false(num_round_calls * 23, \ - round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)), \ - rounds(create_rounds()), \ - num_configs(), \ - full_configuration(configure_all(num_configs, num_round_calls)), \ - rows_amount(rows()) - - template - keccak(ContainerType witness, std::size_t lookup_rows_, - std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : - component_type(witness, {}, {}), - __keccak_init_macro(witness, {}, {}, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; - + std::size_t get_rows_amount(std::size_t num_round_calls) { + std::size_t res = padding_component_type::get_rows_amount() + + round_tt_rows + + round_tf_rows * (num_round_calls - 1) + + round_ff_rows * num_round_calls * 23; + res += full_configuration.back().last_coordinate.row; + return res; + } + static std::size_t get_gates_amount(std::size_t witness_amount) { + std::size_t res = 0; + if (witness_amount == 9) res = 1; + if (witness_amount == 15) res = 3; + res += padding_component_type::gates_amount; + return res; + } template @@ -317,8 +352,31 @@ namespace nil { std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : - component_type(witness, constant, public_input), - __keccak_init_macro(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; + component_type(witness, constant, public_input, get_manifest()), + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + num_blocks(num_blocks_), + num_bits(num_bits_), + limit_permutation_column(lpc_), + padding(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_), + num_round_calls(calculate_num_round_calls(num_blocks_)) {}; + // { + // round_true_true = round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_), + // for (std::size_t i = 1; i < num_round_calls; ++i) { + // rounds_true_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)); + // } + // for (std::size_t i = 0; i < num_round_calls; ++i) { + // for (std::size_t j = 0; j < 23; ++j) { + // rounds_false_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)); + // } + // } + // round_tt_rows = round_true_true.rows_amount; + // round_tf_rows = rounds_true_false[0].rows_amount; + // round_ff_rows = rounds_false_false[0].rows_amount; + // round_tt_gates = round_true_true.gates_amount; + // round_tf_gates = rounds_true_false[0].gates_amount; + // round_ff_gates = rounds_false_false[0].gates_amount; + // }; keccak( std::initializer_list witnesses, @@ -326,23 +384,71 @@ namespace nil { std::initializer_list public_inputs, std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs), - __keccak_init_macro(witnesses, constants, public_inputs, - lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; - - #undef __keccak_init_macro + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + num_blocks(num_blocks_), + num_bits(num_bits_), + limit_permutation_column(lpc_), + padding(witnesses, constants, public_inputs, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_), + num_round_calls(calculate_num_round_calls(num_blocks_)) {}; + // round_true_true(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_), + // { + // for (std::size_t i = 1; i < num_round_calls; ++i) { + // rounds_true_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)); + // } + // for (std::size_t i = 0; i < num_round_calls; ++i) { + // for (std::size_t j = 0; j < 23; ++j) { + // rounds_false_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)); + // } + // } + // }; + + + using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; + + class sparse_values_base8_table: public lookup_table_definition{ + public: + sparse_values_base8_table(): lookup_table_definition("keccak_sparse_base8"){ + this->subtables["full"] = {{0,1}, 0, 255}; + this->subtables["first_column"] = {{0}, 0, 255}; + this->subtables["second_column"] = {{1}, 0, 255}; + }; + virtual void generate(){ + this->_table.resize(2); + std::vector value_sizes = {8}; + + // lookup table for sparse values with base = 8 + std::cout << "keccak_sparse_base8" << std::endl; + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(256); + i++ + ) { + std::vector value(8); + for (std::size_t j = 0; j < 8; j++) { + value[8 - j - 1] = crypto3::multiprecision::bit_test(i, j); + } + std::array, 2> value_chunks = + detail::split_and_sparse(value, value_sizes, 8); + std::cout << value_chunks[0][0] << " " << value_chunks[1][0] << std::endl; + this->_table[0].push_back(value_chunks[0][0]); + this->_table[1].push_back(value_chunks[1][0]); + } + std::cout << "=============================" << std::endl; + } + + virtual std::size_t get_columns_number(){return 2;} + virtual std::size_t get_rows_number(){return 256;} + }; }; - template + template using keccak_component = keccak, - WitnessesAmount>; - - template= 9, bool> = true> - void generate_gates( - const keccak_component + ArithmetizationParams>>; + + template + std::vector generate_gates( + const keccak_component &component, circuit> @@ -350,24 +456,21 @@ namespace nil { assignment> &assignment, - const typename keccak_component::input_type - &instance_input, - const std::size_t first_selector_index) { + const typename keccak_component::input_type + &instance_input) { - using component_type = keccak_component; + using component_type = keccak_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; + + } - template= 9, bool> = true> + template void generate_copy_constraints( - const keccak_component + const keccak_component &component, circuit> @@ -375,24 +478,21 @@ namespace nil { assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_component; + using component_type = keccak_component; using var = typename component_type::var; std::uint32_t row = start_row_index; + + } - template= 9, bool> = true> - typename keccak_component::result_type + template + typename keccak_component::result_type generate_circuit( - const keccak_component + const keccak_component &component, circuit> @@ -400,17 +500,15 @@ namespace nil { assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - auto selector_iterator = assignment.find_selector(component); + auto selector_index = generate_gates(component, bp, assignment, instance_input); std::size_t first_selector_index; std::size_t row = start_row_index; - using component_type = keccak_component; + using component_type = keccak_component; using var = typename component_type::var; generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -418,56 +516,107 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template= 9, bool> = true> - typename keccak_component::result_type + template + typename keccak_component::result_type generate_assignments( - const keccak_component + const keccak_component &component, assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t row = start_row_index; - using component_type = keccak_component; + using component_type = keccak_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - // std::vector> padded_message = generate_assignments(component.padding, assignment, - // {instance_input.message}, row).output; - // row += component.padding.rows_amount; + std::vector padded_message = generate_assignments(component.padding, assignment, + {instance_input.message}, row).padded_message; + row += component.padding.rows_amount; + + // to sparse + std::size_t config_index = 0; + std::vector sparse_padded_message; + for (std::size_t index = 0; index < padded_message.size(); ++index) { + value_type regular_value = var_value(assignment, padded_message[index]); + integral_type regular = integral_type(regular_value.data); + integral_type sparse = component.pack(regular); + auto chunk_size = component.pack_chunk_size; + auto num_chunks = component.pack_num_chunks; + std::vector integral_chunks; + std::vector integral_sparse_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_chunks.push_back(regular & mask); + regular >>= chunk_size; + integral_sparse_chunks.push_back(component.pack(integral_chunks.back())); + } + sparse_padded_message[index] = value_type(sparse); + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + row) = regular_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + row) = value_type(sparse); + for (int j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + row) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + row) = value_type(integral_sparse_chunks[j - 1]); + } + } + config_index += padded_message.size(); + row += component.full_configuration[config_index - 1].last_coordinate.row; std::array inner_state; - for (std::size_t i = 0; i < component.num_round_calls; ++i) { - for (std::size_t j = 0; j < 24; ++j) { - auto round_input = typename component_type::round_component_type::input_type(); - round_input.padded_message_chunk;// = instance_input.message; - round_input.inner_state = inner_state; - round_input.round_constant = var(component.C(0), row + i, false, var::column_type::constant); - inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row).inner_state; - row += component.rounds[i * 24 + j].rows_amount; + // for (std::size_t i = 0; i < component.num_round_calls; ++i) { + // for (std::size_t j = 0; j < 24; ++j) { + // auto round_input = typename component_type::round_component_type::input_type(); + // round_input.padded_message_chunk;// = instance_input.message; + // round_input.inner_state = inner_state; + // round_input.round_constant = var(component.C(0), row + i, false, var::column_type::constant); + // inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row).inner_state; + // row += component.rounds[i * 24 + j].rows_amount; + // } + // } + + // from sparse + std::array result_message; + for (std::size_t index = 0; index < 5; ++index) { + value_type sparse_value = var_value(assignment, inner_state[index]); + integral_type sparse = integral_type(sparse_value.data); + integral_type regular = component.unpack(sparse); + auto chunk_size = component.pack_chunk_size; + auto num_chunks = component.pack_num_chunks; + std::vector integral_sparse_chunks; + std::vector integral_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_chunks.push_back(sparse & mask); + sparse >>= chunk_size; + integral_sparse_chunks.push_back(component.unpack(integral_chunks.back())); + } + sparse_padded_message[index] = value_type(regular); + + auto cur_config = component.full_configuration[index + config_index]; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + start_row_index) = sparse_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + start_row_index) = value_type(regular); + for (int j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + start_row_index) = value_type(integral_sparse_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + start_row_index) = value_type(integral_chunks[j - 1]); } } + row += component.full_configuration[config_index + 5].last_coordinate.row - component.full_configuration[config_index - 1].last_coordinate.row; BOOST_ASSERT(row == start_row_index + component.rows_amount); return typename component_type::result_type(component, start_row_index); } - template= 9, bool> = true> + template void generate_assignments_constant( - const keccak_component + const keccak_component &component, circuit> @@ -475,13 +624,11 @@ namespace nil { assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_component; using integral_type = typename BlueprintFieldType::integral_type; std::size_t row = start_row_index; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 2576ab66a..795f6cec3 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -27,22 +27,25 @@ #include -#include +#include + +#include +#include +#include +#include namespace nil { namespace blueprint { namespace components { - template + template class keccak_padding; - template + template class keccak_padding, - WitnessesAmount> : - public plonk_component { + ArithmetizationParams>> : + public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; public: @@ -138,6 +141,43 @@ namespace nil { }; using var = typename component_type::var; + using manifest_type = nil::blueprint::plonk_component_manifest; + + class gate_manifest_type : public component_gate_manifest { + public: + std::size_t witness_amount; + std::size_t num_blocks; + std::size_t shift; + std::size_t last_gate; + static const std::size_t clamp = 15; + + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t shift_, std::size_t last_gate_) + : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), shift(shift_), last_gate(last_gate_) {}; + + std::uint32_t gates_amount() const override { + return keccak_padding::get_gates_amount(witness_amount, num_blocks, shift, last_gate) + num_blocks; + } + }; + + static gate_manifest get_gate_manifest(std::size_t witness_amount, + std::size_t lookup_column_amount, + std::size_t num_blocks, + std::size_t num_bits) { + auto shift = num_blocks * 64 - num_bits; + auto last_gate = calculate_last_gate(witness_amount, num_blocks); + gate_manifest manifest = gate_manifest(gate_manifest_type(witness_amount, num_blocks, + shift, last_gate)); + return manifest; + } + + static manifest_type get_manifest() { + static manifest_type manifest = manifest_type( + std::shared_ptr( + new nil::blueprint::manifest_single_value_param(9)), + true + ); + return manifest; + } const std::size_t lookup_rows; const std::size_t lookup_columns; @@ -146,26 +186,29 @@ namespace nil { const std::size_t num_blocks; const std::size_t num_bits; - const std::size_t bits_per_block = 64; - std::size_t shift; - std::size_t num_padding_zeros; + std::size_t shift = get_shift(); + std::size_t num_padding_zeros = calculate_num_padding_zeros(); - padding_gate first_gate_15; - std::size_t last_gate; - std::size_t confs_per_gate; - const std::vector full_configuration; - std::vector gates_rows; - const std::vector gates_configuration; - const std::vector lookup_gates_configuration; + padding_gate first_gate_15 = calculate_first_gate_15(); + std::size_t last_gate = calculate_last_gate(this->witness_amount(), num_blocks); + std::size_t confs_per_gate = calculate_confs_per_gate(this->witness_amount()); + const std::vector full_configuration = configure_all(this->witness_amount()); + std::vector gates_rows = calculate_gates_rows(this->witness_amount()); + // const std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount()); - const std::size_t rows_amount; - const std::size_t gates_amount; + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), full_configuration.back().copy_to.back().row); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), shift, last_gate, full_configuration.size()); + const std::size_t lookup_gates_amount = num_blocks; struct input_type { // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + message[num_blocks - 1] // all message[i] are 64-bit for i > 0 // message[0] is <= 64-bit std::vector message; + + std::vector all_vars() const { + return message; + } }; struct result_type { @@ -180,15 +223,19 @@ namespace nil { padded_message.push_back(var(component.C(0), start_row_index, false)); } } + + std::vector all_vars() const { + return padded_message; + } }; std::size_t get_shift() { return num_blocks * 64 - num_bits; } - padding_gate padding(std::size_t row = 0) { - if (WitnessesAmount == 9) return padding_9(row); - if (WitnessesAmount == 15) return padding_15(row); + padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { + if (witness_amount == 9) return padding_9(row); + if (witness_amount == 15) return padding_15(row); throw std::runtime_error("Unsupported number of witnesses"); return padding_gate(); } @@ -226,31 +273,31 @@ namespace nil { res.range_check = {{0 + row,8}, {0 + row,9}}; return res; } - std::size_t calculate_last_gate() { - if (WitnessesAmount == 9) { + static std::size_t calculate_last_gate(std::size_t witness_amount, std::size_t num_blocks) { + if (witness_amount == 9) { return num_blocks % 5; - } else if (WitnessesAmount == 15) { + } else if (witness_amount == 15) { if (num_blocks <= 2) { return 7; } return (num_blocks - 2) % 6; } } - std::size_t calculate_confs_per_gate() { - if (WitnessesAmount == 9) { + std::size_t calculate_confs_per_gate(std::size_t witness_amount) { + if (witness_amount == 9) { return 5; - } else if (WitnessesAmount == 15) { + } else if (witness_amount == 15) { return 6; } } - std::vector configure_batching() { + std::vector configure_batching(std::size_t witness_amount) { std::vector result; std::size_t conf_ind = 0; std::size_t row = 1; - while (conf_ind < num_blocks - 2 * (WitnessesAmount == 15)) { + while (conf_ind < num_blocks - 2 * (witness_amount == 15)) { auto pg = padding(row); std::size_t j = 0; { @@ -266,7 +313,7 @@ namespace nil { j++; conf_ind++; } - while ((j < confs_per_gate) && (conf_ind < num_blocks - 2 * (WitnessesAmount == 15))) { + while ((j < confs_per_gate) && (conf_ind < num_blocks - 2 * (witness_amount == 15))) { configuration conf; conf.last_coordinate = pg.second[j]; conf.copy_to = {pg.value[j]}; @@ -279,14 +326,14 @@ namespace nil { j++; conf_ind++; } - if (WitnessesAmount == 9) row += 3; - if (WitnessesAmount == 15) row += 2; + if (witness_amount == 9) row += 3; + if (witness_amount == 15) row += 2; } return result; } - std::vector configure_all() { + std::vector configure_all(std::size_t witness_amount) { std::vector result; if (shift == 0) { std::size_t row = 0, @@ -302,7 +349,7 @@ namespace nil { result.push_back(conf); } } else { - if (WitnessesAmount % 15 == 0) { + if (witness_amount % 15 == 0) { configuration conf0; conf0.copy_to = {{0, 0}, {0, 1}}; conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, @@ -321,19 +368,19 @@ namespace nil { result.push_back(conf1); } - auto batch_configs = configure_batching(); + auto batch_configs = configure_batching(witness_amount); result.insert(result.end(), batch_configs.begin(), batch_configs.end()); } return result; } - std::vector calculate_gates_rows() { + std::vector calculate_gates_rows(std::size_t witness_amount) { std::vector res; std::size_t incr = 3; std::size_t block_per_gate = 5; std::size_t first_block = 0; - if (WitnessesAmount == 15) { + if (witness_amount == 15) { res.push_back(0); incr = 2; block_per_gate = 6; @@ -347,62 +394,46 @@ namespace nil { return res; } - std::size_t gates() { + static std::size_t get_gates_amount(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t shift, + std::size_t last_gate) { if (shift == 0) { return 0; } - if (WitnessesAmount == 9) { - if (last_gate == 0 || last_gate == full_configuration.size()) { + if (witness_amount == 9) { + if (last_gate == 0 || last_gate == num_blocks - 1) { return 1; } return 2; } - if (WitnessesAmount == 15) { + if (witness_amount == 15) { if (last_gate == 7) { return 1; } - if (last_gate == 0 || last_gate == full_configuration.size() - 2) { + if (last_gate == 0 || last_gate == num_blocks - 3) { return 2; } return 3; } throw std::runtime_error("Unsupported number of witnesses"); } - std::size_t rows() { - return full_configuration.back().copy_to.back().row; + static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t rows_amount) { + return rows_amount; } - #define __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) \ - lookup_rows(lookup_rows_), \ - lookup_columns(lookup_columns_), \ - num_blocks(num_blocks_), \ - num_bits(num_bits_), \ - limit_permutation_column(lpc_), \ - shift(get_shift()), \ - num_padding_zeros(calculate_num_padding_zeros()), \ - first_gate_15(calculate_first_gate_15()), \ - last_gate(calculate_last_gate()), \ - confs_per_gate(calculate_confs_per_gate()), \ - full_configuration(configure_all()), \ - gates_rows(calculate_gates_rows()), \ - gates_amount(gates()), \ - rows_amount(rows()) - - template - keccak_padding(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : - component_type(witness, {}, {}), - __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; - - template keccak_padding(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_): - component_type(witness, constant, public_input), - __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) {}; + std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7): + component_type(witness, constant, public_input, get_manifest()), + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + num_blocks(num_blocks_), + num_bits(num_bits_), + limit_permutation_column(lpc_) {}; keccak_padding( std::initializer_list witnesses, @@ -410,25 +441,27 @@ namespace nil { std::initializer_list public_inputs, std::size_t lookup_rows_, std::size_t lookup_columns_, - std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_) : - component_type(witnesses, constants, public_inputs), - __keccak_padding_init_macro(lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_) - {}; + std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : + component_type(witnesses, constants, public_inputs, get_manifest()), + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + num_blocks(num_blocks_), + num_bits(num_bits_), + limit_permutation_column(lpc_) {}; + + + using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; - #undef __keccak_padding_init_macro }; - template + template using padding_component = keccak_padding, - WitnessesAmount>; - - template= 9, bool> = true> - void generate_gates( - const padding_component + ArithmetizationParams>>; + + template + std::vector generate_gates( + const padding_component &component, circuit> @@ -436,22 +469,18 @@ namespace nil { assignment> &assignment, - const typename padding_component::input_type - &instance_input, - const std::size_t first_selector_index) { + const typename padding_component::input_type + &instance_input) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - auto selector_index = first_selector_index; + std::vector selector_indexes; auto config = component.full_configuration; - auto gate_config = component.gates_configuration; // auto lookup_gate_config = component.lookup_gates_configuration; std::size_t config_index = 0; std::size_t gate_index = 0; @@ -462,23 +491,22 @@ namespace nil { if (component.shift > 0) { std::vector cur_constraints; - if (WitnessesAmount == 15) { + if (component.witness_amount() == 15) { for (std::size_t i = 0; i < 2; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); + cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; } - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); } @@ -488,51 +516,49 @@ namespace nil { if (component.gates_amount - gate_index - (bool)(component.last_gate % 7) > 0) { for (int i = 0; i < component.confs_per_gate; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); + cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; } - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); } if (component.last_gate % 7) { for (int i = 0; i < component.last_gate; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row))); - cur_constraints.push_back(bp.add_constraint(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row))); + cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) + - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) + - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) + - (integral_type(1) << (64 - component.shift)) + + (integral_type(1) << 64) + - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; } - gate_type gate(selector_index, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; } } BOOST_ASSERT(gate_index == component.gates_amount); + + return selector_indexes; } - template= 9, bool> = true> + template void generate_copy_constraints( - const padding_component + const padding_component &component, circuit> @@ -540,24 +566,23 @@ namespace nil { assignment> &assignment, - const typename padding_component::input_type + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; std::size_t config_index = 0; + std::size_t input_index = 0; std::size_t strow = start_row_index; while (config_index < component.full_configuration.size() - (component.shift != 0)) { auto config = component.full_configuration[config_index]; - bp.add_copy_constraint({instance_input.message[config_index], + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); - if (config_index == 1 && component.shift != 0) { - bp.add_copy_constraint({instance_input.message[config_index], + if (config_index == 0 && component.shift != 0) { + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, false)}); } config_index++; @@ -569,13 +594,10 @@ namespace nil { } } - template= 9, bool> = true> - typename padding_component::result_type + template + typename padding_component::result_type generate_circuit( - const padding_component + const padding_component &component, circuit> @@ -583,33 +605,25 @@ namespace nil { assignment> &assignment, - const typename padding_component::input_type + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; - auto selector_iterator = assignment.find_selector(component); - std::size_t first_selector_index; - if (selector_iterator == assignment.selectors_end()) { - first_selector_index = assignment.allocate_selector(component, component.gates_amount); - generate_gates(component, bp, assignment, instance_input, first_selector_index); - } else { - first_selector_index = selector_iterator->second; - } + auto selector_indexes = generate_gates(component, bp, assignment, instance_input); + std::size_t ind = 0; std::size_t gate_row_ind = 0; - if (WitnessesAmount == 15) { - assignment.enable_selector(first_selector_index++, component.gates_rows[gate_row_ind++] + start_row_index); + if (component.witness_amount() == 15) { + assignment.enable_selector(selector_indexes[ind++], component.gates_rows[gate_row_ind++] + start_row_index); } for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { - assignment.enable_selector(first_selector_index, component.gates_rows[gate_row_ind++] + start_row_index); + assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); } if (component.last_gate % 7) { - assignment.enable_selector(first_selector_index + 1, component.gates_rows[gate_row_ind] + start_row_index); + assignment.enable_selector(selector_indexes[ind] + 1, component.gates_rows[gate_row_ind] + start_row_index); } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -618,26 +632,21 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template= 9, bool> = true> - typename padding_component::result_type + template + typename padding_component::result_type generate_assignments( - const padding_component + const padding_component &component, assignment> &assignment, - const typename padding_component::input_type + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t strow = start_row_index; - using component_type = padding_component; + using component_type = padding_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -678,11 +687,9 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template= 9, bool> = true> + template void generate_assignments_constant( - const padding_component + const padding_component &component, circuit> @@ -690,13 +697,11 @@ namespace nil { assignment> &assignment, - const typename padding_component::input_type + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; assignment.constant(component.C(0), start_row_index) = 0; } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 81c748c1f..441be718d 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -27,6 +27,15 @@ #include +#include + +#include +#include +#include +#include + +#include + #include #include #include @@ -36,17 +45,15 @@ namespace nil { namespace blueprint { namespace components { - template + template class keccak_round; - template + template class keccak_round, - WitnessesAmount> : - public plonk_component { + ArithmetizationParams>> : + public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -74,7 +81,7 @@ namespace nil { : chi_num_chunks * 2 + 5; return res; } - std::size_t calculate_buff(std::size_t base = 0) { + std::size_t calculate_buff(std::size_t witness_amount, std::size_t base = 0) { std::size_t buff = 0; std::size_t cells = base == 3 ? xor2_cells : base == 4 ? xor3_cells @@ -82,14 +89,14 @@ namespace nil { : base == 7 ? chi_cells : rotate_cells; if (base == 6) { - return WitnessesAmount * ((cells - 1) / WitnessesAmount + 1) - cells; + return witness_amount * ((cells - 1) / witness_amount + 1) - cells; } - if (WitnessesAmount % 9 == 0) { + if (witness_amount % 9 == 0) { while (cells % 3 != 0) { cells++; buff++; } - } else if (WitnessesAmount % 15 == 0) { + } else if (witness_amount % 15 == 0) { while (cells % 5 != 0) { cells++; buff++; @@ -101,7 +108,7 @@ namespace nil { return buff; } - std::size_t calculate_rows() const { + std::size_t calculate_rows(std::size_t witness_amount) const { std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call * xor_with_mes + // xor with last message chunk ((17 - last_round_call) * (xor2_cells + xor2_buff)) @@ -112,7 +119,7 @@ namespace nil { 24 * (rotate_cells + rotate_buff) + // rho/phi 25 * (chi_cells + chi_buff) + // chi xor2_cells; // iota - return num_cells / WitnessesAmount + bool(num_cells % WitnessesAmount); + return num_cells / witness_amount + bool(num_cells % witness_amount); } std::size_t calculate_last_round_call_row() const { if (!last_round_call) { @@ -126,7 +133,7 @@ namespace nil { } return res; } - std::size_t gates() const { + static std::size_t get_gates_amount() { std::size_t res = 0; for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); @@ -135,6 +142,50 @@ namespace nil { } public: + using manifest_type = nil::blueprint::plonk_component_manifest; + + class gate_manifest_type : public component_gate_manifest { + public: + std::size_t witness_amount; + bool xor_with_mes; + bool last_round_call; + std::size_t limit_permutation_column; + + static const std::size_t clamp = 15; + + gate_manifest_type(std::size_t witness_amount_, + bool xor_with_mes_, + bool last_round_call_, + std::size_t limit_permutation_column_) + : witness_amount(std::min(witness_amount_, clamp)), + xor_with_mes(xor_with_mes_), + last_round_call(last_round_call_), + limit_permutation_column(limit_permutation_column_) {} + + std::uint32_t gates_amount() const override { + return keccak_round::get_gates_amount(); + } + }; + + static gate_manifest get_gate_manifest(std::size_t witness_amount, + std::size_t lookup_column_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + gate_manifest manifest = + gate_manifest(gate_manifest_type(witness_amount, xor_with_mes, last_round_call, + limit_permutation_column)); + return manifest; + } + + static manifest_type get_manifest() { + static manifest_type manifest = manifest_type( + std::shared_ptr( + new manifest_range_param(3, 5)), + false + ); + return manifest; + } struct configuration { struct coordinates { @@ -308,7 +359,7 @@ namespace nil { return result; } - configuration configure_inner(std::size_t row, std::size_t column, std::size_t num_args, + configuration configure_inner(std::size_t witness_amount, std::size_t row, std::size_t column, std::size_t num_args, std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { std::pair first_coordinate = {row, column}; @@ -324,13 +375,13 @@ namespace nil { } } else { for (int i = 0; i < num_args; ++i) { - copy_to.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); + copy_to.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); } } std::pair cell_copy_from; - std::size_t final_row = (column + num_cells - 1) / WitnessesAmount + row; + std::size_t final_row = (column + num_cells - 1) / witness_amount + row; if (final_row == copy_to[0].first) { cell_copy_from = {final_row, copy_to.back().second + 1}; } else { @@ -339,28 +390,28 @@ namespace nil { std::vector> cells; if (num_args + column > limit_permutation_column) { - for (int i = column; i < WitnessesAmount; ++i) { + for (int i = column; i < witness_amount; ++i) { cells.push_back({row, i}); } - std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cells_left = num_cells - witness_amount + column; std::size_t cur_row = row + 1, cur_column = num_args; while (cur_column < cells_left) { - if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { + if (cur_column % witness_amount == cell_copy_from.second && (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { cur_column++; continue; } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { std::size_t cur_row = row, cur_column = column + num_args; while (cur_column - column < num_cells) { - if (cur_column % WitnessesAmount == cell_copy_from.second && (cur_row + (cur_column / WitnessesAmount) == cell_copy_from.first)) { + if (cur_column % witness_amount == cell_copy_from.second && (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { cur_column++; continue; } - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } std::size_t cell_index = 0; @@ -386,13 +437,13 @@ namespace nil { } last_column = cells.back().second + 1 + buff; - last_row = cells.back().first + (last_column >= WitnessesAmount); - last_column %= WitnessesAmount; + last_row = cells.back().first + (last_column >= witness_amount); + last_column %= witness_amount; return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - configuration configure_xor(std::size_t row, std::size_t column, int num_args) { + configuration configure_xor(std::size_t witness_amount, std::size_t row, std::size_t column, int num_args) { // regular constraints: // sum = arg1 + arg2 + ... + argn // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) @@ -406,10 +457,10 @@ namespace nil { : num_args == 3 ? xor3_buff : xor5_buff; - return configure_inner(row, column, num_args, num_chunks, num_cells, buff); + return configure_inner(witness_amount, row, column, num_args, num_chunks, num_cells, buff); } - configuration configure_chi(std::size_t row, std::size_t column) { + configuration configure_chi(std::size_t witness_amount, std::size_t row, std::size_t column) { // regular constraints: // sum = sparse_3 - 2 * a + b - c; // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) @@ -418,10 +469,10 @@ namespace nil { std::size_t num_args = 3; std::size_t num_cells = chi_num_chunks * 2 + num_args + 2; - return configure_inner(row, column, num_args, chi_num_chunks, num_cells, chi_buff); + return configure_inner(witness_amount, row, column, num_args, chi_num_chunks, num_cells, chi_buff); } - configuration configure_rot(std::size_t row, std::size_t column) { + configuration configure_rot(std::size_t witness_amount, std::size_t row, std::size_t column) { // regular constraints: // a = small_part << (192 - r) + big_part; // a_rot = big_part << r + small_part; @@ -445,28 +496,28 @@ namespace nil { copy_to.push_back({last_row + 1, 0}); cell_copy_from = {last_row + 1, 1}; } else { - copy_to.push_back({last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}); - cell_copy_from = {last_row + (last_column / WitnessesAmount), - (last_column++) % WitnessesAmount}; + copy_to.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + cell_copy_from = {last_row + (last_column / witness_amount), + (last_column++) % witness_amount}; } std::vector> cells; if (2 + column > limit_permutation_column) { - for (int i = column; i < WitnessesAmount; ++i) { + for (int i = column; i < witness_amount; ++i) { cells.push_back({row, i}); } - std::size_t cells_left = num_cells - WitnessesAmount + column; + std::size_t cells_left = num_cells - witness_amount + column; std::size_t cur_row = row + 1, cur_column = 2; while (cur_column < cells_left) { - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { std::size_t cur_row = row, cur_column = column + 2; while (cur_column - column < num_cells) { - cells.push_back({cur_row + (cur_column / WitnessesAmount), (cur_column++) % WitnessesAmount}); + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } std::size_t cell_index = 0; @@ -506,13 +557,13 @@ namespace nil { constraints[4].push_back(constraints[6][1]); last_column = cells.back().second + 1 + rotate_buff; - last_row = cells.back().first + (last_column / WitnessesAmount); - last_column %= WitnessesAmount; + last_row = cells.back().first + (last_column / witness_amount); + last_column %= witness_amount; return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - std::vector configure_all() { + std::vector configure_all(std::size_t witness_amount) { auto result = std::vector(full_configuration_size); std::size_t row = 0, column = 0; @@ -521,14 +572,14 @@ namespace nil { // inner_state ^ chunk if (xor_with_mes) { for (int i = 0; i < 17 - last_round_call; ++i) { - result[i] = configure_xor(row, column, 2); + result[i] = configure_xor(witness_amount, row, column, 2); row = result[i].last_coordinate.row; column = result[i].last_coordinate.column; cur_config++; } // xor with last message chunk if (last_round_call) { - result[cur_config] = configure_xor(row, column, 3); + result[cur_config] = configure_xor(witness_amount, row, column, 3); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; @@ -536,39 +587,39 @@ namespace nil { } // theta for (int i = 0; i < 5; ++i) { - result[cur_config] = configure_xor(row, column, 5); + result[cur_config] = configure_xor(witness_amount, row, column, 5); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } for (int i = 0; i < 5; ++i) { - result[cur_config] = configure_rot(row, column); + result[cur_config] = configure_rot(witness_amount, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } for (int i = 0; i < 25; ++i) { - result[cur_config] = configure_xor(row, column, 3); + result[cur_config] = configure_xor(witness_amount, row, column, 3); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // rho/phi for (int i = 0; i < 24; ++i) { - result[cur_config] = configure_rot(row, column); + result[cur_config] = configure_rot(witness_amount, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // chi for (int i = 0; i < 25; ++i) { - result[cur_config] = configure_chi(row, column); + result[cur_config] = configure_chi(witness_amount, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // iota - result[cur_config] = configure_xor(row, column, 2); + result[cur_config] = configure_xor(witness_amount, row, column, 2); return result; } @@ -792,14 +843,6 @@ namespace nil { last_round_call_row(calculate_last_round_call_row()), \ gates_amount(gates()) - template - keccak_round(ContainerType witness, std::size_t lookup_rows_, std::size_t lookup_columns_, - bool xor_with_mes_ = false, - bool last_round_call_ = false, - std::size_t lpc_ = 7) : - component_type(witness, {}, {}), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; - template keccak_round(WitnessContainerType witness, ConstantContainerType constant, @@ -808,8 +851,14 @@ namespace nil { bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : - component_type(witness, constant, public_input), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; + component_type(witness, constant, public_input, get_manifest()), + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + xor_with_mes(xor_with_mes_), + last_round_call(last_round_call_), + limit_permutation_column(lpc_) { + check_params(); + }; keccak_round( std::initializer_list witnesses, @@ -820,23 +869,30 @@ namespace nil { bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : - component_type(witnesses, constants, public_inputs), - __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) {}; + component_type(witness, constant, public_input, get_manifest()), + lookup_rows(lookup_rows_), + lookup_columns(lookup_columns_), + xor_with_mes(xor_with_mes_), + last_round_call(last_round_call_), + limit_permutation_column(lpc_) { + check_params(); + }; #undef __keccak_round_init_macro + + + using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; + }; - template + template using keccak_round_component = keccak_round, - WitnessesAmount>; + ArithmetizationParams>>; - template= 9, bool> = true> + template void generate_gates( - const keccak_round_component + const keccak_round_component &component, circuit> @@ -844,13 +900,11 @@ namespace nil { assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, - const std::size_t first_selector_index) { + const typename lookup_library::left_reserved_type &lookup_tables_indices) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; @@ -1174,11 +1228,9 @@ namespace nil { } } - template= 9, bool> = true> + template void generate_copy_constraints( - const keccak_round_component + const keccak_round_component &component, circuit> @@ -1186,13 +1238,11 @@ namespace nil { assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using var = typename component_type::var; std::size_t config_index = 0; @@ -1305,11 +1355,9 @@ namespace nil { {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); } - template= 9, bool> = true> + template void generate_assignments_constant( - const keccak_round_component + const keccak_round_component &component, circuit> @@ -1317,13 +1365,11 @@ namespace nil { assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using integral_type = typename BlueprintFieldType::integral_type; std::size_t row = start_row_index; @@ -1347,13 +1393,10 @@ namespace nil { } } - template= 9, bool> = true> - typename keccak_round_component::result_type + template + typename keccak_round_component::result_type generate_circuit( - const keccak_round_component + const keccak_round_component &component, circuit> @@ -1361,13 +1404,11 @@ namespace nil { assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); @@ -1397,24 +1438,19 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template= 9, bool> = true> - typename keccak_round_component::result_type + template + typename keccak_round_component::result_type generate_assignments( - const keccak_round_component + const keccak_round_component &component, assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 310035132..8e29afb74 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -80,8 +80,8 @@ auto test_keccak_inner(std::vector mess using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - using component_type = nil::blueprint::components::keccak; - using var = typename component_type::var; + using component_type = nil::blueprint::components::keccak; + using var = nil::crypto3::zk::snark::plonk_variable; std::vector public_input; // std::cout << "message:\n"; @@ -106,18 +106,18 @@ auto test_keccak_inner(std::vector mess } }; - component_type component_instance = WitnessesAmount == 15 ? - component_type({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, {0}, - {1}, LookupRows, LookupColumns, num_blocks, num_bits, 7) - : component_type({0, 1, 2, 3, 4, 5, 6, 7, 8}, {0}, {1}, - LookupRows, LookupColumns, num_blocks, num_bits, 7); - if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; } + std::array witnesses; + for (std::uint32_t i = 0; i < WitnessesAmount; i++) { + witnesses[i] = i; + } + component_type component_instance = component_type(witnesses, std::array{0}, std::array{0}, + LookupRows, LookupColumns, num_blocks, num_bits, 7); nil::crypto3::test_component( - boost::get(component_instance), public_input, result_check, instance_input); + component_instance, public_input, result_check, instance_input); } // works diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index a62416923..d61fb4e44 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -112,7 +112,7 @@ auto test_keccak_padding_inner(std::vector; + using component_type = nil::blueprint::components::keccak_padding; using var = typename component_type::var; std::vector public_input; @@ -138,15 +138,16 @@ auto test_keccak_padding_inner(std::vector witnesses; + for (std::uint32_t i = 0; i < WitnessesAmount; i++) { + witnesses[i] = i; + } + component_type component_instance = + component_type(witnesses, std::array{0}, std::array{0}, + LookupRows, LookupColumns, num_blocks, num_bits, 7); nil::crypto3::test_component( boost::get(component_instance), public_input, result_check, instance_input); From 59c189ea2d337f3067a5cb22b1c62cf01d3ea1d2 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 26 Oct 2023 13:53:10 +0000 Subject: [PATCH 16/48] manifest and lookup updates #183 --- .../hashes/keccak/keccak_padding.hpp | 64 +++-- .../components/hashes/keccak/keccak_round.hpp | 219 +++++++++++++----- test/hashes/plonk/keccak_padding.cpp | 3 +- test/hashes/plonk/keccak_round.cpp | 21 +- 4 files changed, 219 insertions(+), 88 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 795f6cec3..a7887fc28 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -34,6 +34,8 @@ #include #include +#include + namespace nil { namespace blueprint { namespace components { @@ -147,26 +149,26 @@ namespace nil { public: std::size_t witness_amount; std::size_t num_blocks; - std::size_t shift; + std::size_t num_bits; std::size_t last_gate; - static const std::size_t clamp = 15; + static constexpr const std::size_t clamp = 15; - gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t shift_, std::size_t last_gate_) - : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), shift(shift_), last_gate(last_gate_) {}; + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t last_gate_) + : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_), last_gate(last_gate_) {}; std::uint32_t gates_amount() const override { - return keccak_padding::get_gates_amount(witness_amount, num_blocks, shift, last_gate) + num_blocks; + return keccak_padding::get_gates_amount(witness_amount, num_blocks, num_bits, last_gate); } }; static gate_manifest get_gate_manifest(std::size_t witness_amount, std::size_t lookup_column_amount, std::size_t num_blocks, - std::size_t num_bits) { - auto shift = num_blocks * 64 - num_bits; + std::size_t num_bits, + std::size_t limit_permutation_column) { auto last_gate = calculate_last_gate(witness_amount, num_blocks); gate_manifest manifest = gate_manifest(gate_manifest_type(witness_amount, num_blocks, - shift, last_gate)); + num_bits, last_gate)); return manifest; } @@ -192,12 +194,12 @@ namespace nil { padding_gate first_gate_15 = calculate_first_gate_15(); std::size_t last_gate = calculate_last_gate(this->witness_amount(), num_blocks); std::size_t confs_per_gate = calculate_confs_per_gate(this->witness_amount()); - const std::vector full_configuration = configure_all(this->witness_amount()); + const std::vector full_configuration = configure_all(this->witness_amount(), num_blocks, num_bits, limit_permutation_column); std::vector gates_rows = calculate_gates_rows(this->witness_amount()); // const std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount()); - const std::size_t rows_amount = get_rows_amount(this->witness_amount(), full_configuration.back().copy_to.back().row); - const std::size_t gates_amount = get_gates_amount(this->witness_amount(), shift, last_gate, full_configuration.size()); + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), lookup_columns, num_blocks, num_bits, limit_permutation_column); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, shift, last_gate); const std::size_t lookup_gates_amount = num_blocks; struct input_type { @@ -233,13 +235,13 @@ namespace nil { return num_blocks * 64 - num_bits; } - padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { + static padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { if (witness_amount == 9) return padding_9(row); if (witness_amount == 15) return padding_15(row); throw std::runtime_error("Unsupported number of witnesses"); return padding_gate(); } - padding_gate padding_9(std::size_t row = 0) { + static padding_gate padding_9(std::size_t row = 0) { padding_gate res; res.relay = {-1 + row, 0}; res.value = {{-1 + row, 1}, {-1 + row, 3}, {0 + row, 0}, {0 + row, 2}, {1 + row, 0}}; @@ -249,7 +251,7 @@ namespace nil { res.range_check = {{1 + row, 4}, {1 + row, 5}, {1 + row, 6}, {1 + row, 7}, {1 + row, 8}}; return res; } - padding_gate padding_15(std::size_t row = 0) { + static padding_gate padding_15(std::size_t row = 0) { padding_gate res; res.relay = {-1 + row, 11}; res.value = {{0 + row,0}, {0 + row,1}, {0 + row,2}, {1 + row,0}, {1 + row,1}, {1 + row,2}}; @@ -282,20 +284,24 @@ namespace nil { } return (num_blocks - 2) % 6; } + throw std::runtime_error("Unsupported number of witnesses"); } - std::size_t calculate_confs_per_gate(std::size_t witness_amount) { + static std::size_t calculate_confs_per_gate(std::size_t witness_amount) { if (witness_amount == 9) { return 5; } else if (witness_amount == 15) { return 6; } + throw std::runtime_error("Unsupported number of witnesses"); } - std::vector configure_batching(std::size_t witness_amount) { + static std::vector configure_batching(std::size_t witness_amount, + std::size_t num_blocks) { std::vector result; std::size_t conf_ind = 0; std::size_t row = 1; + std::size_t confs_per_gate = calculate_confs_per_gate(witness_amount); while (conf_ind < num_blocks - 2 * (witness_amount == 15)) { auto pg = padding(row); @@ -333,7 +339,11 @@ namespace nil { return result; } - std::vector configure_all(std::size_t witness_amount) { + static std::vector configure_all(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + std::size_t limit_permutation_column) { + std::size_t shift = num_blocks * 64 - num_bits; std::vector result; if (shift == 0) { std::size_t row = 0, @@ -368,7 +378,7 @@ namespace nil { result.push_back(conf1); } - auto batch_configs = configure_batching(witness_amount); + auto batch_configs = configure_batching(witness_amount, num_blocks); result.insert(result.end(), batch_configs.begin(), batch_configs.end()); } @@ -396,9 +406,9 @@ namespace nil { static std::size_t get_gates_amount(std::size_t witness_amount, std::size_t num_blocks, - std::size_t shift, + std::size_t num_bits, std::size_t last_gate) { - if (shift == 0) { + if (num_blocks * 64 - num_bits == 0) { return 0; } if (witness_amount == 9) { @@ -418,8 +428,14 @@ namespace nil { } throw std::runtime_error("Unsupported number of witnesses"); } - static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t rows_amount) { - return rows_amount; + static std::size_t get_rows_amount(std::size_t witness_amount, + std::size_t lookup_column_amount, + std::size_t num_blocks, + std::size_t num_bits, + std::size_t limit_permutation_column) { + auto conf = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); + + return conf.back().constraints.back().back().row; } template 0) { for (int i = 0; i < component.confs_per_gate; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) + cur_constraints.push_back(constraint_type(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 441be718d..a17a6cf21 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -56,8 +56,9 @@ namespace nil { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; - std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base) { + static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base) { std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -66,28 +67,22 @@ namespace nil { } return chunk_size * 3; } - std::size_t calculate_num_chunks(std::size_t base = 0) { - std::size_t chunk_size = base == 3 ? normalize3_chunk_size - : base == 4 ? normalize4_chunk_size - : base == 6 ? normalize6_chunk_size - : chi_chunk_size; + static std::size_t calculate_num_chunks(std::size_t num_rows, std::size_t base = 2) { + std::size_t chunk_size = calculate_chunk_size(num_rows, base); std::size_t res = 192 / chunk_size + bool(192 % chunk_size); return res; } - std::size_t calculate_num_cells(std::size_t base = 0) { - std::size_t res = base == 3 ? normalize3_num_chunks * 2 + 2 + 2 - : base == 4 ? normalize4_num_chunks * 2 + 3 + 2 - : base == 6 ? normalize6_num_chunks * 2 + 5 + 2 - : chi_num_chunks * 2 + 5; + static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 2) { + std::size_t res = base == 3 ? 2 + 2 + : base == 4 ? 3 + 2 + : base == 6 ? 5 + 2 + : 5; + res += 2 * calculate_num_chunks(num_rows, base); return res; } - std::size_t calculate_buff(std::size_t witness_amount, std::size_t base = 0) { + static std::size_t calculate_buff(std::size_t witness_amount, std::size_t num_rows, std::size_t base = 0) { std::size_t buff = 0; - std::size_t cells = base == 3 ? xor2_cells - : base == 4 ? xor3_cells - : base == 6 ? xor5_cells - : base == 7 ? chi_cells - : rotate_cells; + std::size_t cells = calculate_num_cells(num_rows, base); if (base == 6) { return witness_amount * ((cells - 1) / witness_amount + 1) - cells; } @@ -108,7 +103,23 @@ namespace nil { return buff; } - std::size_t calculate_rows(std::size_t witness_amount) const { + static std::size_t get_rows_amount(std::size_t witness_amount, + std::size_t lookup_column_amount, + std::size_t num_rows, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + std::size_t xor2_cells = calculate_num_cells(num_rows, 2); + std::size_t xor3_cells = calculate_num_cells(num_rows, 3); + std::size_t xor5_cells = calculate_num_cells(num_rows, 5); + std::size_t rotate_cells = 24; + std::size_t chi_cells = calculate_num_cells(num_rows, 3); + std::size_t xor2_buff = calculate_buff(witness_amount, num_rows, 2); + std::size_t xor3_buff = calculate_buff(witness_amount, num_rows, 3); + std::size_t xor5_buff = calculate_buff(witness_amount, num_rows, 5); + std::size_t rotate_buff = 0; + std::size_t chi_buff = calculate_buff(witness_amount, num_rows, 3); + std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call * xor_with_mes + // xor with last message chunk ((17 - last_round_call) * (xor2_cells + xor2_buff)) @@ -133,7 +144,10 @@ namespace nil { } return res; } - static std::size_t get_gates_amount() { + static std::size_t get_gates_amount(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { std::size_t res = 0; for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); @@ -141,6 +155,78 @@ namespace nil { return res; } + virtual std::array to_base(std::size_t base, std::size_t num) { + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type normalized_result = 0; + while (num > 0) { + result = result * 8 + (num % base); + normalized_result = normalized_result * 8 + (num % base) & 1; + num /= base; + } + return {result, normalized_result}; + } + virtual std::array to_base_chi(std::size_t num) { + std::size_t base = 5; + int table[5] = {0, 1, 1, 0, 0}; + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type chi_result = 0; + while (num > 0) { + result = result * 8 + (num % base); + chi_result = chi_result * 8 + table[(num % base)]; + num /= base; + } + return {result, chi_result}; + } + + class normalize_table_type : public lookup_table_definition{ + std::size_t base; + public: + normalize_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { + this->subtables["full"] = {{0,1}, 0, 65536}; + } + virtual void generate(){ + this->_table.resize(2); + std::vector value_sizes = {8}; + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(65536); + i++ + ) { + std::array value = to_base(base, i); + this->_table[0].push_back(value[0]); + this->_table[1].push_back(value[1]); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 65536; } + }; + class chi_table_type : public lookup_table_definition{ + public: + chi_table_type(): lookup_table_definition("keccak_chi_table") { + this->subtables["full"] = {{0,1}, 0, 65536}; + } + virtual void generate(){ + this->_table.resize(2); + std::vector value_sizes = {8}; + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(65536); + i++ + ) { + std::array value = to_base_chi(i); + this->_table[0].push_back(value[0]); + this->_table[1].push_back(value[1]); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 65536; } + }; + + protected: + std::shared_ptr normalize3_table; + std::shared_ptr normalize4_table; + std::shared_ptr normalize6_table; + std::shared_ptr chi_table; public: using manifest_type = nil::blueprint::plonk_component_manifest; @@ -151,7 +237,7 @@ namespace nil { bool last_round_call; std::size_t limit_permutation_column; - static const std::size_t clamp = 15; + static constexpr const std::size_t clamp = 15; gate_manifest_type(std::size_t witness_amount_, bool xor_with_mes_, @@ -163,7 +249,7 @@ namespace nil { limit_permutation_column(limit_permutation_column_) {} std::uint32_t gates_amount() const override { - return keccak_round::get_gates_amount(); + return keccak_round::get_gates_amount(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); } }; @@ -359,7 +445,8 @@ namespace nil { return result; } - configuration configure_inner(std::size_t witness_amount, std::size_t row, std::size_t column, std::size_t num_args, + static configuration configure_inner(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column, std::size_t num_args, std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { std::pair first_coordinate = {row, column}; @@ -443,7 +530,7 @@ namespace nil { return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - configuration configure_xor(std::size_t witness_amount, std::size_t row, std::size_t column, int num_args) { + static configuration configure_xor(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column, int num_args) { // regular constraints: // sum = arg1 + arg2 + ... + argn // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) @@ -457,10 +544,10 @@ namespace nil { : num_args == 3 ? xor3_buff : xor5_buff; - return configure_inner(witness_amount, row, column, num_args, num_chunks, num_cells, buff); + return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); } - configuration configure_chi(std::size_t witness_amount, std::size_t row, std::size_t column) { + static configuration configure_chi(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { // regular constraints: // sum = sparse_3 - 2 * a + b - c; // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) @@ -469,10 +556,10 @@ namespace nil { std::size_t num_args = 3; std::size_t num_cells = chi_num_chunks * 2 + num_args + 2; - return configure_inner(witness_amount, row, column, num_args, chi_num_chunks, num_cells, chi_buff); + return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, chi_num_chunks, num_cells, chi_buff); } - configuration configure_rot(std::size_t witness_amount, std::size_t row, std::size_t column) { + static configuration configure_rot(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { // regular constraints: // a = small_part << (192 - r) + big_part; // a_rot = big_part << r + small_part; @@ -485,8 +572,8 @@ namespace nil { std::size_t last_row = row, last_column = column; - std::size_t num_chunks = rotate_num_chunks; - std::size_t num_cells = rotate_cells; + std::size_t num_chunks = 8; + std::size_t num_cells = 24; std::vector> copy_to; std::pair cell_copy_from; @@ -556,14 +643,18 @@ namespace nil { constraints[2].push_back(constraints[6][0]); constraints[4].push_back(constraints[6][1]); - last_column = cells.back().second + 1 + rotate_buff; + last_column = cells.back().second + 1 + calculate_rot_buff(num_chunks); last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - std::vector configure_all(std::size_t witness_amount) { + static std::vector configure_all(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + std::size_t full_configuration_size = 17 * xor_with_mes + 85; auto result = std::vector(full_configuration_size); std::size_t row = 0, column = 0; @@ -572,14 +663,14 @@ namespace nil { // inner_state ^ chunk if (xor_with_mes) { for (int i = 0; i < 17 - last_round_call; ++i) { - result[i] = configure_xor(witness_amount, row, column, 2); + result[i] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); row = result[i].last_coordinate.row; column = result[i].last_coordinate.column; cur_config++; } // xor with last message chunk if (last_round_call) { - result[cur_config] = configure_xor(witness_amount, row, column, 3); + result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 3); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; @@ -587,45 +678,49 @@ namespace nil { } // theta for (int i = 0; i < 5; ++i) { - result[cur_config] = configure_xor(witness_amount, row, column, 5); + result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 5); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } for (int i = 0; i < 5; ++i) { - result[cur_config] = configure_rot(witness_amount, row, column); + result[cur_config] = configure_rot(witness_amount, limit_permutation_column, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } for (int i = 0; i < 25; ++i) { - result[cur_config] = configure_xor(witness_amount, row, column, 3); + result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 3); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // rho/phi for (int i = 0; i < 24; ++i) { - result[cur_config] = configure_rot(witness_amount, row, column); + result[cur_config] = configure_rot(witness_amount, limit_permutation_column, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // chi for (int i = 0; i < 25; ++i) { - result[cur_config] = configure_chi(witness_amount, row, column); + result[cur_config] = configure_chi(witness_amount, limit_permutation_column, row, column); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; } // iota - result[cur_config] = configure_xor(witness_amount, row, column, 2); + result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); return result; } - std::map, std::vector> configure_map() { - auto config = full_configuration; + static std::map, + std::vector> configure_map(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + auto config = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); std::size_t row = 0, column = 0; std::size_t cur_config = 0; @@ -812,6 +907,28 @@ namespace nil { return result; } + std::vector> component_custom_lookup_tables(){ + std::vector> result = {}; + normalize3_table = std::shared_ptr(new normalize_table_type(3)); + normalize4_table = std::shared_ptr(new normalize_table_type(4)); + normalize6_table = std::shared_ptr(new normalize_table_type(6)); + chi_table = std::shared_ptr(new chi_table_type()); + result.push_back(normalize3_table); + result.push_back(normalize4_table); + result.push_back(normalize6_table); + result.push_back(chi_table); + return result; + } + + std::map component_lookup_tables(){ + std::map lookup_tables; + lookup_tables["keccak_normalize3_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize4_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize6_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_chi_table/full"] = 0; // REQUIRED_TABLE + return lookup_tables; + } + #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) \ lookup_rows(lookup_rows_), \ lookup_columns(lookup_columns_), \ @@ -857,7 +974,7 @@ namespace nil { xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { - check_params(); + // check_params(); }; keccak_round( @@ -869,20 +986,16 @@ namespace nil { bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : - component_type(witness, constant, public_input, get_manifest()), + component_type(witnesses, constants, public_inputs, get_manifest()), lookup_rows(lookup_rows_), lookup_columns(lookup_columns_), xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { - check_params(); + // check_params(); }; #undef __keccak_round_init_macro - - - using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; - }; template @@ -891,7 +1004,7 @@ namespace nil { ArithmetizationParams>>; template - void generate_gates( + std::vector generate_gates( const keccak_round_component &component, circuit lookup_constraints; std::size_t index = 0; - std::size_t selector_index = first_selector_index; + std::size_t selector_index = 0; for (auto gm: gate_map) { std::vector cur_config_vec = gate_config[index]; std::size_t i = 0, j = 0, cur_len = 0; @@ -932,9 +1045,9 @@ namespace nil { switch (gm.first.first) { case 2: { - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index d61fb4e44..ecdecd0ba 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -150,7 +150,8 @@ auto test_keccak_padding_inner(std::vector( - boost::get(component_instance), public_input, result_check, instance_input); + component_instance, public_input, result_check, instance_input, + nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, 7); } // works diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 4db6c193e..b80bc9eb8 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -154,7 +154,7 @@ std::array sparse_round_function(st } template + std::size_t LookupColumns, bool xor_with_mes, bool last_round_call, std::size_t last_perm_col = 7> auto test_keccak_round_inner(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC, @@ -172,7 +172,7 @@ auto test_keccak_round_inner(std::array; + using component_type = nil::blueprint::components::keccak_round; using var = typename component_type::var; std::vector public_input; @@ -203,15 +203,16 @@ auto test_keccak_round_inner(std::array witnesses; + for (std::uint32_t i = 0; i < WitnessesAmount; i++) { + witnesses[i] = i; + } + component_type component_instance = + component_type(witnesses, std::array{0}, std::array{0}, + LookupRows, LookupColumns, xor_with_mes, last_round_call, last_perm_col); nil::crypto3::test_component( boost::get(component_instance), public_input, result_check, instance_input); @@ -342,7 +343,7 @@ void test_keccak_round_not_random() { } template + std::size_t LookupColumns, bool xor_with_mes, bool last_round_call, std::size_t last_perm_col = 7> void test_keccak_round_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -369,7 +370,7 @@ void test_keccak_round_random() { auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } From b0e5aa621842caa4d59ddd81266ad284acf26e5d Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 2 Nov 2023 18:56:18 +0000 Subject: [PATCH 17/48] minor changes #183 --- .../hashes/keccak/keccak_padding.hpp | 66 ++- .../components/hashes/keccak/keccak_round.hpp | 548 +++++++++--------- test/hashes/plonk/keccak_padding.cpp | 9 +- test/hashes/plonk/keccak_round.cpp | 51 +- ...tnesses_size: 9 public_inputs_size: 1 .cpp | 217 +++++++ test/test_plonk_component.hpp | 84 ++- 6 files changed, 660 insertions(+), 315 deletions(-) create mode 100644 test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index a7887fc28..da0e1f16c 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -181,8 +181,8 @@ namespace nil { return manifest; } - const std::size_t lookup_rows; - const std::size_t lookup_columns; + static const std::size_t lookup_rows = 65536; + // const std::size_t lookup_columns; const std::size_t limit_permutation_column = 7; @@ -198,7 +198,7 @@ namespace nil { std::vector gates_rows = calculate_gates_rows(this->witness_amount()); // const std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount()); - const std::size_t rows_amount = get_rows_amount(this->witness_amount(), lookup_columns, num_blocks, num_bits, limit_permutation_column); + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, shift, last_gate); const std::size_t lookup_gates_amount = num_blocks; @@ -238,7 +238,6 @@ namespace nil { static padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { if (witness_amount == 9) return padding_9(row); if (witness_amount == 15) return padding_15(row); - throw std::runtime_error("Unsupported number of witnesses"); return padding_gate(); } static padding_gate padding_9(std::size_t row = 0) { @@ -284,7 +283,7 @@ namespace nil { } return (num_blocks - 2) % 6; } - throw std::runtime_error("Unsupported number of witnesses"); + return 0; } static std::size_t calculate_confs_per_gate(std::size_t witness_amount) { if (witness_amount == 9) { @@ -292,19 +291,19 @@ namespace nil { } else if (witness_amount == 15) { return 6; } - throw std::runtime_error("Unsupported number of witnesses"); + return 0; } static std::vector configure_batching(std::size_t witness_amount, std::size_t num_blocks) { std::vector result; - + std::cout << witness_amount << std::endl; std::size_t conf_ind = 0; std::size_t row = 1; std::size_t confs_per_gate = calculate_confs_per_gate(witness_amount); while (conf_ind < num_blocks - 2 * (witness_amount == 15)) { - auto pg = padding(row); + auto pg = padding(witness_amount, row); std::size_t j = 0; { configuration conf; @@ -416,17 +415,16 @@ namespace nil { return 1; } return 2; - } - if (witness_amount == 15) { + } else if (witness_amount == 15) { if (last_gate == 7) { return 1; } - if (last_gate == 0 || last_gate == num_blocks - 3) { + if (last_gate == 0 || last_gate == num_blocks - 2) { return 2; } return 3; } - throw std::runtime_error("Unsupported number of witnesses"); + return 0; } static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, @@ -442,11 +440,8 @@ namespace nil { typename PublicInputContainerType> keccak_padding(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7): component_type(witness, constant, public_input, get_manifest()), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; @@ -456,11 +451,8 @@ namespace nil { std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs, get_manifest()), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; @@ -589,9 +581,9 @@ namespace nil { using component_type = padding_component; using var = typename component_type::var; + std::size_t strow = start_row_index; std::size_t config_index = 0; std::size_t input_index = 0; - std::size_t strow = start_row_index; while (config_index < component.full_configuration.size() - (component.shift != 0)) { auto config = component.full_configuration[config_index]; @@ -606,8 +598,33 @@ namespace nil { if (component.shift != 0) { auto config = component.full_configuration[config_index]; bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), - var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, false)}); + var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); } + + // if (component.shift != 0) { + // std::size_t config_index = 0; + // std::size_t input_index = 0; + // auto config = component.full_configuration[config_index++]; + // bp.add_copy_constraint({instance_input.message[input_index++], + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // bp.add_copy_constraint({instance_input.message[input_index++], + // var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, false)}); + // while (input_index < instance_input.message.size()) { + // std::cout << input_index << ' ' << config_index << ' ' << component.full_configuration.size() << std::endl; + // config = component.full_configuration[config_index++]; + // bp.add_copy_constraint({instance_input.message[input_index++], + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // } + // // config = component.full_configuration[config_index]; + // // bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), + // // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // } else { + // for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + // auto config = component.full_configuration[i]; + // bp.add_copy_constraint({instance_input.message[i], + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // } + // } } template @@ -635,11 +652,14 @@ namespace nil { if (component.witness_amount() == 15) { assignment.enable_selector(selector_indexes[ind++], component.gates_rows[gate_row_ind++] + start_row_index); } - for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { - assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); + if (gate_row_ind < component.gates_rows.size() - (bool)(component.last_gate % 7)) { + for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { + assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); + } + ind++; } if (component.last_gate % 7) { - assignment.enable_selector(selector_indexes[ind] + 1, component.gates_rows[gate_row_ind] + start_row_index); + assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind] + start_row_index); } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index a17a6cf21..0e068e42a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -58,7 +58,11 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; - static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base) { + // xor2 - base=3, xor3 - base=4, xor5 - base=6, chi - base=2, rotate - base=0 + int bases[5] = {3, 4, 6, 2, 0}; + + static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base = 0) { + if (base == 0) return 8; std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -67,12 +71,14 @@ namespace nil { } return chunk_size * 3; } - static std::size_t calculate_num_chunks(std::size_t num_rows, std::size_t base = 2) { + static std::size_t calculate_num_chunks(std::size_t num_rows, std::size_t base = 0) { + if (base == 0) return 8; std::size_t chunk_size = calculate_chunk_size(num_rows, base); std::size_t res = 192 / chunk_size + bool(192 % chunk_size); return res; } - static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 2) { + static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 0) { + if (base == 0) return 24; std::size_t res = base == 3 ? 2 + 2 : base == 4 ? 3 + 2 : base == 6 ? 5 + 2 @@ -102,41 +108,15 @@ namespace nil { // } return buff; } - - static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t lookup_column_amount, - std::size_t num_rows, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { - std::size_t xor2_cells = calculate_num_cells(num_rows, 2); - std::size_t xor3_cells = calculate_num_cells(num_rows, 3); - std::size_t xor5_cells = calculate_num_cells(num_rows, 5); - std::size_t rotate_cells = 24; - std::size_t chi_cells = calculate_num_cells(num_rows, 3); - std::size_t xor2_buff = calculate_buff(witness_amount, num_rows, 2); - std::size_t xor3_buff = calculate_buff(witness_amount, num_rows, 3); - std::size_t xor5_buff = calculate_buff(witness_amount, num_rows, 5); - std::size_t rotate_buff = 0; - std::size_t chi_buff = calculate_buff(witness_amount, num_rows, 3); - - std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call - * xor_with_mes + // xor with last message chunk - ((17 - last_round_call) * (xor2_cells + xor2_buff)) - * xor_with_mes + // inner_state ^ chunk - 5 * (xor5_cells + xor5_buff) + // theta - 5 * (rotate_cells + rotate_buff) + // theta - 25 * (xor3_cells + xor3_buff) + // theta - 24 * (rotate_cells + rotate_buff) + // rho/phi - 25 * (chi_cells + chi_buff) + // chi - xor2_cells; // iota - return num_cells / witness_amount + bool(num_cells % witness_amount); - } - std::size_t calculate_last_round_call_row() const { + static std::size_t calculate_last_round_call_row(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { if (!last_round_call) { return 0; } std::size_t res = 0; + auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); for (auto g : gates_configuration_map) { if (g.first.first == 3) { res = g.second[0]; @@ -144,42 +124,19 @@ namespace nil { } return res; } - static std::size_t get_gates_amount(std::size_t witness_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { - std::size_t res = 0; - for (std::size_t i = 0; i < gates_configuration.size(); ++i) { - res += gates_configuration[i].size(); - } - return res; - } - - virtual std::array to_base(std::size_t base, std::size_t num) { - typename BlueprintFieldType::integral_type result = 0; - typename BlueprintFieldType::integral_type normalized_result = 0; - while (num > 0) { - result = result * 8 + (num % base); - normalized_result = normalized_result * 8 + (num % base) & 1; - num /= base; - } - return {result, normalized_result}; - } - virtual std::array to_base_chi(std::size_t num) { - std::size_t base = 5; - int table[5] = {0, 1, 1, 0, 0}; - typename BlueprintFieldType::integral_type result = 0; - typename BlueprintFieldType::integral_type chi_result = 0; - while (num > 0) { - result = result * 8 + (num % base); - chi_result = chi_result * 8 + table[(num % base)]; - num /= base; - } - return {result, chi_result}; - } class normalize_table_type : public lookup_table_definition{ std::size_t base; + virtual std::array to_base(std::size_t base, typename BlueprintFieldType::integral_type num) { + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type normalized_result = 0; + while (num > 0) { + result = result * 8 + (num % base); + normalized_result = normalized_result * 8 + (num % base) & 1; + num /= base; + } + return {result, normalized_result}; + } public: normalize_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { this->subtables["full"] = {{0,1}, 0, 65536}; @@ -201,6 +158,18 @@ namespace nil { virtual std::size_t get_rows_number(){ return 65536; } }; class chi_table_type : public lookup_table_definition{ + virtual std::array to_base_chi(typename BlueprintFieldType::integral_type num) { + std::size_t base = 5; + int table[5] = {0, 1, 1, 0, 0}; + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type chi_result = 0; + while (num > 0) { + result = result * 8 + (num % base); + chi_result = chi_result * 8 + table[int((num % base))]; + num /= base; + } + return {result, chi_result}; + } public: chi_table_type(): lookup_table_definition("keccak_chi_table") { this->subtables["full"] = {{0,1}, 0, 65536}; @@ -267,7 +236,7 @@ namespace nil { static manifest_type get_manifest() { static manifest_type manifest = manifest_type( std::shared_ptr( - new manifest_range_param(3, 5)), + new manifest_range_param(9, 15)), false ); return manifest; @@ -342,8 +311,8 @@ namespace nil { using var = typename component_type::var; - const std::size_t lookup_rows; - const std::size_t lookup_columns; + static const std::size_t lookup_rows = 65536; + // const std::size_t lookup_columns; // need to xor inner state with message only on the first round const bool xor_with_mes; @@ -352,43 +321,42 @@ namespace nil { // num columns for the permutation argument const std::size_t limit_permutation_column; - const std::size_t normalize3_chunk_size; - const std::size_t normalize4_chunk_size; - const std::size_t normalize6_chunk_size; - const std::size_t chi_chunk_size; + const std::size_t normalize3_chunk_size = calculate_chunk_size(lookup_rows, 3); + const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); + const std::size_t normalize6_chunk_size = calculate_chunk_size(lookup_rows, 6); + const std::size_t chi_chunk_size = calculate_chunk_size(lookup_rows, 2); const std::size_t rotate_chunk_size = 24; - const std::size_t normalize3_num_chunks; - const std::size_t normalize4_num_chunks; - const std::size_t normalize6_num_chunks; - const std::size_t chi_num_chunks; + const std::size_t normalize3_num_chunks = calculate_num_chunks(lookup_rows, 3); + const std::size_t normalize4_num_chunks = calculate_num_chunks(lookup_rows, 4); + const std::size_t normalize6_num_chunks = calculate_num_chunks(lookup_rows, 6); + const std::size_t chi_num_chunks = calculate_num_chunks(lookup_rows, 2); const std::size_t rotate_num_chunks = 8; - const std::size_t xor2_cells; - const std::size_t xor3_cells; - const std::size_t xor5_cells; + const std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); + const std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); + const std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); + const std::size_t chi_cells = calculate_num_cells(lookup_rows, 2); const std::size_t rotate_cells = 24; - const std::size_t chi_cells; - const std::size_t xor2_buff; - const std::size_t xor3_buff; - const std::size_t xor5_buff; - const std::size_t rotate_buff; - const std::size_t chi_buff; + const std::size_t xor2_buff = calculate_buff(this->witness_amount(), lookup_rows, 3); + const std::size_t xor3_buff = calculate_buff(this->witness_amount(), lookup_rows, 4); + const std::size_t xor5_buff = calculate_buff(this->witness_amount(), lookup_rows, 6); + const std::size_t chi_buff = calculate_buff(this->witness_amount(), lookup_rows, 2); + const std::size_t rotate_buff = calculate_buff(this->witness_amount(), lookup_rows); - const std::size_t rows_amount; + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, xor_with_mes, last_round_call, limit_permutation_column); // full configuration is precalculated, then used in other functions const std::size_t full_configuration_size = 17 * xor_with_mes + 85; - std::vector full_configuration = std::vector(full_configuration_size); + std::vector full_configuration = configure_all(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); // number represents relative selector index for each constraint - std::map, std::vector> gates_configuration_map; - std::vector> gates_configuration; - std::vector lookup_gates_configuration; - std::vector gates_rows; + std::map, std::vector> gates_configuration_map = configure_map(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector> gates_configuration = configure_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - const std::size_t last_round_call_row; - const std::size_t gates_amount; + const std::size_t last_round_call_row = calculate_last_round_call_row(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; @@ -402,6 +370,14 @@ namespace nil { std::array inner_state; std::array padded_message_chunk; var round_constant; + + std::vector all_vars() const { + std::vector result; + result.insert(result.end(), inner_state.begin(), inner_state.end()); + result.insert(result.end(), padded_message_chunk.begin(), padded_message_chunk.end()); + result.push_back(round_constant); + return result; + } }; struct result_type { @@ -410,12 +386,18 @@ namespace nil { result_type(const keccak_round &component, std::size_t start_row_index) { std::size_t num_config = component.full_configuration.size() - 1; inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.column), - component.full_configuration[num_config].copy_from.row); + component.full_configuration[num_config].copy_from.row + start_row_index); for (int i = 1; i < 25; ++i) { inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from.column), - component.full_configuration[num_config - i].copy_from.row); + component.full_configuration[num_config - i].copy_from.row + start_row_index); } } + + std::vector all_vars() const { + std::vector result; + result.insert(result.end(), inner_state.begin(), inner_state.end()); + return result; + } }; integral_type normalize(const integral_type& integral_value) const { @@ -535,14 +517,10 @@ namespace nil { // sum = arg1 + arg2 + ... + argn // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) // norm_sum = norm_sum_chunk0 + norm_sum_chunk1 * 2^chunk_size + ... + norm_sum_chunkk * 2^(k*chunk_size) - - std::size_t num_chunks = num_args == 2 ? normalize3_num_chunks - : num_args == 3 ? normalize4_num_chunks - : normalize6_num_chunks; - std::size_t num_cells = num_chunks * 2 + num_args + 2; - std::size_t buff = num_args == 2 ? xor2_buff - : num_args == 3 ? xor3_buff - : xor5_buff; + + std::size_t num_chunks = calculate_num_chunks(lookup_rows, num_args + 1); + std::size_t num_cells = calculate_num_cells(lookup_rows, num_args + 1); + std::size_t buff = calculate_buff(witness_amount, lookup_rows, num_args + 1); return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); } @@ -554,9 +532,11 @@ namespace nil { // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * 2^(k*chunk_size) std::size_t num_args = 3; - std::size_t num_cells = chi_num_chunks * 2 + num_args + 2; + std::size_t num_chunks = calculate_num_chunks(lookup_rows, 2); + std::size_t num_cells = calculate_num_cells(lookup_rows, 2); + std::size_t buff = calculate_buff(witness_amount, lookup_rows, 2); - return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, chi_num_chunks, num_cells, chi_buff); + return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); } static configuration configure_rot(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { @@ -643,7 +623,7 @@ namespace nil { constraints[2].push_back(constraints[6][0]); constraints[4].push_back(constraints[6][1]); - last_column = cells.back().second + 1 + calculate_rot_buff(num_chunks); + last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; @@ -712,6 +692,20 @@ namespace nil { // iota result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); + // for (int i = 0; i < full_configuration_size; ++i) { + // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; + // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; + // for (int j = 0; j < result[i].copy_to.size(); ++j) { + // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; + // } + // for (int j = 0; j < result[i].constraints.size(); ++j) { + // for (int k = 0; k < result[i].constraints[j].size(); ++k) { + // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << " "; + // } + // std::cout << std::endl; + // } + // } + return result; } @@ -824,28 +818,46 @@ namespace nil { return config_map; } - std::vector> configure_gates() { + static std::vector> configure_gates(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { std::vector> result; + auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + for (auto config: gates_configuration_map) { configuration cur_config; switch (config.first.first) { case 2: - cur_config = configure_xor(0, config.first.second, 2); + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); break; case 3: - cur_config = configure_xor(0, config.first.second, 3); + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); break; case 5: - cur_config = configure_xor(0, config.first.second, 5); + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); break; case 7: - cur_config = configure_rot(0, config.first.second); + cur_config = configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); break; case 0: - cur_config = configure_chi(0, config.first.second); + cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; } + + // std::cout << config.first.first << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].column << " "; + // } + // std::cout << std::endl; + // } std::vector> pairs; for (auto constr : cur_config.constraints) { @@ -877,9 +889,15 @@ namespace nil { return result; } - std::vector configure_lookup_gates() { + static std::vector configure_lookup_gates(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + auto full_configuration = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto rows_amount = full_configuration.back().last_coordinate.row + 1; + std::vector> pairs; - for (std::size_t i = 0; i < full_configuration_size; ++i) { + for (std::size_t i = 0; i < full_configuration.size(); ++i) { for (auto constr : full_configuration[i].lookups) { std::size_t min = constr[0].row; std::size_t max = constr.back().row; @@ -906,6 +924,46 @@ namespace nil { } return result; } + static std::size_t get_gates_amount(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + std::size_t res = 0; + auto gates_configuration = configure_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + for (std::size_t i = 0; i < gates_configuration.size(); ++i) { + res += gates_configuration[i].size(); + } + return res; + } + + static std::size_t get_rows_amount(std::size_t witness_amount, + std::size_t lookup_column_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); + std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); + std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); + std::size_t chi_cells = calculate_num_cells(lookup_rows, 2); + std::size_t rotate_cells = calculate_num_cells(lookup_rows); + std::size_t xor2_buff = calculate_buff(witness_amount, lookup_rows, 3); + std::size_t xor3_buff = calculate_buff(witness_amount, lookup_rows, 4); + std::size_t xor5_buff = calculate_buff(witness_amount, lookup_rows, 6); + std::size_t chi_buff = calculate_buff(witness_amount, lookup_rows, 2); + std::size_t rotate_buff = calculate_buff(witness_amount, lookup_rows); + + std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call + * xor_with_mes + // xor with last message chunk + ((17 - last_round_call) * (xor2_cells + xor2_buff)) + * xor_with_mes + // inner_state ^ chunk + 5 * (xor5_cells + xor5_buff) + // theta + 5 * (rotate_cells + rotate_buff) + // theta + 25 * (xor3_cells + xor3_buff) + // theta + 24 * (rotate_cells + rotate_buff) + // rho/phi + 25 * (chi_cells + chi_buff) + // chi + xor2_cells; // iota + return num_cells / witness_amount + bool(num_cells % witness_amount); + } std::vector> component_custom_lookup_tables(){ std::vector> result = {}; @@ -929,48 +987,14 @@ namespace nil { return lookup_tables; } - #define __keccak_round_init_macro(lookup_rows_, lookup_columns_, xor_with_mes_, last_round_call_, lpc_) \ - lookup_rows(lookup_rows_), \ - lookup_columns(lookup_columns_), \ - xor_with_mes(xor_with_mes_), \ - last_round_call(last_round_call_),\ - limit_permutation_column(lpc_), \ - normalize3_chunk_size(calculate_chunk_size(lookup_rows_, 3)), \ - normalize4_chunk_size(calculate_chunk_size(lookup_rows_, 4)), \ - normalize6_chunk_size(calculate_chunk_size(lookup_rows_, 6)), \ - chi_chunk_size(calculate_chunk_size(lookup_rows_, 2)), \ - normalize3_num_chunks(calculate_num_chunks(3)), \ - normalize4_num_chunks(calculate_num_chunks(4)), \ - normalize6_num_chunks(calculate_num_chunks(6)), \ - chi_num_chunks(calculate_num_chunks()), \ - xor2_cells(calculate_num_cells(3)), \ - xor3_cells(calculate_num_cells(4)), \ - xor5_cells(calculate_num_cells(6)), \ - chi_cells(calculate_num_cells()), \ - xor2_buff(calculate_buff(3)), \ - xor3_buff(calculate_buff(4)), \ - xor5_buff(calculate_buff(6)), \ - chi_buff(calculate_buff(7)), \ - rotate_buff(calculate_buff()), \ - rows_amount(calculate_rows()), \ - full_configuration(configure_all()), \ - gates_configuration_map(configure_map()), \ - gates_configuration(configure_gates()), \ - lookup_gates_configuration(configure_lookup_gates()), \ - last_round_call_row(calculate_last_round_call_row()), \ - gates_amount(gates()) - template keccak_round(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t lookup_rows_, std::size_t lookup_columns_, bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : component_type(witness, constant, public_input, get_manifest()), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { @@ -982,20 +1006,15 @@ namespace nil { std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, - bool xor_with_mes_ = false, - bool last_round_call_ = false, - std::size_t lpc_ = 7) : + bool xor_with_mes_ = false, + bool last_round_call_ = false, + std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs, get_manifest()), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { // check_params(); }; - - #undef __keccak_round_init_macro }; template @@ -1014,8 +1033,7 @@ namespace nil { ArithmetizationParams>> &assignment, const typename keccak_round_component::input_type - &instance_input, - const typename lookup_library::left_reserved_type &lookup_tables_indices) { + &instance_input) { using component_type = keccak_round_component; using var = typename component_type::var; @@ -1027,6 +1045,7 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; using configuration = typename component_type::configuration; + std::vector selector_indexes; auto gate_config = component.gates_configuration; auto gate_map = component.gates_configuration_map; // auto lookup_gate_config = component.lookup_gates_configuration; @@ -1045,15 +1064,14 @@ namespace nil { switch (gm.first.first) { case 2: { - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(constraint_type(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1063,14 +1081,13 @@ namespace nil { for (int k = 0; k < component.normalize3_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize3_chunk_size)); - } - cur_constraints.push_back(bp.add_constraint(constraint_1)); + } + cur_constraints.push_back(constraint_1); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1081,25 +1098,22 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize3_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); - - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + cur_constraints.push_back(constraint_2); + selector_indexes.push_back(bp.add_gate(cur_constraints)); break; } case 3: { - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1110,13 +1124,12 @@ namespace nil { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize4_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_1)); + cur_constraints.push_back(constraint_1); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1127,27 +1140,24 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize4_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); - - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + cur_constraints.push_back(constraint_2); + selector_indexes.push_back(bp.add_gate(cur_constraints)); break; } case 5: { - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1158,13 +1168,12 @@ namespace nil { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize6_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_1)); + cur_constraints.push_back(constraint_1); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1175,55 +1184,50 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize6_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); - - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + cur_constraints.push_back(constraint_2); + selector_indexes.push_back(bp.add_gate(cur_constraints)); break; } case 7: { - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << 192)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1234,28 +1238,26 @@ namespace nil { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_1)); + cur_constraints.push_back(constraint_1); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << 192)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1266,40 +1268,37 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); + cur_constraints.push_back(constraint_2); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; j %= cur_len; - cur_constraints.push_back(bp.add_constraint(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192))); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + - (integral_type(1) << 192)); - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); break; } case 0: { - cur_constraints.push_back(bp.add_constraint(component.sparse_3 - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + cur_constraints.push_back(component.sparse_3 + - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1310,13 +1309,12 @@ namespace nil { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.chi_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_1)); + cur_constraints.push_back(constraint_1); j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_constraints.clear(); } i += j / cur_len; @@ -1327,18 +1325,15 @@ namespace nil { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.chi_chunk_size)); } - cur_constraints.push_back(bp.add_constraint(constraint_2)); - - { - gate_type gate(selector_index++, cur_constraints); - bp.add_gate(gate); - } + cur_constraints.push_back(constraint_2); + selector_indexes.push_back(bp.add_gate(cur_constraints)); break; } } index++; } + return selector_indexes; } template @@ -1525,25 +1520,31 @@ namespace nil { generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); - auto selector_iterator = assignment.find_selector(component); - std::size_t first_selector_index; - - if (selector_iterator == assignment.selectors_end()) { - first_selector_index = assignment.allocate_selector(component, component.gates_amount); - generate_gates(component, bp, assignment, instance_input, first_selector_index); - } else { - first_selector_index = selector_iterator->second; - } + auto selector_indexes = generate_gates(component, bp, assignment, instance_input); + std::size_t ind = 0; std::size_t index = 0; + // for (auto g : component.gates_configuration_map) { + // for (auto j : g.second) { + // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << ", j: " << j << '\n'; + // assignment.enable_selector(selector_indexes[index], + // start_row_index + j + 1); + // } + // std::cout << '\n'; + // index++; + // } for (auto g : component.gates_configuration_map) { + std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << '\n'; for (std::size_t i = 0; i < component.gates_configuration[index].size(); ++i) { for (auto j : g.second) { - assignment.enable_selector(first_selector_index + i, - start_row_index + j + 1 + component.gates_configuration[index][i].first_coordinate.row); + std::cout << j << ' '; + assignment.enable_selector(selector_indexes[index], + start_row_index + j + component.gates_configuration[index][i].first_coordinate.row + 1); } + std::cout << '\n'; } - first_selector_index += component.gates_configuration[index++].size(); + index++; + break; } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -1647,6 +1648,11 @@ namespace nil { A_1[i] = var_value(assignment, instance_input.inner_state[i]); } } + std::cout << "A_1:\n"; + for (int i = 0; i < 25; ++i) { + std::cout << A_1[i].data << " "; + } + std::cout << "\n"; // theta std::array C; @@ -1686,6 +1692,11 @@ namespace nil { } } config_index += 5; + std::cout << "C:\n"; + for (int i = 0; i < 5; ++i) { + std::cout << C[i].data << " "; + } + std::cout << "\n"; std::array C_rot; for (int index = 0; index < 5; ++index) { @@ -1725,6 +1736,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); } config_index += 5; + std::cout << "C_rot:\n"; + for (int i = 0; i < 5; ++i) { + std::cout << C_rot[i].data << " "; + } + std::cout << "\n"; std::array A_2; for (int index = 0; index < 25; ++index) { @@ -1760,6 +1776,11 @@ namespace nil { } } config_index += 25; + std::cout << "A_2:\n"; + for (int i = 0; i < 25; ++i) { + std::cout << A_2[i].data << " "; + } + std::cout << "\n"; // rho/phi value_type B[25]; @@ -1878,6 +1899,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } + std::cout << "result:\n" << A_4.data << " "; + for (int i = 1; i < 25; ++i) { + std::cout << A_3[i].data << " "; + } + std::cout << "\n"; return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index ecdecd0ba..92c7a5a0e 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -147,7 +147,7 @@ auto test_keccak_padding_inner(std::vector{0}, std::array{0}, - LookupRows, LookupColumns, num_blocks, num_bits, 7); + num_blocks, num_bits, 7); nil::crypto3::test_component( component_instance, public_input, result_check, instance_input, @@ -184,7 +184,8 @@ void test_keccak_padding_random() { integral_type mask = (integral_type(1) << 64) - 1; integral_type mask_zero = (integral_type(1) << 60) - 1; std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), - value_type(integral_type(dis(gen)) & mask_zero)}; + value_type(integral_type(dis(gen)) & mask), + value_type(integral_type(dis(gen)) & mask)}; std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); std::size_t num_blocks = message.size(); @@ -203,8 +204,8 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_random(); - // test_keccak_padding_random(); - test_keccak_padding_random(); + test_keccak_padding_random(); + // test_keccak_padding_random(); } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index b80bc9eb8..a17682153 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -161,7 +161,7 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 25; + constexpr std::size_t SelectorColumns = 15; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; - using var = typename component_type::var; + using var = nil::crypto3::zk::snark::plonk_variable; std::vector public_input; for (int i = 0; i < 25; ++i) { @@ -199,6 +199,7 @@ auto test_keccak_round_inner(std::array{0}, std::array{0}, - LookupRows, LookupColumns, xor_with_mes, last_round_call, last_perm_col); + xor_with_mes, last_round_call, last_perm_col); nil::crypto3::test_component( - boost::get(component_instance), public_input, result_check, instance_input); + boost::get(component_instance), public_input, result_check, instance_input, + nil::crypto3::detail::connectedness_check_type::STRONG, + xor_with_mes, last_round_call, last_perm_col); } template(); + // test_keccak_round_not_random(); // xor_with_mes, last_round_call test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_round_not_random(); - test_keccak_round_not_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_not_random(); + // test_keccak_round_not_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows_to_fail) { diff --git a/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp b/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp new file mode 100644 index 000000000..2306a2b09 --- /dev/null +++ b/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp @@ -0,0 +1,217 @@ +witnesses_size: 9 public_inputs_size: 1 constants_size: 1 selectors_size: 15 max_size: 216 +1 2 3 4 5 6 7 8 9 | 1 | a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +b c d e f 10 11 12 13 | 29 | 14 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 16 17 18 19 1a 1b 1c 1d | 51 | 1e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +c9 20 21 22 23 24 25 26 27 | 79 | 28 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +29 2a 2b 2c 2d 2e 2f 30 31 | a1 | 32 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +33 34 35 36 37 38 39 3a 3b | 2 | 3c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3d 3e 3f 40 41 42 43 44 45 | 2a | 46 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +e7 48 49 4a 4b 4c 4d 4e 4f | 52 | 50 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +51 52 53 54 55 56 57 58 59 | 7a | 5a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5b 5c 5d 5e 5f 60 61 62 63 | a2 | 64 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +65 66 67 68 69 6a 6b 6c 6d | 3 | 6e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +fe 70 71 72 73 74 75 76 77 | 2b | 78 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +79 7a 7b 7c 7d 7e 7f 80 81 | 53 | 82 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +83 84 85 86 87 88 89 8a 8b | 7b | 8c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +8d 8e 8f 90 91 92 93 94 95 | a3 | 96 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +119 98 99 9a 9b 9c 9d 9e 9f | 4 | a0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +a1 a2 a3 a4 a5 a6 a7 a8 a9 | 2c | aa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ab ac ad ae af b0 b1 b2 b3 | 54 | b4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +b5 b6 b7 b8 b9 ba bb bc bd | 7c | be | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +137 c0 c1 c2 c3 c4 c5 c6 c7 | a4 | c8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +c9 1c7 d2 cc cd ce cf d0 d1 | 5 | d2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +d3 d4 d5 d6 d7 d8 d9 da db | 2d | dc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +dd de df e0 e1 e2 e6 e4 e5 | 55 | e6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +e7 14f e9 ea eb ec ed ee ef | 7d | f0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +f1 f2 f3 f4 f5 f6 f7 f8 f9 | a5 | fa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +fb fc fd fe 16d 104 101 102 103 | 88a | 104 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +105 106 107 108 109 10a 10b 10c 10d | 88b | 10e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10f 110 111 112 113 114 115 116 117 | 88c | 118 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +119 18b 122 11c 11d 11e 11f 120 121 | 88d | 122 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +123 124 125 126 127 128 129 12a 12b | 88e | 12c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +12d 12e 12f 130 131 132 136 134 135 | 88f | 136 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +137 1a9 139 13a 13b 13c 13d 13e 13f | 890 | 140 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +141 142 143 144 145 146 147 148 149 | 891 | 14a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +14b 14c 14d 1 14f 137 151 152 153 | 892 | 154 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +155 156 157 158 159 15a 15b 15c 15d | 893 | 15e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15f 160 161 162 163 164 165 166 167 | 894 | 168 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 16a 16b 29 16d c9 16f 170 171 | 895 | 172 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +173 174 175 176 177 178 179 17a 17b | 896 | 17c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +17d 17e 17f 180 181 182 183 184 185 | 897 | 186 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +43c 188 189 51 18b e7 18d 18e 18f | 898 | 190 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +191 192 193 194 195 196 197 198 199 | 899 | 19a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +19b 19c 19d 19e 19f 1a0 1a1 1a2 1a3 | 89a | 1a4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +61c 1a6 1a7 79 1a9 fe 1ab 1ac 1ad | 85e | 1ae | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1af 1b0 1b1 1b2 1b3 1b4 1b5 1b6 1b7 | 0 | 1b8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1b9 1ba 1bb 1bc 1bd 1be 1bf 1c0 1c1 | 0 | 1c2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4dc 1c4 1c5 a1 1c7 119 1c9 1ca 1cb | 0 | 1cc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1cd 1ce 1cf 1d0 1d1 1d2 1d3 1d4 1d5 | 0 | 1d6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1d7 1d8 1d9 1da 1db 1dc 1dd 1de 1df | 0 | 1e0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +57c 1e2 1e3 2 14f 137 1e7 1e8 1e9 | 0 | 1ea | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1eb 1ec 1ed 1ee 1ef 1f0 1f1 1f2 1f3 | 0 | 1f4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1f5 1f6 1f7 1f8 1f9 1fa 1fb 1fc 1fd | 0 | 1fe | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4f7 200 201 2a 16d c9 205 206 207 | 0 | 208 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +209 20a 20b 20c 20d 20e 20f 210 211 | 0 | 212 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +213 214 215 216 217 218 219 21a 21b | 0 | 21c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6a5 21e 21f 52 18b e7 223 224 225 | 0 | 226 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +227 228 229 22a 22b 22c 22d 22e 22f | 0 | 230 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +231 232 233 234 235 236 237 238 239 | 0 | 23a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +475 23c 23d 7a 1a9 fe 241 242 243 | 0 | 244 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +245 246 247 248 249 24a 24b 24c 24d | 0 | 24e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +24f 250 251 252 253 254 255 256 257 | 0 | 258 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +52c 25a 25b a2 1c7 119 25f 260 261 | 0 | 262 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +263 264 265 266 267 268 269 26a 26b | 0 | 26c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +26d 26e 26f 270 271 272 273 274 275 | 0 | 276 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +687 278 279 3 14f 137 27d 27e 27f | 0 | 280 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +281 282 283 284 285 286 287 288 289 | 0 | 28a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +28b 28c 28d 28e 28f 290 291 292 293 | 0 | 294 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +457 296 297 2b 16d c9 29b 29c 29d | 0 | 29e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +29f 2a0 2a1 2a2 2a3 2a4 2a5 2a6 2a7 | 0 | 2a8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2a9 2aa 2ab 2ac 2ad 2ae 2af 2b0 2b1 | 0 | 2b2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +48c 2b4 2b5 53 18b e7 2b9 2ba 2bb | 0 | 2bc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2bd 2be 2bf 2c0 2c1 2c2 2c3 2c4 2c5 | 0 | 2c6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2c7 2c8 2c9 2ca 2cb 2cc 2cd 2ce 2cf | 0 | 2d0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +605 2d2 2d3 7b 1a9 fe 2d7 2d8 2d9 | 0 | 2da | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2db 2dc 2dd 2de 2df 2e0 2e1 2e2 2e3 | 0 | 2e4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2e5 2e6 2e7 2e8 2e9 2ea 2eb 2ec 2ed | 0 | 2ee | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5e7 2f0 2f1 a3 1c7 119 2f5 2f6 2f7 | 0 | 2f8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2f9 2fa 2fb 2fc 2fd 2fe 2ff 300 301 | 0 | 302 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +303 304 305 306 307 308 309 30a 30b | 0 | 30c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +655 30e 30f 4 14f 137 313 314 315 | 0 | 316 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +317 318 319 31a 31b 31c 31d 31e 31f | 0 | 320 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +321 322 323 324 325 326 327 328 329 | 0 | 32a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +597 32c 32d 2c 16d c9 331 332 333 | 0 | 334 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +335 336 337 338 339 33a 33b 33c 33d | 0 | 33e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +33f 340 341 342 343 344 345 346 347 | 0 | 348 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +515 34a 34b 54 18b e7 34f 350 351 | 0 | 352 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +353 354 355 356 357 358 359 35a 35b | 0 | 35c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +35d 35e 35f 360 361 362 363 364 365 | 0 | 366 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4a7 368 369 7c 1a9 fe 36d 36e 36f | 0 | 370 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +371 372 373 374 375 376 377 378 379 | 0 | 37a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +37b 37c 37d 37e 37f 380 381 382 383 | 0 | 384 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4c5 386 387 a4 1c7 119 38b 38c 38d | 0 | 38e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +38f 390 391 392 393 394 395 396 397 | 0 | 398 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +399 39a 39b 39c 39d 39e 39f 3a0 3a1 | 0 | 3a2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5cc 3a4 3a5 5 14f 137 3a9 3aa 3ab | 0 | 3ac | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3ad 3ae 3af 3b0 3b1 3b2 3b3 3b4 3b5 | 0 | 3b6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3b7 3b8 3b9 3ba 3bb 3bc 3bd 3be 3bf | 0 | 3c0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +637 3c2 3c3 2d 16d c9 3c7 3c8 3c9 | 0 | 3ca | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3cb 3cc 3cd 3ce 3cf 3d0 3d1 3d2 3d3 | 0 | 3d4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3d5 3d6 3d7 3d8 3d9 3da 3db 3dc 3dd | 0 | 3de | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +547 3e0 3e1 55 18b e7 3e5 3e6 3e7 | 0 | 3e8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3e9 3ea 3eb 3ec 3ed 3ee 3ef 3f0 3f1 | 0 | 3f2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +3f3 3f4 3f5 3f6 3f7 3f8 3f9 3fa 3fb | 0 | 3fc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +66c 3fe 3ff 7d 1a9 fe 403 404 405 | 0 | 406 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +407 408 409 40a 40b 40c 40d 40e 40f | 0 | 410 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +411 412 413 414 415 416 417 418 419 | 0 | 41a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5b5 41c 41d a5 1c7 119 421 422 423 | 0 | 424 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +425 426 427 428 429 42a 42b 42c 42d | 0 | 42e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +42f 430 431 432 433 434 435 436 437 | 0 | 438 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +565 43a 43b 43c 795 442 43f 440 441 | 0 | 442 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +443 444 445 446 447 448 449 44a 44b | 0 | 44c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +44d 44e 44f 450 451 452 453 454 455 | 0 | 456 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +457 731 460 45a 45b 45c 45d 45e 45f | 0 | 460 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +461 462 463 464 465 466 467 468 469 | 0 | 46a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +46b 46c 46d 46e 46f 470 474 472 473 | 0 | 474 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +475 795 477 478 479 47a 47b 47c 47d | 0 | 47e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +47f 480 481 482 483 484 485 486 487 | 0 | 488 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +489 48a 48b 48c 7f9 492 48f 490 491 | 0 | 492 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +493 494 495 496 497 498 499 49a 49b | 0 | 49c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +49d 49e 49f 4a0 4a1 4a2 4a3 4a4 4a5 | 0 | 4a6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4a7 7f9 4b0 4aa 4ab 4ac 4ad 4ae 4af | 0 | 4b0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4b1 4b2 4b3 4b4 4b5 4b6 4b7 4b8 4b9 | 0 | 4ba | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4bb 4bc 4bd 4be 4bf 4c0 4c4 4c2 4c3 | 0 | 4c4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4c5 6ff 4c7 4c8 4c9 4ca 4cb 4cc 4cd | 0 | 4ce | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4cf 4d0 4d1 4d2 4d3 4d4 4d5 4d6 4d7 | 0 | 4d8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4d9 4da 4db 4dc 713 4e2 4df 4e0 4e1 | 0 | 4e2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4e3 4e4 4e5 4e6 4e7 4e8 4e9 4ea 4eb | 0 | 4ec | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4ed 4ee 4ef 4f0 4f1 4f2 4f3 4f4 4f5 | 0 | 4f6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4f7 7f9 500 4fa 4fb 4fc 4fd 4fe 4ff | 0 | 500 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +501 502 503 504 505 506 507 508 509 | 0 | 50a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +50b 50c 50d 50e 50f 510 514 512 513 | 0 | 514 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +515 731 517 518 519 51a 51b 51c 51d | 0 | 51e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +51f 520 521 522 523 524 525 526 527 | 0 | 528 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +529 52a 52b 52c 80e 532 52f 530 531 | 0 | 532 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +533 534 535 536 537 538 539 53a 53b | 0 | 53c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +53d 53e 53f 540 541 542 543 544 545 | 0 | 546 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +547 82b 550 54a 54b 54c 54d 54e 54f | 0 | 550 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +551 552 553 554 555 556 557 558 559 | 0 | 55a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +55b 55c 55d 55e 55f 560 564 562 563 | 0 | 564 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +565 6ff 567 568 569 56a 56b 56c 56d | 0 | 56e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +56f 570 571 572 573 574 575 576 577 | 0 | 578 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +579 57a 57b 57c 7f9 582 57f 580 581 | 0 | 582 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +583 584 585 586 587 588 589 58a 58b | 0 | 58c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +58d 58e 58f 590 591 592 593 594 595 | 0 | 596 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +597 82b 5a0 59a 59b 59c 59d 59e 59f | 0 | 5a0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5a1 5a2 5a3 5a4 5a5 5a6 5a7 5a8 5a9 | 0 | 5aa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5ab 5ac 5ad 5ae 5af 5b0 5b4 5b2 5b3 | 0 | 5b4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5b5 7f9 5b7 5b8 5b9 5ba 5bb 5bc 5bd | 0 | 5be | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5bf 5c0 5c1 5c2 5c3 5c4 5c5 5c6 5c7 | 0 | 5c8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5c9 5ca 5cb 5cc 795 5d2 5cf 5d0 5d1 | 0 | 5d2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5d3 5d4 5d5 5d6 5d7 5d8 5d9 5da 5db | 0 | 5dc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5dd 5de 5df 5e0 5e1 5e2 5e3 5e4 5e5 | 0 | 5e6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5e7 795 5f0 5ea 5eb 5ec 5ed 5ee 5ef | 0 | 5f0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5f1 5f2 5f3 5f4 5f5 5f6 5f7 5f8 5f9 | 0 | 5fa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +5fb 5fc 5fd 5fe 5ff 600 604 602 603 | 0 | 604 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +605 6ff 607 608 609 60a 60b 60c 60d | 0 | 60e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +60f 610 611 612 613 614 615 616 617 | 0 | 618 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +619 61a 61b 61c 80d 622 61f 620 621 | 0 | 622 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +623 624 625 626 627 628 629 62a 62b | 0 | 62c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +62d 62e 62f 630 631 632 633 634 635 | 0 | 636 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +637 795 640 63a 63b 63c 63d 63e 63f | 0 | 640 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +641 642 643 644 645 646 647 648 649 | 0 | 64a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +64b 64c 64d 64e 64f 650 654 652 653 | 0 | 654 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +655 82b 657 658 659 65a 65b 65c 65d | 0 | 65e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +65f 660 661 662 663 664 665 666 667 | 0 | 668 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +669 66a 66b 66c 731 672 66f 670 671 | 0 | 672 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +673 674 675 676 677 678 679 67a 67b | 0 | 67c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +67d 67e 67f 680 681 682 683 684 685 | 0 | 686 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +687 714 690 68a 68b 68c 68d 68e 68f | 0 | 690 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +691 692 693 694 695 696 697 698 699 | 0 | 69a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +69b 69c 69d 69e 69f 6a0 6a4 6a2 6a3 | 0 | 6a4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6a5 6ff 6a7 6a8 6a9 6aa 6ab 6ac 6ad | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6af 6b0 6b1 6b2 6b3 6b4 6b5 6b6 6b7 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6b9 6ba 6bb 6ff 6ff 6ff 6bf 6c0 6c1 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85d 6c4 6c5 6c6 6c7 6c8 6c9 6ca 6cb | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 6ff 6ff 6ff 6ff 6ff 6dd 6de 6df | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 6ff 6ff 6e4 6e5 6e6 6e7 6e8 6e9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6eb 6ec 6ed 6ff 6ff 6ff 6f1 6f2 6f3 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6f5 6f6 6f7 6f8 6f9 6fa 6fb 6fc 6fd | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6ff 6ff 6ff 6ff 6ff 6ff 70f 710 711 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +713 714 731 716 717 718 719 71a 71b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +71d 71e 71f 714 731 731 723 724 725 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +727 728 729 72a 72b 72c 72d 72e 72f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +731 731 731 731 731 731 731 731 731 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +731 731 731 731 731 731 741 742 743 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +731 731 713 748 749 74a 74b 74c 74d | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +74f 750 751 731 713 714 755 756 757 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +759 75a 75b 75c 75d 75e 75f 760 761 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 795 795 795 795 795 795 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 795 795 795 773 774 775 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 77a 77b 77c 77d 77e 77f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +781 782 783 795 795 795 787 788 789 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +78b 78c 78d 78e 78f 790 791 792 793 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 795 795 795 795 795 795 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 795 795 795 7a5 7a6 7a7 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +795 795 795 7ac 7ad 7ae 7af 7b0 7b1 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7b3 7b4 7b5 7f9 7f9 7f9 7b9 7ba 7bb | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7bd 7be 7bf 7c0 7c1 7c2 7c3 7c4 7c5 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7f9 7f9 7f9 7f9 7f9 7f9 7d7 7d8 7d9 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7f9 7f9 7f9 7de 7df 7e0 7e1 7e2 7e3 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7e5 7e6 7e7 7f9 7f9 7f9 7eb 7ec 7ed | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7ef 7f0 7f1 7f2 7f3 7f4 7f5 7f6 7f7 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7f9 7f9 7f9 7f9 7f9 7f9 809 80a 80b | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +80d 80e 82b 810 811 812 813 814 815 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +817 818 819 80e 82b 82b 81d 81e 81f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +821 822 823 824 825 826 827 828 829 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +82b 82b 82b 82b 82b 82b 82b 82b 82b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +82b 82b 82b 82b 82b 82b 83b 83c 83d | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +82b 82b 80d 842 843 844 845 846 847 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +849 84a 84b 82b 80d 80e 84f 850 851 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +853 854 855 856 857 858 859 85a 85b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85d 85e 85f 860 861 862 863 864 865 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +867 868 869 86a 86b 86c 86d 86e 86f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index b51a5a369..585d44b95 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -341,7 +341,7 @@ namespace nil { static boost::random::mt19937 gen; static boost::random::uniform_int_distribution<> dist(0, 100); - std::size_t start_row = dist(gen); + std::size_t start_row = 0;//dist(gen); if constexpr (PrivateInput) { for (std::size_t i = 0; i < public_input.size(); i++) { @@ -360,8 +360,86 @@ namespace nil { // bp.export_circuit(std::cout); result_check(assignment, component_result); - BOOST_ASSERT(bp.num_gates() == 0); - BOOST_ASSERT(bp.num_lookup_gates() == 0); + if constexpr (!PrivateInput) { + bool is_connected; + if (connectedness_check == detail::connectedness_check_type::STRONG) { + is_connected = check_strong_connectedness( + assignment, + bp, + instance_input.all_vars(), + component_result.all_vars(), start_row, component_instance.rows_amount); + } else if (connectedness_check == detail::connectedness_check_type::WEAK) { + is_connected = check_weak_connectedness( + assignment, + bp, + instance_input.all_vars(), + component_result.all_vars(), start_row, component_instance.rows_amount); + } else if (connectedness_check == detail::connectedness_check_type::NONE) { + is_connected = true; + std::cout << "WARNING: connectedness check disabled" << std::endl; + } + + // Uncomment the following if you want to output a visual representation of the connectedness graph. + // I recommend turning off the starting row randomization + + auto zones = blueprint::detail::generate_connectedness_zones( + assignment, bp, instance_input.all_vars(), start_row, component_instance.rows_amount); + blueprint::detail::export_connectedness_zones( + zones, assignment, instance_input.all_vars(), start_row, component_instance.rows_amount, std::cout); + + BOOST_ASSERT_MSG(is_connected, + "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); + } + + zk::snark::plonk_table_description desc; + desc.usable_rows_amount = assignment.rows_amount(); + + if (start_row + component_instance.rows_amount >= public_input.size()) { + BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == component_instance.rows_amount, + "Component rows amount does not match actual rows amount."); + // Stretched components do not have a manifest, as they are dynamically generated. + if constexpr (!blueprint::components::is_component_stretcher< + BlueprintFieldType, ArithmetizationParams, ComponentType>::value) { + BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == + component_type::get_rows_amount(component_instance.witness_amount(), 0, + component_static_info_args...), + "Static component rows amount does not match actual rows amount."); + } + } + // Stretched components do not have a manifest, as they are dynamically generated. + if constexpr (!blueprint::components::is_component_stretcher< + BlueprintFieldType, ArithmetizationParams, ComponentType>::value) { + BOOST_ASSERT_MSG(bp.num_gates() + bp.num_lookup_gates()== + component_type::get_gate_manifest(component_instance.witness_amount(), 0, + component_static_info_args...).get_gates_amount(), + "Component total gates amount does not match actual gates amount."); + } + + if(nil::blueprint::use_lookups()){ + // Components with lookups may use constant columns. + // But now all constants are placed in the first column. + // So we reserve the first column for non-lookup constants. + // Rather universal for testing + // We may start from zero if component doesn't use ordinary constants. + std::vector lookup_columns_indices; + for( std::size_t i = 1; i < ArithmetizationParams::constant_columns; i++ ) lookup_columns_indices.push_back(i); + desc.usable_rows_amount = zk::snark::detail::pack_lookup_tables( + bp.get_reserved_indices(), + bp.get_reserved_tables(), + bp, assignment, lookup_columns_indices, + desc.usable_rows_amount + ); + } + desc.rows_amount = zk::snark::basic_padding(assignment); + +#ifdef BLUEPRINT_PLONK_PROFILING_ENABLED + std::cout << "Usable rows: " << desc.usable_rows_amount << std::endl; + std::cout << "Padded rows: " << desc.rows_amount << std::endl; + + profiling(assignment); +#endif + + assert(blueprint::is_satisfied(bp, assignment) == expected_to_pass); return std::make_tuple(desc, bp, assignment); } From 8ee021cd2fb238aa843b5e2c31e2b66b54bcbbeb Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 2 Nov 2023 18:58:18 +0000 Subject: [PATCH 18/48] deleted junk file --- ...tnesses_size: 9 public_inputs_size: 1 .cpp | 217 ------------------ 1 file changed, 217 deletions(-) delete mode 100644 test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp diff --git a/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp b/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp deleted file mode 100644 index 2306a2b09..000000000 --- a/test/hashes/plonk/witnesses_size: 9 public_inputs_size: 1 .cpp +++ /dev/null @@ -1,217 +0,0 @@ -witnesses_size: 9 public_inputs_size: 1 constants_size: 1 selectors_size: 15 max_size: 216 -1 2 3 4 5 6 7 8 9 | 1 | a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -b c d e f 10 11 12 13 | 29 | 14 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -15 16 17 18 19 1a 1b 1c 1d | 51 | 1e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -c9 20 21 22 23 24 25 26 27 | 79 | 28 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -29 2a 2b 2c 2d 2e 2f 30 31 | a1 | 32 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -33 34 35 36 37 38 39 3a 3b | 2 | 3c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3d 3e 3f 40 41 42 43 44 45 | 2a | 46 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -e7 48 49 4a 4b 4c 4d 4e 4f | 52 | 50 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -51 52 53 54 55 56 57 58 59 | 7a | 5a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5b 5c 5d 5e 5f 60 61 62 63 | a2 | 64 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -65 66 67 68 69 6a 6b 6c 6d | 3 | 6e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -fe 70 71 72 73 74 75 76 77 | 2b | 78 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -79 7a 7b 7c 7d 7e 7f 80 81 | 53 | 82 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -83 84 85 86 87 88 89 8a 8b | 7b | 8c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8d 8e 8f 90 91 92 93 94 95 | a3 | 96 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -119 98 99 9a 9b 9c 9d 9e 9f | 4 | a0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -a1 a2 a3 a4 a5 a6 a7 a8 a9 | 2c | aa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ab ac ad ae af b0 b1 b2 b3 | 54 | b4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -b5 b6 b7 b8 b9 ba bb bc bd | 7c | be | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -137 c0 c1 c2 c3 c4 c5 c6 c7 | a4 | c8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -c9 1c7 d2 cc cd ce cf d0 d1 | 5 | d2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -d3 d4 d5 d6 d7 d8 d9 da db | 2d | dc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -dd de df e0 e1 e2 e6 e4 e5 | 55 | e6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -e7 14f e9 ea eb ec ed ee ef | 7d | f0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -f1 f2 f3 f4 f5 f6 f7 f8 f9 | a5 | fa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -fb fc fd fe 16d 104 101 102 103 | 88a | 104 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -105 106 107 108 109 10a 10b 10c 10d | 88b | 10e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10f 110 111 112 113 114 115 116 117 | 88c | 118 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -119 18b 122 11c 11d 11e 11f 120 121 | 88d | 122 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -123 124 125 126 127 128 129 12a 12b | 88e | 12c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -12d 12e 12f 130 131 132 136 134 135 | 88f | 136 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -137 1a9 139 13a 13b 13c 13d 13e 13f | 890 | 140 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -141 142 143 144 145 146 147 148 149 | 891 | 14a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14b 14c 14d 1 14f 137 151 152 153 | 892 | 154 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -155 156 157 158 159 15a 15b 15c 15d | 893 | 15e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -15f 160 161 162 163 164 165 166 167 | 894 | 168 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 16a 16b 29 16d c9 16f 170 171 | 895 | 172 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -173 174 175 176 177 178 179 17a 17b | 896 | 17c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -17d 17e 17f 180 181 182 183 184 185 | 897 | 186 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -43c 188 189 51 18b e7 18d 18e 18f | 898 | 190 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -191 192 193 194 195 196 197 198 199 | 899 | 19a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -19b 19c 19d 19e 19f 1a0 1a1 1a2 1a3 | 89a | 1a4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -61c 1a6 1a7 79 1a9 fe 1ab 1ac 1ad | 85e | 1ae | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1af 1b0 1b1 1b2 1b3 1b4 1b5 1b6 1b7 | 0 | 1b8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1b9 1ba 1bb 1bc 1bd 1be 1bf 1c0 1c1 | 0 | 1c2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4dc 1c4 1c5 a1 1c7 119 1c9 1ca 1cb | 0 | 1cc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1cd 1ce 1cf 1d0 1d1 1d2 1d3 1d4 1d5 | 0 | 1d6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1d7 1d8 1d9 1da 1db 1dc 1dd 1de 1df | 0 | 1e0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -57c 1e2 1e3 2 14f 137 1e7 1e8 1e9 | 0 | 1ea | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1eb 1ec 1ed 1ee 1ef 1f0 1f1 1f2 1f3 | 0 | 1f4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1f5 1f6 1f7 1f8 1f9 1fa 1fb 1fc 1fd | 0 | 1fe | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4f7 200 201 2a 16d c9 205 206 207 | 0 | 208 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -209 20a 20b 20c 20d 20e 20f 210 211 | 0 | 212 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -213 214 215 216 217 218 219 21a 21b | 0 | 21c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6a5 21e 21f 52 18b e7 223 224 225 | 0 | 226 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -227 228 229 22a 22b 22c 22d 22e 22f | 0 | 230 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -231 232 233 234 235 236 237 238 239 | 0 | 23a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -475 23c 23d 7a 1a9 fe 241 242 243 | 0 | 244 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -245 246 247 248 249 24a 24b 24c 24d | 0 | 24e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -24f 250 251 252 253 254 255 256 257 | 0 | 258 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -52c 25a 25b a2 1c7 119 25f 260 261 | 0 | 262 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -263 264 265 266 267 268 269 26a 26b | 0 | 26c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -26d 26e 26f 270 271 272 273 274 275 | 0 | 276 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -687 278 279 3 14f 137 27d 27e 27f | 0 | 280 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -281 282 283 284 285 286 287 288 289 | 0 | 28a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -28b 28c 28d 28e 28f 290 291 292 293 | 0 | 294 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -457 296 297 2b 16d c9 29b 29c 29d | 0 | 29e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -29f 2a0 2a1 2a2 2a3 2a4 2a5 2a6 2a7 | 0 | 2a8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2a9 2aa 2ab 2ac 2ad 2ae 2af 2b0 2b1 | 0 | 2b2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -48c 2b4 2b5 53 18b e7 2b9 2ba 2bb | 0 | 2bc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2bd 2be 2bf 2c0 2c1 2c2 2c3 2c4 2c5 | 0 | 2c6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2c7 2c8 2c9 2ca 2cb 2cc 2cd 2ce 2cf | 0 | 2d0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -605 2d2 2d3 7b 1a9 fe 2d7 2d8 2d9 | 0 | 2da | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2db 2dc 2dd 2de 2df 2e0 2e1 2e2 2e3 | 0 | 2e4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2e5 2e6 2e7 2e8 2e9 2ea 2eb 2ec 2ed | 0 | 2ee | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5e7 2f0 2f1 a3 1c7 119 2f5 2f6 2f7 | 0 | 2f8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2f9 2fa 2fb 2fc 2fd 2fe 2ff 300 301 | 0 | 302 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -303 304 305 306 307 308 309 30a 30b | 0 | 30c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -655 30e 30f 4 14f 137 313 314 315 | 0 | 316 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -317 318 319 31a 31b 31c 31d 31e 31f | 0 | 320 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -321 322 323 324 325 326 327 328 329 | 0 | 32a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -597 32c 32d 2c 16d c9 331 332 333 | 0 | 334 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -335 336 337 338 339 33a 33b 33c 33d | 0 | 33e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -33f 340 341 342 343 344 345 346 347 | 0 | 348 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -515 34a 34b 54 18b e7 34f 350 351 | 0 | 352 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -353 354 355 356 357 358 359 35a 35b | 0 | 35c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -35d 35e 35f 360 361 362 363 364 365 | 0 | 366 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4a7 368 369 7c 1a9 fe 36d 36e 36f | 0 | 370 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -371 372 373 374 375 376 377 378 379 | 0 | 37a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -37b 37c 37d 37e 37f 380 381 382 383 | 0 | 384 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4c5 386 387 a4 1c7 119 38b 38c 38d | 0 | 38e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -38f 390 391 392 393 394 395 396 397 | 0 | 398 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -399 39a 39b 39c 39d 39e 39f 3a0 3a1 | 0 | 3a2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5cc 3a4 3a5 5 14f 137 3a9 3aa 3ab | 0 | 3ac | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3ad 3ae 3af 3b0 3b1 3b2 3b3 3b4 3b5 | 0 | 3b6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3b7 3b8 3b9 3ba 3bb 3bc 3bd 3be 3bf | 0 | 3c0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -637 3c2 3c3 2d 16d c9 3c7 3c8 3c9 | 0 | 3ca | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3cb 3cc 3cd 3ce 3cf 3d0 3d1 3d2 3d3 | 0 | 3d4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3d5 3d6 3d7 3d8 3d9 3da 3db 3dc 3dd | 0 | 3de | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -547 3e0 3e1 55 18b e7 3e5 3e6 3e7 | 0 | 3e8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3e9 3ea 3eb 3ec 3ed 3ee 3ef 3f0 3f1 | 0 | 3f2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3f3 3f4 3f5 3f6 3f7 3f8 3f9 3fa 3fb | 0 | 3fc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -66c 3fe 3ff 7d 1a9 fe 403 404 405 | 0 | 406 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -407 408 409 40a 40b 40c 40d 40e 40f | 0 | 410 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -411 412 413 414 415 416 417 418 419 | 0 | 41a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5b5 41c 41d a5 1c7 119 421 422 423 | 0 | 424 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -425 426 427 428 429 42a 42b 42c 42d | 0 | 42e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -42f 430 431 432 433 434 435 436 437 | 0 | 438 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -565 43a 43b 43c 795 442 43f 440 441 | 0 | 442 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -443 444 445 446 447 448 449 44a 44b | 0 | 44c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -44d 44e 44f 450 451 452 453 454 455 | 0 | 456 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -457 731 460 45a 45b 45c 45d 45e 45f | 0 | 460 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -461 462 463 464 465 466 467 468 469 | 0 | 46a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -46b 46c 46d 46e 46f 470 474 472 473 | 0 | 474 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -475 795 477 478 479 47a 47b 47c 47d | 0 | 47e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -47f 480 481 482 483 484 485 486 487 | 0 | 488 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -489 48a 48b 48c 7f9 492 48f 490 491 | 0 | 492 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -493 494 495 496 497 498 499 49a 49b | 0 | 49c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -49d 49e 49f 4a0 4a1 4a2 4a3 4a4 4a5 | 0 | 4a6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4a7 7f9 4b0 4aa 4ab 4ac 4ad 4ae 4af | 0 | 4b0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4b1 4b2 4b3 4b4 4b5 4b6 4b7 4b8 4b9 | 0 | 4ba | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4bb 4bc 4bd 4be 4bf 4c0 4c4 4c2 4c3 | 0 | 4c4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4c5 6ff 4c7 4c8 4c9 4ca 4cb 4cc 4cd | 0 | 4ce | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4cf 4d0 4d1 4d2 4d3 4d4 4d5 4d6 4d7 | 0 | 4d8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4d9 4da 4db 4dc 713 4e2 4df 4e0 4e1 | 0 | 4e2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4e3 4e4 4e5 4e6 4e7 4e8 4e9 4ea 4eb | 0 | 4ec | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4ed 4ee 4ef 4f0 4f1 4f2 4f3 4f4 4f5 | 0 | 4f6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4f7 7f9 500 4fa 4fb 4fc 4fd 4fe 4ff | 0 | 500 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -501 502 503 504 505 506 507 508 509 | 0 | 50a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -50b 50c 50d 50e 50f 510 514 512 513 | 0 | 514 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -515 731 517 518 519 51a 51b 51c 51d | 0 | 51e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -51f 520 521 522 523 524 525 526 527 | 0 | 528 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -529 52a 52b 52c 80e 532 52f 530 531 | 0 | 532 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -533 534 535 536 537 538 539 53a 53b | 0 | 53c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -53d 53e 53f 540 541 542 543 544 545 | 0 | 546 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -547 82b 550 54a 54b 54c 54d 54e 54f | 0 | 550 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -551 552 553 554 555 556 557 558 559 | 0 | 55a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -55b 55c 55d 55e 55f 560 564 562 563 | 0 | 564 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -565 6ff 567 568 569 56a 56b 56c 56d | 0 | 56e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -56f 570 571 572 573 574 575 576 577 | 0 | 578 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -579 57a 57b 57c 7f9 582 57f 580 581 | 0 | 582 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -583 584 585 586 587 588 589 58a 58b | 0 | 58c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -58d 58e 58f 590 591 592 593 594 595 | 0 | 596 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -597 82b 5a0 59a 59b 59c 59d 59e 59f | 0 | 5a0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5a1 5a2 5a3 5a4 5a5 5a6 5a7 5a8 5a9 | 0 | 5aa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5ab 5ac 5ad 5ae 5af 5b0 5b4 5b2 5b3 | 0 | 5b4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5b5 7f9 5b7 5b8 5b9 5ba 5bb 5bc 5bd | 0 | 5be | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5bf 5c0 5c1 5c2 5c3 5c4 5c5 5c6 5c7 | 0 | 5c8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5c9 5ca 5cb 5cc 795 5d2 5cf 5d0 5d1 | 0 | 5d2 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5d3 5d4 5d5 5d6 5d7 5d8 5d9 5da 5db | 0 | 5dc | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5dd 5de 5df 5e0 5e1 5e2 5e3 5e4 5e5 | 0 | 5e6 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5e7 795 5f0 5ea 5eb 5ec 5ed 5ee 5ef | 0 | 5f0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5f1 5f2 5f3 5f4 5f5 5f6 5f7 5f8 5f9 | 0 | 5fa | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5fb 5fc 5fd 5fe 5ff 600 604 602 603 | 0 | 604 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -605 6ff 607 608 609 60a 60b 60c 60d | 0 | 60e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -60f 610 611 612 613 614 615 616 617 | 0 | 618 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -619 61a 61b 61c 80d 622 61f 620 621 | 0 | 622 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -623 624 625 626 627 628 629 62a 62b | 0 | 62c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -62d 62e 62f 630 631 632 633 634 635 | 0 | 636 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -637 795 640 63a 63b 63c 63d 63e 63f | 0 | 640 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -641 642 643 644 645 646 647 648 649 | 0 | 64a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -64b 64c 64d 64e 64f 650 654 652 653 | 0 | 654 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -655 82b 657 658 659 65a 65b 65c 65d | 0 | 65e | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -65f 660 661 662 663 664 665 666 667 | 0 | 668 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -669 66a 66b 66c 731 672 66f 670 671 | 0 | 672 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -673 674 675 676 677 678 679 67a 67b | 0 | 67c | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -67d 67e 67f 680 681 682 683 684 685 | 0 | 686 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -687 714 690 68a 68b 68c 68d 68e 68f | 0 | 690 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -691 692 693 694 695 696 697 698 699 | 0 | 69a | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -69b 69c 69d 69e 69f 6a0 6a4 6a2 6a3 | 0 | 6a4 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6a5 6ff 6a7 6a8 6a9 6aa 6ab 6ac 6ad | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6af 6b0 6b1 6b2 6b3 6b4 6b5 6b6 6b7 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6b9 6ba 6bb 6ff 6ff 6ff 6bf 6c0 6c1 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85d 6c4 6c5 6c6 6c7 6c8 6c9 6ca 6cb | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 6ff 6ff 6ff 6ff 6ff 6dd 6de 6df | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 6ff 6ff 6e4 6e5 6e6 6e7 6e8 6e9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6eb 6ec 6ed 6ff 6ff 6ff 6f1 6f2 6f3 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6f5 6f6 6f7 6f8 6f9 6fa 6fb 6fc 6fd | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff 6ff | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6ff 6ff 6ff 6ff 6ff 6ff 70f 710 711 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -713 714 731 716 717 718 719 71a 71b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -71d 71e 71f 714 731 731 723 724 725 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -727 728 729 72a 72b 72c 72d 72e 72f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -731 731 731 731 731 731 731 731 731 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -731 731 731 731 731 731 741 742 743 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -731 731 713 748 749 74a 74b 74c 74d | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -74f 750 751 731 713 714 755 756 757 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -759 75a 75b 75c 75d 75e 75f 760 761 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 795 795 795 795 795 795 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 795 795 795 773 774 775 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 77a 77b 77c 77d 77e 77f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -781 782 783 795 795 795 787 788 789 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -78b 78c 78d 78e 78f 790 791 792 793 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 795 795 795 795 795 795 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 795 795 795 7a5 7a6 7a7 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -795 795 795 7ac 7ad 7ae 7af 7b0 7b1 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7b3 7b4 7b5 7f9 7f9 7f9 7b9 7ba 7bb | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7bd 7be 7bf 7c0 7c1 7c2 7c3 7c4 7c5 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7f9 7f9 7f9 7f9 7f9 7f9 7d7 7d8 7d9 | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7f9 7f9 7f9 7de 7df 7e0 7e1 7e2 7e3 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7e5 7e6 7e7 7f9 7f9 7f9 7eb 7ec 7ed | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7ef 7f0 7f1 7f2 7f3 7f4 7f5 7f6 7f7 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 7f9 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7f9 7f9 7f9 7f9 7f9 7f9 809 80a 80b | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -80d 80e 82b 810 811 812 813 814 815 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -817 818 819 80e 82b 82b 81d 81e 81f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -821 822 823 824 825 826 827 828 829 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -82b 82b 82b 82b 82b 82b 82b 82b 82b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -82b 82b 82b 82b 82b 82b 83b 83c 83d | 0 | 0 | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -82b 82b 80d 842 843 844 845 846 847 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -849 84a 84b 82b 80d 80e 84f 850 851 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -853 854 855 856 857 858 859 85a 85b | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85d 85e 85f 860 861 862 863 864 865 | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -867 868 869 86a 86b 86c 86d 86e 86f | 0 | 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file From fe9ecbad1fd8c7963c9d3bdedcf93341399f5005 Mon Sep 17 00:00:00 2001 From: Valeh2012 Date: Fri, 10 Nov 2023 06:29:20 +0200 Subject: [PATCH 19/48] keccak padding component fixes --- .../hashes/keccak/keccak_padding.hpp | 512 +++++++++--------- test/hashes/plonk/keccak_padding.cpp | 92 ++-- 2 files changed, 322 insertions(+), 282 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index da0e1f16c..6b1574f31 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -43,27 +43,25 @@ namespace nil { class keccak_padding; template - class keccak_padding> : - public plonk_component { + class keccak_padding> + : public plonk_component { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; public: - struct coordinates { - std::size_t row; - std::size_t column; + std::int32_t row; + std::int32_t column; coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; - bool operator== (const coordinates& other) const { + coordinates(std::int32_t row_, std::int32_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; + bool operator==(const coordinates &other) const { return row == other.row && column == other.column; } - bool operator< (const coordinates& other) const { + bool operator<(const coordinates &other) const { return row < other.row || (row == other.row && column < other.column); } }; @@ -76,46 +74,50 @@ namespace nil { std::vector> constraints; std::vector> lookups; coordinates copy_from; + std::size_t row; configuration() = default; configuration(std::pair first_coordinate_, - std::pair last_coordinate_, - std::vector> copy_to_, - std::vector>> constraints_, - std::vector>> lookups_, - std::pair copy_from_) { - first_coordinate = coordinates(first_coordinate_); - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to.push_back(coordinates(copy_to_[i])); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - std::vector constr; - for (std::size_t j = 0; j < constraints_[i].size(); ++j) { - constr.push_back(coordinates(constraints_[i][j])); - } - constraints.push_back(constr); + std::pair + last_coordinate_, + std::vector> + copy_to_, + std::vector>> + constraints_, + std::vector>> + lookups_, + std::pair + copy_from_, std::size_t row_) { + first_coordinate = coordinates(first_coordinate_); + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to.push_back(coordinates(copy_to_[i])); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - std::vector lookup; - for (std::size_t j = 0; j < lookups_[i].size(); ++j) { - lookup.push_back(coordinates(lookups_[i][j])); - } - lookups.push_back(lookup); + constraints.push_back(constr); + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); } - copy_from = coordinates(copy_from_); - }; - bool operator== (const configuration& other) const { - return first_coordinate == other.first_coordinate && - last_coordinate == other.last_coordinate && - copy_to == other.copy_to && - constraints == other.constraints && - lookups == other.lookups && - copy_from == other.copy_from; + lookups.push_back(lookup); + } + copy_from = coordinates(copy_from_); + row = row_; + }; + bool operator==(const configuration &other) const { + return first_coordinate == other.first_coordinate && last_coordinate == other.last_coordinate && + copy_to == other.copy_to && constraints == other.constraints && + lookups == other.lookups && copy_from == other.copy_from; } - bool operator< (const configuration& other) const { + bool operator<(const configuration &other) const { return first_coordinate < other.first_coordinate || - (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); } }; struct padding_gate { @@ -130,15 +132,12 @@ namespace nil { padding_gate(coordinates relay_, std::vector value_, std::vector sum_, std::vector range_check_, std::vector first_, std::vector second_) : - relay(relay_), value(value_), sum(sum_), range_check(range_check_), first(first_), second(second_) {}; - - bool operator== (const padding_gate& other) const { - return relay == other.relay && - value == other.value && - sum == other.sum && - range_check == other.range_check && - first == other.first && - second == other.second; + relay(relay_), + value(value_), sum(sum_), range_check(range_check_), first(first_), second(second_) {}; + + bool operator==(const padding_gate &other) const { + return relay == other.relay && value == other.value && sum == other.sum && + range_check == other.range_check && first == other.first && second == other.second; } }; @@ -153,8 +152,10 @@ namespace nil { std::size_t last_gate; static constexpr const std::size_t clamp = 15; - gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t last_gate_) - : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_), last_gate(last_gate_) {}; + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, + std::size_t last_gate_) : + witness_amount(std::min(witness_amount_, clamp)), + num_blocks(num_blocks_), num_bits(num_bits_), last_gate(last_gate_) {}; std::uint32_t gates_amount() const override { return keccak_padding::get_gates_amount(witness_amount, num_blocks, num_bits, last_gate); @@ -167,20 +168,19 @@ namespace nil { std::size_t num_bits, std::size_t limit_permutation_column) { auto last_gate = calculate_last_gate(witness_amount, num_blocks); - gate_manifest manifest = gate_manifest(gate_manifest_type(witness_amount, num_blocks, - num_bits, last_gate)); + gate_manifest manifest = + gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, last_gate)); return manifest; } static manifest_type get_manifest() { - static manifest_type manifest = manifest_type( - std::shared_ptr( - new nil::blueprint::manifest_single_value_param(9)), - true - ); + static manifest_type manifest = + manifest_type(std::shared_ptr( + new nil::blueprint::manifest_single_value_param(9)), + true); return manifest; } - + static const std::size_t lookup_rows = 65536; // const std::size_t lookup_columns; @@ -194,18 +194,20 @@ namespace nil { padding_gate first_gate_15 = calculate_first_gate_15(); std::size_t last_gate = calculate_last_gate(this->witness_amount(), num_blocks); std::size_t confs_per_gate = calculate_confs_per_gate(this->witness_amount()); - const std::vector full_configuration = configure_all(this->witness_amount(), num_blocks, num_bits, limit_permutation_column); + const std::vector full_configuration = + configure_all(this->witness_amount(), num_blocks, num_bits, limit_permutation_column); std::vector gates_rows = calculate_gates_rows(this->witness_amount()); - // const std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount()); + // const std::vector lookup_gates_configuration = + // configure_lookup_gates(this->witness_amount()); - const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, limit_permutation_column); + const std::size_t rows_amount = + get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, shift, last_gate); const std::size_t lookup_gates_amount = num_blocks; struct input_type { - // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + message[num_blocks - 1] - // all message[i] are 64-bit for i > 0 - // message[0] is <= 64-bit + // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + + // message[num_blocks - 1] all message[i] are 64-bit for i > 0 message[0] is <= 64-bit std::vector message; std::vector all_vars() const { @@ -219,10 +221,11 @@ namespace nil { result_type(const keccak_padding &component, std::size_t start_row_index) { for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { auto config = component.full_configuration[i]; - padded_message.push_back(var(component.W(config.copy_from.column), config.copy_from.row + start_row_index, false)); + padded_message.push_back(var(component.W(config.copy_from.column), + config.copy_from.row + config.row + start_row_index, false)); } for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { - padded_message.push_back(var(component.C(0), start_row_index, false)); + padded_message.push_back(var(component.C(0), start_row_index, false, var::column_type::constant)); } } @@ -236,28 +239,32 @@ namespace nil { } static padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { - if (witness_amount == 9) return padding_9(row); - if (witness_amount == 15) return padding_15(row); + if (witness_amount == 9) + return padding_9(row); + if (witness_amount == 15) + return padding_15(row); return padding_gate(); } static padding_gate padding_9(std::size_t row = 0) { padding_gate res; - res.relay = {-1 + row, 0}; - res.value = {{-1 + row, 1}, {-1 + row, 3}, {0 + row, 0}, {0 + row, 2}, {1 + row, 0}}; - res.sum = {{-1 + row, 2}, {-1 + row, 4}, {0 + row, 1}, {0 + row, 3}, {1 + row, 1}}; - res.first = {{-1 + row, 5}, {-1 + row, 7}, {0 + row, 4}, {0 + row, 6}, {1 + row, 2}}; - res.second = {{-1 + row, 6}, {-1 + row, 8}, {0 + row, 5}, {0 + row, 7}, {1 + row, 3}}; - res.range_check = {{1 + row, 4}, {1 + row, 5}, {1 + row, 6}, {1 + row, 7}, {1 + row, 8}}; + res.relay = {-1, 0}; + res.value = {{-1, 1}, {-1, 3}, {0, 0}, {0, 2}, {1, 0}}; + res.sum = {{-1, 2}, {-1, 4}, {0, 1}, {0, 3}, {1, 1}}; + res.first = {{-1, 5}, {-1, 7}, {0, 4}, {0, 6}, {1, 2}}; + res.second = {{-1, 6}, {-1, 8}, {0, 5}, {0, 7}, {1, 3}}; + res.range_check = {{1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}}; return res; } static padding_gate padding_15(std::size_t row = 0) { padding_gate res; - res.relay = {-1 + row, 11}; - res.value = {{0 + row,0}, {0 + row,1}, {0 + row,2}, {1 + row,0}, {1 + row,1}, {1 + row,2}}; - res.sum = {{0 + row,3}, {0 + row,4}, {0 + row,5}, {1 + row,3}, {1 + row,4}, {1 + row,5}}; - res.first = {{0 + row,6}, {0 + row,7}, {0 + row,8}, {1 + row,6}, {1 + row,7}, {1 + row,8}}; - res.second = {{0 + row,9}, {0 + row,10}, {0 + row,11}, {1 + row,9}, {1 + row,10}, {1 + row,11}}; - res.range_check = {{0 + row,12}, {0 + row,13}, {0 + row,14}, {1 + row,12}, {1 + row,13}, {1 + row,14}}; + res.relay = {-1, 11}; + res.value = {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}}; + res.sum = {{0, 3}, {0, 4}, {0, 5}, {1, 3}, {1, 4}, {1, 5}}; + res.first = {{0, 6}, {0, 7}, {0, 8}, {1, 6}, {1, 7}, {1, 8}}; + res.second = {{0, 9}, {0, 10}, {0, 11}, + {1, 9}, {1, 10}, {1, 11}}; + res.range_check = {{0, 12}, {0, 13}, {0, 14}, + {1, 12}, {1, 13}, {1, 14}}; return res; } @@ -266,12 +273,12 @@ namespace nil { } padding_gate calculate_first_gate_15(std::size_t row = 0) { padding_gate res; - res.relay = {0 + row, 0}; - res.value = {{0 + row,1}, {0 + row,2}}; - res.sum = {{0 + row,3}, {0 + row,4}}; - res.first = {{0 + row,5}, {0 + row,6}}; - res.second = {{0 + row,7}, {0 + row,11}}; - res.range_check = {{0 + row,8}, {0 + row,9}}; + res.relay = {0, 0}; + res.value = {{0, 1}, {0, 2}}; + res.sum = {{0, 3}, {0, 4}}; + res.first = {{0, 5}, {0, 6}}; + res.second = {{0, 7}, {0, 11}}; + res.range_check = {{0, 8}, {0, 9}}; return res; } static std::size_t calculate_last_gate(std::size_t witness_amount, std::size_t num_blocks) { @@ -295,9 +302,8 @@ namespace nil { } static std::vector configure_batching(std::size_t witness_amount, - std::size_t num_blocks) { + std::size_t num_blocks) { std::vector result; - std::cout << witness_amount << std::endl; std::size_t conf_ind = 0; std::size_t row = 1; std::size_t confs_per_gate = calculate_confs_per_gate(witness_amount); @@ -307,8 +313,9 @@ namespace nil { std::size_t j = 0; { configuration conf; + conf.row = row; conf.last_coordinate = pg.second[0]; - conf.copy_to = {pg.relay, pg.value[0]}; + conf.copy_to = {pg.value[0], pg.relay}; conf.constraints = {{pg.value[0], pg.first[0], pg.second[0]}, {pg.sum[0], pg.relay, pg.first[0]}, {pg.range_check[0], pg.relay}}; @@ -320,33 +327,34 @@ namespace nil { } while ((j < confs_per_gate) && (conf_ind < num_blocks - 2 * (witness_amount == 15))) { configuration conf; + conf.row = row; conf.last_coordinate = pg.second[j]; conf.copy_to = {pg.value[j]}; conf.constraints = {{pg.value[j], pg.first[j], pg.second[j]}, - {pg.sum[j], pg.second[j-1], pg.first[j]}, - {pg.range_check[j], pg.second[j-1]}}; + {pg.sum[j], pg.second[j - 1], pg.first[j]}, + {pg.range_check[j], pg.second[j - 1]}}; conf.lookups = {{pg.range_check[j]}}; conf.copy_from = pg.sum[j]; result.push_back(conf); j++; conf_ind++; } - if (witness_amount == 9) row += 3; - if (witness_amount == 15) row += 2; + if (witness_amount == 9) + row += 3; + if (witness_amount == 15) + row += 2; } - return result; } static std::vector configure_all(std::size_t witness_amount, - std::size_t num_blocks, + std::size_t num_blocks, std::size_t num_bits, std::size_t limit_permutation_column) { std::size_t shift = num_blocks * 64 - num_bits; std::vector result; if (shift == 0) { - std::size_t row = 0, - column = 0; + std::size_t row = 0, column = 0; for (std::size_t i = 0; i < num_blocks; ++i) { configuration conf; conf.copy_from = {row, column}; @@ -361,17 +369,13 @@ namespace nil { if (witness_amount % 15 == 0) { configuration conf0; conf0.copy_to = {{0, 0}, {0, 1}}; - conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, - {{0, 3}, {0, 0}, {0, 5}}, - {{0, 8}, {0, 0}}}; + conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, {{0, 3}, {0, 0}, {0, 5}}, {{0, 8}, {0, 0}}}; conf0.lookups = {{{0, 8}}}; conf0.copy_from = {0, 3}; result.push_back(conf0); configuration conf1; conf1.copy_to = {{0, 2}}; - conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, - {{0, 4}, {0, 7}, {0, 6}}, - {{0, 9}, {0, 7}}}; + conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, {{0, 4}, {0, 7}, {0, 6}}, {{0, 9}, {0, 7}}}; conf1.lookups = {{{0, 9}}}; conf1.copy_from = {0, 4}; result.push_back(conf1); @@ -387,8 +391,8 @@ namespace nil { std::vector calculate_gates_rows(std::size_t witness_amount) { std::vector res; std::size_t incr = 3; - std::size_t block_per_gate = 5; - std::size_t first_block = 0; + std::size_t block_per_gate = 5; + std::size_t first_block = 0; if (witness_amount == 15) { res.push_back(0); incr = 2; @@ -411,7 +415,7 @@ namespace nil { return 0; } if (witness_amount == 9) { - if (last_gate == 0 || last_gate == num_blocks - 1) { + if (last_gate == 0 || last_gate == num_blocks) { return 1; } return 2; @@ -427,24 +431,27 @@ namespace nil { return 0; } static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t lookup_column_amount, - std::size_t num_blocks, - std::size_t num_bits, - std::size_t limit_permutation_column) { + std::size_t lookup_column_amount, + std::size_t num_blocks, + std::size_t num_bits, + std::size_t limit_permutation_column) { auto conf = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); - return conf.back().constraints.back().back().row; + if(witness_amount == 9) { + return std::ceil(conf.size() / 5.0) * 3; + } + if(witness_amount == 15) { + return std::ceil(conf.size() / 6.0) * 2; + } } template keccak_padding(WitnessContainerType witness, ConstantContainerType constant, - PublicInputContainerType public_input, - std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7): - component_type(witness, constant, public_input, get_manifest()), - num_blocks(num_blocks_), - num_bits(num_bits_), - limit_permutation_column(lpc_) {}; + PublicInputContainerType public_input, std::size_t num_blocks_, std::size_t num_bits_, + std::size_t lpc_ = 7) : + component_type(witness, constant, public_input, get_manifest()), + num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; keccak_padding( std::initializer_list witnesses, @@ -452,34 +459,26 @@ namespace nil { std::initializer_list public_inputs, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : - component_type(witnesses, constants, public_inputs, get_manifest()), - num_blocks(num_blocks_), - num_bits(num_bits_), - limit_permutation_column(lpc_) {}; - - - using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; + component_type(witnesses, constants, public_inputs, get_manifest()), + num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; + using lookup_table_definition = + typename nil::crypto3::zk::snark::detail::lookup_table_definition; }; template using padding_component = - keccak_padding>; + keccak_padding>; template std::vector generate_gates( - const padding_component - &component, - circuit> - &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, const typename padding_component::input_type &instance_input) { - + using component_type = padding_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; @@ -502,16 +501,20 @@ namespace nil { if (component.witness_amount() == 15) { for (std::size_t i = 0; i < 2; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); - cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_constraints.push_back( + var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - + var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * + (integral_type(1) << component.shift) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + cur_constraints.push_back( + var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - + var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * + (integral_type(1) << component.shift) - + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back( + var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - + (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - + var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; } selector_indexes.push_back(bp.add_gate(cur_constraints)); @@ -524,36 +527,50 @@ namespace nil { if (component.gates_amount - gate_index - (bool)(component.last_gate % 7) > 0) { for (int i = 0; i < component.confs_per_gate; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(constraint_type(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_constraints.push_back(constraint_type( + var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - + var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * + (integral_type(1) << (64 - component.shift)) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); + cur_constraints.push_back( + var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - + var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * + (integral_type(1) << component.shift) - + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back( + var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - + (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - + var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; + if(config_index >= config.size()){ + break; + } } selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); } - if (component.last_gate % 7) { + if (component.last_gate % 7 && config_index < config.size()) { for (int i = 0; i < component.last_gate; ++i) { auto cur_config = config[config_index]; - cur_constraints.push_back(var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); - cur_constraints.push_back(var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back(var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) - + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_constraints.push_back( + var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - + var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * + (integral_type(1) << (64 - component.shift)) - + var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); + cur_constraints.push_back( + var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - + var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * + (integral_type(1) << component.shift) - + var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); + cur_constraints.push_back( + var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - + (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - + var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; + if(config_index >= config.size()){ + break; + } } selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; @@ -566,16 +583,11 @@ namespace nil { template void generate_copy_constraints( - const padding_component - &component, - circuit> - &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type - &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = padding_component; @@ -585,61 +597,74 @@ namespace nil { std::size_t config_index = 0; std::size_t input_index = 0; + if (component.shift != 0) { + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); + } + while (config_index < component.full_configuration.size() - (component.shift != 0)) { auto config = component.full_configuration[config_index]; - bp.add_copy_constraint({instance_input.message[input_index++], - var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); - if (config_index == 0 && component.shift != 0) { - bp.add_copy_constraint({instance_input.message[input_index++], - var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, false)}); - } + bp.add_copy_constraint( + {instance_input.message[input_index++], + var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow + config.row, false)}); config_index++; } + if (component.shift != 0) { auto config = component.full_configuration[config_index]; - bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), - var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + bp.add_copy_constraint( + {var(component.C(0), start_row_index, false, var::column_type::constant), + var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow + config.row, false)}); + + config_index = component.confs_per_gate; + while( config_index < component.full_configuration.size()){ + auto config1 = component.full_configuration[config_index]; + auto config2 = component.full_configuration[config_index-1]; + bp.add_copy_constraint( + {var(component.W(config1.copy_to[1].column), config1.copy_to[1].row + strow + config1.row, false), + var(component.W(config2.last_coordinate.column), config2.last_coordinate.row + strow + config2.row, false)}); + config_index += component.confs_per_gate; + } } - + // if (component.shift != 0) { // std::size_t config_index = 0; // std::size_t input_index = 0; // auto config = component.full_configuration[config_index++]; // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, + // false)}); // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, false)}); + // var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, + // false)}); // while (input_index < instance_input.message.size()) { - // std::cout << input_index << ' ' << config_index << ' ' << component.full_configuration.size() << std::endl; - // config = component.full_configuration[config_index++]; + // std::cout << input_index << ' ' << config_index << ' ' << component.full_configuration.size() + // << std::endl; config = component.full_configuration[config_index++]; // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + + // strow, false)}); // } // // config = component.full_configuration[config_index]; - // // bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), - // // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // // bp.add_copy_constraint({var(component.C(0), start_row_index, false, + // var::column_type::constant), + // // var(component.W(config.copy_to[0].column), config.copy_to[0].row + + // strow, false)}); // } else { // for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { // auto config = component.full_configuration[i]; // bp.add_copy_constraint({instance_input.message[i], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, false)}); + // var(component.W(config.copy_to[0].column), config.copy_to[0].row + + // strow, false)}); // } // } } template - typename padding_component::result_type - generate_circuit( - const padding_component - &component, - circuit> - &bp, - assignment> + typename padding_component::result_type generate_circuit( + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type - &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = padding_component; @@ -650,16 +675,20 @@ namespace nil { std::size_t gate_row_ind = 0; if (component.witness_amount() == 15) { - assignment.enable_selector(selector_indexes[ind++], component.gates_rows[gate_row_ind++] + start_row_index); + assignment.enable_selector(selector_indexes[ind++], + component.gates_rows[gate_row_ind++] + start_row_index); } if (gate_row_ind < component.gates_rows.size() - (bool)(component.last_gate % 7)) { - for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { - assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); + for (std::size_t i = gate_row_ind; + i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { + assignment.enable_selector(selector_indexes[ind], + component.gates_rows[gate_row_ind++] + start_row_index); } ind++; } if (component.last_gate % 7) { - assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind] + start_row_index); + assignment.enable_selector(selector_indexes[ind], + component.gates_rows[gate_row_ind] + start_row_index); } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -669,15 +698,11 @@ namespace nil { } template - typename padding_component::result_type - generate_assignments( - const padding_component - &component, - assignment> + typename padding_component::result_type generate_assignments( + const padding_component &component, + assignment> &assignment, - const typename padding_component::input_type - &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t strow = start_row_index; @@ -697,44 +722,50 @@ namespace nil { chunk = var_value(assignment, instance_input.message[index]); } integral_type integral_chunk = integral_type(chunk.data); - integral_type mask = (integral_type(1) << (64-component.shift)) - 1; - std::array chunk_parts = {integral_chunk >> (64-component.shift), integral_chunk & mask}; + integral_type mask = (integral_type(1) << (64 - component.shift)) - 1; + std::array chunk_parts = {integral_chunk >> (64 - component.shift), + integral_chunk & mask}; integral_type first_chunk = (relay_chunk << component.shift) + chunk_parts[0]; - integral_type relay_range_check = relay_chunk - (1 << (64-component.shift)) + (integral_type(1) << 64); + integral_type relay_range_check = + relay_chunk - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + strow) = chunk; + assignment.witness(component.W(cur_config.constraints[0][0].column), + cur_config.constraints[0][0].row + strow + cur_config.row) = chunk; + if(config_index % component.confs_per_gate == 0){ + assignment.witness(component.W(cur_config.constraints[1][1].column), + cur_config.constraints[1][1].row + strow + cur_config.row) = value_type(relay_chunk); + } for (int j = 1; j < 3; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_parts[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), + cur_config.constraints[0][j].row + strow + cur_config.row) = + value_type(chunk_parts[j - 1]); } - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = value_type(first_chunk); - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(relay_range_check); - + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow + cur_config.row) = value_type(first_chunk); + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow + cur_config.row) = value_type(relay_range_check); + relay_chunk = chunk_parts[1]; config_index++; } } else { for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = var_value(assignment, instance_input.message[index]); + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow + cur_config.row) = + var_value(assignment, instance_input.message[index]); } } - return typename component_type::result_type(component, start_row_index); } template void generate_assignments_constant( - const padding_component - &component, - circuit> - &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type - &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = padding_component; @@ -742,9 +773,8 @@ namespace nil { assignment.constant(component.C(0), start_row_index) = 0; } - } // namespace components } // namespace blueprint -} // namespace nil +} // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP \ No newline at end of file diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 92c7a5a0e..3010cf3ae 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -64,8 +64,8 @@ std::size_t number_bits(typename BlueprintFieldType::value_type value) { } template -std::vector padding_function(std::vector message, - std::size_t num_bits) { +std::vector + padding_function(std::vector message, std::size_t num_bits) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -76,8 +76,8 @@ std::vector padding_function(std::vecto if (shift > 0) { integral_type relay_value = integral_type(message[0].data); for (int i = 1; i < message.size(); ++i) { - integral_type mask = (integral_type(1) << (64-shift)) - 1; - integral_type left_part = integral_type(message[i].data >> (64-shift)); + integral_type mask = (integral_type(1) << (64 - shift)) - 1; + integral_type left_part = integral_type(message[i].data >> (64 - shift)); integral_type right_part = integral_type(message[i].data) & mask; result.push_back(value_type((relay_value << shift) + left_part)); relay_value = right_part; @@ -94,20 +94,20 @@ std::vector padding_function(std::vecto return result; } -template +template auto test_keccak_padding_inner(std::vector message, std::vector expected_result, const std::size_t num_blocks, const std::size_t num_bits) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; constexpr std::size_t SelectorColumns = 3; - using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< - WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; - using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + using ArithmetizationParams = + nil::crypto3::zk::snark::plonk_arithmetization_params; + using ArithmetizationType = + nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; - using hash_type = nil::crypto3::hashes::keccak_1600<256>; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; using value_type = typename BlueprintFieldType::value_type; @@ -128,35 +128,36 @@ auto test_keccak_padding_inner(std::vector witnesses; for (std::uint32_t i = 0; i < WitnessesAmount; i++) { witnesses[i] = i; } - component_type component_instance = - component_type(witnesses, std::array{0}, std::array{0}, - num_blocks, num_bits, 7); + component_type component_instance = component_type(witnesses, std::array {0}, + std::array {0}, num_blocks, num_bits, 7); nil::crypto3::test_component( - component_instance, public_input, result_check, instance_input, - nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, 7); + component_instance, public_input, result_check, instance_input, + nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, 7); } // works -template +template void test_keccak_padding_0() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -165,15 +166,14 @@ void test_keccak_padding_0() { const std::size_t num_blocks = 1; const std::size_t num_bits = 1; - std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + std::vector expected_result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - test_keccak_padding_inner - (message, expected_result, num_blocks, num_bits); + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits); } -template -void test_keccak_padding_random() { +template +void test_keccak_padding_random(std::size_t message_size) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -183,20 +183,24 @@ void test_keccak_padding_random() { integral_type mask = (integral_type(1) << 64) - 1; integral_type mask_zero = (integral_type(1) << 60) - 1; - std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), - value_type(integral_type(dis(gen)) & mask), - value_type(integral_type(dis(gen)) & mask)}; - std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); - std::size_t num_blocks = message.size(); - - for (int i = 0; i < message.size(); ++i) { - std::cout << "message: " << message[i].data << std::endl; + value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero); + std::vector message; + message.push_back(message_zero); + for (std::size_t i = 1; i < message_size; i++) { + message.push_back(value_type(integral_type(dis(gen)) & mask)); } - + assert(message_size == message.size()); + std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); + std::size_t num_blocks = message_size; + std::cout << "message size: " << message_size << " blocks\n"; + for (int i = 0; i < message_size; ++i) { + std::cout << "message:" << message[i].data << std::endl; + } + auto expected_result = padding_function(message, num_bits); - test_keccak_padding_inner - (message, expected_result, num_blocks, num_bits); + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits); } BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) @@ -204,12 +208,18 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_random(); - test_keccak_padding_random(); - // test_keccak_padding_random(); + test_keccak_padding_0(); + // test_keccak_padding_random(1); + for (std::size_t i = 1; i < 17; i++) { + test_keccak_padding_random(i); + } } // BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { // using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; + +// test_keccak_padding_0(); +// test_keccak_padding_random(); // } BOOST_AUTO_TEST_SUITE_END() From 543049b1538122cdc2ba3f990067422cb28015a2 Mon Sep 17 00:00:00 2001 From: Valeh2012 Date: Wed, 15 Nov 2023 11:37:18 +0200 Subject: [PATCH 20/48] keccak padding witness_amount=15 fixed --- .../hashes/keccak/keccak_padding.hpp | 143 +++++++++++------- test/hashes/plonk/keccak_padding.cpp | 27 ++-- 2 files changed, 104 insertions(+), 66 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 6b1574f31..9c631a4dd 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -78,16 +78,11 @@ namespace nil { configuration() = default; configuration(std::pair first_coordinate_, - std::pair - last_coordinate_, - std::vector> - copy_to_, - std::vector>> - constraints_, - std::vector>> - lookups_, - std::pair - copy_from_, std::size_t row_) { + std::pair last_coordinate_, + std::vector> copy_to_, + std::vector>> constraints_, + std::vector>> lookups_, + std::pair copy_from_, std::size_t row_) { first_coordinate = coordinates(first_coordinate_); last_coordinate = coordinates(last_coordinate_); for (std::size_t i = 0; i < copy_to_.size(); ++i) { @@ -219,13 +214,17 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { - for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + for (std::size_t i = 0; + i < component.full_configuration.size() - + 1 * (component.witness_amount() == 15 && component.num_blocks == 1); + ++i) { auto config = component.full_configuration[i]; padded_message.push_back(var(component.W(config.copy_from.column), config.copy_from.row + config.row + start_row_index, false)); } for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { - padded_message.push_back(var(component.C(0), start_row_index, false, var::column_type::constant)); + padded_message.push_back( + var(component.C(0), start_row_index, false, var::column_type::constant)); } } @@ -259,16 +258,17 @@ namespace nil { padding_gate res; res.relay = {-1, 11}; res.value = {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}}; - res.sum = {{0, 3}, {0, 4}, {0, 5}, {1, 3}, {1, 4}, {1, 5}}; + res.sum = {{1, 3}, {1, 4}, {1, 5}, {0, 3}, {0, 4}, {0, 5}}; res.first = {{0, 6}, {0, 7}, {0, 8}, {1, 6}, {1, 7}, {1, 8}}; - res.second = {{0, 9}, {0, 10}, {0, 11}, - {1, 9}, {1, 10}, {1, 11}}; - res.range_check = {{0, 12}, {0, 13}, {0, 14}, - {1, 12}, {1, 13}, {1, 14}}; + res.second = {{0, 9}, {0, 10}, {0, 11}, {1, 9}, {1, 10}, {1, 11}}; + res.range_check = {{0, 12}, {0, 13}, {0, 14}, {1, 12}, {1, 13}, {1, 14}}; return res; } std::size_t calculate_num_padding_zeros() { + if(num_blocks % 17 == 0){ + return 0; + } return 17 - num_blocks % 17; } padding_gate calculate_first_gate_15(std::size_t row = 0) { @@ -307,8 +307,16 @@ namespace nil { std::size_t conf_ind = 0; std::size_t row = 1; std::size_t confs_per_gate = calculate_confs_per_gate(witness_amount); + std::size_t loop_end = num_blocks; + if (witness_amount == 15) { + if (num_blocks <= 2) { + loop_end = 0; + } else { + loop_end -= 2; + } + } - while (conf_ind < num_blocks - 2 * (witness_amount == 15)) { + while (conf_ind < loop_end) { auto pg = padding(witness_amount, row); std::size_t j = 0; { @@ -325,7 +333,7 @@ namespace nil { j++; conf_ind++; } - while ((j < confs_per_gate) && (conf_ind < num_blocks - 2 * (witness_amount == 15))) { + while ((j < confs_per_gate) && (conf_ind < loop_end)) { configuration conf; conf.row = row; conf.last_coordinate = pg.second[j]; @@ -368,13 +376,17 @@ namespace nil { } else { if (witness_amount % 15 == 0) { configuration conf0; - conf0.copy_to = {{0, 0}, {0, 1}}; + conf0.row = 0; + conf0.last_coordinate = {0, 7}; + conf0.copy_to = {{0, 1}, {0, 0}}; conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, {{0, 3}, {0, 0}, {0, 5}}, {{0, 8}, {0, 0}}}; conf0.lookups = {{{0, 8}}}; conf0.copy_from = {0, 3}; result.push_back(conf0); configuration conf1; + conf1.row = 0; conf1.copy_to = {{0, 2}}; + conf0.last_coordinate = {0, 11}; conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, {{0, 4}, {0, 7}, {0, 6}}, {{0, 9}, {0, 7}}}; conf1.lookups = {{{0, 9}}}; conf1.copy_from = {0, 4}; @@ -435,13 +447,15 @@ namespace nil { std::size_t num_blocks, std::size_t num_bits, std::size_t limit_permutation_column) { - auto conf = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); - - if(witness_amount == 9) { - return std::ceil(conf.size() / 5.0) * 3; + + if (witness_amount == 9) { + return std::ceil(num_blocks/ 5.0) * 3; } - if(witness_amount == 15) { - return std::ceil(conf.size() / 6.0) * 2; + if (witness_amount == 15) { + if (num_blocks <= 2) { + return 1; + } + return 1 + std::ceil((num_blocks - 2) / 6.0) * 2; } } @@ -495,16 +509,16 @@ namespace nil { std::vector constraints; // std::vector lookup_constraints; - + const std::size_t two = 2; if (component.shift > 0) { std::vector cur_constraints; if (component.witness_amount() == 15) { - for (std::size_t i = 0; i < 2; ++i) { + for (std::size_t i = 0; i < std::min(two, component.num_blocks); ++i) { auto cur_config = config[config_index]; cur_constraints.push_back( var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * - (integral_type(1) << component.shift) - + (integral_type(1) << (64 - component.shift)) - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); cur_constraints.push_back( var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - @@ -542,7 +556,7 @@ namespace nil { (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; - if(config_index >= config.size()){ + if (config_index >= config.size()) { break; } } @@ -568,7 +582,7 @@ namespace nil { (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); config_index++; - if(config_index >= config.size()){ + if (config_index >= config.size()) { break; } } @@ -596,33 +610,38 @@ namespace nil { std::size_t strow = start_row_index; std::size_t config_index = 0; std::size_t input_index = 0; + std::size_t witness_amount = component.witness_amount(); if (component.shift != 0) { bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); } - while (config_index < component.full_configuration.size() - (component.shift != 0)) { + while (config_index < component.full_configuration.size() - (component.shift != 0) - + (witness_amount == 15 && component.num_blocks == 1)) { auto config = component.full_configuration[config_index]; - bp.add_copy_constraint( - {instance_input.message[input_index++], - var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow + config.row, false)}); + bp.add_copy_constraint({instance_input.message[input_index++], + var(component.W(config.copy_to[0].column), + config.copy_to[0].row + strow + config.row, false)}); config_index++; } if (component.shift != 0) { auto config = component.full_configuration[config_index]; - bp.add_copy_constraint( - {var(component.C(0), start_row_index, false, var::column_type::constant), - var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow + config.row, false)}); - - config_index = component.confs_per_gate; - while( config_index < component.full_configuration.size()){ - auto config1 = component.full_configuration[config_index]; - auto config2 = component.full_configuration[config_index-1]; - bp.add_copy_constraint( - {var(component.W(config1.copy_to[1].column), config1.copy_to[1].row + strow + config1.row, false), - var(component.W(config2.last_coordinate.column), config2.last_coordinate.row + strow + config2.row, false)}); - config_index += component.confs_per_gate; + bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), + var(component.W(config.copy_to[0].column), + config.copy_to[0].row + strow + config.row, false)}); + + if (witness_amount == 9) { + config_index = component.confs_per_gate; + while (config_index < component.full_configuration.size()) { + auto config1 = component.full_configuration[config_index]; + auto config2 = component.full_configuration[config_index - 1]; + bp.add_copy_constraint({var(component.W(config1.copy_to[1].column), + config1.copy_to[1].row + strow + config1.row, false), + var(component.W(config2.last_coordinate.column), + config2.last_coordinate.row + strow + config2.row, false)}); + config_index += component.confs_per_gate; + } } } @@ -680,7 +699,8 @@ namespace nil { } if (gate_row_ind < component.gates_rows.size() - (bool)(component.last_gate % 7)) { for (std::size_t i = gate_row_ind; - i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { + i < component.gates_rows.size() - (bool)(component.last_gate % 7); + ++i) { assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); } @@ -712,6 +732,7 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; std::size_t config_index = 0; + std::size_t witness_amount = component.witness_amount(); // batching if (component.shift != 0) { @@ -732,9 +753,19 @@ namespace nil { auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + strow + cur_config.row) = chunk; - if(config_index % component.confs_per_gate == 0){ - assignment.witness(component.W(cur_config.constraints[1][1].column), - cur_config.constraints[1][1].row + strow + cur_config.row) = value_type(relay_chunk); + if (witness_amount == 9) { + if (config_index % component.confs_per_gate == 0) { + assignment.witness(component.W(cur_config.constraints[1][1].column), + cur_config.constraints[1][1].row + strow + cur_config.row) = + value_type(relay_chunk); + } + } + if (witness_amount == 15) { + if (config_index == 0) { + assignment.witness(component.W(cur_config.constraints[1][1].column), + cur_config.constraints[1][1].row + strow + cur_config.row) = + value_type(relay_chunk); + } } for (int j = 1; j < 3; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].column), @@ -742,9 +773,11 @@ namespace nil { value_type(chunk_parts[j - 1]); } assignment.witness(component.W(cur_config.constraints[1][0].column), - cur_config.constraints[1][0].row + strow + cur_config.row) = value_type(first_chunk); + cur_config.constraints[1][0].row + strow + cur_config.row) = + value_type(first_chunk); assignment.witness(component.W(cur_config.constraints[2][0].column), - cur_config.constraints[2][0].row + strow + cur_config.row) = value_type(relay_range_check); + cur_config.constraints[2][0].row + strow + cur_config.row) = + value_type(relay_range_check); relay_chunk = chunk_parts[1]; config_index++; @@ -752,10 +785,12 @@ namespace nil { } else { for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow + cur_config.row) = + assignment.witness(component.W(cur_config.copy_from.column), + cur_config.copy_from.row + strow + cur_config.row) = var_value(assignment, instance_input.message[index]); } } + return typename component_type::result_type(component, start_row_index); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 3010cf3ae..3dc7d272c 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -130,12 +130,12 @@ auto test_keccak_padding_inner(std::vector(message[0]); std::size_t num_blocks = message_size; std::cout << "message size: " << message_size << " blocks\n"; - for (int i = 0; i < message_size; ++i) { - std::cout << "message:" << message[i].data << std::endl; - } + // for (int i = 0; i < message_size; ++i) { + // std::cout << "message:" << message[i].data << std::endl; + // } auto expected_result = padding_function(message, num_bits); @@ -207,19 +207,22 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_random(); + test_keccak_padding_0(); - // test_keccak_padding_random(1); - for (std::size_t i = 1; i < 17; i++) { + // test_keccak_padding_random(17); + for (std::size_t i = 1; i < 35; i++) { test_keccak_padding_random(i); } } -// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { -// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { + using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; -// test_keccak_padding_0(); -// test_keccak_padding_random(); -// } + test_keccak_padding_0(); + // test_keccak_padding_random(17); + for (std::size_t i = 1; i < 35; i++) { + test_keccak_padding_random(i); + } +} BOOST_AUTO_TEST_SUITE_END() From 88bfb9063d7d7b7a054da75a7ef154f990b311fb Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Sat, 18 Nov 2023 17:17:39 +0000 Subject: [PATCH 21/48] added lookups to keccak_round #183 --- .../components/hashes/keccak/keccak_round.hpp | 310 +++++++++++++----- include/nil/blueprint/lookup_library.hpp | 52 ++- test/hashes/plonk/keccak_round.cpp | 2 +- 3 files changed, 276 insertions(+), 88 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 0e068e42a..2aeb4e358 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -353,7 +354,7 @@ namespace nil { // number represents relative selector index for each constraint std::map, std::vector> gates_configuration_map = configure_map(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); std::vector> gates_configuration = configure_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - std::vector lookup_gates_configuration = configure_lookup_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector> lookup_gates_configuration = configure_lookup_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); const std::size_t last_round_call_row = calculate_last_round_call_row(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); @@ -493,7 +494,7 @@ namespace nil { constraints.push_back({constraints[0][0]}); constraints.push_back({cell_copy_from}); - std::vector>> lookups(num_chunks, std::vector>()); + std::vector>> lookups(num_chunks); for (std::size_t i = 1; i < 3; ++i) { for (std::size_t j = 0; j < num_chunks; ++j) { constraints[i].push_back(cells[cell_index++]); @@ -607,6 +608,7 @@ namespace nil { for (std::size_t j = 0; j < num_chunks; ++j) { constraints[3].push_back(cells[cell_index++]); lookups[0].push_back(constraints[3].back()); + lookups[1].push_back(constraints[3].back()); } constraints.push_back({cells[cell_index++]}); @@ -614,6 +616,7 @@ namespace nil { constraints.push_back({constraints[4][0]}); for (std::size_t j = 0; j < num_chunks; ++j) { constraints[5].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[5].back()); lookups[1].push_back(constraints[5].back()); } constraints.push_back({rot_const, minus_rot_const}); @@ -692,19 +695,27 @@ namespace nil { // iota result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); - // for (int i = 0; i < full_configuration_size; ++i) { - // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; - // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; - // for (int j = 0; j < result[i].copy_to.size(); ++j) { - // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; - // } - // for (int j = 0; j < result[i].constraints.size(); ++j) { - // for (int k = 0; k < result[i].constraints[j].size(); ++k) { - // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << " "; - // } - // std::cout << std::endl; - // } - // } + for (int i = 0; i < result.size(); ++i) { + // std::cout << "\n config: " << i << std::endl; + // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; + // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; + // for (int j = 0; j < result[i].copy_to.size(); ++j) { + // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; + // } + // for (int j = 0; j < result[i].constraints.size(); ++j) { + // for (int k = 0; k < result[i].constraints[j].size(); ++k) { + // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // std::cout << "lookups: " << result[i].lookups.size() << std::endl; + // for (int j = 0; j < result[i].lookups.size(); ++j) { + // for (int k = 0; k < result[i].lookups[j].size(); ++k) { + // std::cout << result[i].lookups[j][k].row << " " << result[i].lookups[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + } return result; } @@ -846,6 +857,7 @@ namespace nil { break; } + // std::cout << "\nconfig:\n"; // std::cout << config.first.first << "\n"; // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; @@ -854,7 +866,7 @@ namespace nil { // } // for (int j = 0; j < cur_config.constraints.size(); ++j) { // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].column << " "; + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; // } // std::cout << std::endl; // } @@ -889,16 +901,37 @@ namespace nil { return result; } - static std::vector configure_lookup_gates(std::size_t witness_amount, + static std::vector> configure_lookup_gates(std::size_t witness_amount, bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { auto full_configuration = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); auto rows_amount = full_configuration.back().last_coordinate.row + 1; + std::vector> result; + auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); - std::vector> pairs; - for (std::size_t i = 0; i < full_configuration.size(); ++i) { - for (auto constr : full_configuration[i].lookups) { + for (auto config: gates_configuration_map) { + configuration cur_config; + switch (config.first.first) { + case 2: + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); + break; + case 3: + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); + break; + case 5: + cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); + break; + case 7: + cur_config = configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); + break; + case 0: + cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); + break; + } + + std::vector> pairs; + for (auto constr : cur_config.lookups) { std::size_t min = constr[0].row; std::size_t max = constr.back().row; for (std::size_t j = 0; j < constr.size(); ++j) { @@ -908,20 +941,35 @@ namespace nil { BOOST_ASSERT(max - min <= 2); pairs.push_back({min, max}); } - } - std::vector result; - std::size_t cur_row = 0; - std::size_t cur_constr = 0; - while (cur_row < rows_amount) { - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { - result.push_back(cur_row + 1); - ++cur_constr; - } - if (cur_constr == pairs.size()) { - break; + + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + c.lookups.push_back(cur_config.lookups[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + cur_row = pairs[cur_constr].first; + cur_result.push_back(c); } - cur_row = pairs[cur_constr].first; + result.push_back(cur_result); } + // std::size_t cur_row = 0; + // std::size_t cur_constr = 0; + // while (cur_row < rows_amount) { + // while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + // result.push_back(cur_row + 1); + // ++cur_constr; + // } + // if (cur_constr == pairs.size()) { + // break; + // } + // cur_row = pairs[cur_constr].first; + // } + std::cout << "lookup gates: " << result.size() << std::endl; return result; } static std::size_t get_gates_amount(std::size_t witness_amount, @@ -933,6 +981,11 @@ namespace nil { for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); } + auto lookup_gates_configuration = configure_lookup_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + for (std::size_t i = 0; i < lookup_gates_configuration.size(); ++i) { + res += lookup_gates_configuration[i].size(); + } + std::cout << "GATES: " << res << '\n'; return res; } @@ -984,6 +1037,7 @@ namespace nil { lookup_tables["keccak_normalize4_table/full"] = 0; // REQUIRED_TABLE lookup_tables["keccak_normalize6_table/full"] = 0; // REQUIRED_TABLE lookup_tables["keccak_chi_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/range_check_sparse"] = 0; // REQUIRED_TABLE return lookup_tables; } @@ -1033,34 +1087,38 @@ namespace nil { ArithmetizationParams>> &assignment, const typename keccak_round_component::input_type - &instance_input) { + &instance_input, + const std::map lookup_tables_indices) { using component_type = keccak_round_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; - // using lookup_constraint_type = typename crypto3::zk::snark::lookup_constraint; - // using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; + using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; + using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using configuration = typename component_type::configuration; - std::vector selector_indexes; - auto gate_config = component.gates_configuration; auto gate_map = component.gates_configuration_map; - // auto lookup_gate_config = component.lookup_gates_configuration; + auto gate_config = component.gates_configuration; + auto lookup_gate_config = component.lookup_gates_configuration; std::size_t gate_index = 0; - // std::size_t lookup_gate_index = 0; + std::size_t lookup_gate_index = 0; + std::vector selector_indexes; std::vector constraints; - // std::vector lookup_constraints; + std::vector lookup_constraints; + // general gates std::size_t index = 0; - std::size_t selector_index = 0; for (auto gm: gate_map) { std::vector cur_config_vec = gate_config[index]; std::size_t i = 0, j = 0, cur_len = 0; std::vector cur_constraints; + std::vector cur_lookup_config_vec = lookup_gate_config[index]; + std::vector cur_lookup_constraints; + std::string cur_lookup_table_name; switch (gm.first.first) { case 2: { @@ -1101,6 +1159,7 @@ namespace nil { cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_lookup_table_name = "keccak_normalize3_table/full"; break; } case 3: @@ -1143,6 +1202,7 @@ namespace nil { cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_lookup_table_name = "keccak_normalize4_table/full"; break; } case 5: @@ -1187,6 +1247,7 @@ namespace nil { cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_lookup_table_name = "keccak_normalize6_table/full"; break; } case 7: @@ -1285,6 +1346,7 @@ namespace nil { selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_lookup_table_name = "keccak_pack_table/range_check_sparse"; break; } case 0: @@ -1328,11 +1390,91 @@ namespace nil { cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_lookup_table_name = "keccak_chi_table/full"; break; } } + if (gm.first.first == 7) { + for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { + for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { + lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), + {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), static_cast(cur_lookup_config_vec[i].lookups[j][0].row) + - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; + cur_lookup_constraints.push_back(lookup_constraint); + } + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + cur_lookup_constraints.clear(); + } + ++index; + continue; + } + for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { + for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { + lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), + {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), static_cast(cur_lookup_config_vec[i].lookups[j][0].row) + - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1), + var(component.W(cur_lookup_config_vec[i].lookups[j][1].column), static_cast(cur_lookup_config_vec[i].lookups[j][1].row) + - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; + cur_lookup_constraints.push_back(lookup_constraint); + } + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + cur_lookup_constraints.clear(); + } index++; } + // lookup gates + index = 0; + // for (auto gm: gate_map) { + // std::vector cur_lookup_config_vec = lookup_gate_config[index]; + // std::vector cur_lookup_constraints; + // std::string cur_lookup_table_name; + // std::cout << "lookups: " << gm.first.first << std::endl; + // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { + // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { + // for (int k = 0; k < cur_config_vec[i].lookups[j].size(); ++k) { + // std::cout << static_cast(cur_config_vec[i].lookups[j][k].row) - static_cast(cur_config_vec[i].first_coordinate.row) - 1 << " " << cur_config_vec[i].lookups[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + // switch (gm.first.first) { + // case 2: + // { + // cur_lookup_table_name = "keccak_normalize3_table/full"; + // break; + // } + // case 3: { + // cur_lookup_table_name = "keccak_normalize4_table/full"; + // break; + // } + // case 5: { + // cur_lookup_table_name = "keccak_normalize6_table/full"; + // break; + // } + // case 7: { + // // TODO: add pack table + // cur_lookup_table_name = "keccak_chi_table/full"; + // break; + // } + // case 0: { + // cur_lookup_table_name = "keccak_chi_table/full"; + // break; + // } + // } + // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { + // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { + // lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), + // {var(component.W(cur_config_vec[i].lookups[j][0].column), static_cast(cur_config_vec[i].lookups[j][0].row) + // - static_cast(cur_config_vec[i].first_coordinate.row) - 1), + // var(component.W(cur_config_vec[i].lookups[j][1].column), static_cast(cur_config_vec[i].lookups[j][1].row) + // - static_cast(cur_config_vec[i].first_coordinate.row) - 1)}}; + // cur_constraints.push_back(lookup_constraint); + // } + // selector_indexes.push_back(bp.add_lookup_gate(cur_constraints)); + // cur_constraints.clear(); + // } + // index++; + // } return selector_indexes; } @@ -1362,16 +1504,16 @@ namespace nil { if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), config[i].copy_to[0].row + start_row_index, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), config[i].copy_to[1].row + start_row_index, false)}); + bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), static_cast(config[i].copy_to[0].row + start_row_index), false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), static_cast(config[i].copy_to[1].row + start_row_index), false)}); num_copy_constr += 2; } config_index += 16; if (component.last_round_call) { - bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), config[config_index].copy_to[0].row + start_row_index, false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), config[config_index].copy_to[1].row + start_row_index, false)}); + bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + start_row_index), false)}); + bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false)}); bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index, false, var::column_type::constant), - var(component.W(config[config_index].copy_to[2].column), config[config_index].copy_to[2].row + start_row_index, false)}); + var(component.W(config[config_index].copy_to[2].column), static_cast(config[config_index].copy_to[2].row + start_row_index), false)}); num_copy_constr += 3; } config_index += 1; @@ -1520,7 +1662,7 @@ namespace nil { generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); - auto selector_indexes = generate_gates(component, bp, assignment, instance_input); + auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); std::size_t ind = 0; std::size_t index = 0; @@ -1534,17 +1676,27 @@ namespace nil { // index++; // } for (auto g : component.gates_configuration_map) { - std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << '\n'; - for (std::size_t i = 0; i < component.gates_configuration[index].size(); ++i) { + // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << '\n'; + // if (g.first.first == 5) continue; + for (std::size_t i = 0; i < component.gates_configuration[ind].size(); ++i) { for (auto j : g.second) { - std::cout << j << ' '; + // std::cout << j + component.gates_configuration[ind][i].first_coordinate.row + 1 << ' '; assignment.enable_selector(selector_indexes[index], - start_row_index + j + component.gates_configuration[index][i].first_coordinate.row + 1); + start_row_index + j + component.gates_configuration[ind][i].first_coordinate.row + 1); } - std::cout << '\n'; + // std::cout << '\n'; + index++; } - index++; - break; + for (std::size_t i = 0; i < component.lookup_gates_configuration[ind].size(); ++i) { + for (auto j : g.second) { + // std::cout << j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; + assignment.enable_selector(selector_indexes[index], + start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1); + } + // std::cout << '\n'; + index++; + } + ind++; } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -1648,11 +1800,11 @@ namespace nil { A_1[i] = var_value(assignment, instance_input.inner_state[i]); } } - std::cout << "A_1:\n"; - for (int i = 0; i < 25; ++i) { - std::cout << A_1[i].data << " "; - } - std::cout << "\n"; + // std::cout << "A_1:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << A_1[i].data << " "; + // } + // std::cout << "\n"; // theta std::array C; @@ -1692,11 +1844,11 @@ namespace nil { } } config_index += 5; - std::cout << "C:\n"; - for (int i = 0; i < 5; ++i) { - std::cout << C[i].data << " "; - } - std::cout << "\n"; + // std::cout << "C:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C[i].data << " "; + // } + // std::cout << "\n"; std::array C_rot; for (int index = 0; index < 5; ++index) { @@ -1736,11 +1888,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); } config_index += 5; - std::cout << "C_rot:\n"; - for (int i = 0; i < 5; ++i) { - std::cout << C_rot[i].data << " "; - } - std::cout << "\n"; + // std::cout << "C_rot:\n"; + // for (int i = 0; i < 5; ++i) { + // std::cout << C_rot[i].data << " "; + // } + // std::cout << "\n"; std::array A_2; for (int index = 0; index < 25; ++index) { @@ -1776,11 +1928,11 @@ namespace nil { } } config_index += 25; - std::cout << "A_2:\n"; - for (int i = 0; i < 25; ++i) { - std::cout << A_2[i].data << " "; - } - std::cout << "\n"; + // std::cout << "A_2:\n"; + // for (int i = 0; i < 25; ++i) { + // std::cout << A_2[i].data << " "; + // } + // std::cout << "\n"; // rho/phi value_type B[25]; @@ -1899,11 +2051,11 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } } - std::cout << "result:\n" << A_4.data << " "; - for (int i = 1; i < 25; ++i) { - std::cout << A_3[i].data << " "; - } - std::cout << "\n"; + // std::cout << "result:\n" << A_4.data << " "; + // for (int i = 1; i < 25; ++i) { + // std::cout << A_3[i].data << " "; + // } + // std::cout << "\n"; return typename component_type::result_type(component, start_row_index); } diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index 7df4c6c2b..2a154ccbc 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -84,6 +84,46 @@ namespace nil { virtual std::size_t get_rows_number(){ return 4; } }; + class keccak_pack_table_type : public lookup_table_definition{ + typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 1; + power = power << 3; + } + return value_type(result_integral); + } + public: + keccak_pack_table_type(): lookup_table_definition("keccak_pack_table"){ + this->subtables["full"] = {{0,1}, 0, 255}; + this->subtables["range_check"] = {{0}, 0, 255}; + this->subtables["range_check_sparse"] = {{1}, 0, 255}; + } + virtual void generate(){ + this->_table.resize(2); + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(256); + i++ + ) { + this->_table[0].push_back(i); + this->_table[1].push_back(to_sparse(i)); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 256; } + }; + protected: + std::shared_ptr binary_xor_table; + std::shared_ptr keccak_pack_table; + bool reserved_all; + class binary_and_table_type : public lookup_table_definition{ public: binary_and_table_type(): lookup_table_definition("binary_and_table"){ @@ -252,14 +292,10 @@ namespace nil { lookup_library(){ tables = {}; reserved_all = false; - tables["binary_xor_table"] = std::shared_ptr(new binary_xor_table_type()); - tables["binary_and_table"] = std::shared_ptr(new binary_and_table_type()); - tables["sha256_sparse_base4"] = std::shared_ptr(new sparse_values_base4_table()); - tables["sha256_reverse_sparse_base4"] = std::shared_ptr(new reverse_sparse_sigmas_base4_table()); - tables["sha256_sparse_base7"] = std::shared_ptr(new sparse_values_base7_table()); - tables["sha256_reverse_sparse_base7"] = std::shared_ptr(new reverse_sparse_sigmas_base7_table()); - tables["sha256_maj"] = std::shared_ptr(new maj_function_table()); - tables["sha256_ch"] = std::shared_ptr(new ch_function_table()); + binary_xor_table = std::shared_ptr(new binary_xor_table_type()); + tables["binary_xor_table"] = binary_xor_table; + keccak_pack_table = std::shared_ptr(new keccak_pack_table_type()); + tables["keccak_pack_table"] = keccak_pack_table; } void register_lookup_table(std::shared_ptr table){ diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index a17682153..46be6658e 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -161,7 +161,7 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 15; + constexpr std::size_t SelectorColumns = 25; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system Date: Mon, 20 Nov 2023 14:51:04 +0000 Subject: [PATCH 22/48] added padding lookups #183 --- .../hashes/keccak/keccak_padding.hpp | 65 +++++++++++++------ test/hashes/plonk/keccak_padding.cpp | 20 +++--- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 9c631a4dd..e85a44e55 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -52,11 +53,11 @@ namespace nil { public: struct coordinates { std::int32_t row; - std::int32_t column; + std::size_t column; coordinates() = default; - coordinates(std::int32_t row_, std::int32_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + coordinates(std::int32_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; bool operator==(const coordinates &other) const { return row == other.row && column == other.column; @@ -177,7 +178,6 @@ namespace nil { } static const std::size_t lookup_rows = 65536; - // const std::size_t lookup_columns; const std::size_t limit_permutation_column = 7; @@ -198,7 +198,6 @@ namespace nil { const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, shift, last_gate); - const std::size_t lookup_gates_amount = num_blocks; struct input_type { // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + @@ -362,7 +361,8 @@ namespace nil { std::size_t shift = num_blocks * 64 - num_bits; std::vector result; if (shift == 0) { - std::size_t row = 0, column = 0; + std::int32_t row = 0; + std::size_t column = 0; for (std::size_t i = 0; i < num_blocks; ++i) { configuration conf; conf.copy_from = {row, column}; @@ -386,7 +386,7 @@ namespace nil { configuration conf1; conf1.row = 0; conf1.copy_to = {{0, 2}}; - conf0.last_coordinate = {0, 11}; + conf1.last_coordinate = {0, 11}; conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, {{0, 4}, {0, 7}, {0, 6}}, {{0, 9}, {0, 7}}}; conf1.lookups = {{{0, 9}}}; conf1.copy_from = {0, 4}; @@ -428,17 +428,17 @@ namespace nil { } if (witness_amount == 9) { if (last_gate == 0 || last_gate == num_blocks) { - return 1; + return 1 * 2; } - return 2; + return 2 * 2; } else if (witness_amount == 15) { if (last_gate == 7) { - return 1; + return 1 * 2; } if (last_gate == 0 || last_gate == num_blocks - 2) { - return 2; + return 2 * 2; } - return 3; + return 3 * 2; } return 0; } @@ -459,6 +459,12 @@ namespace nil { } } + std::map component_lookup_tables(){ + std::map lookup_tables; + lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE + return lookup_tables; + } + template keccak_padding(WitnessContainerType witness, ConstantContainerType constant, @@ -491,27 +497,28 @@ namespace nil { assignment> &assignment, const typename padding_component::input_type - &instance_input) { + &instance_input, + const std::map lookup_tables_indices) { using component_type = padding_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; + using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; + using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; std::vector selector_indexes; auto config = component.full_configuration; - // auto lookup_gate_config = component.lookup_gates_configuration; std::size_t config_index = 0; std::size_t gate_index = 0; - // std::size_t lookup_gate_index = 0; + std::size_t lookup_gate_index = 0; - std::vector constraints; - // std::vector lookup_constraints; const std::size_t two = 2; if (component.shift > 0) { std::vector cur_constraints; + std::vector cur_lookup_constraints; if (component.witness_amount() == 15) { for (std::size_t i = 0; i < std::min(two, component.num_blocks); ++i) { auto cur_config = config[config_index]; @@ -529,11 +536,16 @@ namespace nil { var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); config_index++; } selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); } std::cout << "gate_index: " << gate_index << std::endl; std::cout << "component.gates_amount: " << component.gates_amount << std::endl; @@ -555,6 +567,8 @@ namespace nil { var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); config_index++; if (config_index >= config.size()) { break; @@ -563,6 +577,9 @@ namespace nil { selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); } if (component.last_gate % 7 && config_index < config.size()) { for (int i = 0; i < component.last_gate; ++i) { @@ -581,6 +598,8 @@ namespace nil { var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); config_index++; if (config_index >= config.size()) { break; @@ -588,9 +607,11 @@ namespace nil { } selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; } } - BOOST_ASSERT(gate_index == component.gates_amount); + BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); return selector_indexes; } @@ -689,11 +710,13 @@ namespace nil { using component_type = padding_component; using var = typename component_type::var; - auto selector_indexes = generate_gates(component, bp, assignment, instance_input); + auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); std::size_t ind = 0; std::size_t gate_row_ind = 0; if (component.witness_amount() == 15) { + assignment.enable_selector(selector_indexes[ind++], + component.gates_rows[gate_row_ind] + start_row_index); assignment.enable_selector(selector_indexes[ind++], component.gates_rows[gate_row_ind++] + start_row_index); } @@ -701,12 +724,16 @@ namespace nil { for (std::size_t i = gate_row_ind; i < component.gates_rows.size() - (bool)(component.last_gate % 7); ++i) { + assignment.enable_selector(selector_indexes[ind], + component.gates_rows[gate_row_ind] + start_row_index); assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind++] + start_row_index); } ind++; } if (component.last_gate % 7) { + assignment.enable_selector(selector_indexes[ind++], + component.gates_rows[gate_row_ind] + start_row_index); assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind] + start_row_index); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 3dc7d272c..ece3323a4 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -99,7 +99,7 @@ auto test_keccak_padding_inner(std::vector expected_result, const std::size_t num_blocks, const std::size_t num_bits) { constexpr std::size_t PublicInputColumns = 1; - constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t ConstantColumns = 3; constexpr std::size_t SelectorColumns = 3; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params(); // test_keccak_padding_random(17); - for (std::size_t i = 1; i < 35; i++) { + for (std::size_t i = 1; i < 3; i++) { test_keccak_padding_random(i); } } -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { - using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { +// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - test_keccak_padding_0(); - // test_keccak_padding_random(17); - for (std::size_t i = 1; i < 35; i++) { - test_keccak_padding_random(i); - } -} +// test_keccak_padding_0(); +// // test_keccak_padding_random(17); +// for (std::size_t i = 1; i < 35; i++) { +// test_keccak_padding_random(i); +// } +// } BOOST_AUTO_TEST_SUITE_END() From e98fb44142711055ea8fddcc7c35ee02503891d2 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 20 Nov 2023 19:39:59 +0000 Subject: [PATCH 23/48] padding fixes #183 --- .../hashes/keccak/keccak_padding.hpp | 6 +++--- test/hashes/plonk/keccak_padding.cpp | 20 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index e85a44e55..30a9e4e1a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -612,7 +612,7 @@ namespace nil { } } BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); - + std::cout << "SELS: " << selector_indexes.size() << std::endl; return selector_indexes; } @@ -726,10 +726,10 @@ namespace nil { ++i) { assignment.enable_selector(selector_indexes[ind], component.gates_rows[gate_row_ind] + start_row_index); - assignment.enable_selector(selector_indexes[ind], + assignment.enable_selector(selector_indexes[ind + 1], component.gates_rows[gate_row_ind++] + start_row_index); } - ind++; + ind += 2; } if (component.last_gate % 7) { assignment.enable_selector(selector_indexes[ind++], diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index ece3323a4..6b9ec2a4e 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -100,7 +100,7 @@ auto test_keccak_padding_inner(std::vector; @@ -209,20 +209,18 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; test_keccak_padding_0(); - // test_keccak_padding_random(17); - for (std::size_t i = 1; i < 3; i++) { + for (std::size_t i = 1; i < 35; i++) { test_keccak_padding_random(i); } } -// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { -// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { + using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; -// test_keccak_padding_0(); -// // test_keccak_padding_random(17); -// for (std::size_t i = 1; i < 35; i++) { -// test_keccak_padding_random(i); -// } -// } + test_keccak_padding_0(); + for (std::size_t i = 1; i < 35; i++) { + test_keccak_padding_random(i); + } +} BOOST_AUTO_TEST_SUITE_END() From 257bc31bf1c62fee10ba2577603647ee8de0441b Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 23 Nov 2023 13:21:24 +0000 Subject: [PATCH 24/48] pack table in lookup lib #183 --- include/nil/blueprint/lookup_library.hpp | 50 ++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index 2a154ccbc..172dced67 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -284,6 +284,43 @@ namespace nil { virtual std::size_t get_columns_number(){return 2;} virtual std::size_t get_rows_number(){return 5764801;} }; + + class sparse_values_base8_table : public lookup_table_definition{ + typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 1; + power = power << 3; + } + return value_type(result_integral); + } + public: + sparse_values_base8_table(): lookup_table_definition("keccak_pack_table"){ + this->subtables["full"] = {{0,1}, 0, 255}; + this->subtables["range_check"] = {{0}, 0, 255}; + this->subtables["range_check_sparse"] = {{1}, 0, 255}; + this->subtables["64bit"] = {{0}, 128, 255}; + } + virtual void generate(){ + this->_table.resize(2); + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(256); + i++ + ) { + this->_table[0].push_back(i); + this->_table[1].push_back(to_sparse(i)); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 256; } + }; public: using bimap_type = boost::bimap, boost::bimaps::set_of>; using left_reserved_type = typename bimap_type::left_map; @@ -292,10 +329,15 @@ namespace nil { lookup_library(){ tables = {}; reserved_all = false; - binary_xor_table = std::shared_ptr(new binary_xor_table_type()); - tables["binary_xor_table"] = binary_xor_table; - keccak_pack_table = std::shared_ptr(new keccak_pack_table_type()); - tables["keccak_pack_table"] = keccak_pack_table; + tables["binary_xor_table"] = std::shared_ptr(new binary_xor_table_type()); + tables["binary_and_table"] = std::shared_ptr(new binary_and_table_type()); + tables["sha256_sparse_base4"] = std::shared_ptr(new sparse_values_base4_table()); + tables["sha256_reverse_sparse_base4"] = std::shared_ptr(new reverse_sparse_sigmas_base4_table()); + tables["sha256_sparse_base7"] = std::shared_ptr(new sparse_values_base7_table()); + tables["sha256_reverse_sparse_base7"] = std::shared_ptr(new reverse_sparse_sigmas_base7_table()); + tables["sha256_maj"] = std::shared_ptr(new maj_function_table()); + tables["sha256_ch"] = std::shared_ptr(new ch_function_table()); + tables["keccak_pack_table"] = std::shared_ptr(new sparse_values_base8_table()); } void register_lookup_table(std::shared_ptr table){ From f23e91b8c40e0a8be5c99a6a9b1cba55dc7e2694 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Tue, 28 Nov 2023 12:04:59 +0000 Subject: [PATCH 25/48] keccak padding almost done #183 --- .../hashes/keccak/keccak_padding.hpp | 955 ++++++++++-------- test/hashes/plonk/keccak_padding.cpp | 107 +- 2 files changed, 624 insertions(+), 438 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 30a9e4e1a..5d5d5e671 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -52,13 +52,13 @@ namespace nil { public: struct coordinates { - std::int32_t row; + std::size_t row; std::size_t column; coordinates() = default; - coordinates(std::int32_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; bool operator==(const coordinates &other) const { return row == other.row && column == other.column; } @@ -66,7 +66,8 @@ namespace nil { return row < other.row || (row == other.row && column < other.column); } }; - struct configuration { + + struct configuration { // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. coordinates first_coordinate; @@ -75,7 +76,6 @@ namespace nil { std::vector> constraints; std::vector> lookups; coordinates copy_from; - std::size_t row; configuration() = default; configuration(std::pair first_coordinate_, @@ -83,37 +83,39 @@ namespace nil { std::vector> copy_to_, std::vector>> constraints_, std::vector>> lookups_, - std::pair copy_from_, std::size_t row_) { - first_coordinate = coordinates(first_coordinate_); - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to.push_back(coordinates(copy_to_[i])); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - std::vector constr; - for (std::size_t j = 0; j < constraints_[i].size(); ++j) { - constr.push_back(coordinates(constraints_[i][j])); + std::pair copy_from_) { + first_coordinate = coordinates(first_coordinate_); + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to.push_back(coordinates(copy_to_[i])); } - constraints.push_back(constr); - } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - std::vector lookup; - for (std::size_t j = 0; j < lookups_[i].size(); ++j) { - lookup.push_back(coordinates(lookups_[i][j])); + for (std::size_t i = 0; i < constraints_.size(); ++i) { + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); + } + constraints.push_back(constr); } - lookups.push_back(lookup); - } - copy_from = coordinates(copy_from_); - row = row_; - }; - bool operator==(const configuration &other) const { - return first_coordinate == other.first_coordinate && last_coordinate == other.last_coordinate && - copy_to == other.copy_to && constraints == other.constraints && - lookups == other.lookups && copy_from == other.copy_from; - } - bool operator<(const configuration &other) const { + for (std::size_t i = 0; i < lookups_.size(); ++i) { + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); + } + lookups.push_back(lookup); + } + copy_from = coordinates(copy_from_); + }; + bool operator== (const configuration& other) const { + return first_coordinate == other.first_coordinate && + last_coordinate == other.last_coordinate && + copy_to == other.copy_to && + constraints == other.constraints && + lookups == other.lookups && + copy_from == other.copy_from; + } + bool operator< (const configuration& other) const { return first_coordinate < other.first_coordinate || - (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); } }; struct padding_gate { @@ -145,16 +147,18 @@ namespace nil { std::size_t witness_amount; std::size_t num_blocks; std::size_t num_bits; - std::size_t last_gate; + bool range_check_input; + std::size_t limit_permutation_column; static constexpr const std::size_t clamp = 15; gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, - std::size_t last_gate_) : + bool range_check_input_, std::size_t limit_permutation_column_ = 7) : witness_amount(std::min(witness_amount_, clamp)), - num_blocks(num_blocks_), num_bits(num_bits_), last_gate(last_gate_) {}; + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), + limit_permutation_column(limit_permutation_column_) {}; std::uint32_t gates_amount() const override { - return keccak_padding::get_gates_amount(witness_amount, num_blocks, num_bits, last_gate); + return keccak_padding::get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); } }; @@ -162,10 +166,10 @@ namespace nil { std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, - std::size_t limit_permutation_column) { - auto last_gate = calculate_last_gate(witness_amount, num_blocks); + bool range_check_input, + std::size_t limit_permutation_column = 7) { gate_manifest manifest = - gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, last_gate)); + gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)); return manifest; } @@ -178,26 +182,31 @@ namespace nil { } static const std::size_t lookup_rows = 65536; + static const std::size_t num_chunks = 8; const std::size_t limit_permutation_column = 7; + const bool range_check_input; const std::size_t num_blocks; const std::size_t num_bits; - std::size_t shift = get_shift(); - std::size_t num_padding_zeros = calculate_num_padding_zeros(); + std::size_t shift = calculate_shift(num_blocks, num_bits); + std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks); + + const std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + const std::size_t buff = calculate_buff(this->witness_amount(), range_check_input); - padding_gate first_gate_15 = calculate_first_gate_15(); - std::size_t last_gate = calculate_last_gate(this->witness_amount(), num_blocks); - std::size_t confs_per_gate = calculate_confs_per_gate(this->witness_amount()); const std::vector full_configuration = - configure_all(this->witness_amount(), num_blocks, num_bits, limit_permutation_column); + configure_all(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::map> gates_configuration_map = + configure_map(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::vector> gates_configuration = + configure_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + std::vector gates_rows = calculate_gates_rows(this->witness_amount()); - // const std::vector lookup_gates_configuration = - // configure_lookup_gates(this->witness_amount()); const std::size_t rows_amount = - get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, limit_permutation_column); - const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, shift, last_gate); + get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input); struct input_type { // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + @@ -213,13 +222,10 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { - for (std::size_t i = 0; - i < component.full_configuration.size() - - 1 * (component.witness_amount() == 15 && component.num_blocks == 1); - ++i) { + for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { auto config = component.full_configuration[i]; - padded_message.push_back(var(component.W(config.copy_from.column), - config.copy_from.row + config.row + start_row_index, false)); + padded_message.push_back(var(component.W(config.copy_to.back().column), + config.copy_to.back().row + start_row_index, false)); } for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { padded_message.push_back( @@ -232,170 +238,356 @@ namespace nil { } }; - std::size_t get_shift() { + static std::size_t calculate_shift(std::size_t num_blocks, std::size_t num_bits) { return num_blocks * 64 - num_bits; } - - static padding_gate padding(std::size_t witness_amount, std::size_t row = 0) { - if (witness_amount == 9) - return padding_9(row); - if (witness_amount == 15) - return padding_15(row); - return padding_gate(); - } - static padding_gate padding_9(std::size_t row = 0) { - padding_gate res; - res.relay = {-1, 0}; - res.value = {{-1, 1}, {-1, 3}, {0, 0}, {0, 2}, {1, 0}}; - res.sum = {{-1, 2}, {-1, 4}, {0, 1}, {0, 3}, {1, 1}}; - res.first = {{-1, 5}, {-1, 7}, {0, 4}, {0, 6}, {1, 2}}; - res.second = {{-1, 6}, {-1, 8}, {0, 5}, {0, 7}, {1, 3}}; - res.range_check = {{1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}}; - return res; - } - static padding_gate padding_15(std::size_t row = 0) { - padding_gate res; - res.relay = {-1, 11}; - res.value = {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}}; - res.sum = {{1, 3}, {1, 4}, {1, 5}, {0, 3}, {0, 4}, {0, 5}}; - res.first = {{0, 6}, {0, 7}, {0, 8}, {1, 6}, {1, 7}, {1, 8}}; - res.second = {{0, 9}, {0, 10}, {0, 11}, {1, 9}, {1, 10}, {1, 11}}; - res.range_check = {{0, 12}, {0, 13}, {0, 14}, {1, 12}, {1, 13}, {1, 14}}; - return res; - } - - std::size_t calculate_num_padding_zeros() { - if(num_blocks % 17 == 0){ + static std::size_t calculate_num_padding_zeros(std::size_t num_blocks) { + if (num_blocks % 17 == 0){ return 0; } return 17 - num_blocks % 17; } - padding_gate calculate_first_gate_15(std::size_t row = 0) { - padding_gate res; - res.relay = {0, 0}; - res.value = {{0, 1}, {0, 2}}; - res.sum = {{0, 3}, {0, 4}}; - res.first = {{0, 5}, {0, 6}}; - res.second = {{0, 7}, {0, 11}}; - res.range_check = {{0, 8}, {0, 9}}; + static std::size_t calculate_num_cells(std::size_t num_blocks, std::size_t num_bits, bool range_check_input) { + if (calculate_shift(num_blocks, num_bits) == 0 && range_check_input) { + return 1 + 8; // chunk, chunk range_check + } + std::size_t res = 1 // relay + + 1 // chunk = first * 2^k + second + + 2 // first, second + + 1 // sum = relay * 2^(64-k) + first + + 8; // sum range_check + if (range_check_input) { + res += 8; // chunk range_check + } return res; } - static std::size_t calculate_last_gate(std::size_t witness_amount, std::size_t num_blocks) { - if (witness_amount == 9) { - return num_blocks % 5; - } else if (witness_amount == 15) { - if (num_blocks <= 2) { - return 7; - } - return (num_blocks - 2) % 6; + static std::size_t calculate_buff(std::size_t witness_amount, bool range_check_input) { + if (!range_check_input) { + return 2; + } + if (witness_amount == 15) { + return 4; } return 0; } - static std::size_t calculate_confs_per_gate(std::size_t witness_amount) { - if (witness_amount == 9) { - return 5; - } else if (witness_amount == 15) { - return 6; + static int32_t calculate_row_shift(std::size_t num_blocks, std::size_t num_bits) { + auto shift = calculate_shift(num_blocks, num_bits); + if (shift == 0) { + return 0; } - return 0; + return 1; } - static std::vector configure_batching(std::size_t witness_amount, - std::size_t num_blocks) { - std::vector result; - std::size_t conf_ind = 0; - std::size_t row = 1; - std::size_t confs_per_gate = calculate_confs_per_gate(witness_amount); - std::size_t loop_end = num_blocks; - if (witness_amount == 15) { - if (num_blocks <= 2) { - loop_end = 0; - } else { - loop_end -= 2; - } + static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t limit_permutation_column, std::size_t row, std::size_t column, + std::size_t num_cells, std::size_t buff) { + // std::cout << "configure_inner_no_padding\n"; + + if (column > 0) { + row += 1; + column = 0; + } + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + + // chunk + std::vector> copy_to; + if (column > limit_permutation_column) { + copy_to.push_back({last_row + 1, 0}); + } else { + copy_to.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + } + if (!range_check_input) { + return configuration(first_coordinate, {last_row, last_column}, copy_to, {}, {}, {}); } - while (conf_ind < loop_end) { - auto pg = padding(witness_amount, row); - std::size_t j = 0; - { - configuration conf; - conf.row = row; - conf.last_coordinate = pg.second[0]; - conf.copy_to = {pg.value[0], pg.relay}; - conf.constraints = {{pg.value[0], pg.first[0], pg.second[0]}, - {pg.sum[0], pg.relay, pg.first[0]}, - {pg.range_check[0], pg.relay}}; - conf.lookups = {{{pg.range_check[0].row, pg.range_check[0].column}}}; - conf.copy_from = pg.sum[0]; - result.push_back(conf); - j++; - conf_ind++; + std::vector>> constraints; + // chunk range_check + constraints.push_back({copy_to[0]}); + for (int i = 0; i < 8; ++i) { + constraints[0].push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + } + + last_row += last_column / witness_amount; + last_column %= witness_amount; + + auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); + + // std::cout << "config: " << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); + } + static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t row, std::size_t column, + std::size_t num_cells, std::size_t buff) { + // std::cout << "configure_inner_with_padding\n"; + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + + // relay, chunk, sum; second + std::vector> copy_to; + std::pair cell_copy_from; + if (column > 3) { + for (int i = 0; i < 3; ++i) { + copy_to.push_back({last_row + 1, i}); } - while ((j < confs_per_gate) && (conf_ind < loop_end)) { - configuration conf; - conf.row = row; - conf.last_coordinate = pg.second[j]; - conf.copy_to = {pg.value[j]}; - conf.constraints = {{pg.value[j], pg.first[j], pg.second[j]}, - {pg.sum[j], pg.second[j - 1], pg.first[j]}, - {pg.range_check[j], pg.second[j - 1]}}; - conf.lookups = {{pg.range_check[j]}}; - conf.copy_from = pg.sum[j]; - result.push_back(conf); - j++; - conf_ind++; + cell_copy_from = {last_row + 1, 3}; + } else { + for (int i = 0; i < 3; ++i) { + copy_to.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); } - if (witness_amount == 9) - row += 3; - if (witness_amount == 15) - row += 2; + cell_copy_from = {last_row + (last_column / witness_amount), + (last_column++) % witness_amount}; } - return result; + + + std::vector> cells; + if (column > 3) { + for (int i = column; i < witness_amount; ++i) { + cells.push_back({row, i}); + } + std::size_t cells_left = num_cells - witness_amount + column; + std::size_t cur_row = row + 1, + cur_column = 4; + while (cur_column < cells_left) { + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + } + } else { + std::size_t cur_row = row, + cur_column = column + 4; + while (cur_column - column < num_cells) { + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + } + } + std::size_t cell_index = 0; + + std::vector>> constraints; + std::vector>> lookups(1 + range_check_input); + // chunk, first, second + constraints.push_back({copy_to[1]}); + constraints[0].push_back(cells[cell_index++]); + constraints[0].push_back(cell_copy_from); + // sum, relay, first + constraints.push_back({copy_to[2]}); + constraints[1].push_back(copy_to[0]); + constraints[1].push_back(constraints[0][1]); + // sum range_check + constraints.push_back({constraints[1][0]}); + for (int i = 0; i < 8; ++i) { + constraints[2].push_back(cells[cell_index++]); + lookups[0].push_back(constraints.back().back()); + } + // chunk range_check + if (range_check_input) { + constraints.push_back({constraints[0][0]}); + for (int i = 0; i < 8; ++i) { + constraints[3].push_back(cells[cell_index++]); + lookups[1].push_back(constraints.back().back()); + } + } + + if (cell_copy_from.first > cells.back().first) { + cells.back() = cell_copy_from; + } + + last_column = cells.back().second + 1 + buff; + last_row = cells.back().first + (last_column >= witness_amount); + last_column %= witness_amount; + + auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + + // std::cout << "config: " << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + } + static configuration configure_inner(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t limit_permutation_column, + std::size_t row, std::size_t column, + std::size_t num_cells, std::size_t buff) { + if (calculate_shift(num_blocks, num_bits) == 0) { + return configure_inner_no_padding(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column, row, column, num_cells, buff); + } + return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells, buff); } + + static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t limit_permutation_column) { - static std::vector configure_all(std::size_t witness_amount, - std::size_t num_blocks, - std::size_t num_bits, - std::size_t limit_permutation_column) { - std::size_t shift = num_blocks * 64 - num_bits; + std::size_t row = 0, + column = 0; std::vector result; - if (shift == 0) { - std::int32_t row = 0; - std::size_t column = 0; + if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { for (std::size_t i = 0; i < num_blocks; ++i) { configuration conf; conf.copy_from = {row, column}; + conf.copy_to.push_back({row, column}); column += 1; if (column == limit_permutation_column) { column = 0; row += 1; } + conf.last_coordinate = {row, column}; result.push_back(conf); } - } else { - if (witness_amount % 15 == 0) { - configuration conf0; - conf0.row = 0; - conf0.last_coordinate = {0, 7}; - conf0.copy_to = {{0, 1}, {0, 0}}; - conf0.constraints = {{{0, 1}, {0, 5}, {0, 7}}, {{0, 3}, {0, 0}, {0, 5}}, {{0, 8}, {0, 0}}}; - conf0.lookups = {{{0, 8}}}; - conf0.copy_from = {0, 3}; - result.push_back(conf0); - configuration conf1; - conf1.row = 0; - conf1.copy_to = {{0, 2}}; - conf1.last_coordinate = {0, 11}; - conf1.constraints = {{{0, 2}, {0, 6}, {0, 11}}, {{0, 4}, {0, 7}, {0, 6}}, {{0, 9}, {0, 7}}}; - conf1.lookups = {{{0, 9}}}; - conf1.copy_from = {0, 4}; - result.push_back(conf1); + return result; + } + + std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + std::size_t buff = calculate_buff(witness_amount, range_check_input); + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column, row, column, num_cells, buff); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } + + // std::cout << "num_cofigs: " << result.size() << "\n"; + // for (std::size_t i = 0; i < result.size(); ++i) { + // auto cur_config = result[i]; + // std::cout << "config: " << i << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + + return result; + } + static std::map> configure_map(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + + auto shift = calculate_shift(num_blocks, num_bits); + if (shift == 0 && !range_check_input) { + return {}; + } + + auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + std::size_t row = 0, + column = 0; + int32_t row_shift = (shift == 0 || witness_amount == 15) ? 0 : 1; + + std::map> config_map; + + for (std::size_t i = 0; i < num_blocks; ++i) { + row = config[i].first_coordinate.row; + column = config[i].first_coordinate.column; + if (config_map.find(column) != config_map.end()) { + config_map[column].push_back(row + row_shift); + } else { + config_map[column] = {row + row_shift}; } + } - auto batch_configs = configure_batching(witness_amount, num_blocks); - result.insert(result.end(), batch_configs.begin(), batch_configs.end()); + // std::cout << "MAP\n"; + // for (auto c : config_map) { + // std::cout << c.first << ": "; + // for (auto r : c.second) { + // std::cout << r << " "; + // } + // std::cout << std::endl; + // } + + return config_map; + } + + static std::vector> configure_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { + return {}; + } + + std::vector> result; + auto gates_configuration_map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + std::size_t buff = calculate_buff(witness_amount, range_check_input); + + for (auto config: gates_configuration_map) { + configuration cur_config = configure_inner(witness_amount, num_blocks, num_bits, + range_check_input, limit_permutation_column, + 0, config.first, num_cells, buff); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max - min <= 2); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + cur_row = pairs[cur_constr].first; + cur_result.push_back(c); + } + result.push_back(cur_result); } + + // for (std::size_t i = 0; i < result.size(); ++i) { + // std::cout << "config " << i << ":\n"; + // for (auto cur_config : result[i]) { + // std::cout << "gate:\n"; + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + // } return result; } @@ -422,46 +614,27 @@ namespace nil { static std::size_t get_gates_amount(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, - std::size_t last_gate) { - if (num_blocks * 64 - num_bits == 0) { - return 0; - } - if (witness_amount == 9) { - if (last_gate == 0 || last_gate == num_blocks) { - return 1 * 2; - } - return 2 * 2; - } else if (witness_amount == 15) { - if (last_gate == 7) { - return 1 * 2; - } - if (last_gate == 0 || last_gate == num_blocks - 2) { - return 2 * 2; - } - return 3 * 2; - } - return 0; + bool range_check_input, + std::size_t limit_permutation_column = 7) { + auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + return map.size() * 2; } static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t limit_permutation_column) { - - if (witness_amount == 9) { - return std::ceil(num_blocks/ 5.0) * 3; - } - if (witness_amount == 15) { - if (num_blocks <= 2) { - return 1; - } - return 1 + std::ceil((num_blocks - 2) / 6.0) * 2; - } + auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + std::cout << "NUM ROWS: " << confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0) << "\n"; + return confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); } std::map component_lookup_tables(){ std::map lookup_tables; lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_ONE_table/full"] = 0; // REQUIRED_TABLE return lookup_tables; } @@ -469,21 +642,23 @@ namespace nil { typename PublicInputContainerType> keccak_padding(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, std::size_t num_blocks_, std::size_t num_bits_, - std::size_t lpc_ = 7) : + bool range_check_input_ = true, std::size_t limit_permutation_column_ = 7) : component_type(witness, constant, public_input, get_manifest()), - num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), + limit_permutation_column(limit_permutation_column_) {}; keccak_padding( std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : + std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_ = true, std::size_t limit_permutation_column_ = 7) : component_type(witnesses, constants, public_inputs, get_manifest()), - num_blocks(num_blocks_), num_bits(num_bits_), limit_permutation_column(lpc_) {}; + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), + limit_permutation_column(limit_permutation_column_) {}; using lookup_table_definition = - typename nil::crypto3::zk::snark::detail::lookup_table_definition; + typename nil::crypto3::zk::snark::lookup_table_definition; }; template @@ -498,7 +673,7 @@ namespace nil { &assignment, const typename padding_component::input_type &instance_input, - const std::map lookup_tables_indices) { + const typename lookup_library::left_reserved_type lookup_tables_indices) { using component_type = padding_component; using var = typename component_type::var; @@ -510,109 +685,90 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; std::vector selector_indexes; - auto config = component.full_configuration; + auto gates_configuration = component.gates_configuration; std::size_t config_index = 0; std::size_t gate_index = 0; std::size_t lookup_gate_index = 0; - - const std::size_t two = 2; - if (component.shift > 0) { - std::vector cur_constraints; - std::vector cur_lookup_constraints; - if (component.witness_amount() == 15) { - for (std::size_t i = 0; i < std::min(two, component.num_blocks); ++i) { - auto cur_config = config[config_index]; - cur_constraints.push_back( - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * - (integral_type(1) << (64 - component.shift)) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); - cur_constraints.push_back( - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * - (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back( - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); - config_index++; + int32_t row_shift = (component.shift == 0 || component.witness_amount() == 15) ? 0 : 1; + + std::vector cur_constraints; + std::vector cur_lookup_constraints; + if (component.shift == 0) { + if (component.range_check_input) { + for (auto confs : gates_configuration) { + auto conf = confs[0]; + constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) + * (integral_type(1) << ((i-1) * 8)); + if (i == 8) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/64bit"), + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); + } else { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); + } + } + selector_indexes.push_back(bp.add_gate(constraint)); + gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); } - selector_indexes.push_back(bp.add_gate(cur_constraints)); - gate_index++; - cur_constraints.clear(); - selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); - lookup_gate_index++; - cur_lookup_constraints.clear(); } - std::cout << "gate_index: " << gate_index << std::endl; - std::cout << "component.gates_amount: " << component.gates_amount << std::endl; - std::cout << "component.last_gate: " << component.last_gate << std::endl; - if (component.gates_amount - gate_index - (bool)(component.last_gate % 7) > 0) { - for (int i = 0; i < component.confs_per_gate; ++i) { - auto cur_config = config[config_index]; - cur_constraints.push_back(constraint_type( - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * - (integral_type(1) << (64 - component.shift)) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row))); - cur_constraints.push_back( - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * - (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back( - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); - config_index++; - if (config_index >= config.size()) { - break; + } else { + for (auto confs : gates_configuration) { + auto conf = confs[0]; + // chunk, first, second + cur_constraints.push_back(constraint_type( + var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift) - + var(conf.constraints[0][1].column, static_cast(conf.constraints[0][1].row) - row_shift) * + (integral_type(1) << (64 - component.shift)) - + var(conf.constraints[0][2].column, static_cast(conf.constraints[0][2].row) - row_shift))); + // sum, relay, first + cur_constraints.push_back( + var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row) - row_shift) - + var(conf.constraints[1][1].column, static_cast(conf.constraints[1][1].row) - row_shift) * + (integral_type(1) << component.shift) - + var(conf.constraints[1][2].column, static_cast(conf.constraints[1][2].row) - row_shift)); + // sum, range_check + constraint_type constraint = var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row) - row_shift); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(conf.constraints[2][i].column, static_cast(conf.constraints[2][i].row) - row_shift) + * (integral_type(1) << ((i-1) * 8)); + if (i == 8) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/64bit"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); + } else { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); } } - selector_indexes.push_back(bp.add_gate(cur_constraints)); - gate_index++; - cur_constraints.clear(); - selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); - lookup_gate_index++; - cur_lookup_constraints.clear(); - } - if (component.last_gate % 7 && config_index < config.size()) { - for (int i = 0; i < component.last_gate; ++i) { - auto cur_config = config[config_index]; - cur_constraints.push_back( - var(cur_config.constraints[0][0].column, cur_config.constraints[0][0].row) - - var(cur_config.constraints[0][1].column, cur_config.constraints[0][1].row) * - (integral_type(1) << (64 - component.shift)) - - var(cur_config.constraints[0][2].column, cur_config.constraints[0][2].row)); - cur_constraints.push_back( - var(cur_config.constraints[1][0].column, cur_config.constraints[1][0].row) - - var(cur_config.constraints[1][1].column, cur_config.constraints[1][1].row) * - (integral_type(1) << component.shift) - - var(cur_config.constraints[1][2].column, cur_config.constraints[1][2].row)); - cur_constraints.push_back( - var(cur_config.constraints[2][1].column, cur_config.constraints[2][1].row) - - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64) - - var(cur_config.constraints[2][0].column, cur_config.constraints[2][0].row)); - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row)}}); - config_index++; - if (config_index >= config.size()) { - break; + cur_constraints.push_back(constraint); + if (component.range_check_input) { + // chunk, range_check + constraint = var(conf.constraints[3][0].column, static_cast(conf.constraints[3][0].row) - row_shift); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(conf.constraints[3][i].column, static_cast(conf.constraints[3][i].row) - row_shift) + * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift)}}); } + cur_constraints.push_back(constraint); } selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; + cur_constraints.clear(); selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); lookup_gate_index++; + cur_lookup_constraints.clear(); } } + // std::cout << "gate_index: " << gate_index << std::endl; + // std::cout << "component.gates_amount: " << component.gates_amount << std::endl; + // std::cout << "ind: " << gate_index << ' ' << lookup_gate_index << std::endl; + // std::cout << "SELS: " << selector_indexes.size() << std::endl; BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); - std::cout << "SELS: " << selector_indexes.size() << std::endl; return selector_indexes; } @@ -633,69 +789,37 @@ namespace nil { std::size_t input_index = 0; std::size_t witness_amount = component.witness_amount(); + std::size_t conf_index_for_input = 0; if (component.shift != 0) { bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); + conf_index_for_input = 1; } - while (config_index < component.full_configuration.size() - (component.shift != 0) - - (witness_amount == 15 && component.num_blocks == 1)) { + while (config_index < component.full_configuration.size() - 1) { auto config = component.full_configuration[config_index]; bp.add_copy_constraint({instance_input.message[input_index++], - var(component.W(config.copy_to[0].column), - config.copy_to[0].row + strow + config.row, false)}); + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); + if (component.shift != 0) { + auto next_config = component.full_configuration[config_index + 1]; + bp.add_copy_constraint({var(component.W(config.copy_from.column), + config.copy_from.row + strow, false), + var(component.W(next_config.copy_to[0].column), + next_config.copy_to[0].row + strow, false)}); + } config_index++; } - if (component.shift != 0) { auto config = component.full_configuration[config_index]; bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), - var(component.W(config.copy_to[0].column), - config.copy_to[0].row + strow + config.row, false)}); - - if (witness_amount == 9) { - config_index = component.confs_per_gate; - while (config_index < component.full_configuration.size()) { - auto config1 = component.full_configuration[config_index]; - auto config2 = component.full_configuration[config_index - 1]; - bp.add_copy_constraint({var(component.W(config1.copy_to[1].column), - config1.copy_to[1].row + strow + config1.row, false), - var(component.W(config2.last_coordinate.column), - config2.last_coordinate.row + strow + config2.row, false)}); - config_index += component.confs_per_gate; - } - } + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); + } else { + auto config = component.full_configuration[config_index]; + bp.add_copy_constraint({instance_input.message[input_index++], + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); } - - // if (component.shift != 0) { - // std::size_t config_index = 0; - // std::size_t input_index = 0; - // auto config = component.full_configuration[config_index++]; - // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + strow, - // false)}); - // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[1].column), config.copy_to[1].row + strow, - // false)}); - // while (input_index < instance_input.message.size()) { - // std::cout << input_index << ' ' << config_index << ' ' << component.full_configuration.size() - // << std::endl; config = component.full_configuration[config_index++]; - // bp.add_copy_constraint({instance_input.message[input_index++], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + - // strow, false)}); - // } - // // config = component.full_configuration[config_index]; - // // bp.add_copy_constraint({var(component.C(0), start_row_index, false, - // var::column_type::constant), - // // var(component.W(config.copy_to[0].column), config.copy_to[0].row + - // strow, false)}); - // } else { - // for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { - // auto config = component.full_configuration[i]; - // bp.add_copy_constraint({instance_input.message[i], - // var(component.W(config.copy_to[0].column), config.copy_to[0].row + - // strow, false)}); - // } - // } } template @@ -711,31 +835,16 @@ namespace nil { using var = typename component_type::var; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); - std::size_t ind = 0; + auto gc_map = component.gates_configuration_map; + std::size_t sel_ind = 0; std::size_t gate_row_ind = 0; - if (component.witness_amount() == 15) { - assignment.enable_selector(selector_indexes[ind++], - component.gates_rows[gate_row_ind] + start_row_index); - assignment.enable_selector(selector_indexes[ind++], - component.gates_rows[gate_row_ind++] + start_row_index); - } - if (gate_row_ind < component.gates_rows.size() - (bool)(component.last_gate % 7)) { - for (std::size_t i = gate_row_ind; - i < component.gates_rows.size() - (bool)(component.last_gate % 7); - ++i) { - assignment.enable_selector(selector_indexes[ind], - component.gates_rows[gate_row_ind] + start_row_index); - assignment.enable_selector(selector_indexes[ind + 1], - component.gates_rows[gate_row_ind++] + start_row_index); - } - ind += 2; - } - if (component.last_gate % 7) { - assignment.enable_selector(selector_indexes[ind++], - component.gates_rows[gate_row_ind] + start_row_index); - assignment.enable_selector(selector_indexes[ind], - component.gates_rows[gate_row_ind] + start_row_index); + for (auto gc : gc_map) { + for (auto gate_row : gc.second) { + assignment.enable_selector(selector_indexes[sel_ind], gate_row + start_row_index); + assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + start_row_index); + } + sel_ind += 2; } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -761,7 +870,6 @@ namespace nil { std::size_t config_index = 0; std::size_t witness_amount = component.witness_amount(); - // batching if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { @@ -773,47 +881,68 @@ namespace nil { integral_type mask = (integral_type(1) << (64 - component.shift)) - 1; std::array chunk_parts = {integral_chunk >> (64 - component.shift), integral_chunk & mask}; - integral_type first_chunk = (relay_chunk << component.shift) + chunk_parts[0]; - integral_type relay_range_check = - relay_chunk - (integral_type(1) << (64 - component.shift)) + (integral_type(1) << 64); + integral_type sum = (relay_chunk << component.shift) + chunk_parts[0]; + + integral_type mask_range_check = (integral_type(1) << 8) - 1; + std::vector sum_range_check; + integral_type sum_to_check = sum; + for (std::size_t i = 0; i < 7; ++i) { + sum_range_check.push_back(sum_to_check & mask_range_check); + sum_to_check >>= 8; + } + sum_range_check.push_back(sum_to_check); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), - cur_config.constraints[0][0].row + strow + cur_config.row) = chunk; - if (witness_amount == 9) { - if (config_index % component.confs_per_gate == 0) { - assignment.witness(component.W(cur_config.constraints[1][1].column), - cur_config.constraints[1][1].row + strow + cur_config.row) = - value_type(relay_chunk); - } + // chunk, first, second + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + strow) = chunk; + for (int j = 1; j < 3; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_parts[j - 1]); } - if (witness_amount == 15) { - if (config_index == 0) { - assignment.witness(component.W(cur_config.constraints[1][1].column), - cur_config.constraints[1][1].row + strow + cur_config.row) = - value_type(relay_chunk); - } + // sum, relay, first + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = value_type(sum); + assignment.witness(component.W(cur_config.constraints[1][1].column), cur_config.constraints[1][1].row + strow) = value_type(relay_chunk); + assignment.witness(component.W(cur_config.constraints[1][2].column), cur_config.constraints[1][2].row + strow) = value_type(chunk_parts[0]); + // sum range_check + for (int j = 1; j < 9; ++j) { + std::cout << "sum_range_check: " << sum_range_check[j - 1] << std::endl; + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(sum_range_check[j - 1]); } - for (int j = 1; j < 3; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), - cur_config.constraints[0][j].row + strow + cur_config.row) = - value_type(chunk_parts[j - 1]); + if (component.range_check_input) { + std::vector chunk_range_check; + integral_type chunk_to_check = integral_chunk; + for (std::size_t i = 0; i < 7; ++i) { + chunk_range_check.push_back(chunk_to_check & mask_range_check); + chunk_to_check >>= 8; + } + chunk_range_check.push_back(chunk_to_check); + // chunk range_check + for (int j = 1; j < 9; ++j) { + assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(chunk_range_check[j - 1]); + } } - assignment.witness(component.W(cur_config.constraints[1][0].column), - cur_config.constraints[1][0].row + strow + cur_config.row) = - value_type(first_chunk); - assignment.witness(component.W(cur_config.constraints[2][0].column), - cur_config.constraints[2][0].row + strow + cur_config.row) = - value_type(relay_range_check); - relay_chunk = chunk_parts[1]; config_index++; } } else { for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_from.column), - cur_config.copy_from.row + strow + cur_config.row) = + + if (component.range_check_input) { + integral_type chunk_to_check = integral_type(var_value(assignment, instance_input.message[index]).data); + integral_type mask_range_check = (integral_type(1) << 8) - 1; + std::vector chunk_range_check; + for (std::size_t i = 0; i < 8; ++i) { + chunk_range_check.push_back(chunk_to_check & mask_range_check); + chunk_to_check >>= 8; + } + // chunk range_check + for (int j = 1; j < 9; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_range_check[j - 1]); + } + } + + assignment.witness(component.W(cur_config.copy_to[0].column), + cur_config.copy_to[0].row + strow) = var_value(assignment, instance_input.message[index]); } } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 6b9ec2a4e..fa98a8f35 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -71,7 +71,6 @@ std::vector std::vector result; std::size_t shift = 64 * message.size() - num_bits; - std::cout << "shift: " << shift << ' ' << num_bits << std::endl; if (shift > 0) { integral_type relay_value = integral_type(message[0].data); @@ -97,10 +96,11 @@ std::vector template auto test_keccak_padding_inner(std::vector message, std::vector expected_result, - const std::size_t num_blocks, const std::size_t num_bits) { + const std::size_t num_blocks, const std::size_t num_bits, const bool range_check_input = true, + const std::size_t limit_permutation_column = 7) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; - constexpr std::size_t SelectorColumns = 6; + constexpr std::size_t SelectorColumns = 8; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params; @@ -116,10 +116,8 @@ auto test_keccak_padding_inner(std::vector public_input; - // std::cout << "message:\n"; for (int i = 0; i < num_blocks; ++i) { public_input.push_back(message[i]); - // std::cout << message[i].data << std::endl; } std::vector message_vars; @@ -129,15 +127,9 @@ auto test_keccak_padding_inner(std::vector {0}, - std::array {0}, num_blocks, num_bits, 7); + std::array {0}, num_blocks, num_bits, + range_check_input, limit_permutation_column); nil::crypto3::test_component( component_instance, public_input, result_check, instance_input, - nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, 7); + nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); } // works @@ -173,7 +166,8 @@ void test_keccak_padding_0() { } template -void test_keccak_padding_random(std::size_t message_size) { +void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero = true, bool range_check_input = true, + std::size_t limit_permutation_column = 7) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -182,8 +176,15 @@ void test_keccak_padding_random(std::size_t message_size) { std::uniform_int_distribution dis; integral_type mask = (integral_type(1) << 64) - 1; - integral_type mask_zero = (integral_type(1) << 60) - 1; + std::size_t power_for_mask = 64; + if (random_mask_zero) { + power_for_mask = dis(gen) % 63 + 1; + } + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero); + while ((integral_type(message_zero.data) & (integral_type(1) << (power_for_mask - 1))) == 0) { + message_zero = value_type(integral_type(dis(gen)) & mask_zero); + } std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -192,15 +193,54 @@ void test_keccak_padding_random(std::size_t message_size) { assert(message_size == message.size()); std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); std::size_t num_blocks = message_size; - std::cout << "message size: " << message_size << " blocks\n"; - // for (int i = 0; i < message_size; ++i) { - // std::cout << "message:" << message[i].data << std::endl; - // } auto expected_result = padding_function(message, num_bits); test_keccak_padding_inner(message, expected_result, - num_blocks, num_bits); + num_blocks, num_bits, + range_check_input, limit_permutation_column); +} + +template +void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits, bool random_mask_zero = true, bool range_check_input = true, + std::size_t limit_permutation_column = 7) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; + + integral_type mask = (integral_type(1) << 64) - 1; + std::size_t power_for_mask = 64; + if (random_mask_zero) { + power_for_mask = dis(gen) % 63 + 1; + } + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; + value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero); + while ((integral_type(message_zero.data) & (integral_type(1) << (power_for_mask - 1))) == 0) { + message_zero = value_type(integral_type(dis(gen)) & mask_zero); + } + std::vector message; + message.push_back(message_zero); + for (std::size_t i = 1; i < message_size; i++) { + message.push_back(value_type(integral_type(dis(gen)) & mask)); + } + assert(message_size == message.size()); + std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); + std::size_t num_blocks = message_size; + + auto expected_result = padding_function(message, num_bits); + + if (more_bits) { + num_bits -= 1; + } else { + num_bits += 1; + } + + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits, + range_check_input, limit_permutation_column); } BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) @@ -208,18 +248,35 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_padding_0(); - for (std::size_t i = 1; i < 35; i++) { + // test_keccak_padding_0(); + for (std::size_t i = 1; i < 100; i++) { test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); } } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - test_keccak_padding_0(); - for (std::size_t i = 1; i < 35; i++) { + // test_keccak_padding_0(); + for (std::size_t i = 1; i < 100; i++) { test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); + } +} + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + + for (std::size_t i = 1; i < 2; i++) { + // test_to_fail_keccak_padding_random(i, false); + // test_to_fail_keccak_padding_random(i, true); + // test_to_fail_keccak_padding_random(i, true, false); + // test_to_fail_keccak_padding_random(i, false, false); } } From 2d2c9262c602cf26f72420891dab78ccf0741f2b Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 29 Nov 2023 16:34:03 +0000 Subject: [PATCH 26/48] finished padding ver1 #183 --- .../hashes/keccak/keccak_padding.hpp | 138 +++++++++++------- include/nil/blueprint/lookup_library.hpp | 37 +++++ test/hashes/plonk/keccak_padding.cpp | 70 ++++++--- 3 files changed, 173 insertions(+), 72 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 5d5d5e671..ff8d26603 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -118,26 +118,6 @@ namespace nil { (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); } }; - struct padding_gate { - coordinates relay; - std::vector value; - std::vector sum; - std::vector range_check; - std::vector first; - std::vector second; - - padding_gate() = default; - padding_gate(coordinates relay_, std::vector value_, std::vector sum_, - std::vector range_check_, std::vector first_, - std::vector second_) : - relay(relay_), - value(value_), sum(sum_), range_check(range_check_), first(first_), second(second_) {}; - - bool operator==(const padding_gate &other) const { - return relay == other.relay && value == other.value && sum == other.sum && - range_check == other.range_check && first == other.first && second == other.second; - } - }; using var = typename component_type::var; using manifest_type = nil::blueprint::plonk_component_manifest; @@ -239,6 +219,7 @@ namespace nil { }; static std::size_t calculate_shift(std::size_t num_blocks, std::size_t num_bits) { + assert(num_blocks * 64 >= num_bits); return num_blocks * 64 - num_bits; } static std::size_t calculate_num_padding_zeros(std::size_t num_blocks) { @@ -281,7 +262,6 @@ namespace nil { static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column, std::size_t row, std::size_t column, std::size_t num_cells, std::size_t buff) { - // std::cout << "configure_inner_no_padding\n"; if (column > 0) { row += 1; @@ -336,7 +316,6 @@ namespace nil { static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t row, std::size_t column, std::size_t num_cells, std::size_t buff) { - // std::cout << "configure_inner_with_padding\n"; std::pair first_coordinate = {row, column}; @@ -440,6 +419,30 @@ namespace nil { } return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells, buff); } + // static configuration configure_shift(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + // bool range_check_input, std::size_t limit_permutation_column, + // std::size_t row, std::size_t column, + // std::size_t num_cells, std::size_t buff) { + // if (column + 3 > limit_permutation_column) { + // row += 1; + // column = 0; + // } + + // std::pair first_coordinate = {row, column}; + // std::size_t last_row = row, + // last_column = column; + // std::vector> copy_to; + // for (int i = 0; i < 2; ++i) { + // copy_to.push_back({last_row + (last_column / witness_amount), + // (last_column++) % witness_amount}); + // } + // std::pair cell_copy_from = {last_row + (last_column / witness_amount), + // (last_column++) % witness_amount}; + // std::vector>> constraints = {{cell_copy_from, copy_to[0], copy_to[1]}}; + // std::vector>> lookups = {{cell_copy_from}}; + + // return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + // } static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { @@ -617,7 +620,7 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column = 7) { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - return map.size() * 2; + return map.size() * 2 + range_check_input; } static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, @@ -626,7 +629,6 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column) { auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - std::cout << "NUM ROWS: " << confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0) << "\n"; return confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); } @@ -634,7 +636,7 @@ namespace nil { std::map lookup_tables; lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_ONE_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_sign_bit_table/full"] = 0; // REQUIRED_TABLE return lookup_tables; } @@ -690,24 +692,30 @@ namespace nil { std::size_t gate_index = 0; std::size_t lookup_gate_index = 0; int32_t row_shift = (component.shift == 0 || component.witness_amount() == 15) ? 0 : 1; + bool checked_first_bit = false; std::vector cur_constraints; std::vector cur_lookup_constraints; if (component.shift == 0) { if (component.range_check_input) { + auto conf = gates_configuration[0][0]; + for (std::size_t i = 1; i < 8; ++i) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift)}}); + } + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_sign_bit_table/full"), + {var(component.W(conf.constraints[0][8].column), static_cast(conf.constraints[0][8].row) - row_shift)}}); + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); for (auto confs : gates_configuration) { auto conf = confs[0]; - constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); + constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) + constraint -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row) - row_shift) * (integral_type(1) << ((i-1) * 8)); - if (i == 8) { - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/64bit"), - {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); - } else { - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); - } + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift)}}); } selector_indexes.push_back(bp.add_gate(constraint)); gate_index++; @@ -717,6 +725,23 @@ namespace nil { } } } else { + if (component.range_check_input) { + auto conf = gates_configuration[0][0]; + for (std::size_t i = 1; i < 8; ++i) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); + } + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_sign_bit_table/full"), + {var(component.W(conf.constraints[2][8].column), static_cast(conf.constraints[2][8].row) - row_shift)}}); + // chunk, range_check + for (std::size_t i = 1; i < 9; ++i) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift)}}); + } + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); + } for (auto confs : gates_configuration) { auto conf = confs[0]; // chunk, first, second @@ -736,13 +761,8 @@ namespace nil { for (std::size_t i = 1; i < 9; ++i) { constraint -= var(conf.constraints[2][i].column, static_cast(conf.constraints[2][i].row) - row_shift) * (integral_type(1) << ((i-1) * 8)); - if (i == 8) { - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/64bit"), - {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); - } else { - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); - } + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); } cur_constraints.push_back(constraint); if (component.range_check_input) { @@ -764,10 +784,6 @@ namespace nil { cur_lookup_constraints.clear(); } } - // std::cout << "gate_index: " << gate_index << std::endl; - // std::cout << "component.gates_amount: " << component.gates_amount << std::endl; - // std::cout << "ind: " << gate_index << ' ' << lookup_gate_index << std::endl; - // std::cout << "SELS: " << selector_indexes.size() << std::endl; BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); return selector_indexes; } @@ -810,12 +826,12 @@ namespace nil { config_index++; } if (component.shift != 0) { - auto config = component.full_configuration[config_index]; + auto config = component.full_configuration[config_index++]; bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); } else { - auto config = component.full_configuration[config_index]; + auto config = component.full_configuration[config_index++]; bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); @@ -837,14 +853,31 @@ namespace nil { auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); auto gc_map = component.gates_configuration_map; std::size_t sel_ind = 0; + auto gc_iter = gc_map.begin(); - std::size_t gate_row_ind = 0; - for (auto gc : gc_map) { - for (auto gate_row : gc.second) { - assignment.enable_selector(selector_indexes[sel_ind], gate_row + start_row_index); - assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + start_row_index); + if (gc_iter != gc_map.end()) { + if (component.range_check_input) { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + start_row_index); + sel_ind++; + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + start_row_index); + } else { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + start_row_index); + assignment.enable_selector(selector_indexes[sel_ind + 1], gc_iter->second[0] + start_row_index); + } + for (std::size_t i = 1; i < gc_iter->second.size(); ++i) { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[i] + start_row_index); + assignment.enable_selector(selector_indexes[sel_ind + 1], gc_iter->second[i] + start_row_index); } sel_ind += 2; + gc_iter++; + + for (; gc_iter != gc_map.end(); ++gc_iter) { + for (auto gate_row : gc_iter->second) { + assignment.enable_selector(selector_indexes[sel_ind], gate_row + start_row_index); + assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + start_row_index); + } + sel_ind += 2; + } } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -904,7 +937,6 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[1][2].column), cur_config.constraints[1][2].row + strow) = value_type(chunk_parts[0]); // sum range_check for (int j = 1; j < 9; ++j) { - std::cout << "sum_range_check: " << sum_range_check[j - 1] << std::endl; assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(sum_range_check[j - 1]); } if (component.range_check_input) { diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index 172dced67..39996a602 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -321,6 +321,42 @@ namespace nil { virtual std::size_t get_columns_number(){ return 2; } virtual std::size_t get_rows_number(){ return 256; } }; + + class sparse_values_base8_sign_bit_table : public lookup_table_definition{ + // "keccak_pack_table/64bit" doesn't work, so we need to use this temporary table + typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 1; + power = power << 3; + } + return value_type(result_integral); + } + public: + sparse_values_base8_sign_bit_table(): lookup_table_definition("keccak_sign_bit_table"){ + this->subtables["full"] = {{0}, 0, 128}; + } + virtual void generate(){ + this->_table.resize(2); + this->_table[0].push_back(0); + this->_table[1].push_back(0); + for (typename BlueprintFieldType::integral_type i = 128; + i < typename BlueprintFieldType::integral_type(256); + i++ + ) { + this->_table[0].push_back(i); + this->_table[1].push_back(to_sparse(i)); + } + } + virtual std::size_t get_columns_number(){ return 1; } + virtual std::size_t get_rows_number(){ return 129; } + }; public: using bimap_type = boost::bimap, boost::bimaps::set_of>; using left_reserved_type = typename bimap_type::left_map; @@ -338,6 +374,7 @@ namespace nil { tables["sha256_maj"] = std::shared_ptr(new maj_function_table()); tables["sha256_ch"] = std::shared_ptr(new ch_function_table()); tables["keccak_pack_table"] = std::shared_ptr(new sparse_values_base8_table()); + tables["keccak_sign_bit_table"] = std::shared_ptr(new sparse_values_base8_sign_bit_table()); } void register_lookup_table(std::shared_ptr table){ diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index fa98a8f35..cd5d3a57e 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -100,7 +100,7 @@ auto test_keccak_padding_inner(std::vector; @@ -129,7 +129,7 @@ auto test_keccak_padding_inner(std::vector(message, expected_result, num_blocks, num_bits); } +template +void test_keccak_padding_1(std::size_t num_bits) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector message = {value_type(integral_type(1) << (num_bits-1)%64)}; + for (std::size_t i = 0; i < (num_bits-1)/64; i++) { + message.push_back(value_type(0)); + } + const std::size_t num_blocks = message.size(); + + std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + for (std::size_t i = 0; i < (num_blocks-1) / 17; i++) { + expected_result.insert(expected_result.end(), {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + } + + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits); +} template void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero = true, bool range_check_input = true, @@ -181,10 +200,7 @@ void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero power_for_mask = dis(gen) % 63 + 1; } integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; - value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero); - while ((integral_type(message_zero.data) & (integral_type(1) << (power_for_mask - 1))) == 0) { - message_zero = value_type(integral_type(dis(gen)) & mask_zero); - } + value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -217,10 +233,7 @@ void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits power_for_mask = dis(gen) % 63 + 1; } integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; - value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero); - while ((integral_type(message_zero.data) & (integral_type(1) << (power_for_mask - 1))) == 0) { - message_zero = value_type(integral_type(dis(gen)) & mask_zero); - } + value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -248,8 +261,9 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_padding_0(); + test_keccak_padding_0(); for (std::size_t i = 1; i < 100; i++) { + test_keccak_padding_1(i); test_keccak_padding_random(i); test_keccak_padding_random(i, false); test_keccak_padding_random(i, true, false); @@ -260,8 +274,9 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - // test_keccak_padding_0(); + test_keccak_padding_0(); for (std::size_t i = 1; i < 100; i++) { + test_keccak_padding_1(i); test_keccak_padding_random(i); test_keccak_padding_random(i, false); test_keccak_padding_random(i, true, false); @@ -271,13 +286,30 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - - for (std::size_t i = 1; i < 2; i++) { - // test_to_fail_keccak_padding_random(i, false); - // test_to_fail_keccak_padding_random(i, true); - // test_to_fail_keccak_padding_random(i, true, false); - // test_to_fail_keccak_padding_random(i, false, false); - } + // test with no result_check asserts + + // test_to_fail_keccak_padding_random(10, false); + // test_to_fail_keccak_padding_random(16, false, false); + // test_to_fail_keccak_padding_random(11, false, false, false); + // test_to_fail_keccak_padding_random(100, true); + // test_to_fail_keccak_padding_random(150, true, false); + // test_to_fail_keccak_padding_random(2, true, true, false); + // test_to_fail_keccak_padding_random(4, true, false, false); + + // test_to_fail_keccak_padding_random(10, false); + // test_to_fail_keccak_padding_random(16, false, false); + // test_to_fail_keccak_padding_random(11, false, false, false); + // test_to_fail_keccak_padding_random(100, true); + // test_to_fail_keccak_padding_random(150, true, false); + // test_to_fail_keccak_padding_random(2, true, true, false); + // test_to_fail_keccak_padding_random(4, true, false, false); + + // this doesn't break, because we switched off range check input + // test_to_fail_keccak_padding_random(5, false, true, false); + // test_to_fail_keccak_padding_random(5, false, true, false); + + // test_to_fail_keccak_padding_random(5, false, true); + // test_to_fail_keccak_padding_random(5, false, true); } BOOST_AUTO_TEST_SUITE_END() From 0a24b3deef472651b9940b46bf735c753c1fed1a Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 11 Dec 2023 15:16:10 +0000 Subject: [PATCH 27/48] padding added shift constraint #183 --- .../hashes/keccak/keccak_padding.hpp | 128 +++++++++++------- test/hashes/plonk/keccak.cpp | 52 +++++-- 2 files changed, 120 insertions(+), 60 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index ff8d26603..918fca549 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -202,14 +202,15 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { + auto size = component.full_configuration.size(); + padded_message.resize(size + component.num_padding_zeros); for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { auto config = component.full_configuration[i]; - padded_message.push_back(var(component.W(config.copy_to.back().column), - config.copy_to.back().row + start_row_index, false)); + padded_message[i] = var(component.W(config.copy_to.back().column), + config.copy_to.back().row + start_row_index, false); } - for (std::size_t i = 0; i < component.num_padding_zeros; ++i) { - padded_message.push_back( - var(component.C(0), start_row_index, false, var::column_type::constant)); + for (std::size_t i = size; i < size + component.num_padding_zeros; ++i) { + padded_message[i] = var(component.C(0), start_row_index, false, var::column_type::constant); } } @@ -219,7 +220,7 @@ namespace nil { }; static std::size_t calculate_shift(std::size_t num_blocks, std::size_t num_bits) { - assert(num_blocks * 64 >= num_bits); + // assert(num_blocks * 64 >= num_bits); return num_blocks * 64 - num_bits; } static std::size_t calculate_num_padding_zeros(std::size_t num_blocks) { @@ -419,37 +420,28 @@ namespace nil { } return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells, buff); } - // static configuration configure_shift(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, - // bool range_check_input, std::size_t limit_permutation_column, - // std::size_t row, std::size_t column, - // std::size_t num_cells, std::size_t buff) { - // if (column + 3 > limit_permutation_column) { - // row += 1; - // column = 0; - // } - - // std::pair first_coordinate = {row, column}; - // std::size_t last_row = row, - // last_column = column; - // std::vector> copy_to; - // for (int i = 0; i < 2; ++i) { - // copy_to.push_back({last_row + (last_column / witness_amount), - // (last_column++) % witness_amount}); - // } - // std::pair cell_copy_from = {last_row + (last_column / witness_amount), - // (last_column++) % witness_amount}; - // std::vector>> constraints = {{cell_copy_from, copy_to[0], copy_to[1]}}; - // std::vector>> lookups = {{cell_copy_from}}; - - // return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); - // } + static configuration configure_shift(std::size_t witness_amount, std::size_t row, std::size_t column) { + + std::pair first_coordinate = {row, column}; + std::size_t last_row = row, + last_column = column; + std::pair cell_copy_from = first_coordinate; + std::vector>> constraints = {{cell_copy_from}}; + for (std::size_t i = 0; i < 8; ++i) { + constraints[0].push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + } + return configuration(first_coordinate, {row + 1, 0}, {}, constraints, {}, cell_copy_from); + } static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - std::size_t row = 0, - column = 0; std::vector result; + // result.push_back(configure_shift(witness_amount, 0, 0)); + std::size_t row = 1, + column = 0; + if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { for (std::size_t i = 0; i < num_blocks; ++i) { configuration conf; @@ -480,9 +472,9 @@ namespace nil { // auto cur_config = result[i]; // std::cout << "config: " << i << "\n"; // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // std::cout << "cf: " << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // std::cout << "ct: " << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; // } // for (int j = 0; j < cur_config.constraints.size(); ++j) { // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { @@ -620,7 +612,7 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column = 7) { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - return map.size() * 2 + range_check_input; + return map.size() * 2 + range_check_input + 2; } static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, @@ -629,7 +621,9 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column) { auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - return confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); + auto res = confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); + if (res < 3) res = 3; + return res; } std::map component_lookup_tables(){ @@ -692,10 +686,26 @@ namespace nil { std::size_t gate_index = 0; std::size_t lookup_gate_index = 0; int32_t row_shift = (component.shift == 0 || component.witness_amount() == 15) ? 0 : 1; - bool checked_first_bit = false; std::vector cur_constraints; std::vector cur_lookup_constraints; + // range_check shift num_blocks * 64 - num_bits; + cur_constraints.push_back(var(component.W(0), -1) + + var(component.C(0), 1, true, var::column_type::constant) + - 64 * var(component.C(0), 0, true, var::column_type::constant)); + cur_constraints.push_back(var(component.W(0), -1)); + for (std::size_t i = 1; i < 9; ++i) { + cur_constraints[1] -= var(component.W(i), -1) * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(i), -1)}}); + } + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_constraints.clear(); + cur_lookup_constraints.clear(); + if (component.shift == 0) { if (component.range_check_input) { auto conf = gates_configuration[0][0]; @@ -712,7 +722,7 @@ namespace nil { auto conf = confs[0]; constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift)}}); @@ -746,20 +756,20 @@ namespace nil { auto conf = confs[0]; // chunk, first, second cur_constraints.push_back(constraint_type( - var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift) - - var(conf.constraints[0][1].column, static_cast(conf.constraints[0][1].row) - row_shift) * + var(component.W(conf.constraints[0][0].column), static_cast(conf.constraints[0][0].row) - row_shift) - + var(component.W(conf.constraints[0][1].column), static_cast(conf.constraints[0][1].row) - row_shift) * (integral_type(1) << (64 - component.shift)) - - var(conf.constraints[0][2].column, static_cast(conf.constraints[0][2].row) - row_shift))); + var(component.W(conf.constraints[0][2].column), static_cast(conf.constraints[0][2].row) - row_shift))); // sum, relay, first cur_constraints.push_back( - var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row) - row_shift) - - var(conf.constraints[1][1].column, static_cast(conf.constraints[1][1].row) - row_shift) * + var(component.W(conf.constraints[1][0].column), static_cast(conf.constraints[1][0].row) - row_shift) - + var(component.W(conf.constraints[1][1].column), static_cast(conf.constraints[1][1].row) - row_shift) * (integral_type(1) << component.shift) - - var(conf.constraints[1][2].column, static_cast(conf.constraints[1][2].row) - row_shift)); + var(component.W(conf.constraints[1][2].column), static_cast(conf.constraints[1][2].row) - row_shift)); // sum, range_check constraint_type constraint = var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row) - row_shift); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(conf.constraints[2][i].column, static_cast(conf.constraints[2][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); @@ -767,9 +777,9 @@ namespace nil { cur_constraints.push_back(constraint); if (component.range_check_input) { // chunk, range_check - constraint = var(conf.constraints[3][0].column, static_cast(conf.constraints[3][0].row) - row_shift); + constraint = var(component.W(conf.constraints[3][0].column), static_cast(conf.constraints[3][0].row) - row_shift); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(conf.constraints[3][i].column, static_cast(conf.constraints[3][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift)}}); @@ -807,7 +817,7 @@ namespace nil { std::size_t conf_index_for_input = 0; if (component.shift != 0) { - bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow + 1, false)}); conf_index_for_input = 1; } @@ -851,8 +861,10 @@ namespace nil { using var = typename component_type::var; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); + assignment.enable_selector(selector_indexes[0], start_row_index + 1); + assignment.enable_selector(selector_indexes[1], start_row_index + 1); auto gc_map = component.gates_configuration_map; - std::size_t sel_ind = 0; + std::size_t sel_ind = 2; auto gc_iter = gc_map.begin(); if (gc_iter != gc_map.end()) { @@ -902,7 +914,20 @@ namespace nil { std::size_t config_index = 0; std::size_t witness_amount = component.witness_amount(); - + // range_check shift + integral_type mask_range_check = (integral_type(1) << 8) - 1; + integral_type shift = component.shift; + std::vector shift_range_check; + for (std::size_t i = 0; i < 7; ++i) { + shift_range_check.push_back(shift & mask_range_check); + shift >>= 8; + } + shift_range_check.push_back(shift); + assignment.witness(component.W(0), strow) = component.shift; + for (int j = 1; j < 9; ++j) { + assignment.witness(component.W(j), strow) = value_type(shift_range_check[j - 1]); + } + if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { @@ -916,7 +941,6 @@ namespace nil { integral_chunk & mask}; integral_type sum = (relay_chunk << component.shift) + chunk_parts[0]; - integral_type mask_range_check = (integral_type(1) << 8) - 1; std::vector sum_range_check; integral_type sum_to_check = sum; for (std::size_t i = 0; i < 7; ++i) { @@ -994,6 +1018,8 @@ namespace nil { using component_type = padding_component; assignment.constant(component.C(0), start_row_index) = 0; + assignment.constant(component.C(0), start_row_index + 1) = component.num_blocks; + assignment.constant(component.C(0), start_row_index + 2) = component.num_bits; } } // namespace components diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 8e29afb74..cfbfbc03b 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -63,8 +63,9 @@ std::size_t number_bits(typename BlueprintFieldType::value_type value) { return result; } -template +template auto test_keccak_inner(std::vector message, std::vector expected_result) { constexpr std::size_t PublicInputColumns = 1; @@ -114,10 +115,11 @@ auto test_keccak_inner(std::vector mess witnesses[i] = i; } component_type component_instance = component_type(witnesses, std::array{0}, std::array{0}, - LookupRows, LookupColumns, num_blocks, num_bits, 7); + num_blocks, num_bits, range_check_input, limit_permutation_column); nil::crypto3::test_component( - component_instance, public_input, result_check, instance_input); + component_instance, public_input, result_check, instance_input, + nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); } // works @@ -127,14 +129,46 @@ void test_keccak_0() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::vector message = {0}; + std::vector message = {1}; const std::size_t num_blocks = 1; const std::size_t num_bits = 1; + const bool range_check_input = true; + const std::size_t limit_permutation_column = 7; + + std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + test_keccak_inner(message, expected_result); +} + +template +void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = true, bool range_check_input = true, + std::size_t limit_permutation_column = 7) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; + + integral_type mask = (integral_type(1) << 64) - 1; + std::size_t power_for_mask = 64; + if (random_mask_zero) { + power_for_mask = dis(gen) % 63 + 1; + } + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; + value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + std::vector message; + message.push_back(message_zero); + for (std::size_t i = 1; i < message_size; i++) { + message.push_back(value_type(integral_type(dis(gen)) & mask)); + } + assert(message_size == message.size()); + std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); + std::size_t num_blocks = message_size; - std::vector expected_result = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - test_keccak_inner(message, expected_result); + test_keccak_inner(message, expected_result); } // template(); - test_keccak_0(); + test_keccak_0(); // test_keccak_round_random(); } From e5deea7e0fae72a5e98add2f6a0ae55d632b0102 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Mon, 11 Dec 2023 15:16:44 +0000 Subject: [PATCH 28/48] keccak gates #183 --- .../hashes/keccak/keccak_component.hpp | 444 +++++++++++++----- test/hashes/plonk/keccak_padding.cpp | 2 +- 2 files changed, 330 insertions(+), 116 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 37f36c444..ed4e005f3 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include // #include @@ -76,25 +77,31 @@ namespace nil { std::size_t witness_amount; std::size_t num_blocks; std::size_t num_bits; + bool range_check_input; + std::size_t limit_permutation_column; - gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_) - : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_) {} + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, + bool range_check_input_, std::size_t limit_permutation_column_) + : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_), + range_check_input(range_check_input_), limit_permutation_column(limit_permutation_column_) {} std::uint32_t gates_amount() const override { - return get_gates_amount(witness_amount); + return get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); } }; static gate_manifest get_gate_manifest(std::size_t witness_amount, std::size_t lookup_column_amount, std::size_t num_blocks, - std::size_t num_bits) { + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { std::size_t num_round_calls = calculate_num_round_calls(num_blocks); gate_manifest manifest = - gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits)) + gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)) .merge_with( padding_component_type::get_gate_manifest(witness_amount, lookup_column_amount, - num_blocks, num_bits)); + num_blocks, num_bits, range_check_input)); // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, // true, true)); // for (std::size_t i = 1; i < num_round_calls; ++i) { @@ -122,11 +129,12 @@ namespace nil { using configuration = typename padding_component_type::configuration; - const std::size_t lookup_rows; - const std::size_t lookup_columns; + const std::size_t lookup_rows = 65536; + const std::size_t witnesses = this->witness_amount(); const std::size_t num_blocks; const std::size_t num_bits; + const bool range_check_input; const std::size_t limit_permutation_column = 7; const std::size_t round_tt_rows = 0; @@ -144,10 +152,15 @@ namespace nil { const std::size_t pack_cells = 2 * (pack_num_chunks + 1); const std::size_t pack_buff = (this->witness_amount() == 15) * 2; - std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls); + std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls, limit_permutation_column); + const std::map> gates_configuration_map = + configure_map(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::vector> gates_configuration = + configure_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); - const std::size_t rows_amount = get_rows_amount(num_round_calls); - const std::size_t gates_amount = get_gates_amount(this->witness_amount()); + const std::size_t rows_amount = + get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); const std::size_t round_constant[24] = {1, 0x8082, 0x800000000000808a, 0x8000000080008000, 0x808b, 0x80000001, 0x8000000080008081, 0x8000000000008009, @@ -177,7 +190,9 @@ namespace nil { return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], final_inner_state[4]}; } }; - + static std::size_t get_rows_amount_round_tt() { + return 0; + } // std::vector create_rounds() { // std::vector rounds; // rounds.push_back(round_true_true); @@ -216,7 +231,9 @@ namespace nil { return res; } - configuration configure_pack_unpack(std::size_t witness_amount, std::size_t row, std::size_t column) { + static configuration configure_pack_unpack(std::size_t witness_amount, std::size_t row, std::size_t column, + std::size_t pack_cells, std::size_t pack_num_chunks, std::size_t pack_buff, + std::size_t limit_permutation_column) { // regular constraints: // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) @@ -283,91 +300,241 @@ namespace nil { } } - last_column = cells.back().second + 1; + last_column = cells.back().second + 1 + pack_buff; last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } - std::vector configure_all(std::size_t witness_amount, const std::size_t num_configs, - const std::size_t num_round_calls) { + static std::vector configure_all(std::size_t witness_amount, const std::size_t num_configs, + const std::size_t num_round_calls, std::size_t limit_permutation_column) { std::vector result; + std::size_t pack_num_chunks = 8; + std::size_t pack_cells = 2 * (pack_num_chunks + 1); + std::size_t pack_buff = (witness_amount == 15) * 2; std::size_t row = 0, column = 0; - // padding - // row += padding_component.rows_amount; + + for (std::size_t index = 0; index < num_round_calls * 17; ++index) { + // to sparse representation + result.push_back(configure_pack_unpack(witness_amount, row, column, + pack_cells, pack_num_chunks, pack_buff, + limit_permutation_column)); + row = result[index].last_coordinate.row; + column = result[index].last_coordinate.column; + } + if (column > 0) { + column = 0; + row++; + } //rounds for (std::size_t index = 0; index < num_round_calls; ++index) { - // to sparse representation - for (std::size_t i = 0; i < 17; ++i) { - result.push_back(configure_pack_unpack(witness_amount, row, column)); - row = result[i].last_coordinate.row; - column = result[i].last_coordinate.column; - } - // round - if (column > 0) { - column = 0; - row++; - } // for (std::size_t i = 0; i < 24; ++i) { // row += rounds[index * 24 + i].rows_amount; // } } + row = 0; // from sparse representation for (std::size_t i = 0; i < 5; ++i) { - result.push_back(configure_pack_unpack(witness_amount, row, column)); - row = result[i].last_coordinate.row; - column = result[i].last_coordinate.column; + result.push_back(configure_pack_unpack(witness_amount, row, column, + pack_cells, pack_num_chunks, pack_buff, + limit_permutation_column)); + row = result.back().last_coordinate.row; + column = result.back().last_coordinate.column; + } + + // std::cout << "num_cofigs: " << result.size() << "\n"; + // for (std::size_t i = 0; i < result.size(); ++i) { + // auto cur_config = result[i]; + // std::cout << "config: " << i << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + + return result; + } + + static std::map> configure_map(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + + auto config = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); + std::size_t row = 0, + column = 0; + std::size_t row_shift = padding_component_type::get_rows_amount(witness_amount, 0, + num_blocks, num_bits, range_check_input, + limit_permutation_column); + + std::map> config_map; + + for (std::size_t i = 0; i < config.size() - 5; ++i) { + row = config[i].first_coordinate.row; + column = config[i].first_coordinate.column; + if (config_map.find(column) != config_map.end()) { + config_map[column].push_back(row + row_shift); + } else { + config_map[column] = {row + row_shift}; + } + } + row_shift += config[config.size() - 6].last_coordinate.row; + for (std::size_t i = config.size() - 5; i < config.size(); ++i) { + row = config[i].first_coordinate.row; + column = config[i].first_coordinate.column + 10 * witness_amount; + if (config_map.find(column) != config_map.end()) { + config_map[column].push_back(row + row_shift); + } else { + config_map[column] = {row + row_shift}; + } + } + + std::cout << "MAP\n"; + for (auto c : config_map) { + std::cout << c.first << ": "; + for (auto r : c.second) { + std::cout << r << " "; + } + std::cout << std::endl; + } + + return config_map; + } + + static std::vector> configure_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + std::vector> result; + auto gates_configuration_map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + std::size_t pack_num_chunks = 8; + std::size_t num_cells = 2 * (pack_num_chunks + 1); + std::size_t buff = (witness_amount == 15) * 2; + + for (auto config: gates_configuration_map) { + if (config.first >= 10 * witness_amount) continue; + configuration cur_config = configure_pack_unpack(witness_amount, 0, config.first, + num_cells, pack_num_chunks, buff, limit_permutation_column); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max - min <= 2); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + cur_row = pairs[cur_constr].first; + cur_result.push_back(c); + } + result.push_back(cur_result); } + + // for (std::size_t i = 0; i < result.size(); ++i) { + // std::cout << "config " << i << ":\n"; + // for (auto cur_config : result[i]) { + // std::cout << "gate:\n"; + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + // } return result; } - std::size_t get_rows_amount(std::size_t num_round_calls) { - std::size_t res = padding_component_type::get_rows_amount() - + round_tt_rows - + round_tf_rows * (num_round_calls - 1) - + round_ff_rows * num_round_calls * 23; - res += full_configuration.back().last_coordinate.row; + static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, + std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + std::size_t limit_permutation_column) { + std::size_t num_round_calls = calculate_num_round_calls(num_blocks); + std::size_t res = padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, + num_blocks, num_bits, range_check_input, + limit_permutation_column); + // + round_tt_rows + // + round_tf_rows * (num_round_calls - 1) + // + round_ff_rows * num_round_calls * 23; + auto config = configure_all(witness_amount, num_blocks, num_round_calls, limit_permutation_column); + auto index = config.size() - 1; + res += config[index].last_coordinate.row + (config[index].last_coordinate.column > 0); + res += config[index - 5].last_coordinate.row + (config[index - 5].last_coordinate.column > 0); return res; } - static std::size_t get_gates_amount(std::size_t witness_amount) { + static std::size_t get_gates_amount(std::size_t witness_amount, + std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + std::size_t limit_permutation_column) { std::size_t res = 0; - if (witness_amount == 9) res = 1; - if (witness_amount == 15) res = 3; - res += padding_component_type::gates_amount; + auto config = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + for (auto c : config) { + if (c.first >= 10 * witness_amount) res++; + else res += 2; + } + // if (witness_amount == 9) res = 1; + // if (witness_amount == 15) res = 3; + res += padding_component_type::get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); return res; } + std::map component_lookup_tables(){ + std::map lookup_tables; + lookup_tables["keccak_pack_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_sign_bit_table/full"] = 0; // REQUIRED_TABLE + return lookup_tables; + } + template keccak(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, - std::size_t lookup_rows_, - std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, + bool range_check_input_, std::size_t lpc_ = 7) : component_type(witness, constant, public_input, get_manifest()), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), num_blocks(num_blocks_), num_bits(num_bits_), + range_check_input(range_check_input_), limit_permutation_column(lpc_), - padding(witness, constant, public_input, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_), + padding(witness, constant, public_input, num_blocks_, num_bits_, range_check_input_, lpc_), num_round_calls(calculate_num_round_calls(num_blocks_)) {}; // { - // round_true_true = round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_), + // round_true_true = round_component_type(witness, constant, public_input, true, true, lpc_), // for (std::size_t i = 1; i < num_round_calls; ++i) { - // rounds_true_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)); + // rounds_true_false.push_back(round_component_type(witness, constant, public_input, true, false, lpc_)); // } // for (std::size_t i = 0; i < num_round_calls; ++i) { // for (std::size_t j = 0; j < 23; ++j) { - // rounds_false_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)); + // rounds_false_false.push_back(round_component_type(witness, constant, public_input, false, false, lpc_)); // } // } // round_tt_rows = round_true_true.rows_amount; @@ -382,63 +549,26 @@ namespace nil { std::initializer_list witnesses, std::initializer_list constants, std::initializer_list public_inputs, - std::size_t lookup_rows_, std::size_t lookup_columns_, std::size_t num_blocks_, std::size_t num_bits_, std::size_t lpc_ = 7) : + std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_, std::size_t lpc_ = 7) : component_type(witnesses, constants, public_inputs), - lookup_rows(lookup_rows_), - lookup_columns(lookup_columns_), num_blocks(num_blocks_), num_bits(num_bits_), + range_check_input(range_check_input_), limit_permutation_column(lpc_), - padding(witnesses, constants, public_inputs, lookup_rows_, lookup_columns_, num_blocks_, num_bits_, lpc_), + padding(witnesses, constants, public_inputs, num_blocks_, num_bits_, range_check_input_, lpc_), num_round_calls(calculate_num_round_calls(num_blocks_)) {}; - // round_true_true(witness, constant, public_input, lookup_rows_, lookup_columns_, true, true, lpc_), + // round_true_true(witness, constant, public_input, true, true, lpc_), // { // for (std::size_t i = 1; i < num_round_calls; ++i) { - // rounds_true_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, true, false, lpc_)); + // rounds_true_false.push_back(round_component_type(witness, constant, public_input, true, false, lpc_)); // } // for (std::size_t i = 0; i < num_round_calls; ++i) { // for (std::size_t j = 0; j < 23; ++j) { - // rounds_false_false.push_back(round_component_type(witness, constant, public_input, lookup_rows_, lookup_columns_, false, false, lpc_)); + // rounds_false_false.push_back(round_component_type(witness, constant, public_input, false, false, lpc_)); // } // } // }; - - using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; - - class sparse_values_base8_table: public lookup_table_definition{ - public: - sparse_values_base8_table(): lookup_table_definition("keccak_sparse_base8"){ - this->subtables["full"] = {{0,1}, 0, 255}; - this->subtables["first_column"] = {{0}, 0, 255}; - this->subtables["second_column"] = {{1}, 0, 255}; - }; - virtual void generate(){ - this->_table.resize(2); - std::vector value_sizes = {8}; - - // lookup table for sparse values with base = 8 - std::cout << "keccak_sparse_base8" << std::endl; - for (typename BlueprintFieldType::integral_type i = 0; - i < typename BlueprintFieldType::integral_type(256); - i++ - ) { - std::vector value(8); - for (std::size_t j = 0; j < 8; j++) { - value[8 - j - 1] = crypto3::multiprecision::bit_test(i, j); - } - std::array, 2> value_chunks = - detail::split_and_sparse(value, value_sizes, 8); - std::cout << value_chunks[0][0] << " " << value_chunks[1][0] << std::endl; - this->_table[0].push_back(value_chunks[0][0]); - this->_table[1].push_back(value_chunks[1][0]); - } - std::cout << "=============================" << std::endl; - } - - virtual std::size_t get_columns_number(){return 2;} - virtual std::size_t get_rows_number(){return 256;} - }; }; template @@ -457,15 +587,49 @@ namespace nil { ArithmetizationParams>> &assignment, const typename keccak_component::input_type - &instance_input) { + &instance_input, + const typename lookup_library::left_reserved_type lookup_tables_indices) { using component_type = keccak_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; + using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; + using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + std::vector selector_indexes; + auto gates_configuration = component.gates_configuration; + std::size_t gate_index = 0; + std::size_t lookup_gate_index = 0; + + for (auto config : gates_configuration) { + std::vector lookup_constraints_0; + std::vector lookup_constraints_1; + auto conf = config[0]; + constraint_type constraint_0 = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); + constraint_type constraint_1 = var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row)); + for (std::size_t i = 1; i < 9; ++i) { + constraint_0 -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) + * (integral_type(1) << ((i-1) * 8)); + constraint_1 -= var(conf.constraints[1][i].column, static_cast(conf.constraints[1][i].row)) + * (integral_type(1) << ((i-1) * 8)); + lookup_constraints_0.push_back({lookup_tables_indices.at("keccak_pack_table/full"), + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row)), + var(component.W(conf.constraints[1][i].column), static_cast(conf.constraints[1][i].row))}}); + lookup_constraints_1.push_back({lookup_tables_indices.at("keccak_pack_table/full"), + {var(component.W(conf.constraints[1][i].column), static_cast(conf.constraints[1][i].row)), + var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); + } + selector_indexes.push_back(bp.add_gate({constraint_0, constraint_1})); + gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); + selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); + lookup_gate_index += 2; + } + return selector_indexes; } template @@ -504,10 +668,51 @@ namespace nil { &instance_input, const std::uint32_t start_row_index) { - auto selector_index = generate_gates(component, bp, assignment, instance_input); - std::size_t first_selector_index; + using component_type = keccak_component; + using padding_type = typename component_type::padding_component_type; + + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); std::size_t row = start_row_index; + std::vector witnesses; + for (std::size_t i = 0; i < component.witnesses; ++i) { + witnesses.push_back(i); + } + std::vector zero_column = {0}; + + padding_type padding_component_instance(witnesses, zero_column, zero_column, + component.num_blocks, component.num_bits, + component.range_check_input, + component.limit_permutation_column); + typename padding_type::input_type padding_input = {instance_input.message}; + typename padding_type::result_type padding_result = generate_circuit(padding_component_instance, bp, assignment, padding_input, row); + row += padding_component_instance.rows_amount; + + auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); + auto config_map = component.gates_configuration_map; + std::size_t sel_ind = 0; + for (auto config : config_map) { + if (config.first < component.witnesses) { + for (auto gate_row : config.second) { + std::cout << "enabling: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 1] << std::endl; + assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); + assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + row); + } + sel_ind += 3; + } + } + sel_ind = 0; + for (auto config : config_map) { + if (config.first >= 10 * component.witnesses) { + for (auto gate_row : config.second) { + std::cout << "enabling2: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 2] << std::endl; + assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); + assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); + } + sel_ind += 3; + } + } + using component_type = keccak_component; using var = typename component_type::var; @@ -528,7 +733,7 @@ namespace nil { &instance_input, const std::uint32_t start_row_index) { - std::size_t row = start_row_index; + std::size_t cur_row = start_row_index; using component_type = keccak_component; using value_type = typename BlueprintFieldType::value_type; @@ -536,15 +741,18 @@ namespace nil { using var = typename component_type::var; std::vector padded_message = generate_assignments(component.padding, assignment, - {instance_input.message}, row).padded_message; - row += component.padding.rows_amount; + {instance_input.message}, cur_row).padded_message; + cur_row += component.padding.rows_amount; + // std::cout << "padded_message: " << padded_message.size() << ' ' << component.padding.rows_amount << std::endl; + // std::cout << component.rows_amount << std::endl; // to sparse std::size_t config_index = 0; - std::vector sparse_padded_message; + std::vector sparse_padded_message(padded_message.size()); for (std::size_t index = 0; index < padded_message.size(); ++index) { value_type regular_value = var_value(assignment, padded_message[index]); integral_type regular = integral_type(regular_value.data); + // std::cout << "pad elem: " << regular << std::endl; integral_type sparse = component.pack(regular); auto chunk_size = component.pack_chunk_size; auto num_chunks = component.pack_num_chunks; @@ -558,16 +766,18 @@ namespace nil { } sparse_padded_message[index] = value_type(sparse); - auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + row) = regular_value; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + row) = value_type(sparse); + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = regular_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(sparse); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + row) = value_type(integral_sparse_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); } + config_index++; } - config_index += padded_message.size(); - row += component.full_configuration[config_index - 1].last_coordinate.row; + std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; + cur_row += component.full_configuration[config_index - 1].last_coordinate.row + + (component.full_configuration[config_index - 1].last_coordinate.column > 0); std::array inner_state; // for (std::size_t i = 0; i < component.num_round_calls; ++i) { @@ -599,17 +809,21 @@ namespace nil { } sparse_padded_message[index] = value_type(regular); - auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + start_row_index) = sparse_value; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + start_row_index) = value_type(regular); + auto cur_config = component.full_configuration[config_index]; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = sparse_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(regular); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + start_row_index) = value_type(integral_sparse_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + start_row_index) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + cur_row) = value_type(integral_chunks[j - 1]); } + config_index++; } - row += component.full_configuration[config_index + 5].last_coordinate.row - component.full_configuration[config_index - 1].last_coordinate.row; + std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; + cur_row += component.full_configuration[config_index - 1].last_coordinate.row + + (component.full_configuration[config_index - 1].last_coordinate.column > 0); - BOOST_ASSERT(row == start_row_index + component.rows_amount); + std::cout << cur_row << ' ' << start_row_index << ' ' << component.rows_amount << std::endl; + BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); return typename component_type::result_type(component, start_row_index); } @@ -631,7 +845,7 @@ namespace nil { using component_type = keccak_component; using integral_type = typename BlueprintFieldType::integral_type; - std::size_t row = start_row_index; + std::size_t row = start_row_index + 3; for (std::size_t i = 0; i < 24; ++i) { assignment.constant(component.C(0), row + i) = component.round_constant[i]; } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index cd5d3a57e..5a2a1cf50 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -100,7 +100,7 @@ auto test_keccak_padding_inner(std::vector; From 2ff5655726f95005a98fb603c56ec34fbaa27042 Mon Sep 17 00:00:00 2001 From: Valeh2012 Date: Fri, 8 Dec 2023 15:11:21 +0200 Subject: [PATCH 29/48] keccak round lookup table fix --- .../components/hashes/keccak/keccak_round.hpp | 91 ++++++----- test/hashes/plonk/keccak_round.cpp | 4 +- test/test_plonk_component.hpp | 153 ++---------------- 3 files changed, 62 insertions(+), 186 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 2aeb4e358..5a41ad436 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -57,7 +57,7 @@ namespace nil { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - using lookup_table_definition = typename nil::crypto3::zk::snark::detail::lookup_table_definition; + using lookup_table_definition = typename nil::crypto3::zk::snark::lookup_table_definition; // xor2 - base=3, xor3 - base=4, xor5 - base=6, chi - base=2, rotate - base=0 int bases[5] = {3, 4, 6, 2, 0}; @@ -131,10 +131,12 @@ namespace nil { virtual std::array to_base(std::size_t base, typename BlueprintFieldType::integral_type num) { typename BlueprintFieldType::integral_type result = 0; typename BlueprintFieldType::integral_type normalized_result = 0; + typename BlueprintFieldType::integral_type power = 1; while (num > 0) { - result = result * 8 + (num % base); - normalized_result = normalized_result * 8 + (num % base) & 1; + result = result + (num % base)*power; + normalized_result = normalized_result + ((num % base) & 1)*power; num /= base; + power <<= 3; } return {result, normalized_result}; } @@ -161,13 +163,16 @@ namespace nil { class chi_table_type : public lookup_table_definition{ virtual std::array to_base_chi(typename BlueprintFieldType::integral_type num) { std::size_t base = 5; - int table[5] = {0, 1, 1, 0, 0}; + typename BlueprintFieldType::integral_type table[5] = {0, 1, 1, 0, 0}; typename BlueprintFieldType::integral_type result = 0; typename BlueprintFieldType::integral_type chi_result = 0; + typename BlueprintFieldType::integral_type power = 1; + typename BlueprintFieldType::integral_type mask = 7; while (num > 0) { - result = result * 8 + (num % base); - chi_result = chi_result * 8 + table[int((num % base))]; + result = result + (num % base) * power; + chi_result = chi_result + table[int(num % base)] * power; num /= base; + power <<= 3; } return {result, chi_result}; } @@ -267,6 +272,7 @@ namespace nil { std::vector> constraints; std::vector> lookups; coordinates copy_from; + std::string name; configuration() = default; configuration(std::pair first_coordinate_, @@ -274,7 +280,7 @@ namespace nil { std::vector> copy_to_, std::vector>> constraints_, std::vector>> lookups_, - std::pair copy_from_) { + std::pair copy_from_){ first_coordinate = coordinates(first_coordinate_); last_coordinate = coordinates(last_coordinate_); for (std::size_t i = 0; i < copy_to_.size(); ++i) { @@ -325,25 +331,25 @@ namespace nil { const std::size_t normalize3_chunk_size = calculate_chunk_size(lookup_rows, 3); const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); const std::size_t normalize6_chunk_size = calculate_chunk_size(lookup_rows, 6); - const std::size_t chi_chunk_size = calculate_chunk_size(lookup_rows, 2); + const std::size_t chi_chunk_size = calculate_chunk_size(lookup_rows, 5); const std::size_t rotate_chunk_size = 24; const std::size_t normalize3_num_chunks = calculate_num_chunks(lookup_rows, 3); const std::size_t normalize4_num_chunks = calculate_num_chunks(lookup_rows, 4); const std::size_t normalize6_num_chunks = calculate_num_chunks(lookup_rows, 6); - const std::size_t chi_num_chunks = calculate_num_chunks(lookup_rows, 2); + const std::size_t chi_num_chunks = calculate_num_chunks(lookup_rows, 5); const std::size_t rotate_num_chunks = 8; const std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); const std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); const std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); - const std::size_t chi_cells = calculate_num_cells(lookup_rows, 2); + const std::size_t chi_cells = calculate_num_cells(lookup_rows, 5); const std::size_t rotate_cells = 24; const std::size_t xor2_buff = calculate_buff(this->witness_amount(), lookup_rows, 3); const std::size_t xor3_buff = calculate_buff(this->witness_amount(), lookup_rows, 4); const std::size_t xor5_buff = calculate_buff(this->witness_amount(), lookup_rows, 6); - const std::size_t chi_buff = calculate_buff(this->witness_amount(), lookup_rows, 2); + const std::size_t chi_buff = calculate_buff(this->witness_amount(), lookup_rows, 5); const std::size_t rotate_buff = calculate_buff(this->witness_amount(), lookup_rows); const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, xor_with_mes, last_round_call, limit_permutation_column); @@ -533,9 +539,9 @@ namespace nil { // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * 2^(k*chunk_size) std::size_t num_args = 3; - std::size_t num_chunks = calculate_num_chunks(lookup_rows, 2); - std::size_t num_cells = calculate_num_cells(lookup_rows, 2); - std::size_t buff = calculate_buff(witness_amount, lookup_rows, 2); + std::size_t num_chunks = calculate_num_chunks(lookup_rows, 5); + std::size_t num_cells = calculate_num_cells(lookup_rows, 5); + std::size_t buff = calculate_buff(witness_amount, lookup_rows, 5); return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); } @@ -695,27 +701,27 @@ namespace nil { // iota result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); - for (int i = 0; i < result.size(); ++i) { - // std::cout << "\n config: " << i << std::endl; - // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; - // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; - // for (int j = 0; j < result[i].copy_to.size(); ++j) { - // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; - // } - // for (int j = 0; j < result[i].constraints.size(); ++j) { - // for (int k = 0; k < result[i].constraints[j].size(); ++k) { - // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - // std::cout << "lookups: " << result[i].lookups.size() << std::endl; - // for (int j = 0; j < result[i].lookups.size(); ++j) { - // for (int k = 0; k < result[i].lookups[j].size(); ++k) { - // std::cout << result[i].lookups[j][k].row << " " << result[i].lookups[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - } + // for (int i = 0; i < result.size(); ++i) { + // std::cout << "\n config: " << result[i].name << std::endl; + // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; + // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; + // for (int j = 0; j < result[i].copy_to.size(); ++j) { + // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; + // } + // for (int j = 0; j < result[i].constraints.size(); ++j) { + // for (int k = 0; k < result[i].constraints[j].size(); ++k) { + // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // std::cout << "lookups: " << result[i].lookups.size() << std::endl; + // for (int j = 0; j < result[i].lookups.size(); ++j) { + // for (int k = 0; k < result[i].lookups[j].size(); ++k) { + // std::cout << result[i].lookups[j][k].row << " " << result[i].lookups[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } return result; } @@ -945,15 +951,20 @@ namespace nil { std::vector cur_result; std::size_t cur_row = 0; std::size_t cur_constr = 0; + bool found; while (cur_constr < pairs.size()) { configuration c; + found = false; while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { c.lookups.push_back(cur_config.lookups[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; + found = true; } cur_row = pairs[cur_constr].first; - cur_result.push_back(c); + if(found){ + cur_result.push_back(c); + } } result.push_back(cur_result); } @@ -997,12 +1008,12 @@ namespace nil { std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); - std::size_t chi_cells = calculate_num_cells(lookup_rows, 2); + std::size_t chi_cells = calculate_num_cells(lookup_rows, 5); std::size_t rotate_cells = calculate_num_cells(lookup_rows); std::size_t xor2_buff = calculate_buff(witness_amount, lookup_rows, 3); std::size_t xor3_buff = calculate_buff(witness_amount, lookup_rows, 4); std::size_t xor5_buff = calculate_buff(witness_amount, lookup_rows, 6); - std::size_t chi_buff = calculate_buff(witness_amount, lookup_rows, 2); + std::size_t chi_buff = calculate_buff(witness_amount, lookup_rows, 5); std::size_t rotate_buff = calculate_buff(witness_amount, lookup_rows); std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call @@ -1088,7 +1099,7 @@ namespace nil { &assignment, const typename keccak_round_component::input_type &instance_input, - const std::map lookup_tables_indices) { + const typename lookup_library::left_reserved_type lookup_tables_indices) { using component_type = keccak_round_component; using var = typename component_type::var; @@ -1689,7 +1700,7 @@ namespace nil { } for (std::size_t i = 0; i < component.lookup_gates_configuration[ind].size(); ++i) { for (auto j : g.second) { - // std::cout << j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; + //std::cout << start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; assignment.enable_selector(selector_indexes[index], start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1); } diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 46be6658e..38682f0c3 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -160,7 +160,7 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; - constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t ConstantColumns = 3; constexpr std::size_t SelectorColumns = 25; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_not_random(); // xor_with_mes, last_round_call - test_keccak_round_random(); + test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index 585d44b95..7ca051773 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -190,6 +190,13 @@ namespace nil { blueprint::circuit> bp; blueprint::assignment> assignment(desc); + if constexpr( nil::blueprint::component_use_custom_lookup_tables() ){ + auto lookup_tables = component_instance.component_custom_lookup_tables(); + for(std::size_t i=0; i< lookup_tables.size(); i++){ + bp.register_lookup_table(lookup_tables[i]); + } + }; + if constexpr( nil::blueprint::use_lookups() ){ auto lookup_tables = component_instance.component_lookup_tables(); for(auto &[k,v]:lookup_tables){ @@ -199,149 +206,7 @@ namespace nil { static boost::random::mt19937 gen; static boost::random::uniform_int_distribution<> dist(0, 100); - std::size_t start_row = 0; // dist(gen); - // resize to ensure that if the component is empty by default (e.g. a component which only uses batching) - if (start_row != 0) { - assignment.witness(0, start_row - 1) = 0; - } - - if constexpr (PrivateInput) { - for (std::size_t i = 0; i < public_input.size(); i++) { - assignment.private_storage(i) = public_input[i]; - } - } else { - for (std::size_t i = 0; i < public_input.size(); i++) { - assignment.public_input(0, i) = public_input[i]; - } - } - - blueprint::components::generate_circuit( - component_instance, bp, assignment, instance_input, start_row); - auto component_result = boost::get( - assigner(component_instance, assignment, instance_input, start_row)); - - // Stretched components do not have a manifest, as they are dynamically generated. - if constexpr (!blueprint::components::is_component_stretcher< - BlueprintFieldType, ComponentType>::value) { - BOOST_ASSERT_MSG(bp.num_gates() + bp.num_lookup_gates() == - component_type::get_gate_manifest(component_instance.witness_amount(), - component_static_info_args...).get_gates_amount(), - "Component total gates amount does not match actual gates amount."); - } - - if (start_row + component_instance.rows_amount >= public_input.size()) { - BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == component_instance.rows_amount, - "Component rows amount does not match actual rows amount."); - // Stretched components do not have a manifest, as they are dynamically generated. - if constexpr (!blueprint::components::is_component_stretcher< - BlueprintFieldType, ComponentType>::value) { - BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == - component_type::get_rows_amount(component_instance.witness_amount(), - component_static_info_args...), - "Static component rows amount does not match actual rows amount."); - } - } - - const std::size_t rows_after_component_batching = - assignment.finalize_component_batches(bp, start_row + component_instance.rows_amount); - const std::size_t rows_after_const_batching = - assignment.finalize_constant_batches(bp, 0, std::max(start_row, 1)); - const std::size_t rows_after_batching = std::max(rows_after_component_batching, rows_after_const_batching); - for (auto variable : component_result.all_vars()) { - if (assignment.get_batch_variable_map().count(variable)) { - variable.get() = assignment.get_batch_variable_map().at(variable); - } - } - - result_check(assignment, component_result); - - if constexpr (!PrivateInput) { - bool is_connected = check_connectedness( - assignment, - bp, - instance_input.all_vars(), - component_result.all_vars(), start_row, rows_after_batching - start_row, - connectedness_check); - if (connectedness_check.t == blueprint::connectedness_check_type::type::NONE) { - std::cout << "WARNING: Connectedness check is disabled." << std::endl; - } - - // Uncomment the following if you want to output a visual representation of the connectedness graph. - // I recommend turning off the starting row randomization - // If the whole of public_input isn't shown, increase the end row - - // auto zones = blueprint::detail::generate_connectedness_zones( - // assignment, bp, instance_input.all_vars(), start_row, rows_after_batching - start_row); - // blueprint::detail::export_connectedness_zones( - // zones, assignment, instance_input.all_vars(), start_row, rows_after_batching - start_row, std::cout); - - // BOOST_ASSERT_MSG(is_connected, - // "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); - } - desc.usable_rows_amount = assignment.rows_amount(); - - if constexpr (nil::blueprint::use_lookups()) { - // Components with lookups may use constant columns. - // But now all constants are placed in the first column. - // So we reserve the first column for non-lookup constants. - // Rather universal for testing - // We may start from zero if component doesn't use ordinary constants. - std::vector lookup_columns_indices; - for(std::size_t i = 1; i < assignment.constants_amount(); i++) { - lookup_columns_indices.push_back(i); - } - - std::size_t cur_selector_id = 0; - for(const auto &gate: bp.gates()){ - cur_selector_id = std::max(cur_selector_id, gate.selector_index); - } - for(const auto &lookup_gate: bp.lookup_gates()){ - cur_selector_id = std::max(cur_selector_id, lookup_gate.tag_index); - } - cur_selector_id++; - desc.usable_rows_amount = zk::snark::pack_lookup_tables_horizontal( - bp.get_reserved_indices(), - bp.get_reserved_tables(), - bp, assignment, lookup_columns_indices, cur_selector_id, - desc.usable_rows_amount, - 500000 - ); - } - desc.rows_amount = zk::snark::basic_padding(assignment); - -#ifdef BLUEPRINT_PLONK_PROFILING_ENABLED - std::cout << "Usable rows: " << desc.usable_rows_amount << std::endl; - std::cout << "Padded rows: " << desc.rows_amount << std::endl; - - profiling(assignment); -#endif - //assignment.export_table(std::cout); - //bp.export_circuit(std::cout); - - assert(blueprint::is_satisfied(bp, assignment) == expected_to_pass); - - return std::make_tuple(desc, bp, assignment); - } - - template< - typename ComponentType, typename BlueprintFieldType, typename Hash, - std::size_t Lambda, typename PublicInputContainerType, typename FunctorResultCheck, bool PrivateInput, - typename... ComponentStaticInfoArgs> - auto prepare_empty_component(ComponentType component_instance, - const zk::snark::plonk_table_description &desc, - const PublicInputContainerType &public_input, - const FunctorResultCheck &result_check, - typename ComponentType::input_type instance_input, - blueprint::connectedness_check_type connectedness_check, - ComponentStaticInfoArgs... component_static_info_args) { - using component_type = ComponentType; - - blueprint::circuit> bp; - blueprint::assignment> assignment(desc); - - static boost::random::mt19937 gen; - static boost::random::uniform_int_distribution<> dist(0, 100); - std::size_t start_row = 0;//dist(gen); + std::size_t start_row = dist(gen); if constexpr (PrivateInput) { for (std::size_t i = 0; i < public_input.size(); i++) { @@ -436,7 +301,7 @@ namespace nil { std::cout << "Usable rows: " << desc.usable_rows_amount << std::endl; std::cout << "Padded rows: " << desc.rows_amount << std::endl; - profiling(assignment); + // profiling(assignment); #endif assert(blueprint::is_satisfied(bp, assignment) == expected_to_pass); From ea5de69572b529afb0ed272593e8a420d2677cf1 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Thu, 14 Dec 2023 16:09:55 +0000 Subject: [PATCH 30/48] fixed keccak_round lookups # 183 --- .../components/hashes/keccak/keccak_round.hpp | 181 ++++++++---------- include/nil/blueprint/lookup_library.hpp | 77 ++++++++ test/hashes/plonk/keccak_round.cpp | 80 +++----- test/test_plonk_component.hpp | 22 +-- 4 files changed, 193 insertions(+), 167 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 5a41ad436..8c66b84f7 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -90,6 +90,9 @@ namespace nil { static std::size_t calculate_buff(std::size_t witness_amount, std::size_t num_rows, std::size_t base = 0) { std::size_t buff = 0; std::size_t cells = calculate_num_cells(num_rows, base); + if (base == 0) { + return 3 * witness_amount - cells; + } if (base == 6) { return witness_amount * ((cells - 1) / witness_amount + 1) - cells; } @@ -125,83 +128,7 @@ namespace nil { } return res; } - - class normalize_table_type : public lookup_table_definition{ - std::size_t base; - virtual std::array to_base(std::size_t base, typename BlueprintFieldType::integral_type num) { - typename BlueprintFieldType::integral_type result = 0; - typename BlueprintFieldType::integral_type normalized_result = 0; - typename BlueprintFieldType::integral_type power = 1; - while (num > 0) { - result = result + (num % base)*power; - normalized_result = normalized_result + ((num % base) & 1)*power; - num /= base; - power <<= 3; - } - return {result, normalized_result}; - } - public: - normalize_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { - this->subtables["full"] = {{0,1}, 0, 65536}; - } - virtual void generate(){ - this->_table.resize(2); - std::vector value_sizes = {8}; - - for (typename BlueprintFieldType::integral_type i = 0; - i < typename BlueprintFieldType::integral_type(65536); - i++ - ) { - std::array value = to_base(base, i); - this->_table[0].push_back(value[0]); - this->_table[1].push_back(value[1]); - } - } - virtual std::size_t get_columns_number(){ return 2; } - virtual std::size_t get_rows_number(){ return 65536; } - }; - class chi_table_type : public lookup_table_definition{ - virtual std::array to_base_chi(typename BlueprintFieldType::integral_type num) { - std::size_t base = 5; - typename BlueprintFieldType::integral_type table[5] = {0, 1, 1, 0, 0}; - typename BlueprintFieldType::integral_type result = 0; - typename BlueprintFieldType::integral_type chi_result = 0; - typename BlueprintFieldType::integral_type power = 1; - typename BlueprintFieldType::integral_type mask = 7; - while (num > 0) { - result = result + (num % base) * power; - chi_result = chi_result + table[int(num % base)] * power; - num /= base; - power <<= 3; - } - return {result, chi_result}; - } - public: - chi_table_type(): lookup_table_definition("keccak_chi_table") { - this->subtables["full"] = {{0,1}, 0, 65536}; - } - virtual void generate(){ - this->_table.resize(2); - std::vector value_sizes = {8}; - - for (typename BlueprintFieldType::integral_type i = 0; - i < typename BlueprintFieldType::integral_type(65536); - i++ - ) { - std::array value = to_base_chi(i); - this->_table[0].push_back(value[0]); - this->_table[1].push_back(value[1]); - } - } - virtual std::size_t get_columns_number(){ return 2; } - virtual std::size_t get_rows_number(){ return 65536; } - }; - protected: - std::shared_ptr normalize3_table; - std::shared_ptr normalize4_table; - std::shared_ptr normalize6_table; - std::shared_ptr chi_table; public: using manifest_type = nil::blueprint::plonk_component_manifest; @@ -328,6 +255,9 @@ namespace nil { // num columns for the permutation argument const std::size_t limit_permutation_column; + const typename BlueprintFieldType::integral_type big_rot_const = calculate_sparse((integral_type(1) << 64) - 1); + const std::array, 29> all_rot_consts = calculate_rot_consts(); + const std::size_t normalize3_chunk_size = calculate_chunk_size(lookup_rows, 3); const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); const std::size_t normalize6_chunk_size = calculate_chunk_size(lookup_rows, 6); @@ -407,6 +337,30 @@ namespace nil { } }; + typename BlueprintFieldType::integral_type calculate_sparse(const typename BlueprintFieldType::integral_type& value) const { + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type power = 1; + typename BlueprintFieldType::integral_type val = value; + while (val > 0) { + result += (val & 1) * power; + power <<= 3; + val >>= 1; + } + return result; + } + std::array, 29> calculate_rot_consts() const { + std::array, 29> result; + for (int i = 0; i < 5; ++i) { + result[i][0] = calculate_sparse((integral_type(1) << 1) - 1); + result[i][1] = calculate_sparse((integral_type(1) << 63) - 1); + } + for (int i = 1; i < 25; ++i) { + result[i + 4][0] = calculate_sparse((integral_type(1) << rho_offsets[i]) - 1); + result[i + 4][1] = calculate_sparse((integral_type(1) << (64 - rho_offsets[i])) - 1); + } + return result; + } + integral_type normalize(const integral_type& integral_value) const { integral_type result = 0; integral_type value = integral_value; @@ -548,12 +502,13 @@ namespace nil { static configuration configure_rot(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { // regular constraints: - // a = small_part << (192 - r) + big_part; - // a_rot = big_part << r + small_part; - // bound_small = small_part - (1 << r) + (1 << 192); + // a = small_part * (1 << (192 - 3 * r)) + big_part; + // a_rot = big_part * (1 << (3 * r)) + small_part; + // bound_small = small_part - sparse((1 << r) - 1) + sparse((1 << 64) - 1); // bound_small = small_chunk0 + small_chunk1 * 2^chunk_size + ... + small_chunkk * 2^(k*chunk_size) - // bound_big = big_part - (1 << (192 - r)) + (1 << 192); + // bound_big = big_part - sparse((1 << (64 - r)) - 1) + sparse((1 << 64) - 1); // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) + // 1 << 192 = (1 << (192 - 3 * r)) * (1 << (3 * r)) std::pair first_coordinate = {row, column}; @@ -980,7 +935,6 @@ namespace nil { // } // cur_row = pairs[cur_constr].first; // } - std::cout << "lookup gates: " << result.size() << std::endl; return result; } static std::size_t get_gates_amount(std::size_t witness_amount, @@ -996,7 +950,6 @@ namespace nil { for (std::size_t i = 0; i < lookup_gates_configuration.size(); ++i) { res += lookup_gates_configuration[i].size(); } - std::cout << "GATES: " << res << '\n'; return res; } @@ -1029,18 +982,18 @@ namespace nil { return num_cells / witness_amount + bool(num_cells % witness_amount); } - std::vector> component_custom_lookup_tables(){ - std::vector> result = {}; - normalize3_table = std::shared_ptr(new normalize_table_type(3)); - normalize4_table = std::shared_ptr(new normalize_table_type(4)); - normalize6_table = std::shared_ptr(new normalize_table_type(6)); - chi_table = std::shared_ptr(new chi_table_type()); - result.push_back(normalize3_table); - result.push_back(normalize4_table); - result.push_back(normalize6_table); - result.push_back(chi_table); - return result; - } + // std::vector> component_custom_lookup_tables(){ + // std::vector> result = {}; + // normalize3_table = std::shared_ptr(new normalize_table_type(3)); + // normalize4_table = std::shared_ptr(new normalize_table_type(4)); + // normalize6_table = std::shared_ptr(new normalize_table_type(6)); + // chi_table = std::shared_ptr(new chi_table_type()); + // result.push_back(normalize3_table); + // result.push_back(normalize4_table); + // result.push_back(normalize6_table); + // result.push_back(chi_table); + // return result; + // } std::map component_lookup_tables(){ std::map lookup_tables; @@ -1263,6 +1216,8 @@ namespace nil { } case 7: { + std::size_t true_first_row = cur_config_vec[i].first_coordinate.row; + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) @@ -1293,8 +1248,8 @@ namespace nil { cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192)); + + var(component.C(0), true_first_row + 1 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) + - component.big_rot_const); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1323,8 +1278,8 @@ namespace nil { cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192)); + + var(component.C(0), true_first_row + 2 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) + - component.big_rot_const); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1648,9 +1603,13 @@ namespace nil { std::sort(rotate_rows.begin(), rotate_rows.end()); for (std::size_t i = 0; i < 5; i++) { assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << 3; + assignment.constant(component.C(0), row + rotate_rows[i] + 1) = component.all_rot_consts[i][0]; + assignment.constant(component.C(0), row + rotate_rows[i] + 2) = component.all_rot_consts[i][1]; } for (std::size_t i = 5; i < 29; i++) { assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i - 4]); + assignment.constant(component.C(0), row + rotate_rows[i] + 1) = component.all_rot_consts[i][0]; + assignment.constant(component.C(0), row + rotate_rows[i] + 2) = component.all_rot_consts[i][1]; } } @@ -1861,15 +1820,22 @@ namespace nil { // } // std::cout << "\n"; + // ROT std::array C_rot; + integral_type for_bound_smaller = component.calculate_sparse((integral_type(1) << 64) - 1) - component.calculate_sparse((integral_type(1) << 1) - 1); + integral_type for_bound_bigger = component.calculate_sparse((integral_type(1) << 64) - 1) - component.calculate_sparse((integral_type(1) << 63) - 1); + // std::cout << "for_bound_smaller: " << for_bound_smaller << ", for_bound_bigger: " << for_bound_bigger << '\n'; + // std::cout << component.calculate_sparse((integral_type(1) << 64) - 1) << "\n" << component.calculate_sparse((integral_type(1) << 63) - 1) << "\n" << component.calculate_sparse((integral_type(1) << 1) - 1) << "\n"; for (int index = 0; index < 5; ++index) { integral_type integral_C = integral_type(C[index].data); integral_type smaller_part = integral_C >> 189; integral_type bigger_part = integral_C & ((integral_type(1) << 189) - 1); integral_type integral_C_rot = (bigger_part << 3) + smaller_part; C_rot[index] = value_type(integral_C_rot); - integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); - integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); + // integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); + // integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); + integral_type bound_smaller = smaller_part + for_bound_smaller; + integral_type bound_bigger = bigger_part + for_bound_bigger; auto copy_bound_smaller = bound_smaller; auto copy_bound_bigger = bound_bigger; auto chunk_size = component.rotate_chunk_size; @@ -1883,6 +1849,13 @@ namespace nil { integral_big_chunks.push_back(bound_bigger & mask); bound_bigger >>= chunk_size; } + // auto check = integral_big_chunks[0]; + // auto power = integral_type(1); + // for (std::size_t j = 1; j < num_chunks; ++j) { + // power <<= chunk_size; + // check += integral_big_chunks[j] * power; + // } + // std::cout << "check: " << check << ' ' << copy_bound_bigger << '\n'; auto cur_config = component.full_configuration[index + config_index]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = C[index]; @@ -1962,8 +1935,12 @@ namespace nil { integral_type bigger_part = integral_A & ((integral_type(1) << minus_r) - 1); integral_type integral_A_rot = (bigger_part << r) + smaller_part; B[perm[index]] = value_type(integral_A_rot); - integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); - integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); + // integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); + // integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); + integral_type bound_smaller = smaller_part + component.calculate_sparse((integral_type(1) << 64) - 1) + - component.calculate_sparse((integral_type(1) << component.rho_offsets[index]) - 1); + integral_type bound_bigger = bigger_part + component.calculate_sparse((integral_type(1) << 64) - 1) + - component.calculate_sparse((integral_type(1) << (64-component.rho_offsets[index])) - 1); auto copy_bound_smaller = bound_smaller; auto copy_bound_bigger = bound_bigger; auto chunk_size = component.rotate_chunk_size; diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index 39996a602..424268b5c 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -357,6 +357,79 @@ namespace nil { virtual std::size_t get_columns_number(){ return 1; } virtual std::size_t get_rows_number(){ return 129; } }; + + class normalize_base8_table_type : public lookup_table_definition{ + std::size_t base; + virtual std::array to_base(std::size_t base, typename BlueprintFieldType::integral_type num) { + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type normalized_result = 0; + typename BlueprintFieldType::integral_type power = 1; + while (num > 0) { + result = result + (num % base)*power; + normalized_result = normalized_result + ((num % base) & 1)*power; + num /= base; + power <<= 3; + } + return {result, normalized_result}; + } + public: + normalize_base8_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { + this->subtables["full"] = {{0,1}, 0, 65536}; + } + virtual void generate(){ + this->_table.resize(2); + std::vector value_sizes = {8}; + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(65536); + i++ + ) { + std::array value = to_base(base, i); + this->_table[0].push_back(value[0]); + this->_table[1].push_back(value[1]); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 65536; } + }; + + class chi_table_type : public lookup_table_definition{ + virtual std::array to_base_chi(typename BlueprintFieldType::integral_type num) { + std::size_t base = 5; + typename BlueprintFieldType::integral_type table[5] = {0, 1, 1, 0, 0}; + typename BlueprintFieldType::integral_type result = 0; + typename BlueprintFieldType::integral_type chi_result = 0; + typename BlueprintFieldType::integral_type power = 1; + typename BlueprintFieldType::integral_type mask = 7; + while (num > 0) { + result = result + (num % base) * power; + chi_result = chi_result + table[int(num % base)] * power; + num /= base; + power <<= 3; + } + return {result, chi_result}; + } + public: + chi_table_type(): lookup_table_definition("keccak_chi_table") { + this->subtables["full"] = {{0,1}, 0, 65536}; + } + virtual void generate(){ + this->_table.resize(2); + std::vector value_sizes = {8}; + + for (typename BlueprintFieldType::integral_type i = 0; + i < typename BlueprintFieldType::integral_type(65536); + i++ + ) { + std::array value = to_base_chi(i); + this->_table[0].push_back(value[0]); + this->_table[1].push_back(value[1]); + } + } + virtual std::size_t get_columns_number(){ return 2; } + virtual std::size_t get_rows_number(){ return 65536; } + }; + public: using bimap_type = boost::bimap, boost::bimaps::set_of>; using left_reserved_type = typename bimap_type::left_map; @@ -375,6 +448,10 @@ namespace nil { tables["sha256_ch"] = std::shared_ptr(new ch_function_table()); tables["keccak_pack_table"] = std::shared_ptr(new sparse_values_base8_table()); tables["keccak_sign_bit_table"] = std::shared_ptr(new sparse_values_base8_sign_bit_table()); + tables["keccak_normalize3_table"] = std::shared_ptr(new normalize_base8_table_type(3)); + tables["keccak_normalize4_table"] = std::shared_ptr(new normalize_base8_table_type(4)); + tables["keccak_normalize6_table"] = std::shared_ptr(new normalize_base8_table_type(6)); + tables["keccak_chi_table"] = std::shared_ptr(new chi_table_type()); } void register_lookup_table(std::shared_ptr table){ diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 38682f0c3..388e6006a 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -153,15 +153,15 @@ std::array sparse_round_function(st return inner_state; } -template +template auto test_keccak_round_inner(std::array inner_state, std::array padded_message_chunk, typename BlueprintFieldType::value_type RC, std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; - constexpr std::size_t SelectorColumns = 25; + constexpr std::size_t SelectorColumns = 30; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system +template void test_keccak_round_not_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -232,7 +231,7 @@ void test_keccak_round_not_random() { std::array inner_state = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; value_type RC = to_sparse(value_type(1)); std::array expected_result = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); //call 2 @@ -243,7 +242,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); //call 3 @@ -257,7 +256,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); //call 4 @@ -271,7 +270,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); //call 5 @@ -285,7 +284,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); //call 6 @@ -299,7 +298,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); // call 12 @@ -320,7 +319,7 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); // call 24 @@ -341,12 +340,12 @@ void test_keccak_round_not_random() { for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } -template +template void test_keccak_round_random() { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -373,7 +372,7 @@ void test_keccak_round_random() { auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); - test_keccak_round_inner + test_keccak_round_inner (inner_state, padded_message_chunk, RC, expected_result); } @@ -381,46 +380,25 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_not_random(); + // test_keccak_round_not_random(); + // test_keccak_round_not_random(); // xor_with_mes, last_round_call - test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); -} - -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows) { - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_not_random(); - // test_keccak_round_not_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); -} - -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_lookup_rows_to_fail) { - // these test need to fail because with small numbers for lookup rows, - // the chunks for normalization will be smaller, so more cells per operation - - // +-1 row for constraints won't be fullfilled: Assertion `max - min <= 2' failed. - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); + // test_keccak_round_random(); + test_keccak_round_random(); + // test_keccak_round_random(); + test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index 7ca051773..5af505930 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -187,15 +187,9 @@ namespace nil { blueprint::connectedness_check_type connectedness_check, ComponentStaticInfoArgs... component_static_info_args) { using component_type = ComponentType; - blueprint::circuit> bp; - blueprint::assignment> assignment(desc); - if constexpr( nil::blueprint::component_use_custom_lookup_tables() ){ - auto lookup_tables = component_instance.component_custom_lookup_tables(); - for(std::size_t i=0; i< lookup_tables.size(); i++){ - bp.register_lookup_table(lookup_tables[i]); - } - }; + blueprint::circuit bp; + blueprint::assignment assignment; if constexpr( nil::blueprint::use_lookups() ){ auto lookup_tables = component_instance.component_lookup_tables(); @@ -206,7 +200,7 @@ namespace nil { static boost::random::mt19937 gen; static boost::random::uniform_int_distribution<> dist(0, 100); - std::size_t start_row = dist(gen); + std::size_t start_row = 0;//dist(gen); if constexpr (PrivateInput) { for (std::size_t i = 0; i < public_input.size(); i++) { @@ -247,10 +241,10 @@ namespace nil { // Uncomment the following if you want to output a visual representation of the connectedness graph. // I recommend turning off the starting row randomization - auto zones = blueprint::detail::generate_connectedness_zones( - assignment, bp, instance_input.all_vars(), start_row, component_instance.rows_amount); - blueprint::detail::export_connectedness_zones( - zones, assignment, instance_input.all_vars(), start_row, component_instance.rows_amount, std::cout); + // auto zones = blueprint::detail::generate_connectedness_zones( + // assignment, bp, instance_input.all_vars(), start_row, component_instance.rows_amount); + // blueprint::detail::export_connectedness_zones( + // zones, assignment, instance_input.all_vars(), start_row, component_instance.rows_amount, std::cout); BOOST_ASSERT_MSG(is_connected, "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); @@ -301,7 +295,7 @@ namespace nil { std::cout << "Usable rows: " << desc.usable_rows_amount << std::endl; std::cout << "Padded rows: " << desc.rows_amount << std::endl; - // profiling(assignment); + profiling(assignment); #endif assert(blueprint::is_satisfied(bp, assignment) == expected_to_pass); From 66be6a9c766ec016ad3751a441fd80800d97a381 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 20 Dec 2023 11:52:51 +0000 Subject: [PATCH 31/48] added gates #183 --- .../hashes/keccak/keccak_component.hpp | 107 ++++++++++-------- test/hashes/plonk/keccak.cpp | 10 +- 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index ed4e005f3..444a63007 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -211,8 +211,8 @@ namespace nil { while (input > 0) { auto bit = input % 2; sparse_res += bit * power; - power *= 8; - input /= 2; + power <<= 3; + input >>= 1; } return sparse_res; } @@ -221,12 +221,14 @@ namespace nil { integral_type sparse_input = const_sparse_input; integral_type res = 0; integral_type power = 1; + integral_type mask = (integral_type(1) << 3) - 1; while (sparse_input > 0) { - auto bit = sparse_input % 8; + auto bit = sparse_input & mask; + std::cout << "bit: " << bit << std::endl; BOOST_ASSERT(bit * (1 - bit) == 0); res += bit * power; - power *= 2; - sparse_input /= 8; + power <<= 1; + sparse_input >>= 3; } return res; } @@ -376,9 +378,9 @@ namespace nil { auto config = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); std::size_t row = 0, column = 0; - std::size_t row_shift = padding_component_type::get_rows_amount(witness_amount, 0, - num_blocks, num_bits, range_check_input, - limit_permutation_column); + std::size_t row_shift = 0;//padding_component_type::get_rows_amount(witness_amount, 0, + // num_blocks, num_bits, range_check_input, + // limit_permutation_column); std::map> config_map; @@ -402,14 +404,14 @@ namespace nil { } } - std::cout << "MAP\n"; - for (auto c : config_map) { - std::cout << c.first << ": "; - for (auto r : c.second) { - std::cout << r << " "; - } - std::cout << std::endl; - } + // std::cout << "MAP\n"; + // for (auto c : config_map) { + // std::cout << c.first << ": "; + // for (auto r : c.second) { + // std::cout << r << " "; + // } + // std::cout << std::endl; + // } return config_map; } @@ -456,18 +458,18 @@ namespace nil { result.push_back(cur_result); } - // for (std::size_t i = 0; i < result.size(); ++i) { - // std::cout << "config " << i << ":\n"; - // for (auto cur_config : result[i]) { - // std::cout << "gate:\n"; - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - // } - // } + for (std::size_t i = 0; i < result.size(); ++i) { + std::cout << "config " << i << ":\n"; + for (auto cur_config : result[i]) { + std::cout << "gate:\n"; + for (int j = 0; j < cur_config.constraints.size(); ++j) { + for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + } + std::cout << std::endl; + } + } + } return result; } @@ -497,9 +499,6 @@ namespace nil { if (c.first >= 10 * witness_amount) res++; else res += 2; } - // if (witness_amount == 9) res = 1; - // if (witness_amount == 15) res = 3; - res += padding_component_type::get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); return res; } @@ -614,7 +613,7 @@ namespace nil { constraint_0 -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) * (integral_type(1) << ((i-1) * 8)); constraint_1 -= var(conf.constraints[1][i].column, static_cast(conf.constraints[1][i].row)) - * (integral_type(1) << ((i-1) * 8)); + * (integral_type(1) << ((i-1) * 24)); lookup_constraints_0.push_back({lookup_tables_indices.at("keccak_pack_table/full"), {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row)), var(component.W(conf.constraints[1][i].column), static_cast(conf.constraints[1][i].row))}}); @@ -624,9 +623,9 @@ namespace nil { } selector_indexes.push_back(bp.add_gate({constraint_0, constraint_1})); gate_index++; - selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); - selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); - lookup_gate_index += 2; + // selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); + // selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); + // lookup_gate_index += 2; } return selector_indexes; @@ -694,22 +693,24 @@ namespace nil { for (auto config : config_map) { if (config.first < component.witnesses) { for (auto gate_row : config.second) { - std::cout << "enabling: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 1] << std::endl; + // std::cout << "enabling: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 1] << std::endl; assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); - assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + row); + // assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + row); } - sel_ind += 3; + // std::cout << std::endl; + sel_ind += 1; } } sel_ind = 0; for (auto config : config_map) { if (config.first >= 10 * component.witnesses) { for (auto gate_row : config.second) { - std::cout << "enabling2: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 2] << std::endl; + // std::cout << "enabling2: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 2] << std::endl; assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); - assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); + // assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); } - sel_ind += 3; + // std::cout << std::endl; + sel_ind += 1; } } @@ -754,28 +755,37 @@ namespace nil { integral_type regular = integral_type(regular_value.data); // std::cout << "pad elem: " << regular << std::endl; integral_type sparse = component.pack(regular); + auto copy_sparse = sparse; auto chunk_size = component.pack_chunk_size; auto num_chunks = component.pack_num_chunks; std::vector integral_chunks; std::vector integral_sparse_chunks; integral_type mask = (integral_type(1) << chunk_size) - 1; + integral_type sparse_mask = (integral_type(1) << (chunk_size * 3)) - 1; + integral_type power = 1; + // std::cout << "sparse: " << sparse << std::endl; for (std::size_t j = 0; j < num_chunks; ++j) { integral_chunks.push_back(regular & mask); regular >>= chunk_size; - integral_sparse_chunks.push_back(component.pack(integral_chunks.back())); + integral_sparse_chunks.push_back(sparse & sparse_mask); + sparse >>= (chunk_size * 3); + // std::cout << "chunks: " << integral_chunks.back() << " " << integral_sparse_chunks.back() << std::endl; + copy_sparse -= power * integral_sparse_chunks.back(); + power <<= (3 * chunk_size); } sparse_padded_message[index] = value_type(sparse); auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = regular_value; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(sparse); + // std::cout << cur_config.constraints[1][0].column << ' ' << cur_config.constraints[1][0].row + cur_row << std::endl; for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_chunks[j - 1]); assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); } config_index++; } - std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; + // std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; cur_row += component.full_configuration[config_index - 1].last_coordinate.row + (component.full_configuration[config_index - 1].last_coordinate.column > 0); @@ -792,11 +802,11 @@ namespace nil { // } // from sparse - std::array result_message; for (std::size_t index = 0; index < 5; ++index) { - value_type sparse_value = var_value(assignment, inner_state[index]); - integral_type sparse = integral_type(sparse_value.data); + // value_type sparse_value = var_value(assignment, inner_state[index]); + integral_type sparse = integral_type(0); integral_type regular = component.unpack(sparse); + // std::cout << "from sparse: " << sparse << " " << regular << std::endl; auto chunk_size = component.pack_chunk_size; auto num_chunks = component.pack_num_chunks; std::vector integral_sparse_chunks; @@ -810,7 +820,7 @@ namespace nil { sparse_padded_message[index] = value_type(regular); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = sparse_value; + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = value_type(sparse); assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(regular); for (int j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); @@ -818,11 +828,10 @@ namespace nil { } config_index++; } - std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; + // std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; cur_row += component.full_configuration[config_index - 1].last_coordinate.row + (component.full_configuration[config_index - 1].last_coordinate.column > 0); - std::cout << cur_row << ' ' << start_row_index << ' ' << component.rows_amount << std::endl; BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); return typename component_type::result_type(component, start_row_index); diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index cfbfbc03b..7606ae18f 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -69,8 +69,8 @@ template message, std::vector expected_result) { constexpr std::size_t PublicInputColumns = 1; - constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = 20; + constexpr std::size_t ConstantColumns = 3; + constexpr std::size_t SelectorColumns = 30; using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system message = {1}; - const std::size_t num_blocks = 1; - const std::size_t num_bits = 1; + std::vector message = {1, 2}; + const std::size_t num_blocks = 2; + const std::size_t num_bits = 65; const bool range_check_input = true; const std::size_t limit_permutation_column = 7; From f1240d07fc158d96bd294585ec5f9e893aece081 Mon Sep 17 00:00:00 2001 From: Polina Chernyshova Date: Wed, 20 Dec 2023 12:01:06 +0000 Subject: [PATCH 32/48] all vars update --- .../components/hashes/keccak/keccak_component.hpp | 7 +++++-- .../blueprint/components/hashes/keccak/keccak_padding.hpp | 7 +++++-- .../blueprint/components/hashes/keccak/keccak_round.hpp | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 444a63007..8094c0917 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -172,8 +172,11 @@ namespace nil { struct input_type { std::vector message; - std::vector all_vars() const { - return message; + std::vector> all_vars() const { + std::vector> res; + res.reserve(message.size()); + res.insert(res.end(), message.begin(), message.end()); + return res; } }; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 918fca549..acd1adbe7 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -193,8 +193,11 @@ namespace nil { // message[num_blocks - 1] all message[i] are 64-bit for i > 0 message[0] is <= 64-bit std::vector message; - std::vector all_vars() const { - return message; + std::vector> all_vars() const { + std::vector> res; + res.reserve(message.size()); + res.insert(res.end(), message.begin(), message.end()); + return res; } }; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 8c66b84f7..ae610cb37 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -308,8 +308,8 @@ namespace nil { std::array padded_message_chunk; var round_constant; - std::vector all_vars() const { - std::vector result; + std::vector> all_vars() const { + std::vector> result; result.insert(result.end(), inner_state.begin(), inner_state.end()); result.insert(result.end(), padded_message_chunk.begin(), padded_message_chunk.end()); result.push_back(round_constant); From 7c019e1bba17d30c5b53329849f698652e63b290 Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Tue, 20 Feb 2024 20:17:50 +0400 Subject: [PATCH 33/48] Updated the components for arithmetization changes. --- .github/workflows/run_tests.yml | 16 +- .../hashes/keccak/keccak_component.hpp | 157 ++++++------- .../hashes/keccak/keccak_padding.hpp | 132 +++++------ .../components/hashes/keccak/keccak_round.hpp | 221 +++++++++--------- test/hashes/plonk/keccak.cpp | 15 +- test/hashes/plonk/keccak_padding.cpp | 14 +- test/hashes/plonk/keccak_round.cpp | 62 +++-- test/test_plonk_component.hpp | 2 +- 8 files changed, 290 insertions(+), 329 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 64d2166a9..91846bef5 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -78,18 +78,10 @@ jobs: blueprint_verifiers_placeholder_f1_loop_test, blueprint_verifiers_placeholder_f3_loop_test, blueprint_verifiers_placeholder_gate_component_test, - blueprint_verifiers_flexible_pow_factor_test, - blueprint_proxy_test, - blueprint_mock_mocked_components_test, - blueprint_component_batch_test, - blueprint_verifiers_placeholder_expression_evaluation_component_test, - blueprint_verifiers_placeholder_final_polynomial_check_test, - blueprint_verifiers_flexible_swap_test, - blueprint_verifiers_flexible_additions_test, - blueprint_verifiers_flexible_multiplications_test, - blueprint_verifiers_flexible_poseidon_test, - blueprint_verifiers_flexible_constant_pow_test, - blueprint_verifiers_placeholder_verifier_test + blueprint_hashes_plonk_keccak_round_test, + blueprint_hashes_plonk_keccak_padding_test, + blueprint_hashes_plonk_keccak_test, + blueprint_proxy_test ] # Tests to execute include: # Abused to enable proof generation for some tests; add more as needed - target: blueprint_algebra_fields_plonk_non_native_logic_ops_test diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 8094c0917..b700db929 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -43,12 +43,11 @@ namespace nil { template class keccak; - template - class keccak> : - public plonk_component { + template + class keccak> : + public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -59,15 +58,13 @@ namespace nil { public: using var = typename component_type::var; - // using round_component_type = keccak_round>; + // using round_component_type = keccak_round>; // round_component_type round_true_true; // std::vector rounds_true_false; // std::vector rounds_false_false; // std::vector rounds; - using padding_component_type = keccak_padding>; + using padding_component_type = keccak_padding>; padding_component_type padding; using manifest_type = nil::blueprint::plonk_component_manifest; @@ -114,7 +111,7 @@ namespace nil { // false, false)); // } // } - + return manifest; } @@ -131,7 +128,7 @@ namespace nil { const std::size_t lookup_rows = 65536; const std::size_t witnesses = this->witness_amount(); - + const std::size_t num_blocks; const std::size_t num_bits; const bool range_check_input; @@ -151,7 +148,7 @@ namespace nil { const std::size_t pack_num_chunks = 8; const std::size_t pack_cells = 2 * (pack_num_chunks + 1); const std::size_t pack_buff = (this->witness_amount() == 15) * 2; - + std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls, limit_permutation_column); const std::map> gates_configuration_map = configure_map(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); @@ -172,7 +169,7 @@ namespace nil { struct input_type { std::vector message; - std::vector> all_vars() const { + std::vector> all_vars() { std::vector> res; res.reserve(message.size()); res.insert(res.end(), message.begin(), message.end()); @@ -242,21 +239,21 @@ namespace nil { // regular constraints: // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) - + std::size_t last_row = row, last_column = column; std::pair first_coordinate = {row, column}; - + std::vector> copy_from; std::vector>> constraints; - + if (1 + column > limit_permutation_column) { copy_from.push_back({last_row + 1, 0}); } else { copy_from.push_back({last_row + (last_column / witness_amount), (last_column++) % witness_amount}); } - + std::pair cell_copy_to; std::size_t final_row = (column + pack_cells - 1) / witness_amount + row; if (final_row == copy_from[0].first) { @@ -264,7 +261,7 @@ namespace nil { } else { cell_copy_to = {final_row, 0}; } - + std::vector> cells; if (1 + column > limit_permutation_column) { for (int i = column; i < witness_amount; ++i) { @@ -290,12 +287,12 @@ namespace nil { } cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } - } + } std::size_t cell_index = 0; - - std::vector>> + + std::vector>> lookups(pack_num_chunks, std::vector>()); - + constraints.push_back({copy_from[0]}); constraints.push_back({cell_copy_to}); for (std::size_t i = 0; i < 2; ++i) { @@ -304,11 +301,11 @@ namespace nil { lookups[j].push_back(constraints[i].back()); } } - + last_column = cells.back().second + 1 + pack_buff; last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; - + return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); } @@ -324,7 +321,7 @@ namespace nil { for (std::size_t index = 0; index < num_round_calls * 17; ++index) { // to sparse representation - result.push_back(configure_pack_unpack(witness_amount, row, column, + result.push_back(configure_pack_unpack(witness_amount, row, column, pack_cells, pack_num_chunks, pack_buff, limit_permutation_column)); row = result[index].last_coordinate.row; @@ -345,7 +342,7 @@ namespace nil { row = 0; // from sparse representation for (std::size_t i = 0; i < 5; ++i) { - result.push_back(configure_pack_unpack(witness_amount, row, column, + result.push_back(configure_pack_unpack(witness_amount, row, column, pack_cells, pack_num_chunks, pack_buff, limit_permutation_column)); row = result.back().last_coordinate.row; @@ -371,18 +368,18 @@ namespace nil { return result; } - + static std::map> configure_map(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - + auto config = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); std::size_t row = 0, column = 0; - std::size_t row_shift = 0;//padding_component_type::get_rows_amount(witness_amount, 0, - // num_blocks, num_bits, range_check_input, + std::size_t row_shift = 0;//padding_component_type::get_rows_amount(witness_amount, 0, + // num_blocks, num_bits, range_check_input, // limit_permutation_column); std::map> config_map; @@ -432,8 +429,8 @@ namespace nil { for (auto config: gates_configuration_map) { if (config.first >= 10 * witness_amount) continue; - configuration cur_config = configure_pack_unpack(witness_amount, 0, config.first, - num_cells, pack_num_chunks, buff, limit_permutation_column); + configuration cur_config = configure_pack_unpack(witness_amount, 0, config.first, + num_cells, pack_num_chunks, buff, limit_permutation_column); std::vector> pairs; for (auto constr : cur_config.constraints) { std::size_t min = constr[0].row; @@ -460,7 +457,7 @@ namespace nil { } result.push_back(cur_result); } - + for (std::size_t i = 0; i < result.size(); ++i) { std::cout << "config " << i << ":\n"; for (auto cur_config : result[i]) { @@ -481,8 +478,8 @@ namespace nil { std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { std::size_t num_round_calls = calculate_num_round_calls(num_blocks); - std::size_t res = padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, - num_blocks, num_bits, range_check_input, + std::size_t res = padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, + num_blocks, num_bits, range_check_input, limit_permutation_column); // + round_tt_rows // + round_tf_rows * (num_round_calls - 1) @@ -573,26 +570,23 @@ namespace nil { }; - template + template using keccak_component = - keccak>; + keccak>; - template + template std::vector generate_gates( - const keccak_component + const keccak_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const typename lookup_library::left_reserved_type lookup_tables_indices) { - - using component_type = keccak_component; + + using component_type = keccak_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; @@ -634,45 +628,41 @@ namespace nil { return selector_indexes; } - template + template void generate_copy_constraints( - const keccak_component + const keccak_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_component; + using component_type = keccak_component; using var = typename component_type::var; std::uint32_t row = start_row_index; } - template - typename keccak_component::result_type + template + typename keccak_component::result_type generate_circuit( - const keccak_component + const keccak_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_component; + using component_type = keccak_component; using padding_type = typename component_type::padding_component_type; - + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); std::size_t row = start_row_index; @@ -682,9 +672,9 @@ namespace nil { } std::vector zero_column = {0}; - padding_type padding_component_instance(witnesses, zero_column, zero_column, - component.num_blocks, component.num_bits, - component.range_check_input, + padding_type padding_component_instance(witnesses, zero_column, zero_column, + component.num_blocks, component.num_bits, + component.range_check_input, component.limit_permutation_column); typename padding_type::input_type padding_input = {instance_input.message}; typename padding_type::result_type padding_result = generate_circuit(padding_component_instance, bp, assignment, padding_input, row); @@ -717,7 +707,7 @@ namespace nil { } } - using component_type = keccak_component; + using component_type = keccak_component; using var = typename component_type::var; generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); @@ -725,21 +715,20 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template - typename keccak_component::result_type + template + typename keccak_component::result_type generate_assignments( - const keccak_component + const keccak_component &component, - assignment> + assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t cur_row = start_row_index; - using component_type = keccak_component; + using component_type = keccak_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; @@ -840,21 +829,19 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template + template void generate_assignments_constant( - const keccak_component + const keccak_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_component::input_type + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_component; + using component_type = keccak_component; using integral_type = typename BlueprintFieldType::integral_type; std::size_t row = start_row_index + 3; @@ -863,7 +850,7 @@ namespace nil { } } - + } // namespace components } // namespace blueprint } // namespace nil diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index acd1adbe7..24a64d7c0 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -43,11 +43,11 @@ namespace nil { template class keccak_padding; - template - class keccak_padding> - : public plonk_component { + template + class keccak_padding> + : public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; public: @@ -67,7 +67,7 @@ namespace nil { } }; - struct configuration { + struct configuration { // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. coordinates first_coordinate; @@ -146,7 +146,7 @@ namespace nil { std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, - bool range_check_input, + bool range_check_input, std::size_t limit_permutation_column = 7) { gate_manifest manifest = gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)); @@ -193,7 +193,7 @@ namespace nil { // message[num_blocks - 1] all message[i] are 64-bit for i > 0 message[0] is <= 64-bit std::vector message; - std::vector> all_vars() const { + std::vector> all_vars() { std::vector> res; res.reserve(message.size()); res.insert(res.end(), message.begin(), message.end()); @@ -263,20 +263,20 @@ namespace nil { return 1; } - static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column, std::size_t row, std::size_t column, std::size_t num_cells, std::size_t buff) { - + if (column > 0) { row += 1; column = 0; } - + std::pair first_coordinate = {row, column}; std::size_t last_row = row, last_column = column; - + // chunk std::vector> copy_to; if (column > limit_permutation_column) { @@ -301,7 +301,7 @@ namespace nil { last_column %= witness_amount; auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); - + // std::cout << "config: " << "\n"; // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; @@ -317,15 +317,15 @@ namespace nil { return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); } - static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t row, std::size_t column, std::size_t num_cells, std::size_t buff) { - + std::pair first_coordinate = {row, column}; std::size_t last_row = row, last_column = column; - + // relay, chunk, sum; second std::vector> copy_to; std::pair cell_copy_from; @@ -342,8 +342,8 @@ namespace nil { cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; } - - + + std::vector> cells; if (column > 3) { for (int i = column; i < witness_amount; ++i) { @@ -363,7 +363,7 @@ namespace nil { } } std::size_t cell_index = 0; - + std::vector>> constraints; std::vector>> lookups(1 + range_check_input); // chunk, first, second @@ -398,7 +398,7 @@ namespace nil { last_column %= witness_amount; auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); - + // std::cout << "config: " << "\n"; // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; @@ -414,7 +414,7 @@ namespace nil { return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - static configuration configure_inner(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + static configuration configure_inner(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column, std::size_t row, std::size_t column, std::size_t num_cells, std::size_t buff) { @@ -436,7 +436,7 @@ namespace nil { } return configuration(first_coordinate, {row + 1, 0}, {}, constraints, {}, cell_copy_from); } - + static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { @@ -494,12 +494,12 @@ namespace nil { std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - + auto shift = calculate_shift(num_blocks, num_bits); if (shift == 0 && !range_check_input) { return {}; } - + auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); std::size_t row = 0, column = 0; @@ -532,7 +532,7 @@ namespace nil { static std::vector> configure_gates(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, - bool range_check_input, + bool range_check_input, std::size_t limit_permutation_column) { if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { return {}; @@ -544,9 +544,9 @@ namespace nil { std::size_t buff = calculate_buff(witness_amount, range_check_input); for (auto config: gates_configuration_map) { - configuration cur_config = configure_inner(witness_amount, num_blocks, num_bits, - range_check_input, limit_permutation_column, - 0, config.first, num_cells, buff); + configuration cur_config = configure_inner(witness_amount, num_blocks, num_bits, + range_check_input, limit_permutation_column, + 0, config.first, num_cells, buff); std::vector> pairs; for (auto constr : cur_config.constraints) { std::size_t min = constr[0].row; @@ -573,7 +573,7 @@ namespace nil { } result.push_back(cur_result); } - + // for (std::size_t i = 0; i < result.size(); ++i) { // std::cout << "config " << i << ":\n"; // for (auto cur_config : result[i]) { @@ -612,7 +612,7 @@ namespace nil { static std::size_t get_gates_amount(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, - bool range_check_input, + bool range_check_input, std::size_t limit_permutation_column = 7) { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); return map.size() * 2 + range_check_input + 2; @@ -621,7 +621,7 @@ namespace nil { std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, - bool range_check_input, + bool range_check_input, std::size_t limit_permutation_column) { auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); auto res = confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); @@ -660,21 +660,21 @@ namespace nil { typename nil::crypto3::zk::snark::lookup_table_definition; }; - template + template using padding_component = - keccak_padding>; + keccak_padding>; - template + template std::vector generate_gates( - const padding_component &component, - circuit> &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type + const typename padding_component::input_type &instance_input, const typename lookup_library::left_reserved_type lookup_tables_indices) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; @@ -693,7 +693,7 @@ namespace nil { std::vector cur_constraints; std::vector cur_lookup_constraints; // range_check shift num_blocks * 64 - num_bits; - cur_constraints.push_back(var(component.W(0), -1) + cur_constraints.push_back(var(component.W(0), -1) + var(component.C(0), 1, true, var::column_type::constant) - 64 * var(component.C(0), 0, true, var::column_type::constant)); cur_constraints.push_back(var(component.W(0), -1)); @@ -801,16 +801,16 @@ namespace nil { return selector_indexes; } - template + template void generate_copy_constraints( - const padding_component &component, - circuit> &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; std::size_t strow = start_row_index; @@ -851,16 +851,16 @@ namespace nil { } } - template - typename padding_component::result_type generate_circuit( - const padding_component &component, - circuit> &bp, - assignment> + template + typename padding_component::result_type generate_circuit( + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; using var = typename component_type::var; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); @@ -901,17 +901,17 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template - typename padding_component::result_type generate_assignments( - const padding_component &component, - assignment> + template + typename padding_component::result_type generate_assignments( + const padding_component &component, + assignment> &assignment, - const typename padding_component::input_type &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t strow = start_row_index; - using component_type = padding_component; + using component_type = padding_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -930,7 +930,7 @@ namespace nil { for (int j = 1; j < 9; ++j) { assignment.witness(component.W(j), strow) = value_type(shift_range_check[j - 1]); } - + if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { @@ -985,7 +985,7 @@ namespace nil { } else { for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { auto cur_config = component.full_configuration[index]; - + if (component.range_check_input) { integral_type chunk_to_check = integral_type(var_value(assignment, instance_input.message[index]).data); integral_type mask_range_check = (integral_type(1) << 8) - 1; @@ -1009,16 +1009,16 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template + template void generate_assignments_constant( - const padding_component &component, - circuit> &bp, - assignment> + const padding_component &component, + circuit> &bp, + assignment> &assignment, - const typename padding_component::input_type &instance_input, + const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; + using component_type = padding_component; assignment.constant(component.C(0), start_row_index) = 0; assignment.constant(component.C(0), start_row_index + 1) = component.num_blocks; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index ae610cb37..be2ab99be 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -49,12 +49,11 @@ namespace nil { template class keccak_round; - template - class keccak_round> : - public plonk_component { + template + class keccak_round> : + public plonk_component { - using component_type = plonk_component; + using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using lookup_table_definition = typename nil::crypto3::zk::snark::lookup_table_definition; @@ -112,8 +111,8 @@ namespace nil { // } return buff; } - static std::size_t calculate_last_round_call_row(std::size_t witness_amount, - bool xor_with_mes, + static std::size_t calculate_last_round_call_row(std::size_t witness_amount, + bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { if (!last_round_call) { @@ -190,7 +189,7 @@ namespace nil { return row < other.row || (row == other.row && column < other.column); } }; - + // In constraints we use such notation: constr[0] - result, // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. coordinates first_coordinate; @@ -307,8 +306,8 @@ namespace nil { std::array inner_state; std::array padded_message_chunk; var round_constant; - - std::vector> all_vars() const { + + std::vector> all_vars() { std::vector> result; result.insert(result.end(), inner_state.begin(), inner_state.end()); result.insert(result.end(), padded_message_chunk.begin(), padded_message_chunk.end()); @@ -388,7 +387,7 @@ namespace nil { return result; } - static configuration configure_inner(std::size_t witness_amount, std::size_t limit_permutation_column, + static configuration configure_inner(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column, std::size_t num_args, std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { @@ -396,7 +395,7 @@ namespace nil { std::size_t last_row = row, last_column = column; - + std::vector> copy_to; if (num_args + column > limit_permutation_column) { @@ -409,7 +408,7 @@ namespace nil { (last_column++) % witness_amount}); } } - + std::pair cell_copy_from; std::size_t final_row = (column + num_cells - 1) / witness_amount + row; if (final_row == copy_to[0].first) { @@ -417,7 +416,7 @@ namespace nil { } else { cell_copy_from = {final_row, 0}; } - + std::vector> cells; if (num_args + column > limit_permutation_column) { for (int i = column; i < witness_amount; ++i) { @@ -445,7 +444,7 @@ namespace nil { } } std::size_t cell_index = 0; - + std::vector>> constraints; constraints.push_back({cells[cell_index++]}); for (int i = 0; i < num_args; ++i) { @@ -478,7 +477,7 @@ namespace nil { // sum = arg1 + arg2 + ... + argn // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) // norm_sum = norm_sum_chunk0 + norm_sum_chunk1 * 2^chunk_size + ... + norm_sum_chunkk * 2^(k*chunk_size) - + std::size_t num_chunks = calculate_num_chunks(lookup_rows, num_args + 1); std::size_t num_cells = calculate_num_cells(lookup_rows, num_args + 1); std::size_t buff = calculate_buff(witness_amount, lookup_rows, num_args + 1); @@ -516,7 +515,7 @@ namespace nil { last_column = column; std::size_t num_chunks = 8; std::size_t num_cells = 24; - + std::vector> copy_to; std::pair cell_copy_from; std::vector>> constraints; @@ -530,7 +529,7 @@ namespace nil { cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; } - + std::vector> cells; if (2 + column > limit_permutation_column) { for (int i = column; i < witness_amount; ++i) { @@ -548,21 +547,21 @@ namespace nil { while (cur_column - column < num_cells) { cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } - } + } std::size_t cell_index = 0; auto rot_const = cells[cell_index++]; auto minus_rot_const = cells[cell_index++]; - + constraints.push_back({copy_to[0]}); constraints[0].push_back(cells[cell_index++]); constraints[0].push_back(cells[cell_index++]); - + constraints.push_back({cell_copy_from}); constraints[1].push_back(constraints[0][2]); constraints[1].push_back(constraints[0][1]); - + std::vector>> lookups(2, std::vector>()); - + constraints.push_back({cells[cell_index++]}); constraints[2].push_back(constraints[0][1]); constraints.push_back({constraints[2][0]}); @@ -571,7 +570,7 @@ namespace nil { lookups[0].push_back(constraints[3].back()); lookups[1].push_back(constraints[3].back()); } - + constraints.push_back({cells[cell_index++]}); constraints[4].push_back(constraints[0][2]); constraints.push_back({constraints[4][0]}); @@ -586,11 +585,11 @@ namespace nil { constraints[1].push_back(constraints[6][0]); constraints[2].push_back(constraints[6][0]); constraints[4].push_back(constraints[6][1]); - + last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; - + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } @@ -681,7 +680,7 @@ namespace nil { return result; } - static std::map, + static std::map, std::vector> configure_map(std::size_t witness_amount, bool xor_with_mes, bool last_round_call, @@ -831,7 +830,7 @@ namespace nil { // } // std::cout << std::endl; // } - + std::vector> pairs; for (auto constr : cur_config.constraints) { std::size_t min = constr[0].row; @@ -858,7 +857,7 @@ namespace nil { } result.push_back(cur_result); } - + return result; } @@ -890,7 +889,7 @@ namespace nil { cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; } - + std::vector> pairs; for (auto constr : cur_config.lookups) { std::size_t min = constr[0].row; @@ -953,9 +952,9 @@ namespace nil { return res; } - static std::size_t get_rows_amount(std::size_t witness_amount, + static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, - bool xor_with_mes, + bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); @@ -1035,26 +1034,23 @@ namespace nil { }; }; - template + template using keccak_round_component = - keccak_round>; + keccak_round>; - template + template std::vector generate_gates( - const keccak_round_component + const keccak_round_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const typename lookup_library::left_reserved_type lookup_tables_indices) { - - using component_type = keccak_round_component; + + using component_type = keccak_round_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; @@ -1084,12 +1080,12 @@ namespace nil { std::vector cur_lookup_constraints; std::string cur_lookup_table_name; switch (gm.first.first) { - case 2: + case 2: { cur_constraints.push_back(constraint_type(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1105,7 +1101,7 @@ namespace nil { * (integral_type(1) << (k * component.normalize3_chunk_size)); } cur_constraints.push_back(constraint_1); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1129,10 +1125,10 @@ namespace nil { case 3: { cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1146,9 +1142,9 @@ namespace nil { for (int k = 0; k < component.normalize4_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize4_chunk_size)); - } + } cur_constraints.push_back(constraint_1); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1172,12 +1168,12 @@ namespace nil { case 5: { cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1191,9 +1187,9 @@ namespace nil { for (int k = 0; k < component.normalize6_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.normalize6_chunk_size)); - } + } cur_constraints.push_back(constraint_1); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1219,10 +1215,10 @@ namespace nil { std::size_t true_first_row = cur_config_vec[i].first_coordinate.row; cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1233,10 +1229,10 @@ namespace nil { j %= cur_len; cur_constraints.push_back(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) + * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1)); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1246,11 +1242,11 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(component.C(0), true_first_row + 1 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) - component.big_rot_const); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1266,7 +1262,7 @@ namespace nil { * (integral_type(1) << (k * component.rotate_chunk_size)); } cur_constraints.push_back(constraint_1); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1276,11 +1272,11 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) + var(component.C(0), true_first_row + 2 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) - component.big_rot_const); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1306,7 +1302,7 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) * var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - (integral_type(1) << 192)); @@ -1319,10 +1315,10 @@ namespace nil { { cur_constraints.push_back(component.sparse_3 - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1336,9 +1332,9 @@ namespace nil { for (int k = 0; k < component.chi_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.chi_chunk_size)); - } + } cur_constraints.push_back(constraint_1); - + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1378,7 +1374,7 @@ namespace nil { for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), static_cast(cur_lookup_config_vec[i].lookups[j][0].row) - - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1), + - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1), var(component.W(cur_lookup_config_vec[i].lookups[j][1].column), static_cast(cur_lookup_config_vec[i].lookups[j][1].row) - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; cur_lookup_constraints.push_back(lookup_constraint); @@ -1404,7 +1400,7 @@ namespace nil { // } // } // switch (gm.first.first) { - // case 2: + // case 2: // { // cur_lookup_table_name = "keccak_normalize3_table/full"; // break; @@ -1431,7 +1427,7 @@ namespace nil { // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { // lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), // {var(component.W(cur_config_vec[i].lookups[j][0].column), static_cast(cur_config_vec[i].lookups[j][0].row) - // - static_cast(cur_config_vec[i].first_coordinate.row) - 1), + // - static_cast(cur_config_vec[i].first_coordinate.row) - 1), // var(component.W(cur_config_vec[i].lookups[j][1].column), static_cast(cur_config_vec[i].lookups[j][1].row) // - static_cast(cur_config_vec[i].first_coordinate.row) - 1)}}; // cur_constraints.push_back(lookup_constraint); @@ -1444,21 +1440,19 @@ namespace nil { return selector_indexes; } - template + template void generate_copy_constraints( - const keccak_round_component + const keccak_round_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using var = typename component_type::var; std::size_t config_index = 0; @@ -1478,7 +1472,7 @@ namespace nil { if (component.last_round_call) { bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + start_row_index), false)}); bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false)}); - bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index, false, var::column_type::constant), + bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index, false, var::column_type::constant), var(component.W(config[config_index].copy_to[2].column), static_cast(config[config_index].copy_to[2].row + start_row_index), false)}); num_copy_constr += 3; } @@ -1486,7 +1480,7 @@ namespace nil { // theta for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, + bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); num_copy_constr += 1; } @@ -1571,21 +1565,19 @@ namespace nil { {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); } - template + template void generate_assignments_constant( - const keccak_round_component + const keccak_round_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using integral_type = typename BlueprintFieldType::integral_type; std::size_t row = start_row_index; @@ -1613,25 +1605,23 @@ namespace nil { } } - template - typename keccak_round_component::result_type + template + typename keccak_round_component::result_type generate_circuit( - const keccak_round_component + const keccak_round_component &component, - circuit> + circuit> &bp, - assignment> + assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; - + using component_type = keccak_round_component; + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); - + auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); std::size_t ind = 0; @@ -1674,19 +1664,18 @@ namespace nil { return typename component_type::result_type(component, start_row_index); } - template - typename keccak_round_component::result_type + template + typename keccak_round_component::result_type generate_assignments( - const keccak_round_component + const keccak_round_component &component, - assignment> + assignment> &assignment, - const typename keccak_round_component::input_type + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_round_component; + using component_type = keccak_round_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; @@ -2028,7 +2017,7 @@ namespace nil { power <<= chunk_size; } A_4 = value_type(integral_normalized_sum); - + auto cur_config = component.full_configuration[config_index]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_3[0]; assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = round_constant; diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 7606ae18f..5b16b8978 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -71,10 +71,9 @@ auto test_keccak_inner(std::vector mess constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; constexpr std::size_t SelectorColumns = 30; - using ArithmetizationParams = nil::crypto3::zk::snark::plonk_arithmetization_params< - WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns>; - using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + zk::snark::plonk_table_description desc( + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; @@ -117,9 +116,9 @@ auto test_keccak_inner(std::vector mess component_type component_instance = component_type(witnesses, std::array{0}, std::array{0}, num_blocks, num_bits, range_check_input, limit_permutation_column); - nil::crypto3::test_component( - component_instance, public_input, result_check, instance_input, - nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); + nil::crypto3::test_component( + component_instance, desc, public_input, result_check, instance_input, + nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); } // works @@ -192,7 +191,7 @@ void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = tr // for (int i = 0; i < message.size(); ++i) { // std::cout << "message: " << message[i].data << std::endl; // } - + // auto expected_result = padding_function(message, num_bits); // test_keccak_padding_inner diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 5a2a1cf50..2e4f4b213 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -51,7 +51,6 @@ template std::size_t number_bits(typename BlueprintFieldType::value_type value) { - using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; integral_type integral_value = integral_type(value.data); @@ -101,11 +100,10 @@ auto test_keccak_padding_inner(std::vector; + zk::snark::plonk_table_description desc( + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); using ArithmetizationType = - nil::crypto3::zk::snark::plonk_constraint_system; + nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; @@ -144,9 +142,9 @@ auto test_keccak_padding_inner(std::vector {0}, num_blocks, num_bits, range_check_input, limit_permutation_column); - nil::crypto3::test_component( - component_instance, public_input, result_check, instance_input, - nil::crypto3::detail::connectedness_check_type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); + nil::crypto3::test_component( + component_instance, desc, public_input, result_check, instance_input, + nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); } // works diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 388e6006a..77c5342bc 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -49,8 +49,8 @@ #include "../../test_plonk_component.hpp" -const int r[5][5] = {{0, 36, 3, 41, 18}, - {1, 44, 10, 45, 2}, +const int r[5][5] = {{0, 36, 3, 41, 18}, + {1, 44, 10, 45, 2}, {62, 6, 43, 15, 61}, {28, 55, 25, 21, 56}, {27, 20, 39, 8, 14}}; @@ -162,16 +162,13 @@ auto test_keccak_round_inner(std::array; - using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + zk::snark::plonk_table_description desc( + WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; using component_type = nil::blueprint::components::keccak_round; using var = nil::crypto3::zk::snark::plonk_variable; @@ -212,19 +209,18 @@ auto test_keccak_round_inner(std::array{0}, std::array{0}, + component_type(witnesses, std::array{0}, std::array{0}, xor_with_mes, last_round_call, last_perm_col); - nil::crypto3::test_component( - boost::get(component_instance), public_input, result_check, instance_input, - nil::crypto3::detail::connectedness_check_type::STRONG, + nil::crypto3::test_component( + boost::get(component_instance), desc, public_input, result_check, instance_input, + nil::blueprint::connectedness_check_type::type::STRONG, xor_with_mes, last_round_call, last_perm_col); } template void test_keccak_round_not_random() { using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //call 1 @@ -249,9 +245,9 @@ void test_keccak_round_not_random() { inner_state = expected_result; RC = to_sparse(value_type(0x800000000000808a)); expected_result = {9236970796698600460, 4092250545529553158, 626057523912327425, 2306538108895626371, 1173341635645358336, - 1293304092434976, 1266393375296193026, 4612686711565066480, 3572814934320349200, 6918386853474468034, - 181437471070544, 17451689225912448, 14123431978033217603, 9612137362626578, 14131171423402623105, - 109225863298950544, 4469910934709993472, 291608492588557700, 4143342752895270928, 722898250671538564, + 1293304092434976, 1266393375296193026, 4612686711565066480, 3572814934320349200, 6918386853474468034, + 181437471070544, 17451689225912448, 14123431978033217603, 9612137362626578, 14131171423402623105, + 109225863298950544, 4469910934709993472, 291608492588557700, 4143342752895270928, 722898250671538564, 9260980282462904729, 14339470011802853602, 37581858268459548, 4683770000893804961, 432358761588732518}; for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); @@ -303,18 +299,18 @@ void test_keccak_round_not_random() { // call 12 inner_state = {8317352591327817587, 3347101423491892088, 13812284588227636790, 6672945709382097013, 14828349229463845968, - 17723229868831098326, 17401130588186959855, 16478565068789518457, 6492452647977334912, 11881899180789479218, - 16234817029224417455, 15219752985751753243, 7353976000907867650, 14188031598247865105, 15212311666827251122, - 11629652489896499652, 9435989968869629838, 3918343313233240239, 7628695717460153542, 12309003921403265649, + 17723229868831098326, 17401130588186959855, 16478565068789518457, 6492452647977334912, 11881899180789479218, + 16234817029224417455, 15219752985751753243, 7353976000907867650, 14188031598247865105, 15212311666827251122, + 11629652489896499652, 9435989968869629838, 3918343313233240239, 7628695717460153542, 12309003921403265649, 345338872853187944, 12040357248728011954, 3576113714317971609, 6768822272106030756, 5816751084285246094}; for (int i = 0; i < 25; ++i) { inner_state[i] = to_sparse(inner_state[i]); } RC = to_sparse(value_type(0x8000000a)); - expected_result = {4650443609753860646, 9514407034135748299, 1325603491995511509, 5593257647634540243, 4316689694591141959, - 7056436588513633967, 3922974518795920519, 9361284003398536963, 12348570714043139801, 9410505497913992340, - 3614675582850630850, 6265106893083717952, 15812212848177019826, 5971330993120196744, 10998285978683370913, - 11166777828240479175, 7385351289822635840, 13873470266315090419, 6746683412968993695, 16204117485081817578, + expected_result = {4650443609753860646, 9514407034135748299, 1325603491995511509, 5593257647634540243, 4316689694591141959, + 7056436588513633967, 3922974518795920519, 9361284003398536963, 12348570714043139801, 9410505497913992340, + 3614675582850630850, 6265106893083717952, 15812212848177019826, 5971330993120196744, 10998285978683370913, + 11166777828240479175, 7385351289822635840, 13873470266315090419, 6746683412968993695, 16204117485081817578, 8627448812002334210, 5809981248579074143, 17919282347891220598, 3921880343594863541, 4864618403575458388}; for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); @@ -324,18 +320,18 @@ void test_keccak_round_not_random() { // call 24 inner_state = {1021834983209491063, 271587765569717919, 4776059245685303294, 6929972956618907976, 15632760037079799599, - 335373011243745427, 4458191160998101431, 1054086133152375554, 2747216341432570284, 16716089959809353091, - 18427037088977732910, 8502882582543089190, 15262916258997799331, 1649067881221390653, 16305756012321036251, - 6396788823285448910, 16280709970257755463, 968684198036765735, 17453107891981340679, 14208300252181521039, + 335373011243745427, 4458191160998101431, 1054086133152375554, 2747216341432570284, 16716089959809353091, + 18427037088977732910, 8502882582543089190, 15262916258997799331, 1649067881221390653, 16305756012321036251, + 6396788823285448910, 16280709970257755463, 968684198036765735, 17453107891981340679, 14208300252181521039, 8344225276973693085, 15466940913106191879, 9691424745450112199, 11326521537916162858, 14617465633943149704}; for (int i = 0; i < 25; ++i) { inner_state[i] = to_sparse(inner_state[i]); } RC = to_sparse(value_type(0x8000000080008008)); expected_result = {17376452488221285863, 9571781953733019530, 15391093639620504046, 13624874521033984333, 10027350355371872343, - 18417369716475457492, 10448040663659726788, 10113917136857017974, 12479658147685402012, 3500241080921619556, - 16959053435453822517, 12224711289652453635, 9342009439668884831, 4879704952849025062, 140226327413610143, - 424854978622500449, 7259519967065370866, 7004910057750291985, 13293599522548616907, 10105770293752443592, + 18417369716475457492, 10448040663659726788, 10113917136857017974, 12479658147685402012, 3500241080921619556, + 16959053435453822517, 12224711289652453635, 9342009439668884831, 4879704952849025062, 140226327413610143, + 424854978622500449, 7259519967065370866, 7004910057750291985, 13293599522548616907, 10105770293752443592, 10668034807192757780, 1747952066141424100, 1654286879329379778, 8500057116360352059, 16929593379567477321}; for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); @@ -369,7 +365,7 @@ void test_keccak_round_random() { } auto random_value = integral_type(dis(gen)) & mask; RC = to_sparse(value_type(random_value)); - + auto expected_result = sparse_round_function(inner_state, padded_message_chunk, RC); test_keccak_round_inner @@ -380,9 +376,9 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_not_random(); - // test_keccak_round_not_random(); - // xor_with_mes, last_round_call + // test_keccak_round_not_random(); + // test_keccak_round_not_random(); + // xor_with_mes, last_round_call // test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index 5af505930..c0ad265ce 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -350,7 +350,7 @@ namespace nil { // How to define it from crypto3 cmake? //#define BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED -#ifdef BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED +#ifdef BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED2 using circuit_params = typename nil::crypto3::zk::snark::placeholder_circuit_params; using lpc_params_type = typename nil::crypto3::zk::commitments::list_polynomial_commitment_params< Hash, Hash, 2 From ca2c624d02c96cf821ba9661b48d197e6d0274c0 Mon Sep 17 00:00:00 2001 From: Valeh Date: Tue, 30 Apr 2024 11:41:37 +0300 Subject: [PATCH 34/48] keccak component updates --- .../hashes/keccak/keccak_component.hpp | 889 +++++++----- .../hashes/keccak/keccak_padding.hpp | 27 +- .../components/hashes/keccak/keccak_round.hpp | 1255 ++++++++++------- test/hashes/plonk/keccak.cpp | 406 +++++- test/hashes/plonk/keccak_padding.cpp | 77 +- test/hashes/plonk/keccak_round.cpp | 21 +- 6 files changed, 1763 insertions(+), 912 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index b700db929..f5a98159e 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova -// +// 2024 Valeh Farzaliyev // MIT License // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -34,7 +34,7 @@ #include #include -// #include +#include #include namespace nil { @@ -44,8 +44,8 @@ namespace nil { class keccak; template - class keccak> : - public plonk_component { + class keccak> + : public plonk_component { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; @@ -58,13 +58,14 @@ namespace nil { public: using var = typename component_type::var; - // using round_component_type = keccak_round>; - // round_component_type round_true_true; - // std::vector rounds_true_false; - // std::vector rounds_false_false; - // std::vector rounds; + using round_component_type = + keccak_round>; + round_component_type round_tt; + round_component_type round_tf; + round_component_type round_ff; - using padding_component_type = keccak_padding>; + using padding_component_type = + keccak_padding>; padding_component_type padding; using manifest_type = nil::blueprint::plonk_component_manifest; @@ -78,12 +79,15 @@ namespace nil { std::size_t limit_permutation_column; gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, - bool range_check_input_, std::size_t limit_permutation_column_) - : witness_amount(std::min(witness_amount_, clamp)), num_blocks(num_blocks_), num_bits(num_bits_), - range_check_input(range_check_input_), limit_permutation_column(limit_permutation_column_) {} + bool range_check_input_, std::size_t limit_permutation_column_) : + witness_amount(std::min(witness_amount_, clamp)), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), + limit_permutation_column(limit_permutation_column_) { + } std::uint32_t gates_amount() const override { - return get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + return get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input, + limit_permutation_column); } }; @@ -94,33 +98,26 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column) { std::size_t num_round_calls = calculate_num_round_calls(num_blocks); - gate_manifest manifest = - gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)) - .merge_with( - padding_component_type::get_gate_manifest(witness_amount, lookup_column_amount, - num_blocks, num_bits, range_check_input)); - // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, - // true, true)); - // for (std::size_t i = 1; i < num_round_calls; ++i) { - // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, - // true, false)); - // } - // for (std::size_t i = 0; i < num_round_calls; ++i) { - // for (std::size_t j = 0; j < 23; ++j) { - // manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, - // false, false)); - // } - // } + gate_manifest manifest = gate_manifest(gate_manifest_type( + witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)); + + manifest.merge_with(padding_component_type::get_gate_manifest( + witness_amount, lookup_column_amount, num_blocks, num_bits, range_check_input)); + manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + true, true, limit_permutation_column)); + // manifest.merge_with(round_component_type::get_gate_manifest( + // witness_amount, lookup_column_amount, true, false, limit_permutation_column)); + // manifest.merge_with(round_component_type::get_gate_manifest( + // witness_amount, lookup_column_amount, false, false, limit_permutation_column)); return manifest; } static manifest_type get_manifest() { - static manifest_type manifest = manifest_type( - std::shared_ptr( - new manifest_range_param(9, 15)), - false - ).merge_with(padding_component_type::get_manifest()); + static manifest_type manifest = + manifest_type(std::shared_ptr(new manifest_range_param(9, 15)), false) + .merge_with(padding_component_type::get_manifest()) + .merge_with(round_component_type::get_manifest()); return manifest; } @@ -134,37 +131,59 @@ namespace nil { const bool range_check_input; const std::size_t limit_permutation_column = 7; - const std::size_t round_tt_rows = 0; - const std::size_t round_tf_rows = 0; - const std::size_t round_ff_rows = 0; - const std::size_t round_tt_gates = 0; - const std::size_t round_tf_gates = 0; - const std::size_t round_ff_gates = 0; + std::size_t round_tt_rows = 0; + std::size_t round_tf_rows = 0; + std::size_t round_ff_rows = 0; + std::size_t round_tt_gates = 0; + std::size_t round_tf_gates = 0; + std::size_t round_ff_gates = 0; const std::size_t num_round_calls = calculate_num_round_calls(num_blocks); const std::size_t num_configs = 5 + num_blocks + (17 - num_blocks % 17); const std::size_t pack_chunk_size = 8; const std::size_t pack_num_chunks = 8; + const std::size_t unpack_chunk_size = 24; + const std::size_t unpack_num_chunks = 8; const std::size_t pack_cells = 2 * (pack_num_chunks + 1); const std::size_t pack_buff = (this->witness_amount() == 15) * 2; - std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls, limit_permutation_column); - const std::map> gates_configuration_map = - configure_map(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); - const std::vector> gates_configuration = - configure_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); - - const std::size_t rows_amount = - get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, range_check_input, limit_permutation_column); - const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); - - const std::size_t round_constant[24] = {1, 0x8082, 0x800000000000808a, 0x8000000080008000, - 0x808b, 0x80000001, 0x8000000080008081, 0x8000000000008009, - 0x8a, 0x88, 0x80008009, 0x8000000a, - 0x8000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, - 0x8000000000008002, 0x8000000000000080, 0x800a, 0x800000008000000a, - 0x8000000080008081, 0x8000000000008080, 0x80000001, 0x8000000080008008}; + std::vector full_configuration = + configure_all(this->witness_amount(), num_configs, num_round_calls, limit_permutation_column); + const std::map> gates_configuration_map = configure_map( + this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::vector> gates_configuration = configure_gates( + this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, + range_check_input, limit_permutation_column); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, + range_check_input, limit_permutation_column); + + const std::size_t round_constant[24] = {1, + 0x8082, + 0x800000000000808a, + 0x8000000080008000, + 0x808b, + 0x80000001, + 0x8000000080008081, + 0x8000000000008009, + 0x8a, + 0x88, + 0x80008009, + 0x8000000a, + 0x8000808b, + 0x800000000000008b, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x800a, + 0x800000008000000a, + 0x8000000080008081, + 0x8000000000008080, + 0x80000001, + 0x8000000080008008}; struct input_type { std::vector message; @@ -181,35 +200,33 @@ namespace nil { std::array final_inner_state; result_type(const keccak &component, std::size_t start_row_index) { + auto offset = + component.full_configuration[component.num_configs - 1].last_coordinate.row + + (component.full_configuration[component.num_configs - 1].last_coordinate.column > 0); for (std::size_t i = 0; i < 5; ++i) { - final_inner_state[i] = var(component.W(component.full_configuration[component.num_configs - 5 + i].copy_from.column), - start_row_index + component.full_configuration[component.num_configs - 5 + i].copy_from.row, false); + final_inner_state[i] = + var(component.W( + component.full_configuration[component.num_configs - 5 + i].copy_from.column), + start_row_index + component.rows_amount - offset + + component.full_configuration[component.num_configs - 5 + i].copy_from.row, + false); } } std::vector all_vars() const { - return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], final_inner_state[4]}; + return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], + final_inner_state[4]}; } }; static std::size_t get_rows_amount_round_tt() { return 0; } - // std::vector create_rounds() { - // std::vector rounds; - // rounds.push_back(round_true_true); - // rounds.insert(rounds.end(), rounds_false_false.begin(), rounds_false_false.begin() + 23); - // for (std::size_t i = 1; i < num_round_calls; ++i) { - // rounds.push_back(rounds_true_false[i - 1]); - // rounds.insert(rounds.end(), rounds_false_false.begin() + i * 23, rounds_false_false.begin() + (i + 1) * 23); - // } - // return rounds; - // } - - integral_type pack(const integral_type& const_input) const { + + integral_type pack(const integral_type &const_input) const { integral_type input = const_input; integral_type sparse_res = 0; integral_type power = 1; while (input > 0) { - auto bit = input % 2; + auto bit = input & 1; sparse_res += bit * power; power <<= 3; input >>= 1; @@ -217,14 +234,13 @@ namespace nil { return sparse_res; } - integral_type unpack(const integral_type& const_sparse_input) const { + integral_type unpack(const integral_type &const_sparse_input) const { integral_type sparse_input = const_sparse_input; integral_type res = 0; integral_type power = 1; integral_type mask = (integral_type(1) << 3) - 1; while (sparse_input > 0) { auto bit = sparse_input & mask; - std::cout << "bit: " << bit << std::endl; BOOST_ASSERT(bit * (1 - bit) == 0); res += bit * power; power <<= 1; @@ -233,15 +249,15 @@ namespace nil { return res; } - static configuration configure_pack_unpack(std::size_t witness_amount, std::size_t row, std::size_t column, - std::size_t pack_cells, std::size_t pack_num_chunks, std::size_t pack_buff, - std::size_t limit_permutation_column) { + static configuration configure_pack_unpack(std::size_t witness_amount, std::size_t row, + std::size_t column, std::size_t pack_cells, + std::size_t pack_num_chunks, std::size_t pack_buff, + std::size_t limit_permutation_column) { // regular constraints: // input = input0 + input1 * 2^chunk_size + ... + inputk * 2^(k*chunk_size) // output = output0 + output1 * 2^chunk_size + ... + outputk * 2^(k*chunk_size) - std::size_t last_row = row, - last_column = column; + std::size_t last_row = row, last_column = column; std::pair first_coordinate = {row, column}; std::vector> copy_from; @@ -250,8 +266,8 @@ namespace nil { if (1 + column > limit_permutation_column) { copy_from.push_back({last_row + 1, 0}); } else { - copy_from.push_back({last_row + (last_column / witness_amount), - (last_column++) % witness_amount}); + copy_from.push_back( + {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); } std::pair cell_copy_to; @@ -268,20 +284,20 @@ namespace nil { cells.push_back({row, i}); } std::size_t cells_left = pack_cells - witness_amount + column; - std::size_t cur_row = row + 1, - cur_column = 1; + std::size_t cur_row = row + 1, cur_column = 1; while (cur_column < cells_left) { - if (cur_column % witness_amount == cell_copy_to.second && (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { + if (cur_column % witness_amount == cell_copy_to.second && + (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { cur_column++; continue; } cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { - std::size_t cur_row = row, - cur_column = column + 1; + std::size_t cur_row = row, cur_column = column + 1; while (cur_column - column < pack_cells) { - if (cur_column % witness_amount == cell_copy_to.second && (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { + if (cur_column % witness_amount == cell_copy_to.second && + (cur_row + (cur_column / witness_amount) == cell_copy_to.first)) { cur_column++; continue; } @@ -290,8 +306,8 @@ namespace nil { } std::size_t cell_index = 0; - std::vector>> - lookups(pack_num_chunks, std::vector>()); + std::vector>> lookups( + pack_num_chunks, std::vector>()); constraints.push_back({copy_from[0]}); constraints.push_back({cell_copy_to}); @@ -306,24 +322,25 @@ namespace nil { last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; - return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, cell_copy_to); + return configuration(first_coordinate, {last_row, last_column}, copy_from, constraints, lookups, + cell_copy_to); } - static std::vector configure_all(std::size_t witness_amount, const std::size_t num_configs, - const std::size_t num_round_calls, std::size_t limit_permutation_column) { + static std::vector configure_all(std::size_t witness_amount, + const std::size_t num_configs, + const std::size_t num_round_calls, + std::size_t limit_permutation_column) { std::vector result; std::size_t pack_num_chunks = 8; std::size_t pack_cells = 2 * (pack_num_chunks + 1); std::size_t pack_buff = (witness_amount == 15) * 2; - std::size_t row = 0, - column = 0; + std::size_t row = 0, column = 0; for (std::size_t index = 0; index < num_round_calls * 17; ++index) { // to sparse representation - result.push_back(configure_pack_unpack(witness_amount, row, column, - pack_cells, pack_num_chunks, pack_buff, - limit_permutation_column)); + result.push_back(configure_pack_unpack(witness_amount, row, column, pack_cells, pack_num_chunks, + pack_buff, limit_permutation_column)); row = result[index].last_coordinate.row; column = result[index].last_coordinate.column; } @@ -332,19 +349,27 @@ namespace nil { row++; } - //rounds - for (std::size_t index = 0; index < num_round_calls; ++index) { - // for (std::size_t i = 0; i < 24; ++i) { - // row += rounds[index * 24 + i].rows_amount; - // } - } + // rounds + // for (std::size_t index = 0; index < num_round_calls; ++index) { + // for (std::size_t i = 0; i < 24; ++i) { + // if (index == num_round_calls - 1 && i == 0) { + // row += round_component_type::get_rows_amount(witness_amount, 0, true, true, + // limit_permutation_column); + // } else if (i == 0) { + // row += round_component_type::get_rows_amount(witness_amount, 0, true, false, + // limit_permutation_column); + // } else { + // row += round_component_type::get_rows_amount(witness_amount, 0, false, false, + // limit_permutation_column); + // } + // } + // } row = 0; // from sparse representation for (std::size_t i = 0; i < 5; ++i) { - result.push_back(configure_pack_unpack(witness_amount, row, column, - pack_cells, pack_num_chunks, pack_buff, - limit_permutation_column)); + result.push_back(configure_pack_unpack(witness_amount, row, column, pack_cells, pack_num_chunks, + pack_buff, limit_permutation_column)); row = result.back().last_coordinate.row; column = result.back().last_coordinate.column; } @@ -353,14 +378,17 @@ namespace nil { // for (std::size_t i = 0; i < result.size(); ++i) { // auto cur_config = result[i]; // std::cout << "config: " << i << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; - // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << + // " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << + // std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << + // std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << + // std::endl; // } // for (int j = 0; j < cur_config.constraints.size(); ++j) { // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // std::cout << cur_config.constraints[j][k].row << " " << + // cur_config.constraints[j][k].column << ", "; // } // std::cout << std::endl; // } @@ -369,18 +397,19 @@ namespace nil { return result; } - static std::map> configure_map(std::size_t witness_amount, - std::size_t num_blocks, - std::size_t num_bits, - bool range_check_input, - std::size_t limit_permutation_column) { + static std::map> + configure_map(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { - auto config = configure_all(witness_amount, num_blocks, num_bits, limit_permutation_column); - std::size_t row = 0, - column = 0; - std::size_t row_shift = 0;//padding_component_type::get_rows_amount(witness_amount, 0, - // num_blocks, num_bits, range_check_input, - // limit_permutation_column); + std::size_t num_configs = 5 + num_blocks + (17 - num_blocks % 17); + std::size_t num_round_calls = calculate_num_round_calls(num_blocks); + auto config = configure_all(witness_amount, num_configs, num_round_calls, limit_permutation_column); + std::size_t row = 0, column = 0; + std::size_t row_shift = 0; // padding_component_type::get_rows_amount( + // witness_amount, 0, num_blocks, num_bits, range_check_input, limit_permutation_column); std::map> config_map; @@ -393,7 +422,7 @@ namespace nil { config_map[column] = {row + row_shift}; } } - row_shift += config[config.size() - 6].last_coordinate.row; + // row_shift += config[config.size() - 6].last_coordinate.row; for (std::size_t i = config.size() - 5; i < config.size(); ++i) { row = config[i].first_coordinate.row; column = config[i].first_coordinate.column + 10 * witness_amount; @@ -417,20 +446,23 @@ namespace nil { } static std::vector> configure_gates(std::size_t witness_amount, - std::size_t num_blocks, - std::size_t num_bits, - bool range_check_input, - std::size_t limit_permutation_column) { + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { std::vector> result; - auto gates_configuration_map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + auto gates_configuration_map = configure_map(witness_amount, num_blocks, num_bits, + range_check_input, limit_permutation_column); std::size_t pack_num_chunks = 8; std::size_t num_cells = 2 * (pack_num_chunks + 1); std::size_t buff = (witness_amount == 15) * 2; - for (auto config: gates_configuration_map) { - if (config.first >= 10 * witness_amount) continue; - configuration cur_config = configure_pack_unpack(witness_amount, 0, config.first, - num_cells, pack_num_chunks, buff, limit_permutation_column); + for (auto config : gates_configuration_map) { + if (config.first >= 10 * witness_amount) + continue; + configuration cur_config = + configure_pack_unpack(witness_amount, 0, config.first, num_cells, pack_num_chunks, buff, + limit_permutation_column); std::vector> pairs; for (auto constr : cur_config.constraints) { std::size_t min = constr[0].row; @@ -447,7 +479,8 @@ namespace nil { std::size_t cur_constr = 0; while (cur_constr < pairs.size()) { configuration c; - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { c.constraints.push_back(cur_config.constraints[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; @@ -458,132 +491,134 @@ namespace nil { result.push_back(cur_result); } - for (std::size_t i = 0; i < result.size(); ++i) { - std::cout << "config " << i << ":\n"; - for (auto cur_config : result[i]) { - std::cout << "gate:\n"; - for (int j = 0; j < cur_config.constraints.size(); ++j) { - for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - } - std::cout << std::endl; - } - } - } + // for (std::size_t i = 0; i < result.size(); ++i) { + // std::cout << "config " << i << ":\n"; + // for (auto cur_config : result[i]) { + // std::cout << "gate:\n"; + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << + // cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + // } return result; } static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, - std::size_t num_blocks, std::size_t num_bits, bool range_check_input, - std::size_t limit_permutation_column) { + std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + std::size_t limit_permutation_column) { std::size_t num_round_calls = calculate_num_round_calls(num_blocks); - std::size_t res = padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, - num_blocks, num_bits, range_check_input, - limit_permutation_column); - // + round_tt_rows - // + round_tf_rows * (num_round_calls - 1) - // + round_ff_rows * num_round_calls * 23; + std::size_t res = + padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, num_blocks, + num_bits, range_check_input, limit_permutation_column); + // + round_tt_rows + for (std::size_t i = 0; i < num_round_calls; i++) { + if (i == num_round_calls - 1) { + res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, true, + true, limit_permutation_column); + } else { + res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, true, + false, limit_permutation_column); + } + for (std::size_t j = 1; j < 24; ++j) { + res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, false, + false, limit_permutation_column); + } + } + auto config = configure_all(witness_amount, num_blocks, num_round_calls, limit_permutation_column); auto index = config.size() - 1; res += config[index].last_coordinate.row + (config[index].last_coordinate.column > 0); res += config[index - 5].last_coordinate.row + (config[index - 5].last_coordinate.column > 0); return res; } - static std::size_t get_gates_amount(std::size_t witness_amount, - std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + static std::size_t get_gates_amount(std::size_t witness_amount, std::size_t num_blocks, + std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { std::size_t res = 0; - auto config = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + auto config = configure_map(witness_amount, num_blocks, num_bits, range_check_input, + limit_permutation_column); for (auto c : config) { - if (c.first >= 10 * witness_amount) res++; - else res += 2; + if (c.first >= 10 * witness_amount) + res += 2; + else + res += 2; } return res; } - std::map component_lookup_tables(){ + std::map component_lookup_tables() { std::map lookup_tables; - lookup_tables["keccak_pack_table/full"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_sign_bit_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_sign_bit_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize3_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize4_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize6_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_chi_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/range_check_sparse"] = 0; // REQUIRED_TABLE return lookup_tables; } template keccak(WitnessContainerType witness, ConstantContainerType constant, - PublicInputContainerType public_input, - std::size_t num_blocks_, - std::size_t num_bits_, - bool range_check_input_, - std::size_t lpc_ = 7) : + PublicInputContainerType public_input, std::size_t num_blocks_, std::size_t num_bits_, + bool range_check_input_, std::size_t lpc_ = 7) : component_type(witness, constant, public_input, get_manifest()), - num_blocks(num_blocks_), - num_bits(num_bits_), - range_check_input(range_check_input_), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), limit_permutation_column(lpc_), padding(witness, constant, public_input, num_blocks_, num_bits_, range_check_input_, lpc_), - num_round_calls(calculate_num_round_calls(num_blocks_)) {}; - // { - // round_true_true = round_component_type(witness, constant, public_input, true, true, lpc_), - // for (std::size_t i = 1; i < num_round_calls; ++i) { - // rounds_true_false.push_back(round_component_type(witness, constant, public_input, true, false, lpc_)); - // } - // for (std::size_t i = 0; i < num_round_calls; ++i) { - // for (std::size_t j = 0; j < 23; ++j) { - // rounds_false_false.push_back(round_component_type(witness, constant, public_input, false, false, lpc_)); - // } - // } - // round_tt_rows = round_true_true.rows_amount; - // round_tf_rows = rounds_true_false[0].rows_amount; - // round_ff_rows = rounds_false_false[0].rows_amount; - // round_tt_gates = round_true_true.gates_amount; - // round_tf_gates = rounds_true_false[0].gates_amount; - // round_ff_gates = rounds_false_false[0].gates_amount; - // }; - - keccak( - std::initializer_list witnesses, - std::initializer_list constants, - std::initializer_list public_inputs, - std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_, std::size_t lpc_ = 7) : - component_type(witnesses, constants, public_inputs), - num_blocks(num_blocks_), - num_bits(num_bits_), - range_check_input(range_check_input_), - limit_permutation_column(lpc_), - padding(witnesses, constants, public_inputs, num_blocks_, num_bits_, range_check_input_, lpc_), - num_round_calls(calculate_num_round_calls(num_blocks_)) {}; - // round_true_true(witness, constant, public_input, true, true, lpc_), - // { - // for (std::size_t i = 1; i < num_round_calls; ++i) { - // rounds_true_false.push_back(round_component_type(witness, constant, public_input, true, false, lpc_)); - // } - // for (std::size_t i = 0; i < num_round_calls; ++i) { - // for (std::size_t j = 0; j < 23; ++j) { - // rounds_false_false.push_back(round_component_type(witness, constant, public_input, false, false, lpc_)); - // } - // } - // }; + num_round_calls(calculate_num_round_calls(num_blocks_)), + round_tt(witness, constant, public_input, true, true, lpc_), + round_tf(witness, constant, public_input, true, false, lpc_), + round_ff(witness, constant, public_input, false, false, lpc_) { + + round_tt_rows = round_tt.rows_amount; + round_tf_rows = round_tf.rows_amount; + round_ff_rows = round_ff.rows_amount; + round_tt_gates = round_tt.gates_amount; + round_tf_gates = round_tf.gates_amount; + round_ff_gates = round_ff.gates_amount; + }; + keccak(std::initializer_list witnesses, + std::initializer_list constants, + std::initializer_list + public_inputs, + std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_, std::size_t lpc_ = 7) : + component_type(witnesses, constants, public_inputs), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), + limit_permutation_column(lpc_), + padding(witnesses, constants, public_inputs, num_blocks_, num_bits_, range_check_input_, lpc_), + num_round_calls(calculate_num_round_calls(num_blocks_)), + round_tt(witnesses, constants, public_inputs, true, true, lpc_), + round_tf(witnesses, constants, public_inputs, true, false, lpc_), + round_ff(witnesses, constants, public_inputs, false, false, lpc_) { + + round_tt_rows = round_tt.rows_amount; + round_tf_rows = round_tf.rows_amount; + round_ff_rows = round_ff.rows_amount; + round_tt_gates = round_tt.gates_amount; + round_tf_gates = round_tf.gates_amount; + round_ff_gates = round_ff.gates_amount; + }; }; template - using keccak_component = - keccak>; + using keccak_component = keccak>; template std::vector generate_gates( - const keccak_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_component::input_type - &instance_input, + const keccak_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_component::input_type &instance_input, const typename lookup_library::left_reserved_type lookup_tables_indices) { using component_type = keccak_component; @@ -591,7 +626,8 @@ namespace nil { using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; - using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; + using lookup_gate_type = + typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -604,25 +640,47 @@ namespace nil { std::vector lookup_constraints_0; std::vector lookup_constraints_1; auto conf = config[0]; - constraint_type constraint_0 = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); - constraint_type constraint_1 = var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row)); + + // pack gate + constraint_type constraint_0 = + var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); + constraint_type constraint_1 = + var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row)); + + constraint_type constraint_2 = + var(conf.constraints[1][0].column, static_cast(conf.constraints[1][0].row)); + constraint_type constraint_3 = + var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); for (std::size_t i = 1; i < 9; ++i) { - constraint_0 -= var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) - * (integral_type(1) << ((i-1) * 8)); - constraint_1 -= var(conf.constraints[1][i].column, static_cast(conf.constraints[1][i].row)) - * (integral_type(1) << ((i-1) * 24)); + constraint_0 -= + var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) * + (integral_type(1) << ((i - 1) * 8)); + constraint_1 -= + var(conf.constraints[1][i].column, static_cast(conf.constraints[1][i].row)) * + (integral_type(1) << ((8 - i) * 24)); + constraint_2 -= + var(conf.constraints[1][i].column, static_cast(conf.constraints[1][i].row)) * + (integral_type(1) << ((i - 1) * 8)); + constraint_3 -= + var(conf.constraints[0][i].column, static_cast(conf.constraints[0][i].row)) * + (integral_type(1) << ((i - 1) * 24)); lookup_constraints_0.push_back({lookup_tables_indices.at("keccak_pack_table/full"), - {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row)), - var(component.W(conf.constraints[1][i].column), static_cast(conf.constraints[1][i].row))}}); + {var(component.W(conf.constraints[0][i].column), + static_cast(conf.constraints[0][i].row)), + var(component.W(conf.constraints[1][i].column), + static_cast(conf.constraints[1][i].row))}}); lookup_constraints_1.push_back({lookup_tables_indices.at("keccak_pack_table/full"), - {var(component.W(conf.constraints[1][i].column), static_cast(conf.constraints[1][i].row)), - var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); + {var(component.W(conf.constraints[1][i].column), + static_cast(conf.constraints[1][i].row)), + var(component.W(conf.constraints[0][i].column), + static_cast(conf.constraints[0][i].row))}}); } selector_indexes.push_back(bp.add_gate({constraint_0, constraint_1})); + selector_indexes.push_back(bp.add_gate({constraint_2})); gate_index++; - // selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); - // selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); - // lookup_gate_index += 2; + selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); + selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); + lookup_gate_index += 2; } return selector_indexes; @@ -630,38 +688,111 @@ namespace nil { template void generate_copy_constraints( - const keccak_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_component::input_type - &instance_input, + const keccak_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_component; + using padding_type = typename component_type::padding_component_type; + using round_type = typename component_type::round_component_type; using var = typename component_type::var; - std::uint32_t row = start_row_index; + std::uint32_t cur_row = start_row_index; + + std::size_t config_index = 0; + std::size_t prev_index = 0; + auto config = component.full_configuration; + + auto padded_message = + typename padding_type::result_type(component.padding, start_row_index).padded_message; + cur_row += component.padding.rows_amount; + + for (std::size_t i = 0; i < padded_message.size(); i++) { + bp.add_copy_constraint( + {padded_message[i], + var(component.W(config[config_index].copy_to[0].column), + static_cast(config[config_index].copy_to[0].row + cur_row), false)}); + config_index++; + } + cur_row += config[config_index - 1].last_coordinate.row + + (config[config_index - 1].last_coordinate.column > 0); + + std::array inner_state; + auto prev_row = cur_row; + + auto gate_map_tf = component.round_tf.gates_configuration_map; + std::vector rotate_rows_tf; + for (auto g : gate_map_tf) { + if (g.first.first == 7) { + rotate_rows_tf.insert(rotate_rows_tf.end(), g.second.begin(), g.second.end()); + } + } + std::sort(rotate_rows_tf.begin(), rotate_rows_tf.end()); + + auto gate_map_ff = component.round_ff.gates_configuration_map; + std::vector rotate_rows_ff; + for (auto g : gate_map_ff) { + if (g.first.first == 7) { + rotate_rows_ff.insert(rotate_rows_ff.end(), g.second.begin(), g.second.end()); + } + } + std::sort(rotate_rows_ff.begin(), rotate_rows_ff.end()); + + for (int i = 0; i < component.num_round_calls; i++) { + for (int j = 0; j < 24; j++) { + // if (i + j != 0) { + // std::cout << "prev: " << prev_row << " vs curr" << cur_row << std::endl; + // for (int k = 0; k < 5; k++) { + // auto ind1 = (j == 1) ? rotate_rows_tf[k] : rotate_rows_ff[k]; + // auto ind2 = rotate_rows_ff[k]; + // std::cout << ind1 << " , " << ind2 << std::endl; + // std::cout + // << var_value(assignment, var(component.C(0), prev_row + ind1, false)).data << + // " vs " + // << var_value(assignment, var(component.C(0), cur_row + ind2, false)).data << + // std::endl; + // bp.add_copy_constraint({var(component.C(0), prev_row + ind1, false), + // var(component.C(0), cur_row + ind2, false)}); + // } + // prev_row = cur_row; + // } + if (i == component.num_round_calls - 1 && j == 0) { + cur_row += component.round_tt.rows_amount; + } else if (j == 0) { + cur_row += component.round_tf.rows_amount; + } else { + inner_state = typename round_type::result_type(component.round_ff, cur_row).inner_state; + cur_row += component.round_ff.rows_amount; + } + } + } + + for (std::size_t i = 0; i < 5; i++) { + bp.add_copy_constraint( + {inner_state[i], var(component.W(config[config_index].copy_to[0].column), + static_cast(config[config_index].copy_to[0].row + cur_row), false)}); + config_index++; + } + cur_row += config[config_index - 1].last_coordinate.row + + (config[config_index - 1].last_coordinate.column > 0); + // BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); } template - typename keccak_component::result_type - generate_circuit( - const keccak_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_component::input_type - &instance_input, + typename keccak_component::result_type generate_circuit( + const keccak_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_component; using padding_type = typename component_type::padding_component_type; + using round_type = typename component_type::round_component_type; + using var = typename component_type::var; generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); std::size_t row = start_row_index; @@ -672,82 +803,128 @@ namespace nil { } std::vector zero_column = {0}; - padding_type padding_component_instance(witnesses, zero_column, zero_column, - component.num_blocks, component.num_bits, - component.range_check_input, + padding_type padding_component_instance(witnesses, zero_column, zero_column, component.num_blocks, + component.num_bits, component.range_check_input, component.limit_permutation_column); typename padding_type::input_type padding_input = {instance_input.message}; - typename padding_type::result_type padding_result = generate_circuit(padding_component_instance, bp, assignment, padding_input, row); + typename padding_type::result_type padding_result = + generate_circuit(padding_component_instance, bp, assignment, padding_input, row); row += padding_component_instance.rows_amount; - auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); + auto selector_indexes = + generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); auto config_map = component.gates_configuration_map; std::size_t sel_ind = 0; for (auto config : config_map) { if (config.first < component.witnesses) { for (auto gate_row : config.second) { - // std::cout << "enabling: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 1] << std::endl; + // std::cout << "enabling: " << selector_indexes[sel_ind] << " " + // << selector_indexes[sel_ind + 1] << " at " << gate_row + row << std::endl; assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); - // assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + row); + assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); } - // std::cout << std::endl; + std::cout << std::endl; sel_ind += 1; } } - sel_ind = 0; + + std::size_t config_index = 0; + std::vector sparse_padded_message_coords(padding_result.padded_message.size()); + for (std::size_t index = 0; index < padding_result.padded_message.size(); index++) { + auto cur_config = component.full_configuration[config_index]; + sparse_padded_message_coords[index] = var(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + row, false); + config_index++; + } + + row += component.full_configuration[config_index - 1].last_coordinate.row + + (component.full_configuration[config_index - 1].last_coordinate.column > 0); + + // round circuits + std::array inner_state; + for (std::uint32_t i = 0; i < 25; i++) { + inner_state[i] = var(component.C(0), start_row_index, false, var::column_type::constant); + } + std::array pmc; + std::size_t offset = 0; + for (std::size_t i = 0; i < component.num_round_calls; ++i) { + std::copy(sparse_padded_message_coords.begin() + offset, + sparse_padded_message_coords.begin() + offset + 17, + pmc.begin()); + + for (std::size_t j = 0; j < 24; ++j) { + typename round_type::input_type round_input = { + inner_state, pmc, + var(component.C(0), start_row_index + j + 4, false, var::column_type::constant)}; + if (i == component.num_round_calls - 1 && j == 0) { + typename round_type::result_type round_result = + generate_circuit(component.round_tt, bp, assignment, round_input, row); + inner_state = round_result.inner_state; + row += component.round_tt.rows_amount; + } else if (j == 0) { + typename round_type::result_type round_result = + generate_circuit(component.round_tf, bp, assignment, round_input, row); + inner_state = round_result.inner_state; + row += component.round_tf.rows_amount; + } else { + typename round_type::result_type round_result = + generate_circuit(component.round_ff, bp, assignment, round_input, row); + inner_state = round_result.inner_state; + row += component.round_ff.rows_amount; + } + } + offset += 17; + } + + std::cout << "after rounds row: " << row << std::endl; + // sel_ind = 0; for (auto config : config_map) { if (config.first >= 10 * component.witnesses) { for (auto gate_row : config.second) { - // std::cout << "enabling2: " << selector_indexes[sel_ind] << " " << selector_indexes[sel_ind + 2] << std::endl; + // std::cout << "enabling2: " << selector_indexes[sel_ind] << " " + // << selector_indexes[sel_ind + 2] << " at " << gate_row + row << std::endl; assignment.enable_selector(selector_indexes[sel_ind], gate_row + row); - // assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); + assignment.enable_selector(selector_indexes[sel_ind + 2], gate_row + row); } - // std::cout << std::endl; + std::cout << std::endl; sel_ind += 1; } } - using component_type = keccak_component; - using var = typename component_type::var; - generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); return typename component_type::result_type(component, start_row_index); } template - typename keccak_component::result_type - generate_assignments( - const keccak_component - &component, - assignment> - &assignment, - const typename keccak_component::input_type - &instance_input, + typename keccak_component::result_type generate_assignments( + const keccak_component &component, + assignment> &assignment, + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { std::size_t cur_row = start_row_index; using component_type = keccak_component; + using round_type = typename component_type::round_component_type; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using var = typename component_type::var; - std::vector padded_message = generate_assignments(component.padding, assignment, - {instance_input.message}, cur_row).padded_message; + std::vector padded_message = + generate_assignments(component.padding, assignment, {instance_input.message}, cur_row) + .padded_message; cur_row += component.padding.rows_amount; - // std::cout << "padded_message: " << padded_message.size() << ' ' << component.padding.rows_amount << std::endl; - // std::cout << component.rows_amount << std::endl; // to sparse std::size_t config_index = 0; std::vector sparse_padded_message(padded_message.size()); + std::vector sparse_padded_message_coords(padded_message.size()); for (std::size_t index = 0; index < padded_message.size(); ++index) { value_type regular_value = var_value(assignment, padded_message[index]); integral_type regular = integral_type(regular_value.data); // std::cout << "pad elem: " << regular << std::endl; - integral_type sparse = component.pack(regular); - auto copy_sparse = sparse; + auto sparse = integral_type(0); auto chunk_size = component.pack_chunk_size; auto num_chunks = component.pack_num_chunks; std::vector integral_chunks; @@ -755,51 +932,90 @@ namespace nil { integral_type mask = (integral_type(1) << chunk_size) - 1; integral_type sparse_mask = (integral_type(1) << (chunk_size * 3)) - 1; integral_type power = 1; - // std::cout << "sparse: " << sparse << std::endl; + for (std::size_t j = 0; j < num_chunks; ++j) { integral_chunks.push_back(regular & mask); regular >>= chunk_size; - integral_sparse_chunks.push_back(sparse & sparse_mask); - sparse >>= (chunk_size * 3); - // std::cout << "chunks: " << integral_chunks.back() << " " << integral_sparse_chunks.back() << std::endl; - copy_sparse -= power * integral_sparse_chunks.back(); + integral_sparse_chunks.push_back(component.pack(integral_chunks.back())); + // std::cout << "chunks: " << integral_chunks.back() << " " << integral_sparse_chunks.back() + // << std::endl; + } + for (std::size_t j = 0; j < num_chunks; ++j) { + sparse = sparse + power * integral_sparse_chunks[num_chunks - j - 1]; power <<= (3 * chunk_size); } + // std::cout << "sparse: " << sparse << std::endl; sparse_padded_message[index] = value_type(sparse); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = regular_value; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(sparse); - // std::cout << cur_config.constraints[1][0].column << ' ' << cur_config.constraints[1][0].row + cur_row << std::endl; + assignment.witness(component.W(cur_config.constraints[0][0].column), + cur_config.constraints[0][0].row + cur_row) = regular_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + cur_row) = value_type(sparse); + // std::cout << cur_config.constraints[1][0].column << ' ' << cur_config.constraints[1][0].row + + // cur_row << std::endl; + sparse_padded_message_coords[index] = var(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + cur_row, false); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), + cur_config.constraints[0][j].row + cur_row) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + cur_row) = + value_type(integral_sparse_chunks[j - 1]); } config_index++; } - // std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; - cur_row += component.full_configuration[config_index - 1].last_coordinate.row - + (component.full_configuration[config_index - 1].last_coordinate.column > 0); + + cur_row += component.full_configuration[config_index - 1].last_coordinate.row + + (component.full_configuration[config_index - 1].last_coordinate.column > 0); std::array inner_state; - // for (std::size_t i = 0; i < component.num_round_calls; ++i) { - // for (std::size_t j = 0; j < 24; ++j) { - // auto round_input = typename component_type::round_component_type::input_type(); - // round_input.padded_message_chunk;// = instance_input.message; - // round_input.inner_state = inner_state; - // round_input.round_constant = var(component.C(0), row + i, false, var::column_type::constant); - // inner_state = generate_assignments(component.rounds[i * 24 + j], assignment, round_input, row).inner_state; - // row += component.rounds[i * 24 + j].rows_amount; - // } - // } + for (std::uint32_t i = 0; i < 25; i++) { + inner_state[i] = var(component.C(0), start_row_index, false, var::column_type::constant); + } + + std::size_t offset = 0; + std::array pmc; + for (std::size_t i = 0; i < component.num_round_calls; ++i) { + std::copy(sparse_padded_message_coords.begin() + offset, + sparse_padded_message_coords.begin() + offset + 17, pmc.begin()); + for (auto &el : pmc) { + std::cout << component.unpack(integral_type(var_value(assignment, el).data)) << ","; + } + std::cout << std::endl; + + for (std::size_t j = 0; j < 24; ++j) { + typename round_type::input_type round_input = { + inner_state, pmc, + var(component.C(0), start_row_index + j + 4, false, var::column_type::constant)}; + if (i == component.num_round_calls - 1 && j == 0) { + typename round_type::result_type round_result = + generate_assignments(component.round_tt, assignment, round_input, cur_row); + inner_state = round_result.inner_state; + cur_row += component.round_tt.rows_amount; + } else if (j == 0) { + typename round_type::result_type round_result = + generate_assignments(component.round_tf, assignment, round_input, cur_row); + inner_state = round_result.inner_state; + cur_row += component.round_tf.rows_amount; + } else { + typename round_type::result_type round_result = + generate_assignments(component.round_ff, assignment, round_input, cur_row); + inner_state = round_result.inner_state; + cur_row += component.round_ff.rows_amount; + } + } + offset += 17; + } // from sparse for (std::size_t index = 0; index < 5; ++index) { - // value_type sparse_value = var_value(assignment, inner_state[index]); - integral_type sparse = integral_type(0); + value_type sparse_value = var_value(assignment, inner_state[index]); + integral_type sparse = integral_type(sparse_value.data); integral_type regular = component.unpack(sparse); - // std::cout << "from sparse: " << sparse << " " << regular << std::endl; - auto chunk_size = component.pack_chunk_size; + // std::cout << "from sparse: " << sparse << " to regular " << regular << std::endl; + auto chunk_size = component.pack_chunk_size * 3; auto num_chunks = component.pack_num_chunks; std::vector integral_sparse_chunks; std::vector integral_chunks; @@ -809,50 +1025,53 @@ namespace nil { sparse >>= chunk_size; integral_sparse_chunks.push_back(component.unpack(integral_chunks.back())); } + sparse_padded_message[index] = value_type(regular); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + cur_row) = value_type(sparse); - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(regular); + assignment.witness(component.W(cur_config.constraints[0][0].column), + cur_config.constraints[0][0].row + cur_row) = sparse_value; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + cur_row) = value_type(regular); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_sparse_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + cur_row) = value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[0][j].column), + cur_config.constraints[0][j].row + cur_row) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + cur_row) = + value_type(integral_sparse_chunks[j - 1]); } config_index++; } - // std::cout << "here: " << component.full_configuration[config_index - 1].last_coordinate.row << std::endl; - cur_row += component.full_configuration[config_index - 1].last_coordinate.row - + (component.full_configuration[config_index - 1].last_coordinate.column > 0); - BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); + cur_row += component.full_configuration[config_index - 1].last_coordinate.row + + (component.full_configuration[config_index - 1].last_coordinate.column > 0); + + // BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); + std::cout << cur_row << " vs " << component.rows_amount << std::endl; return typename component_type::result_type(component, start_row_index); } template void generate_assignments_constant( - const keccak_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_component::input_type - &instance_input, + const keccak_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_component; using integral_type = typename BlueprintFieldType::integral_type; - std::size_t row = start_row_index + 3; + std::size_t row = start_row_index + 4; for (std::size_t i = 0; i < 24; ++i) { - assignment.constant(component.C(0), row + i) = component.round_constant[i]; + assignment.constant(component.C(0), row + i) = component.pack(component.round_constant[i]); } } - } // namespace components } // namespace blueprint -} // namespace nil +} // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 24a64d7c0..bf4aeda8a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -1,5 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova +// 2024 Valeh Farzaliyev // // MIT License // @@ -49,6 +50,7 @@ namespace nil { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; public: struct coordinates { @@ -170,7 +172,9 @@ namespace nil { const std::size_t num_blocks; const std::size_t num_bits; std::size_t shift = calculate_shift(num_blocks, num_bits); - std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks); + std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks, shift); + + const integral_type padding_delimiter = integral_type(1) << 56; const std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); const std::size_t buff = calculate_buff(this->witness_amount(), range_check_input); @@ -212,7 +216,11 @@ namespace nil { padded_message[i] = var(component.W(config.copy_to.back().column), config.copy_to.back().row + start_row_index, false); } - for (std::size_t i = size; i < size + component.num_padding_zeros; ++i) { + if(component.shift == 0){ + padded_message[size] = var(component.C(0), start_row_index + 3, false, var::column_type::constant); + } + + for (std::size_t i = size + (component.shift == 0); i < size + component.num_padding_zeros; ++i) { padded_message[i] = var(component.C(0), start_row_index, false, var::column_type::constant); } } @@ -226,8 +234,11 @@ namespace nil { // assert(num_blocks * 64 >= num_bits); return num_blocks * 64 - num_bits; } - static std::size_t calculate_num_padding_zeros(std::size_t num_blocks) { + static std::size_t calculate_num_padding_zeros(std::size_t num_blocks, std::size_t shift) { if (num_blocks % 17 == 0){ + if(shift == 0 ){ + return 17; + } return 0; } return 17 - num_blocks % 17; @@ -625,7 +636,7 @@ namespace nil { std::size_t limit_permutation_column) { auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); auto res = confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); - if (res < 3) res = 3; + if (res < 4) res = 4; return res; } @@ -840,7 +851,7 @@ namespace nil { } if (component.shift != 0) { auto config = component.full_configuration[config_index++]; - bp.add_copy_constraint({var(component.C(0), start_row_index, false, var::column_type::constant), + bp.add_copy_constraint({var(component.C(0), start_row_index + 3, false, var::column_type::constant), var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); } else { @@ -934,7 +945,7 @@ namespace nil { if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { - value_type chunk = 0; + value_type chunk = value_type(component.padding_delimiter); if (index < component.num_blocks) { chunk = var_value(assignment, instance_input.message[index]); } @@ -1019,10 +1030,12 @@ namespace nil { const std::uint32_t start_row_index) { using component_type = padding_component; + using value_type = typename BlueprintFieldType::value_type; - assignment.constant(component.C(0), start_row_index) = 0; + assignment.constant(component.C(0), start_row_index) = 0; assignment.constant(component.C(0), start_row_index + 1) = component.num_blocks; assignment.constant(component.C(0), start_row_index + 2) = component.num_bits; + assignment.constant(component.C(0), start_row_index + 3) = value_type(component.padding_delimiter); } } // namespace components diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index be2ab99be..6524b567d 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova -// +// 2024 Valeh Farzaliyev // MIT License // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -42,7 +42,6 @@ #include #include - namespace nil { namespace blueprint { namespace components { @@ -50,19 +49,21 @@ namespace nil { class keccak_round; template - class keccak_round> : - public plonk_component { + class keccak_round> + : public plonk_component { using component_type = plonk_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - using lookup_table_definition = typename nil::crypto3::zk::snark::lookup_table_definition; + using lookup_table_definition = + typename nil::crypto3::zk::snark::lookup_table_definition; // xor2 - base=3, xor3 - base=4, xor5 - base=6, chi - base=2, rotate - base=0 int bases[5] = {3, 4, 6, 2, 0}; static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base = 0) { - if (base == 0) return 8; + if (base == 0) + return 8; std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -72,21 +73,21 @@ namespace nil { return chunk_size * 3; } static std::size_t calculate_num_chunks(std::size_t num_rows, std::size_t base = 0) { - if (base == 0) return 8; + if (base == 0) + return 8; std::size_t chunk_size = calculate_chunk_size(num_rows, base); std::size_t res = 192 / chunk_size + bool(192 % chunk_size); return res; } static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 0) { - if (base == 0) return 24; - std::size_t res = base == 3 ? 2 + 2 - : base == 4 ? 3 + 2 - : base == 6 ? 5 + 2 - : 5; + if (base == 0) + return 24; + std::size_t res = base == 3 ? 2 + 2 : base == 4 ? 3 + 2 : base == 6 ? 5 + 2 : 5; res += 2 * calculate_num_chunks(num_rows, base); return res; } - static std::size_t calculate_buff(std::size_t witness_amount, std::size_t num_rows, std::size_t base = 0) { + static std::size_t calculate_buff(std::size_t witness_amount, std::size_t num_rows, + std::size_t base = 0) { std::size_t buff = 0; std::size_t cells = calculate_num_cells(num_rows, base); if (base == 0) { @@ -112,14 +113,15 @@ namespace nil { return buff; } static std::size_t calculate_last_round_call_row(std::size_t witness_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { if (!last_round_call) { return 0; } std::size_t res = 0; - auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto gates_configuration_map = + configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); for (auto g : gates_configuration_map) { if (g.first.first == 3) { res = g.second[0]; @@ -143,14 +145,15 @@ namespace nil { gate_manifest_type(std::size_t witness_amount_, bool xor_with_mes_, bool last_round_call_, - std::size_t limit_permutation_column_) - : witness_amount(std::min(witness_amount_, clamp)), - xor_with_mes(xor_with_mes_), - last_round_call(last_round_call_), - limit_permutation_column(limit_permutation_column_) {} + std::size_t limit_permutation_column_) : + witness_amount(std::min(witness_amount_, clamp)), + xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), + limit_permutation_column(limit_permutation_column_) { + } std::uint32_t gates_amount() const override { - return keccak_round::get_gates_amount(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + return keccak_round::get_gates_amount(witness_amount, xor_with_mes, last_round_call, + limit_permutation_column); } }; @@ -159,18 +162,14 @@ namespace nil { bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { - gate_manifest manifest = - gate_manifest(gate_manifest_type(witness_amount, xor_with_mes, last_round_call, - limit_permutation_column)); + gate_manifest manifest = gate_manifest( + gate_manifest_type(witness_amount, xor_with_mes, last_round_call, limit_permutation_column)); return manifest; } static manifest_type get_manifest() { - static manifest_type manifest = manifest_type( - std::shared_ptr( - new manifest_range_param(9, 15)), - false - ); + static manifest_type manifest = + manifest_type(std::shared_ptr(new manifest_range_param(9, 15)), false); return manifest; } @@ -182,10 +181,10 @@ namespace nil { coordinates() = default; coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - bool operator== (const coordinates& other) const { + bool operator==(const coordinates &other) const { return row == other.row && column == other.column; } - bool operator< (const coordinates& other) const { + bool operator<(const coordinates &other) const { return row < other.row || (row == other.row && column < other.column); } }; @@ -202,43 +201,45 @@ namespace nil { configuration() = default; configuration(std::pair first_coordinate_, - std::pair last_coordinate_, - std::vector> copy_to_, - std::vector>> constraints_, - std::vector>> lookups_, - std::pair copy_from_){ - first_coordinate = coordinates(first_coordinate_); - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to.push_back(coordinates(copy_to_[i])); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - std::vector constr; - for (std::size_t j = 0; j < constraints_[i].size(); ++j) { - constr.push_back(coordinates(constraints_[i][j])); - } - constraints.push_back(constr); + std::pair + last_coordinate_, + std::vector> + copy_to_, + std::vector>> + constraints_, + std::vector>> + lookups_, + std::pair + copy_from_) { + first_coordinate = coordinates(first_coordinate_); + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to.push_back(coordinates(copy_to_[i])); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - std::vector lookup; - for (std::size_t j = 0; j < lookups_[i].size(); ++j) { - lookup.push_back(coordinates(lookups_[i][j])); - } - lookups.push_back(lookup); + constraints.push_back(constr); + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); } - copy_from = coordinates(copy_from_); - }; - bool operator== (const configuration& other) const { - return first_coordinate == other.first_coordinate && - last_coordinate == other.last_coordinate && - copy_to == other.copy_to && - constraints == other.constraints && - lookups == other.lookups && - copy_from == other.copy_from; - } - bool operator< (const configuration& other) const { + lookups.push_back(lookup); + } + copy_from = coordinates(copy_from_); + }; + bool operator==(const configuration &other) const { + return first_coordinate == other.first_coordinate && last_coordinate == other.last_coordinate && + copy_to == other.copy_to && constraints == other.constraints && + lookups == other.lookups && copy_from == other.copy_from; + } + bool operator<(const configuration &other) const { return first_coordinate < other.first_coordinate || - (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); } }; @@ -254,8 +255,10 @@ namespace nil { // num columns for the permutation argument const std::size_t limit_permutation_column; - const typename BlueprintFieldType::integral_type big_rot_const = calculate_sparse((integral_type(1) << 64) - 1); - const std::array, 29> all_rot_consts = calculate_rot_consts(); + const typename BlueprintFieldType::integral_type big_rot_const = + calculate_sparse((integral_type(1) << 64) - 1); + const std::array, 29> all_rot_consts = + calculate_rot_consts(); const std::size_t normalize3_chunk_size = calculate_chunk_size(lookup_rows, 3); const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); @@ -281,26 +284,32 @@ namespace nil { const std::size_t chi_buff = calculate_buff(this->witness_amount(), lookup_rows, 5); const std::size_t rotate_buff = calculate_buff(this->witness_amount(), lookup_rows); - const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, xor_with_mes, last_round_call, limit_permutation_column); + const std::size_t rows_amount = + get_rows_amount(this->witness_amount(), 0, xor_with_mes, last_round_call, limit_permutation_column); // full configuration is precalculated, then used in other functions const std::size_t full_configuration_size = 17 * xor_with_mes + 85; - std::vector full_configuration = configure_all(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector full_configuration = + configure_all(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); // number represents relative selector index for each constraint - std::map, std::vector> gates_configuration_map = configure_map(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - std::vector> gates_configuration = configure_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - std::vector> lookup_gates_configuration = configure_lookup_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - - const std::size_t last_round_call_row = calculate_last_round_call_row(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); - const std::size_t gates_amount = get_gates_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::map, std::vector> gates_configuration_map = + configure_map(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector> gates_configuration = + configure_gates(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + std::vector> lookup_gates_configuration = configure_lookup_gates( + this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + + const std::size_t last_round_call_row = calculate_last_round_call_row( + this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); + const std::size_t gates_amount = + get_gates_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); const value_type sparse_3 = 0x6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB_cppui255; - constexpr static const std::array - rho_offsets = {0, 1, 3, 6, 10, 15, 21, - 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, - 62, 18, 39, 61, 20, 44}; + const integral_type sparse_x80 = calculate_sparse(integral_type(0x8000000000000000)); + + constexpr static const std::array rho_offsets = { + 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44}; struct input_type { std::array inner_state; @@ -321,11 +330,13 @@ namespace nil { result_type(const keccak_round &component, std::size_t start_row_index) { std::size_t num_config = component.full_configuration.size() - 1; - inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.column), - component.full_configuration[num_config].copy_from.row + start_row_index); + inner_state[0] = + var(component.W(component.full_configuration[num_config].copy_from.column), + component.full_configuration[num_config].copy_from.row + start_row_index, false); for (int i = 1; i < 25; ++i) { - inner_state[25 - i] = var(component.W(component.full_configuration[num_config - i].copy_from.column), - component.full_configuration[num_config - i].copy_from.row + start_row_index); + inner_state[25 - i] = var( + component.W(component.full_configuration[num_config - i].copy_from.column), + component.full_configuration[num_config - i].copy_from.row + start_row_index, false); } } @@ -336,7 +347,8 @@ namespace nil { } }; - typename BlueprintFieldType::integral_type calculate_sparse(const typename BlueprintFieldType::integral_type& value) const { + typename BlueprintFieldType::integral_type + calculate_sparse(const typename BlueprintFieldType::integral_type &value) const { typename BlueprintFieldType::integral_type result = 0; typename BlueprintFieldType::integral_type power = 1; typename BlueprintFieldType::integral_type val = value; @@ -360,7 +372,7 @@ namespace nil { return result; } - integral_type normalize(const integral_type& integral_value) const { + integral_type normalize(const integral_type &integral_value) const { integral_type result = 0; integral_type value = integral_value; integral_type power = 1; @@ -372,7 +384,7 @@ namespace nil { return result; } - integral_type chi(const integral_type& integral_value) const { + integral_type chi(const integral_type &integral_value) const { integral_type result = 0; integral_type value = integral_value; integral_type power = 1; @@ -388,13 +400,13 @@ namespace nil { } static configuration configure_inner(std::size_t witness_amount, std::size_t limit_permutation_column, - std::size_t row, std::size_t column, std::size_t num_args, - std::size_t num_chunks, std::size_t num_cells, std::size_t buff = 0) { + std::size_t row, std::size_t column, std::size_t num_args, + std::size_t num_chunks, std::size_t num_cells, + std::size_t buff = 0) { std::pair first_coordinate = {row, column}; - std::size_t last_row = row, - last_column = column; + std::size_t last_row = row, last_column = column; std::vector> copy_to; @@ -404,8 +416,8 @@ namespace nil { } } else { for (int i = 0; i < num_args; ++i) { - copy_to.push_back({last_row + (last_column / witness_amount), - (last_column++) % witness_amount}); + copy_to.push_back( + {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); } } @@ -423,20 +435,20 @@ namespace nil { cells.push_back({row, i}); } std::size_t cells_left = num_cells - witness_amount + column; - std::size_t cur_row = row + 1, - cur_column = num_args; + std::size_t cur_row = row + 1, cur_column = num_args; while (cur_column < cells_left) { - if (cur_column % witness_amount == cell_copy_from.second && (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { + if (cur_column % witness_amount == cell_copy_from.second && + (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { cur_column++; continue; } cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { - std::size_t cur_row = row, - cur_column = column + num_args; + std::size_t cur_row = row, cur_column = column + num_args; while (cur_column - column < num_cells) { - if (cur_column % witness_amount == cell_copy_from.second && (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { + if (cur_column % witness_amount == cell_copy_from.second && + (cur_row + (cur_column / witness_amount) == cell_copy_from.first)) { cur_column++; continue; } @@ -469,37 +481,45 @@ namespace nil { last_row = cells.back().first + (last_column >= witness_amount); last_column %= witness_amount; - return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + cell_copy_from); } - static configuration configure_xor(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column, int num_args) { + static configuration configure_xor(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column, int num_args) { // regular constraints: // sum = arg1 + arg2 + ... + argn // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) - // norm_sum = norm_sum_chunk0 + norm_sum_chunk1 * 2^chunk_size + ... + norm_sum_chunkk * 2^(k*chunk_size) + // norm_sum = norm_sum_chunk0 + norm_sum_chunk1 * 2^chunk_size + ... + norm_sum_chunkk * + // 2^(k*chunk_size) std::size_t num_chunks = calculate_num_chunks(lookup_rows, num_args + 1); std::size_t num_cells = calculate_num_cells(lookup_rows, num_args + 1); std::size_t buff = calculate_buff(witness_amount, lookup_rows, num_args + 1); - return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); + return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, + num_cells, buff); } - static configuration configure_chi(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { + static configuration configure_chi(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column) { // regular constraints: // sum = sparse_3 - 2 * a + b - c; // sum = sum_chunk0 + sum_chunk1 * 2^chunk_size + ... + sum_chunkk * 2^(k*chunk_size) - // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * 2^(k*chunk_size) + // chi_sum = chi_sum_chunk0 + chi_sum_chunk1 * 2^chunk_size + ... + chi_sum_chunkk * + // 2^(k*chunk_size) std::size_t num_args = 3; std::size_t num_chunks = calculate_num_chunks(lookup_rows, 5); std::size_t num_cells = calculate_num_cells(lookup_rows, 5); std::size_t buff = calculate_buff(witness_amount, lookup_rows, 5); - return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, num_cells, buff); + return configure_inner(witness_amount, limit_permutation_column, row, column, num_args, num_chunks, + num_cells, buff); } - static configuration configure_rot(std::size_t witness_amount, std::size_t limit_permutation_column, std::size_t row, std::size_t column) { + static configuration configure_rot(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column) { // regular constraints: // a = small_part * (1 << (192 - 3 * r)) + big_part; // a_rot = big_part * (1 << (3 * r)) + small_part; @@ -511,8 +531,7 @@ namespace nil { std::pair first_coordinate = {row, column}; - std::size_t last_row = row, - last_column = column; + std::size_t last_row = row, last_column = column; std::size_t num_chunks = 8; std::size_t num_cells = 24; @@ -524,10 +543,9 @@ namespace nil { copy_to.push_back({last_row + 1, 0}); cell_copy_from = {last_row + 1, 1}; } else { - copy_to.push_back({last_row + (last_column / witness_amount), - (last_column++) % witness_amount}); - cell_copy_from = {last_row + (last_column / witness_amount), - (last_column++) % witness_amount}; + copy_to.push_back( + {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); + cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; } std::vector> cells; @@ -536,14 +554,12 @@ namespace nil { cells.push_back({row, i}); } std::size_t cells_left = num_cells - witness_amount + column; - std::size_t cur_row = row + 1, - cur_column = 2; + std::size_t cur_row = row + 1, cur_column = 2; while (cur_column < cells_left) { cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } } else { - std::size_t cur_row = row, - cur_column = column + 2; + std::size_t cur_row = row, cur_column = column + 2; while (cur_column - column < num_cells) { cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); } @@ -560,7 +576,8 @@ namespace nil { constraints[1].push_back(constraints[0][2]); constraints[1].push_back(constraints[0][1]); - std::vector>> lookups(2, std::vector>()); + std::vector>> lookups( + 2, std::vector>()); constraints.push_back({cells[cell_index++]}); constraints[2].push_back(constraints[0][1]); @@ -590,7 +607,8 @@ namespace nil { last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; - return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + cell_copy_from); } static std::vector configure_all(std::size_t witness_amount, @@ -599,8 +617,7 @@ namespace nil { std::size_t limit_permutation_column) { std::size_t full_configuration_size = 17 * xor_with_mes + 85; auto result = std::vector(full_configuration_size); - std::size_t row = 0, - column = 0; + std::size_t row = 0, column = 0; std::size_t cur_config = 0; // inner_state ^ chunk @@ -613,7 +630,8 @@ namespace nil { } // xor with last message chunk if (last_round_call) { - result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 3); + result[cur_config] = + configure_xor(witness_amount, limit_permutation_column, row, column, 3); row = result[cur_config].last_coordinate.row; column = result[cur_config].last_coordinate.column; cur_config++; @@ -657,21 +675,24 @@ namespace nil { // for (int i = 0; i < result.size(); ++i) { // std::cout << "\n config: " << result[i].name << std::endl; - // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; + // std::cout << result[i].first_coordinate.row << " " << result[i].first_coordinate.column << " + // " << result[i].last_coordinate.row << " " << result[i].last_coordinate.column << std::endl; // std::cout << result[i].copy_from.row << " " << result[i].copy_from.column << std::endl; // for (int j = 0; j < result[i].copy_to.size(); ++j) { // std::cout << result[i].copy_to[j].row << " " << result[i].copy_to[j].column << std::endl; // } // for (int j = 0; j < result[i].constraints.size(); ++j) { // for (int k = 0; k < result[i].constraints[j].size(); ++k) { - // std::cout << result[i].constraints[j][k].row << " " << result[i].constraints[j][k].column << ", "; + // std::cout << result[i].constraints[j][k].row << " " << + // result[i].constraints[j][k].column << ", "; // } // std::cout << std::endl; // } // std::cout << "lookups: " << result[i].lookups.size() << std::endl; // for (int j = 0; j < result[i].lookups.size(); ++j) { // for (int k = 0; k < result[i].lookups[j].size(); ++k) { - // std::cout << result[i].lookups[j][k].row << " " << result[i].lookups[j][k].column << ", "; + // std::cout << result[i].lookups[j][k].row << " " << result[i].lookups[j][k].column << + // ", "; // } // std::cout << std::endl; // } @@ -680,14 +701,14 @@ namespace nil { return result; } - static std::map, - std::vector> configure_map(std::size_t witness_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { - auto config = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); - std::size_t row = 0, - column = 0; + static std::map, std::vector> + configure_map(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + auto config = + configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + std::size_t row = 0, column = 0; std::size_t cur_config = 0; std::map, std::vector> config_map; @@ -790,43 +811,52 @@ namespace nil { } static std::vector> configure_gates(std::size_t witness_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { std::vector> result; - auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto gates_configuration_map = + configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); - for (auto config: gates_configuration_map) { + for (auto config : gates_configuration_map) { configuration cur_config; switch (config.first.first) { case 2: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); break; case 3: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); break; case 5: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); break; case 7: - cur_config = configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); + cur_config = + configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); break; case 0: - cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); + cur_config = + configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; } // std::cout << "\nconfig:\n"; // std::cout << config.first.first << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; - // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << + // " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << + // std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << + // std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << + // std::endl; // } // for (int j = 0; j < cur_config.constraints.size(); ++j) { // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // std::cout << cur_config.constraints[j][k].row << " " << + // cur_config.constraints[j][k].column << ", "; // } // std::cout << std::endl; // } @@ -847,7 +877,8 @@ namespace nil { std::size_t cur_constr = 0; while (cur_constr < pairs.size()) { configuration c; - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { c.constraints.push_back(cur_config.constraints[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; @@ -861,32 +892,40 @@ namespace nil { return result; } - static std::vector> configure_lookup_gates(std::size_t witness_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { - auto full_configuration = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + static std::vector> + configure_lookup_gates(std::size_t witness_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { + auto full_configuration = + configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); auto rows_amount = full_configuration.back().last_coordinate.row + 1; std::vector> result; - auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto gates_configuration_map = + configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); - for (auto config: gates_configuration_map) { + for (auto config : gates_configuration_map) { configuration cur_config; switch (config.first.first) { case 2: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 2); break; case 3: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 3); break; case 5: - cur_config = configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); + cur_config = + configure_xor(witness_amount, limit_permutation_column, 0, config.first.second, 5); break; case 7: - cur_config = configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); + cur_config = + configure_rot(witness_amount, limit_permutation_column, 0, config.first.second); break; case 0: - cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); + cur_config = + configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; } @@ -909,14 +948,15 @@ namespace nil { while (cur_constr < pairs.size()) { configuration c; found = false; - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { c.lookups.push_back(cur_config.lookups[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; found = true; } cur_row = pairs[cur_constr].first; - if(found){ + if (found) { cur_result.push_back(c); } } @@ -925,7 +965,8 @@ namespace nil { // std::size_t cur_row = 0; // std::size_t cur_constr = 0; // while (cur_row < rows_amount) { - // while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + // while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + // pairs[cur_constr].first >= cur_row) { // result.push_back(cur_row + 1); // ++cur_constr; // } @@ -941,11 +982,13 @@ namespace nil { bool last_round_call, std::size_t limit_permutation_column) { std::size_t res = 0; - auto gates_configuration = configure_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto gates_configuration = + configure_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); for (std::size_t i = 0; i < gates_configuration.size(); ++i) { res += gates_configuration[i].size(); } - auto lookup_gates_configuration = configure_lookup_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + auto lookup_gates_configuration = + configure_lookup_gates(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); for (std::size_t i = 0; i < lookup_gates_configuration.size(); ++i) { res += lookup_gates_configuration[i].size(); } @@ -953,10 +996,10 @@ namespace nil { } static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t lookup_column_amount, - bool xor_with_mes, - bool last_round_call, - std::size_t limit_permutation_column) { + std::size_t lookup_column_amount, + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column) { std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); @@ -968,16 +1011,15 @@ namespace nil { std::size_t chi_buff = calculate_buff(witness_amount, lookup_rows, 5); std::size_t rotate_buff = calculate_buff(witness_amount, lookup_rows); - std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call - * xor_with_mes + // xor with last message chunk - ((17 - last_round_call) * (xor2_cells + xor2_buff)) - * xor_with_mes + // inner_state ^ chunk - 5 * (xor5_cells + xor5_buff) + // theta - 5 * (rotate_cells + rotate_buff) + // theta - 25 * (xor3_cells + xor3_buff) + // theta - 24 * (rotate_cells + rotate_buff) + // rho/phi - 25 * (chi_cells + chi_buff) + // chi - xor2_cells; // iota + std::size_t num_cells = + (xor3_cells + xor3_buff) * last_round_call * xor_with_mes + // xor with last message chunk + ((17 - last_round_call) * (xor2_cells + xor2_buff)) * xor_with_mes + // inner_state ^ chunk + 5 * (xor5_cells + xor5_buff) + // theta + 5 * (rotate_cells + rotate_buff) + // theta + 25 * (xor3_cells + xor3_buff) + // theta + 24 * (rotate_cells + rotate_buff) + // rho/phi + 25 * (chi_cells + chi_buff) + // chi + xor2_cells; // iota return num_cells / witness_amount + bool(num_cells % witness_amount); } @@ -994,44 +1036,39 @@ namespace nil { // return result; // } - std::map component_lookup_tables(){ + std::map component_lookup_tables() { std::map lookup_tables; - lookup_tables["keccak_normalize3_table/full"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_normalize4_table/full"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_normalize6_table/full"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_chi_table/full"] = 0; // REQUIRED_TABLE - lookup_tables["keccak_pack_table/range_check_sparse"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize3_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize4_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_normalize6_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_chi_table/full"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/range_check_sparse"] = 0; // REQUIRED_TABLE return lookup_tables; } template keccak_round(WitnessContainerType witness, ConstantContainerType constant, - PublicInputContainerType public_input, - bool xor_with_mes_ = false, - bool last_round_call_ = false, - std::size_t lpc_ = 7) : - component_type(witness, constant, public_input, get_manifest()), - xor_with_mes(xor_with_mes_), - last_round_call(last_round_call_), - limit_permutation_column(lpc_) { - // check_params(); - }; - - keccak_round( - std::initializer_list witnesses, - std::initializer_list constants, - std::initializer_list - public_inputs, - bool xor_with_mes_ = false, - bool last_round_call_ = false, - std::size_t lpc_ = 7) : - component_type(witnesses, constants, public_inputs, get_manifest()), - xor_with_mes(xor_with_mes_), - last_round_call(last_round_call_), - limit_permutation_column(lpc_) { - // check_params(); - }; + PublicInputContainerType public_input, bool xor_with_mes_ = false, + bool last_round_call_ = false, std::size_t lpc_ = 7) : + component_type(witness, constant, public_input, get_manifest()), + xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { + // check_params(); + }; + + keccak_round(std::initializer_list + witnesses, + std::initializer_list + constants, + std::initializer_list + public_inputs, + bool xor_with_mes_ = false, + bool last_round_call_ = false, + std::size_t lpc_ = 7) : + component_type(witnesses, constants, public_inputs, get_manifest()), + xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { + // check_params(); + }; }; template @@ -1040,14 +1077,10 @@ namespace nil { template std::vector generate_gates( - const keccak_round_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_round_component::input_type - &instance_input, + const keccak_round_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_round_component::input_type &instance_input, const typename lookup_library::left_reserved_type lookup_tables_indices) { using component_type = keccak_round_component; @@ -1055,7 +1088,8 @@ namespace nil { using constraint_type = crypto3::zk::snark::plonk_constraint; using gate_type = typename crypto3::zk::snark::plonk_gate; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; - using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; + using lookup_gate_type = + typename crypto3::zk::snark::plonk_gate; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using configuration = typename component_type::configuration; @@ -1072,7 +1106,7 @@ namespace nil { // general gates std::size_t index = 0; - for (auto gm: gate_map) { + for (auto gm : gate_map) { std::vector cur_config_vec = gate_config[index]; std::size_t i = 0, j = 0, cur_len = 0; std::vector cur_constraints; @@ -1080,11 +1114,17 @@ namespace nil { std::vector cur_lookup_constraints; std::string cur_lookup_table_name; switch (gm.first.first) { - case 2: - { - cur_constraints.push_back(constraint_type(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1))); + case 2: { + cur_constraints.push_back( + constraint_type(var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, + cur_config_vec[i].constraints[j][2].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1))); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1095,10 +1135,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize3_num_chunks; ++k) { - constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize3_chunk_size)); + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize3_chunk_size)); } cur_constraints.push_back(constraint_1); @@ -1111,10 +1155,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize3_num_chunks; ++k) { - constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize3_chunk_size)); + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize3_chunk_size)); } cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); @@ -1122,12 +1170,19 @@ namespace nil { cur_lookup_table_name = "keccak_normalize3_table/full"; break; } - case 3: - { - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); + case 3: { + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, + cur_config_vec[i].constraints[j][2].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, + cur_config_vec[i].constraints[j][3].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1138,10 +1193,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize4_num_chunks; ++k) { - constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize4_chunk_size)); + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize4_chunk_size)); } cur_constraints.push_back(constraint_1); @@ -1154,10 +1213,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize4_num_chunks; ++k) { - constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize4_chunk_size)); + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize4_chunk_size)); } cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); @@ -1165,14 +1228,25 @@ namespace nil { cur_lookup_table_name = "keccak_normalize4_table/full"; break; } - case 5: - { - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][4].column, cur_config_vec[i].constraints[j][4].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][5].column, cur_config_vec[i].constraints[j][5].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); + case 5: { + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, + cur_config_vec[i].constraints[j][2].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][3].column, + cur_config_vec[i].constraints[j][3].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][4].column, + cur_config_vec[i].constraints[j][4].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][5].column, + cur_config_vec[i].constraints[j][5].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1183,10 +1257,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize6_num_chunks; ++k) { - constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize6_chunk_size)); + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize6_chunk_size)); } cur_constraints.push_back(constraint_1); @@ -1199,10 +1277,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.normalize6_num_chunks; ++k) { - constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.normalize6_chunk_size)); + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.normalize6_chunk_size)); } cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); @@ -1210,14 +1292,21 @@ namespace nil { cur_lookup_table_name = "keccak_normalize6_table/full"; break; } - case 7: - { + case 7: { std::size_t true_first_row = cur_config_vec[i].first_coordinate.row; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) * + var(cur_config_vec[i].constraints[j][3].column, + cur_config_vec[i].constraints[j][3].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[j][2].column, + cur_config_vec[i].constraints[j][2].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1228,10 +1317,18 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[1][1].column, cur_config_vec[i].constraints[1][1].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[1][2].column, cur_config_vec[i].constraints[1][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[1][0].column, cur_config_vec[i].constraints[1][0].row - cur_config_vec[i].first_coordinate.row - 1)); + cur_constraints.push_back(var(cur_config_vec[i].constraints[1][1].column, + cur_config_vec[i].constraints[1][1].row - + cur_config_vec[i].first_coordinate.row - 1) * + var(cur_config_vec[i].constraints[j][3].column, + cur_config_vec[i].constraints[j][3].row - + cur_config_vec[i].first_coordinate.row - 1) + + var(cur_config_vec[i].constraints[1][2].column, + cur_config_vec[i].constraints[1][2].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[1][0].column, + cur_config_vec[i].constraints[1][0].row - + cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1242,10 +1339,16 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(component.C(0), true_first_row + 1 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) - - component.big_rot_const); + cur_constraints.push_back( + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - + 1) - + var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - + 1) + + var(component.C(0), true_first_row + 1 - cur_config_vec[i].first_coordinate.row - 1, + true, var::column_type::constant) - + component.big_rot_const); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1256,10 +1359,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.rotate_num_chunks; ++k) { - constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.rotate_chunk_size)); + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.rotate_chunk_size)); } cur_constraints.push_back(constraint_1); @@ -1272,10 +1379,16 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - + var(component.C(0), true_first_row + 2 - cur_config_vec[i].first_coordinate.row - 1, true, var::column_type::constant) - - component.big_rot_const); + cur_constraints.push_back( + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - + 1) - + var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - + 1) + + var(component.C(0), true_first_row + 2 - cur_config_vec[i].first_coordinate.row - 1, + true, var::column_type::constant) - + component.big_rot_const); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1286,10 +1399,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.rotate_num_chunks; ++k) { - constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.rotate_chunk_size)); + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.rotate_chunk_size)); } cur_constraints.push_back(constraint_2); @@ -1302,22 +1419,34 @@ namespace nil { i += j / cur_len; j %= cur_len; - cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1) - * var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) - - (integral_type(1) << 192)); + cur_constraints.push_back(var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1) * + var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) - + (integral_type(1) << 192)); selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_lookup_table_name = "keccak_pack_table/range_check_sparse"; break; } - case 0: - { - cur_constraints.push_back(component.sparse_3 - - var(cur_config_vec[i].constraints[j][1].column, cur_config_vec[i].constraints[j][1].row - cur_config_vec[i].first_coordinate.row - 1) * 2 - + var(cur_config_vec[i].constraints[j][2].column, cur_config_vec[i].constraints[j][2].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][3].column, cur_config_vec[i].constraints[j][3].row - cur_config_vec[i].first_coordinate.row - 1) - - var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1)); + case 0: { + cur_constraints.push_back(component.sparse_3 - + var(cur_config_vec[i].constraints[j][1].column, + cur_config_vec[i].constraints[j][1].row - + cur_config_vec[i].first_coordinate.row - 1) * + 2 + + var(cur_config_vec[i].constraints[j][2].column, + cur_config_vec[i].constraints[j][2].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][3].column, + cur_config_vec[i].constraints[j][3].row - + cur_config_vec[i].first_coordinate.row - 1) - + var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1)); j++; cur_len = cur_config_vec[i].constraints.size(); @@ -1328,10 +1457,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.chi_num_chunks; ++k) { - constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.chi_chunk_size)); + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.chi_chunk_size)); } cur_constraints.push_back(constraint_1); @@ -1344,10 +1477,14 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); for (int k = 0; k < component.chi_num_chunks; ++k) { - constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) - * (integral_type(1) << (k * component.chi_chunk_size)); + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.chi_chunk_size)); } cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); @@ -1359,9 +1496,11 @@ namespace nil { if (gm.first.first == 7) { for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { - lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), - {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), static_cast(cur_lookup_config_vec[i].lookups[j][0].row) - - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; + lookup_constraint_type lookup_constraint = { + lookup_tables_indices.at(cur_lookup_table_name), + {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), + static_cast(cur_lookup_config_vec[i].lookups[j][0].row) - + static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; cur_lookup_constraints.push_back(lookup_constraint); } selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); @@ -1372,11 +1511,14 @@ namespace nil { } for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { - lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), - {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), static_cast(cur_lookup_config_vec[i].lookups[j][0].row) - - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1), - var(component.W(cur_lookup_config_vec[i].lookups[j][1].column), static_cast(cur_lookup_config_vec[i].lookups[j][1].row) - - static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; + lookup_constraint_type lookup_constraint = { + lookup_tables_indices.at(cur_lookup_table_name), + {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), + static_cast(cur_lookup_config_vec[i].lookups[j][0].row) - + static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1), + var(component.W(cur_lookup_config_vec[i].lookups[j][1].column), + static_cast(cur_lookup_config_vec[i].lookups[j][1].row) - + static_cast(cur_lookup_config_vec[i].first_coordinate.row) - 1)}}; cur_lookup_constraints.push_back(lookup_constraint); } selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); @@ -1394,7 +1536,9 @@ namespace nil { // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { // for (int k = 0; k < cur_config_vec[i].lookups[j].size(); ++k) { - // std::cout << static_cast(cur_config_vec[i].lookups[j][k].row) - static_cast(cur_config_vec[i].first_coordinate.row) - 1 << " " << cur_config_vec[i].lookups[j][k].column << ", "; + // std::cout << static_cast(cur_config_vec[i].lookups[j][k].row) - + // static_cast(cur_config_vec[i].first_coordinate.row) - 1 << " " << + // cur_config_vec[i].lookups[j][k].column << ", "; // } // std::cout << std::endl; // } @@ -1425,10 +1569,13 @@ namespace nil { // } // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { - // lookup_constraint_type lookup_constraint = {lookup_tables_indices.at(cur_lookup_table_name), - // {var(component.W(cur_config_vec[i].lookups[j][0].column), static_cast(cur_config_vec[i].lookups[j][0].row) + // lookup_constraint_type lookup_constraint = + // {lookup_tables_indices.at(cur_lookup_table_name), + // {var(component.W(cur_config_vec[i].lookups[j][0].column), + // static_cast(cur_config_vec[i].lookups[j][0].row) // - static_cast(cur_config_vec[i].first_coordinate.row) - 1), - // var(component.W(cur_config_vec[i].lookups[j][1].column), static_cast(cur_config_vec[i].lookups[j][1].row) + // var(component.W(cur_config_vec[i].lookups[j][1].column), + // static_cast(cur_config_vec[i].lookups[j][1].row) // - static_cast(cur_config_vec[i].first_coordinate.row) - 1)}}; // cur_constraints.push_back(lookup_constraint); // } @@ -1442,14 +1589,10 @@ namespace nil { template void generate_copy_constraints( - const keccak_round_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_round_component::input_type - &instance_input, + const keccak_round_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_round_component; @@ -1464,46 +1607,78 @@ namespace nil { if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], var(component.W(config[i].copy_to[0].column), static_cast(config[i].copy_to[0].row + start_row_index), false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), static_cast(config[i].copy_to[1].row + start_row_index), false)}); + bp.add_copy_constraint( + {instance_input.inner_state[i], + var(component.W(config[i].copy_to[0].column), + static_cast(config[i].copy_to[0].row + start_row_index), false)}); + bp.add_copy_constraint( + {instance_input.padded_message_chunk[i], + var(component.W(config[i].copy_to[1].column), + static_cast(config[i].copy_to[1].row + start_row_index), false)}); num_copy_constr += 2; } config_index += 16; if (component.last_round_call) { - bp.add_copy_constraint({instance_input.inner_state[config_index], var(component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + start_row_index), false)}); - bp.add_copy_constraint({instance_input.padded_message_chunk[config_index], var(component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false)}); - bp.add_copy_constraint({var(component.C(0), component.last_round_call_row + start_row_index, false, var::column_type::constant), - var(component.W(config[config_index].copy_to[2].column), static_cast(config[config_index].copy_to[2].row + start_row_index), false)}); + bp.add_copy_constraint( + {instance_input.inner_state[config_index], + var(component.W(config[config_index].copy_to[0].column), + static_cast(config[config_index].copy_to[0].row + start_row_index), false)}); + bp.add_copy_constraint( + {instance_input.padded_message_chunk[config_index], + var(component.W(config[config_index].copy_to[1].column), + static_cast(config[config_index].copy_to[1].row + start_row_index), false)}); + bp.add_copy_constraint( + {var(component.C(0), component.last_round_call_row + start_row_index, false, + var::column_type::constant), + var(component.W(config[config_index].copy_to[2].column), + static_cast(config[config_index].copy_to[2].row + start_row_index), false)}); num_copy_constr += 3; } config_index += 1; // theta for (int i = 0; i < 17; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, - {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[prev_index + i].copy_from.column), + static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i % 5].copy_to[i / 5].column), + static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), + false}}); num_copy_constr += 1; } for (int i = 17; i < 25; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); + bp.add_copy_constraint( + {instance_input.inner_state[i], + {component.W(config[config_index + i % 5].copy_to[i / 5].column), + static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), + false}}); num_copy_constr += 1; } config_index += 5; prev_index += 17; } else { for (int i = 0; i < 25; ++i) { - bp.add_copy_constraint({instance_input.inner_state[i], - {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); + bp.add_copy_constraint( + {instance_input.inner_state[i], + {component.W(config[config_index + i % 5].copy_to[i / 5].column), + static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), + false}}); num_copy_constr += 1; } config_index += 5; } for (int i = 0; i < 5; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + i].copy_from.column), static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[config_index + i].constraints[6][0].column), static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, - var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); + bp.add_copy_constraint( + {{component.W(config[prev_index + i].copy_from.column), + static_cast(config[prev_index + i].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), + static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[config_index + i].constraints[6][0].column), + static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, + var(component.C(0), + static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, + var::column_type::constant)}); num_copy_constr += 2; } config_index += 5; @@ -1511,70 +1686,91 @@ namespace nil { for (int i = 0; i < 25; ++i) { std::size_t x = i % 5; - bp.add_copy_constraint({{component.W(config[prev_index - 5 + i % 5].copy_to[i / 5].column), static_cast(config[prev_index - 5 + i % 5].copy_to[i / 5].row + start_row_index), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (x + 1) % 5].copy_from.column), static_cast(config[prev_index + (x + 1) % 5].copy_from.row + start_row_index), false}, - {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[prev_index + (x + 4) % 5].copy_to[0].column), static_cast(config[prev_index + (x + 4) % 5].copy_to[0].row + start_row_index), false}, - {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[prev_index - 5 + i % 5].copy_to[i / 5].column), + static_cast(config[prev_index - 5 + i % 5].copy_to[i / 5].row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), + static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[prev_index + (x + 1) % 5].copy_from.column), + static_cast(config[prev_index + (x + 1) % 5].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[1].column), + static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[prev_index + (x + 4) % 5].copy_to[0].column), + static_cast(config[prev_index + (x + 4) % 5].copy_to[0].row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[2].column), + static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); num_copy_constr += 3; } config_index += 25; prev_index += 5; // rho/phi - std::size_t perm_rho[24] = {1, 10, 7, 11, 17, 18, 3, - 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6}; + std::size_t perm_rho[24] = {1, 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, + 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6}; for (int i = 0; i < 24; ++i) { - bp.add_copy_constraint({{component.W(config[prev_index + perm_rho[i]].copy_from.column), static_cast(config[prev_index + perm_rho[i]].copy_from.row + start_row_index), false}, - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({{component.W(config[config_index + i].constraints[6][0].column), static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, - var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); + bp.add_copy_constraint( + {{component.W(config[prev_index + perm_rho[i]].copy_from.column), + static_cast(config[prev_index + perm_rho[i]].copy_from.row + start_row_index), false}, + {component.W(config[config_index + i].copy_to[0].column), + static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[config_index + i].constraints[6][0].column), + static_cast(config[config_index + i].constraints[6][0].row + start_row_index), false}, + var(component.C(0), + static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, + var::column_type::constant)}); } // chi - std::size_t perm_chi[24] = {23, 17, 5, 11, 6, 22, - 1, 8, 21, 0, 2, 16, - 15, 19, 12, 7, 3, 4, - 14, 18, 9, 20, 13, 10}; - std::vector B = {{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row + start_row_index), false}}; + std::size_t perm_chi[24] = {23, 17, 5, 11, 6, 22, 1, 8, 21, 0, 2, 16, + 15, 19, 12, 7, 3, 4, 14, 18, 9, 20, 13, 10}; + std::vector B = {{component.W(config[prev_index].copy_from.column), + static_cast(config[prev_index].copy_from.row + start_row_index), false}}; for (auto i : perm_chi) { - B.push_back({component.W(config[config_index + i].copy_from.column), static_cast(config[config_index + i].copy_from.row + start_row_index), false}); + B.push_back({component.W(config[config_index + i].copy_from.column), + static_cast(config[config_index + i].copy_from.row + start_row_index), false}); } config_index += 24; prev_index += 25; for (int i = 0; i < 25; ++i) { int x = i % 5; int y = i / 5; - bp.add_copy_constraint({B[x + 5 * y], - {component.W(config[config_index + i].copy_to[0].column), static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({B[(x + 1) % 5 + 5 * y], - {component.W(config[config_index + i].copy_to[1].column), static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); - bp.add_copy_constraint({B[(x + 2) % 5 + 5 * y], - {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); + bp.add_copy_constraint( + {B[x + 5 * y], + {component.W(config[config_index + i].copy_to[0].column), + static_cast(config[config_index + i].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint( + {B[(x + 1) % 5 + 5 * y], + {component.W(config[config_index + i].copy_to[1].column), + static_cast(config[config_index + i].copy_to[1].row + start_row_index), false}}); + bp.add_copy_constraint( + {B[(x + 2) % 5 + 5 * y], + {component.W(config[config_index + i].copy_to[2].column), + static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); } config_index += 25; prev_index += 24; // iota - bp.add_copy_constraint({{component.W(config[prev_index].copy_from.column), static_cast(config[prev_index].copy_from.row + start_row_index), false}, - {component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + start_row_index), false}}); - bp.add_copy_constraint({instance_input.round_constant, - {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); + bp.add_copy_constraint( + {{component.W(config[prev_index].copy_from.column), + static_cast(config[prev_index].copy_from.row + start_row_index), false}, + {component.W(config[config_index].copy_to[0].column), + static_cast(config[config_index].copy_to[0].row + start_row_index), false}}); + bp.add_copy_constraint( + {instance_input.round_constant, + {component.W(config[config_index].copy_to[1].column), + static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); } template void generate_assignments_constant( - const keccak_round_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_round_component::input_type - &instance_input, + const keccak_round_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_round_component; @@ -1582,7 +1778,8 @@ namespace nil { std::size_t row = start_row_index; if (component.last_round_call) { - assignment.constant(component.C(0), row + component.last_round_call_row) = 2097152; // sparse 0x80 + assignment.constant(component.C(0), row + component.last_round_call_row) = + component.sparse_x80; // sparse 0x80 } auto gate_map = component.gates_configuration_map; @@ -1599,59 +1796,57 @@ namespace nil { assignment.constant(component.C(0), row + rotate_rows[i] + 2) = component.all_rot_consts[i][1]; } for (std::size_t i = 5; i < 29; i++) { - assignment.constant(component.C(0), row + rotate_rows[i]) = integral_type(1) << (3 * component_type::rho_offsets[i - 4]); + assignment.constant(component.C(0), row + rotate_rows[i]) = + integral_type(1) << (3 * component_type::rho_offsets[i - 4]); assignment.constant(component.C(0), row + rotate_rows[i] + 1) = component.all_rot_consts[i][0]; assignment.constant(component.C(0), row + rotate_rows[i] + 2) = component.all_rot_consts[i][1]; } } template - typename keccak_round_component::result_type - generate_circuit( - const keccak_round_component - &component, - circuit> - &bp, - assignment> - &assignment, - const typename keccak_round_component::input_type - &instance_input, + typename keccak_round_component::result_type generate_circuit( + const keccak_round_component &component, + circuit> &bp, + assignment> &assignment, + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_round_component; - generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); - - auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); + auto selector_indexes = + generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); std::size_t ind = 0; - std::size_t index = 0; // for (auto g : component.gates_configuration_map) { // for (auto j : g.second) { - // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << ", j: " << j << '\n'; - // assignment.enable_selector(selector_indexes[index], + // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << + // ", j: " << j << '\n'; assignment.enable_selector(selector_indexes[index], // start_row_index + j + 1); // } // std::cout << '\n'; // index++; // } for (auto g : component.gates_configuration_map) { - // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << '\n'; - // if (g.first.first == 5) continue; + // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << + // '\n'; if (g.first.first == 5) continue; for (std::size_t i = 0; i < component.gates_configuration[ind].size(); ++i) { for (auto j : g.second) { // std::cout << j + component.gates_configuration[ind][i].first_coordinate.row + 1 << ' '; - assignment.enable_selector(selector_indexes[index], - start_row_index + j + component.gates_configuration[ind][i].first_coordinate.row + 1); + assignment.enable_selector( + selector_indexes[index], + start_row_index + j + component.gates_configuration[ind][i].first_coordinate.row + 1); } // std::cout << '\n'; index++; } for (std::size_t i = 0; i < component.lookup_gates_configuration[ind].size(); ++i) { for (auto j : g.second) { - //std::cout << start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; - assignment.enable_selector(selector_indexes[index], - start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1); + // std::cout << start_row_index + j + + // component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; + assignment.enable_selector( + selector_indexes[index], + start_row_index + j + + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1); } // std::cout << '\n'; index++; @@ -1660,19 +1855,14 @@ namespace nil { } generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); - return typename component_type::result_type(component, start_row_index); } template - typename keccak_round_component::result_type - generate_assignments( - const keccak_round_component - &component, - assignment> - &assignment, - const typename keccak_round_component::input_type - &instance_input, + typename keccak_round_component::result_type generate_assignments( + const keccak_round_component &component, + assignment> &assignment, + const typename keccak_round_component::input_type &instance_input, const std::uint32_t start_row_index) { using component_type = keccak_round_component; @@ -1708,20 +1898,29 @@ namespace nil { A_1[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = state; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = message; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), + cur_config.copy_to[0].row + strow) = state; + assignment.witness(component.W(cur_config.copy_to[1].column), + cur_config.copy_to[1].row + strow) = message; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = + value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_normalized_chunks[j - 1]); } } // last round call if (component.last_round_call) { value_type state = var_value(assignment, instance_input.inner_state[16]); value_type message = var_value(assignment, instance_input.padded_message_chunk[16]); - value_type sum = state + message + value_type(2097152); + value_type sum = state + message + value_type(component.sparse_x80); integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; auto num_chunks = component.normalize4_num_chunks; @@ -1740,14 +1939,24 @@ namespace nil { A_1[16] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[16]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = state; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = message; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = value_type(2097152); - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), + cur_config.copy_to[0].row + strow) = state; + assignment.witness(component.W(cur_config.copy_to[1].column), + cur_config.copy_to[1].row + strow) = message; + assignment.witness(component.W(cur_config.copy_to[2].column), + cur_config.copy_to[2].row + strow) = value_type(component.sparse_x80); + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = + value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_normalized_chunks[j - 1]); } } for (int i = 17; i < 25; ++i) { @@ -1790,16 +1999,27 @@ namespace nil { C[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = A_1[index + 5]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = A_1[index + 10]; - assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row + strow) = A_1[index + 15]; - assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row + strow) = A_1[index + 20]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + A_1[index]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = + A_1[index + 5]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = + A_1[index + 10]; + assignment.witness(component.W(cur_config.copy_to[3].column), cur_config.copy_to[3].row + strow) = + A_1[index + 15]; + assignment.witness(component.W(cur_config.copy_to[4].column), cur_config.copy_to[4].row + strow) = + A_1[index + 20]; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_normalized_chunks[j - 1]); } } config_index += 5; @@ -1811,10 +2031,14 @@ namespace nil { // ROT std::array C_rot; - integral_type for_bound_smaller = component.calculate_sparse((integral_type(1) << 64) - 1) - component.calculate_sparse((integral_type(1) << 1) - 1); - integral_type for_bound_bigger = component.calculate_sparse((integral_type(1) << 64) - 1) - component.calculate_sparse((integral_type(1) << 63) - 1); - // std::cout << "for_bound_smaller: " << for_bound_smaller << ", for_bound_bigger: " << for_bound_bigger << '\n'; - // std::cout << component.calculate_sparse((integral_type(1) << 64) - 1) << "\n" << component.calculate_sparse((integral_type(1) << 63) - 1) << "\n" << component.calculate_sparse((integral_type(1) << 1) - 1) << "\n"; + integral_type for_bound_smaller = component.calculate_sparse((integral_type(1) << 64) - 1) - + component.calculate_sparse((integral_type(1) << 1) - 1); + integral_type for_bound_bigger = component.calculate_sparse((integral_type(1) << 64) - 1) - + component.calculate_sparse((integral_type(1) << 63) - 1); + // std::cout << "for_bound_smaller: " << for_bound_smaller << ", for_bound_bigger: " << for_bound_bigger + // << '\n'; std::cout << component.calculate_sparse((integral_type(1) << 64) - 1) << "\n" << + // component.calculate_sparse((integral_type(1) << 63) - 1) << "\n" << + // component.calculate_sparse((integral_type(1) << 1) - 1) << "\n"; for (int index = 0; index < 5; ++index) { integral_type integral_C = integral_type(C[index].data); integral_type smaller_part = integral_C >> 189; @@ -1847,18 +2071,30 @@ namespace nil { // std::cout << "check: " << check << ' ' << copy_bound_bigger << '\n'; auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = C[index]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = C_rot[index]; - assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); - assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); - assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); - assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + C[index]; + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = + C_rot[index]; + assignment.witness(component.W(cur_config.constraints[0][1].column), + cur_config.constraints[0][1].row + strow) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].column), + cur_config.constraints[0][2].row + strow) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].column), + cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].column), + cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); - } - assignment.witness(component.W(cur_config.constraints[6][0].column), cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << 3); - assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); + assignment.witness(component.W(cur_config.constraints[3][j].column), + cur_config.constraints[3][j].row + strow) = + value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].column), + cur_config.constraints[5][j].row + strow) = + value_type(integral_big_chunks[j - 1]); + } + assignment.witness(component.W(cur_config.constraints[6][0].column), + cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << 3); + assignment.witness(component.W(cur_config.constraints[6][1].column), + cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); } config_index += 5; // std::cout << "C_rot:\n"; @@ -1890,14 +2126,23 @@ namespace nil { A_2[index] = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_1[index]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = C_rot[(x + 1) % 5]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = C[(x + 4) % 5]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = A_2[index]; + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + A_1[index]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = + C_rot[(x + 1) % 5]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = + C[(x + 4) % 5]; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = A_2[index]; for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_normalized_chunks[j - 1]); } } config_index += 25; @@ -1909,10 +2154,8 @@ namespace nil { // rho/phi value_type B[25]; - std::size_t perm[25] = {1, 10, 7, 11, 17, 18, 3, - 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; + std::size_t perm[25] = {1, 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1}; B[0] = A_2[0]; for (int index = 1; index < 25; ++index) { int x = index % 5; @@ -1925,11 +2168,14 @@ namespace nil { integral_type integral_A_rot = (bigger_part << r) + smaller_part; B[perm[index]] = value_type(integral_A_rot); // integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); - // integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << 192); - integral_type bound_smaller = smaller_part + component.calculate_sparse((integral_type(1) << 64) - 1) - - component.calculate_sparse((integral_type(1) << component.rho_offsets[index]) - 1); - integral_type bound_bigger = bigger_part + component.calculate_sparse((integral_type(1) << 64) - 1) - - component.calculate_sparse((integral_type(1) << (64-component.rho_offsets[index])) - 1); + // integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << + // 192); + integral_type bound_smaller = + smaller_part + component.calculate_sparse((integral_type(1) << 64) - 1) - + component.calculate_sparse((integral_type(1) << component.rho_offsets[index]) - 1); + integral_type bound_bigger = + bigger_part + component.calculate_sparse((integral_type(1) << 64) - 1) - + component.calculate_sparse((integral_type(1) << (64 - component.rho_offsets[index])) - 1); auto copy_bound_smaller = bound_smaller; auto copy_bound_bigger = bound_bigger; auto chunk_size = component.rotate_chunk_size; @@ -1945,18 +2191,31 @@ namespace nil { } auto cur_config = component.full_configuration[index - 1 + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_2[perm[index - 1]]; - assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = value_type(integral_A_rot); - assignment.witness(component.W(cur_config.constraints[0][1].column), cur_config.constraints[0][1].row + strow) = value_type(smaller_part); - assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); - assignment.witness(component.W(cur_config.constraints[3][0].column), cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); - assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + A_2[perm[index - 1]]; + assignment.witness(component.W(cur_config.copy_from.column), cur_config.copy_from.row + strow) = + value_type(integral_A_rot); + assignment.witness(component.W(cur_config.constraints[0][1].column), + cur_config.constraints[0][1].row + strow) = value_type(smaller_part); + assignment.witness(component.W(cur_config.constraints[0][2].column), + cur_config.constraints[0][2].row + strow) = value_type(bigger_part); + assignment.witness(component.W(cur_config.constraints[3][0].column), + cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); + assignment.witness(component.W(cur_config.constraints[5][0].column), + cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[5][j].column), cur_config.constraints[5][j].row + strow) = value_type(integral_big_chunks[j - 1]); - } - assignment.witness(component.W(cur_config.constraints[6][0].column), cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << r); - assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << minus_r); + assignment.witness(component.W(cur_config.constraints[3][j].column), + cur_config.constraints[3][j].row + strow) = + value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[5][j].column), + cur_config.constraints[5][j].row + strow) = + value_type(integral_big_chunks[j - 1]); + } + assignment.witness(component.W(cur_config.constraints[6][0].column), + cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << r); + assignment.witness(component.W(cur_config.constraints[6][1].column), + cur_config.constraints[6][1].row + strow) = + value_type(integral_type(1) << minus_r); } config_index += 24; @@ -1965,7 +2224,8 @@ namespace nil { for (int index = 0; index < 25; ++index) { int x = index % 5; int y = index / 5; - value_type sum = component.sparse_3 - 2 * B[x + 5 * y] + B[(x+1)%5 + 5 * y] - B[(x+2)%5 + 5 * y]; + value_type sum = + component.sparse_3 - 2 * B[x + 5 * y] + B[(x + 1) % 5 + 5 * y] - B[(x + 2) % 5 + 5 * y]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.chi_chunk_size; auto num_chunks = component.chi_num_chunks; @@ -1984,14 +2244,23 @@ namespace nil { A_3[index] = value_type(integral_chi_sum); auto cur_config = component.full_configuration[index + config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = B[x + 5 * y]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = B[(x+1)%5 + 5 * y]; - assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = B[(x+2)%5 + 5 * y]; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_chi_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + B[x + 5 * y]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = + B[(x + 1) % 5 + 5 * y]; + assignment.witness(component.W(cur_config.copy_to[2].column), cur_config.copy_to[2].row + strow) = + B[(x + 2) % 5 + 5 * y]; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = value_type(integral_chi_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_chi_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_chi_chunks[j - 1]); } } config_index += 25; @@ -2019,13 +2288,21 @@ namespace nil { A_4 = value_type(integral_normalized_sum); auto cur_config = component.full_configuration[config_index]; - assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_3[0]; - assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = round_constant; - assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = sum; - assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); + assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = + A_3[0]; + assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = + round_constant; + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = sum; + assignment.witness(component.W(cur_config.constraints[2][0].column), + cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); for (int j = 1; j < num_chunks + 1; ++j) { - assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); - assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[2][j].column), + cur_config.constraints[2][j].row + strow) = + value_type(integral_normalized_chunks[j - 1]); } } // std::cout << "result:\n" << A_4.data << " "; @@ -2039,6 +2316,6 @@ namespace nil { } // namespace components } // namespace blueprint -} // namespace nil +} // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 5b16b8978..093759bd6 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova -// +// 2024 Valeh Farzaliyev // MIT License // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -35,10 +35,12 @@ #include #include #include +#include +#include -#include +// #include #include -#include +// #include #include @@ -49,6 +51,12 @@ #include "../../test_plonk_component.hpp" +const int r[5][5] = {{0, 36, 3, 41, 18}, + {1, 44, 10, 45, 2}, + {62, 6, 43, 15, 61}, + {28, 55, 25, 21, 56}, + {27, 20, 39, 8, 14}}; + template std::size_t number_bits(typename BlueprintFieldType::value_type value) { using value_type = typename BlueprintFieldType::value_type; @@ -63,19 +71,283 @@ std::size_t number_bits(typename BlueprintFieldType::value_type value) { return result; } -template +template +typename BlueprintFieldType::value_type to_sparse(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 1; + power = power << 3; + } + return value_type(result_integral); +} + +template +typename BlueprintFieldType::value_type to_le(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + for (int i = 0; i < 64; ++i) { + integral_type bit = value_integral & 1; + result_integral = (result_integral << 1) + bit; + value_integral = value_integral >> 1; + } + return value_type(result_integral); +} + +template +typename BlueprintFieldType::value_type to_le_bytes(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + for (int i = 0; i < 64; i += 8) { + integral_type bit = value_integral & 0xff; + result_integral = (result_integral << 8) + bit; + value_integral = value_integral >> 8; + } + return value_type(result_integral); +} + +template +typename BlueprintFieldType::value_type unpack(typename BlueprintFieldType::value_type value) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + integral_type value_integral = integral_type(value.data); + integral_type result_integral = 0; + integral_type power = 1; + while (value_integral >= 1) { + integral_type bit = value_integral & 1; + result_integral = result_integral + bit * power; + value_integral = value_integral >> 3; + power = power << 1; + } + return value_type(result_integral); +} + +template +std::vector + padding_function(std::vector message, std::size_t num_bits) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector result; + std::size_t shift = 64 * message.size() - num_bits; + + if (shift > 0) { + // message[message.size() - 1] = message[message.size() - 1] * 2 + value_type(1); + // shift--; + integral_type relay_value = integral_type(message[0].data); + for (int i = 1; i < message.size(); ++i) { + integral_type mask = (integral_type(1) << (64 - shift)) - 1; + integral_type left_part = integral_type(message[i].data >> (64 - shift)); + integral_type right_part = integral_type(message[i].data) & mask; + result.push_back(value_type((relay_value << shift) + left_part)); + relay_value = right_part; + } + relay_value <<= shift; + relay_value += integral_type(1) << (shift - 8); + result.push_back(value_type(relay_value)); + } else { + for (int i = 0; i < message.size(); ++i) { + result.push_back(message[i]); + } + result.push_back(value_type(integral_type(1) << 56)); + } + + while (result.size() % 17 != 0) { + result.push_back(value_type(0)); + } + // result[result.size() - 1] += value_type(1); + + for (int i = 0; i < result.size(); i++) { + result[i] = to_le_bytes(result[i]); + } + + return result; +} + +template +std::array + sparse_round_function(std::array inner_state, + std::array + padded_message_chunk, + typename BlueprintFieldType::value_type RC) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::array, 5> inner_state_integral; + std::array padded_message_chunk_integral; + integral_type RC_integral = integral_type(RC.data); + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state_integral[x][y] = integral_type(inner_state[x + 5 * y].data); + } + } + for (int i = 0; i < 17; ++i) { + padded_message_chunk_integral[i] = integral_type(padded_message_chunk[i].data); + } + + auto rot = [](integral_type x, const int s) { + return ((x << (3 * s)) | (x >> (192 - 3 * s))) & ((integral_type(1) << 192) - 1); + }; + + if (xor_with_mes) { + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + if (last_round_call && (x + 5 * y == 16)) { + continue; + } + if (x + 5 * y < 17) { + inner_state_integral[x][y] = inner_state_integral[x][y] ^ padded_message_chunk_integral[x + 5 * y]; + } + } + } + if (last_round_call) { + value_type last_round_const = to_sparse(value_type(0x8000000000000000)); + integral_type last_round_const_integral = integral_type(last_round_const.data); + inner_state_integral[1][3] = + inner_state_integral[1][3] ^ padded_message_chunk_integral[16] ^ last_round_const_integral; + } + } + // std::cout << "["; + // for (int x = 0; x < 5; ++x) { + // std::cout << "["; + // for (int y = 0; y < 5; ++y) { + // std::cout << unpack(inner_state_integral[x][y]).data << ","; + // } + // std::cout << "],"; + // } + // std::cout << "]\n"; + + // theta + std::array C; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + C[x] ^= inner_state_integral[x][y]; + } + } + std::array D; + for (int x = 0; x < 5; ++x) { + D[x] = C[(x + 4) % 5] ^ rot(C[(x + 1) % 5], 1); + } + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state_integral[x][y] ^= D[x]; + } + } + + // rho and pi + std::array, 5> B; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + B[y][(2 * x + 3 * y) % 5] = rot(inner_state_integral[x][y], r[x][y]); + } + } + + // chi + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state_integral[x][y] = B[x][y] ^ ((~B[(x + 1) % 5][y]) & B[(x + 2) % 5][y]); + } + } + + // iota + inner_state_integral[0][0] = inner_state_integral[0][0] ^ RC_integral; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + inner_state[x + 5 * y] = value_type(inner_state_integral[x][y]); + } + } + return inner_state; +} + +template +std::array + keccak_function(std::vector message, std::size_t num_bits) { + + using value_type = typename BlueprintFieldType::value_type; + + std::array hash; + std::vector padded_message = + padding_function(message, num_bits); + std::array inner_state; + const typename BlueprintFieldType::value_type round_constant[24] = {value_type(1), + value_type(0x8082), + value_type(0x800000000000808a), + value_type(0x8000000080008000), + value_type(0x808b), + value_type(0x80000001), + value_type(0x8000000080008081), + value_type(0x8000000000008009), + value_type(0x8a), + value_type(0x88), + value_type(0x80008009), + value_type(0x8000000a), + value_type(0x8000808b), + value_type(0x800000000000008b), + value_type(0x8000000000008089), + value_type(0x8000000000008003), + value_type(0x8000000000008002), + value_type(0x8000000000000080), + value_type(0x800a), + value_type(0x800000008000000a), + value_type(0x8000000080008081), + value_type(0x8000000000008080), + value_type(0x80000001), + value_type(0x8000000080008008)}; + + std::size_t i = 0, j, x, y; + std::array padded_message_chunk; + // Absorbing + for (i = 0; i < padded_message.size(); i++) { + std::cout << padded_message[i].data << ","; + } + std::cout << std::endl; + + std::size_t p17 = padded_message.size() / 17; + for (i = 0; i < p17; i++) { + for (j = 0; j < 17; j++) + padded_message_chunk[j] = to_sparse(padded_message[17 * i + j]); + for (j = 0; j < 24; j++) { + auto rc = to_sparse(round_constant[j]); + if (j == 0 && i == p17 - 1) { + inner_state = + sparse_round_function(inner_state, padded_message_chunk, rc); + } else if (j == 0) { + inner_state = + sparse_round_function(inner_state, padded_message_chunk, rc); + } else + inner_state = + sparse_round_function(inner_state, padded_message_chunk, rc); + } + } + + for (i = 0; i < 5; i++) { + hash[i] = unpack(inner_state[i]); + } + + return hash; +} + +template auto test_keccak_inner(std::vector message, - std::vector expected_result) { + std::array expected_result, std::size_t num_blocks, + std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; constexpr std::size_t SelectorColumns = 30; - zk::snark::plonk_table_description desc( - WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); + nil::crypto3::zk::snark::plonk_table_description desc(WitnessesAmount, PublicInputColumns, + ConstantColumns, SelectorColumns); using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; - using hash_type = nil::crypto3::hashes::keccak_1600<256>; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; using value_type = typename BlueprintFieldType::value_type; @@ -96,52 +368,109 @@ auto test_keccak_inner(std::vector mess } typename component_type::input_type instance_input = {message_vars}; - auto result_check = [expected_result] - (AssignmentType &assignment, typename component_type::result_type &real_res) { - // std::cout << "sizes: " << expected_result.size() << " " << real_res.padded_message.size() << std::endl; - // assert(expected_result.size() == real_res.padded_message.size()); + auto result_check = [expected_result](AssignmentType &assignment, typename component_type::result_type &real_res) { + std::cout << "sizes: " << expected_result.size() << " " << real_res.final_inner_state.size() << std::endl; + assert(expected_result.size() == real_res.final_inner_state.size()); for (int i = 0; i < expected_result.size(); ++i) { - // std::cout << "res:\n" << expected_result[i].data << "\n" << var_value(assignment, real_res.padded_message[i]).data << std::endl; - // assert(expected_result[i] == var_value(assignment, real_res.padded_message[i])); + std::cout << "res:\n" + << expected_result[i].data << "\n" + << var_value(assignment, real_res.final_inner_state[i]).data << std::endl; + assert(expected_result[i] == var_value(assignment, real_res.final_inner_state[i])); } }; if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { - BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!") ; + BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!"); } std::array witnesses; for (std::uint32_t i = 0; i < WitnessesAmount; i++) { witnesses[i] = i; } - component_type component_instance = component_type(witnesses, std::array{0}, std::array{0}, - num_blocks, num_bits, range_check_input, limit_permutation_column); + component_type component_instance = + component_type(witnesses, std::array {0}, std::array {0}, num_blocks, + num_bits, range_check_input, limit_permutation_column); nil::crypto3::test_component( component_instance, desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); + nil::blueprint::connectedness_check_type::type::NONE, num_blocks, num_bits, range_check_input, + limit_permutation_column); } // works -template -void test_keccak_0() { +template +void test_keccak_0(std::size_t num_bytes = 1) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::vector message = {1, 2}; - const std::size_t num_blocks = 2; - const std::size_t num_bits = 65; + std::vector message; + std::size_t num_blocks = (num_bytes + 7) / 8; + std::size_t num_bits = num_bytes * 8; + + message.resize(num_blocks); + for (std::size_t i = 0; i < num_blocks; i++) { + message[i] = value_type(0); + } const bool range_check_input = true; const std::size_t limit_permutation_column = 7; - std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::array expected_result = keccak_function(message, num_bits); + + std::cout << expected_result[0].data << " " << expected_result[1].data << " " << expected_result[2].data << " " + << expected_result[3].data << std::endl; + + // std::cout << std::hex << message[0].data << std::endl; + integral_type result = integral_type(expected_result[0].data); + result = (result << 64) + integral_type(expected_result[1].data); + result = (result << 64) + integral_type(expected_result[2].data); + result = (result << 64) + integral_type(expected_result[3].data); + + // std::cout << std::hex << expected_result[0].data << std::endl; + // std::cout << std::hex << expected_result[1].data << std::endl; + // std::cout << std::hex << expected_result[2].data << std::endl; + // std::cout << std::hex << expected_result[3].data << std::endl; + + // std::cout << std::hex << result << std::endl; + + test_keccak_inner(message, expected_result, num_blocks, num_bits, + range_check_input, limit_permutation_column); +} + +template +void test_keccak_hello_world() { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector message = {value_type(0x68656c), value_type(0x6c6f20776f726c64)}; + const std::size_t num_blocks = 2; + const std::size_t num_bits = 88; + const bool range_check_input = false; + const std::size_t limit_permutation_column = 7; + + std::array expected_result = keccak_function(message, num_bits); + + std::cout << expected_result[0].data << " " << expected_result[1].data << " " << expected_result[2].data << " " + << expected_result[3].data << std::endl; + + // std::cout << std::hex << message[0].data << std::endl; + integral_type result = integral_type(expected_result[0].data); + result = (result << 64) + integral_type(expected_result[1].data); + result = (result << 64) + integral_type(expected_result[2].data); + result = (result << 64) + integral_type(expected_result[3].data); + + // std::cout << std::hex << expected_result[0].data << std::endl; + // std::cout << std::hex << expected_result[1].data << std::endl; + // std::cout << std::hex << expected_result[2].data << std::endl; + // std::cout << std::hex << expected_result[3].data << std::endl; + + // std::cout << std::hex << result << std::endl; - test_keccak_inner(message, expected_result); + test_keccak_inner(message, expected_result, num_blocks, num_bits, + range_check_input, limit_permutation_column); } template void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = true, bool range_check_input = true, - std::size_t limit_permutation_column = 7) { + std::size_t limit_permutation_column = 7) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -154,8 +483,10 @@ void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = tr if (random_mask_zero) { power_for_mask = dis(gen) % 63 + 1; } - integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; - value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; + ; + value_type message_zero = + value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -165,9 +496,11 @@ void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = tr std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); std::size_t num_blocks = message_size; - std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector expected_result = { + value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - test_keccak_inner(message, expected_result); + test_keccak_inner(message, expected_result, num_blocks, num_bits, + range_check_input, limit_permutation_column); } // template(); - test_keccak_0(); + // test_keccak_round_random(1); + // test_keccak_0(136); + test_keccak_0(136); + test_keccak_hello_world(); // test_keccak_round_random(); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 2e4f4b213..73f122322 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -1,6 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova -// +// 2024 Valeh Farzaliyev // MIT License // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -36,9 +36,9 @@ #include #include -#include +// #include #include -#include +// #include #include @@ -62,6 +62,7 @@ std::size_t number_bits(typename BlueprintFieldType::value_type value) { return result; } + template std::vector padding_function(std::vector message, std::size_t num_bits) { @@ -80,30 +81,33 @@ std::vector result.push_back(value_type((relay_value << shift) + left_part)); relay_value = right_part; } - result.push_back(value_type(relay_value << shift)); + relay_value <<= shift; + relay_value += integral_type(1) << (shift - 8); + result.push_back(value_type(relay_value)); } else { for (int i = 0; i < message.size(); ++i) { result.push_back(message[i]); } + result.push_back(value_type(integral_type(1) << 56)); } while (result.size() % 17 != 0) { result.push_back(value_type(0)); } + return result; } template auto test_keccak_padding_inner(std::vector message, std::vector expected_result, - const std::size_t num_blocks, const std::size_t num_bits, const bool range_check_input = true, - const std::size_t limit_permutation_column = 7) { + const std::size_t num_blocks, const std::size_t num_bits, + const bool range_check_input = true, const std::size_t limit_permutation_column = 7) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; constexpr std::size_t SelectorColumns = 12; - zk::snark::plonk_table_description desc( - WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); - using ArithmetizationType = - nil::crypto3::zk::snark::plonk_constraint_system; + nil::crypto3::zk::snark::plonk_table_description desc(WitnessesAmount, PublicInputColumns, + ConstantColumns, SelectorColumns); + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; @@ -127,6 +131,8 @@ auto test_keccak_padding_inner(std::vector {0}, - std::array {0}, num_blocks, num_bits, - range_check_input, limit_permutation_column); + component_type component_instance = + component_type(witnesses, std::array {0}, std::array {0}, num_blocks, + num_bits, range_check_input, limit_permutation_column); nil::crypto3::test_component( component_instance, desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); + nil::blueprint::connectedness_check_type::type::NONE, num_blocks, num_bits, range_check_input, + limit_permutation_column); } // works @@ -155,9 +162,9 @@ void test_keccak_padding_0() { std::vector message = {0}; const std::size_t num_blocks = 1; - const std::size_t num_bits = 1; + const std::size_t num_bits = 8; - std::vector expected_result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector expected_result = {281474976710656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; test_keccak_padding_inner(message, expected_result, num_blocks, num_bits); @@ -167,16 +174,13 @@ void test_keccak_padding_1(std::size_t num_bits) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::vector message = {value_type(integral_type(1) << (num_bits-1)%64)}; - for (std::size_t i = 0; i < (num_bits-1)/64; i++) { + std::vector message = {value_type(integral_type(1) << (num_bits - 1) % 64)}; + for (std::size_t i = 0; i < (num_bits - 1) / 64; i++) { message.push_back(value_type(0)); } const std::size_t num_blocks = message.size(); - std::vector expected_result = {value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (std::size_t i = 0; i < (num_blocks-1) / 17; i++) { - expected_result.insert(expected_result.end(), {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - } + auto expected_result = padding_function(message, num_bits); test_keccak_padding_inner(message, expected_result, num_blocks, num_bits); @@ -197,8 +201,10 @@ void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero if (random_mask_zero) { power_for_mask = dis(gen) % 63 + 1; } - integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; - value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; + value_type message_zero = + value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -210,14 +216,13 @@ void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero auto expected_result = padding_function(message, num_bits); - test_keccak_padding_inner(message, expected_result, - num_blocks, num_bits, - range_check_input, limit_permutation_column); + test_keccak_padding_inner( + message, expected_result, num_blocks, num_bits, range_check_input, limit_permutation_column); } template -void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits, bool random_mask_zero = true, bool range_check_input = true, - std::size_t limit_permutation_column = 7) { +void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits, bool random_mask_zero = true, + bool range_check_input = true, std::size_t limit_permutation_column = 7) { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; @@ -230,8 +235,9 @@ void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits if (random_mask_zero) { power_for_mask = dis(gen) % 63 + 1; } - integral_type mask_zero = (integral_type(1) << power_for_mask) - 1;; - value_type message_zero = value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; + value_type message_zero = + value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -249,9 +255,8 @@ void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits num_bits += 1; } - test_keccak_padding_inner(message, expected_result, - num_blocks, num_bits, - range_check_input, limit_permutation_column); + test_keccak_padding_inner( + message, expected_result, num_blocks, num_bits, range_check_input, limit_permutation_column); } BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) @@ -263,7 +268,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { for (std::size_t i = 1; i < 100; i++) { test_keccak_padding_1(i); test_keccak_padding_random(i); - test_keccak_padding_random(i, false); + test_keccak_padding_random(i, false); test_keccak_padding_random(i, true, false); test_keccak_padding_random(i, false, false); } @@ -310,4 +315,4 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { // test_to_fail_keccak_padding_random(5, false, true); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 77c5342bc..66ba5423f 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -1,5 +1,6 @@ //---------------------------------------------------------------------------// // Copyright (c) 2023 Polina Chernyshova +// 2024 Valeh Farzaliyev // // MIT License // @@ -36,9 +37,9 @@ #include #include -#include +// #include #include -#include +// #include #include @@ -162,7 +163,7 @@ auto test_keccak_round_inner(std::array desc( + nil::crypto3::zk::snark::plonk_table_description desc( WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; using AssignmentType = nil::blueprint::assignment; @@ -214,7 +215,7 @@ auto test_keccak_round_inner(std::array( boost::get(component_instance), desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::STRONG, + nil::blueprint::connectedness_check_type::type::NONE, xor_with_mes, last_round_call, last_perm_col); } @@ -377,11 +378,10 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_not_random(); - // test_keccak_round_not_random(); // xor_with_mes, last_round_call - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); @@ -389,10 +389,11 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + // test_keccak_round_not_random(); // test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); // test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); } From e40594cbd45023a1f5a0445ee8456cb666e68e7b Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Tue, 30 Apr 2024 13:35:47 +0400 Subject: [PATCH 35/48] Master rebase + warning fixes. --- .../hashes/keccak/keccak_component.hpp | 63 +++---- .../hashes/keccak/keccak_padding.hpp | 43 ++--- .../components/hashes/keccak/keccak_round.hpp | 41 ++-- include/nil/blueprint/lookup_library.hpp | 12 +- test/hashes/plonk/keccak.cpp | 7 +- test/hashes/plonk/keccak_padding.cpp | 11 +- test/hashes/plonk/keccak_round.cpp | 8 +- test/test_plonk_component.hpp | 177 ++++++++++++------ 8 files changed, 198 insertions(+), 164 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index f5a98159e..cabfb9d19 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -60,13 +60,9 @@ namespace nil { using round_component_type = keccak_round>; - round_component_type round_tt; - round_component_type round_tf; - round_component_type round_ff; using padding_component_type = keccak_padding>; - padding_component_type padding; using manifest_type = nil::blueprint::plonk_component_manifest; class gate_manifest_type : public component_gate_manifest { @@ -92,18 +88,16 @@ namespace nil { }; static gate_manifest get_gate_manifest(std::size_t witness_amount, - std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - std::size_t num_round_calls = calculate_num_round_calls(num_blocks); gate_manifest manifest = gate_manifest(gate_manifest_type( witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)); manifest.merge_with(padding_component_type::get_gate_manifest( - witness_amount, lookup_column_amount, num_blocks, num_bits, range_check_input)); - manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, lookup_column_amount, + witness_amount, num_blocks, num_bits, range_check_input)); + manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, true, true, limit_permutation_column)); // manifest.merge_with(round_component_type::get_gate_manifest( // witness_amount, lookup_column_amount, true, false, limit_permutation_column)); @@ -113,11 +107,14 @@ namespace nil { return manifest; } - static manifest_type get_manifest() { + static manifest_type get_manifest( + std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t lpc = 7 + ) { static manifest_type manifest = manifest_type(std::shared_ptr(new manifest_range_param(9, 15)), false) - .merge_with(padding_component_type::get_manifest()) - .merge_with(round_component_type::get_manifest()); + .merge_with(padding_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)) + .merge_with(round_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)); return manifest; } @@ -148,6 +145,11 @@ namespace nil { const std::size_t pack_cells = 2 * (pack_num_chunks + 1); const std::size_t pack_buff = (this->witness_amount() == 15) * 2; + padding_component_type padding; + round_component_type round_tt; + round_component_type round_tf; + round_component_type round_ff; + std::vector full_configuration = configure_all(this->witness_amount(), num_configs, num_round_calls, limit_permutation_column); const std::map> gates_configuration_map = configure_map( @@ -155,7 +157,7 @@ namespace nil { const std::vector> gates_configuration = configure_gates( this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); - const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, + const std::size_t rows_amount = get_rows_amount(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); @@ -212,7 +214,7 @@ namespace nil { false); } } - std::vector all_vars() const { + std::vector> all_vars() { return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], final_inner_state[4]}; } @@ -353,13 +355,13 @@ namespace nil { // for (std::size_t index = 0; index < num_round_calls; ++index) { // for (std::size_t i = 0; i < 24; ++i) { // if (index == num_round_calls - 1 && i == 0) { - // row += round_component_type::get_rows_amount(witness_amount, 0, true, true, + // row += round_component_type::get_rows_amount(witness_amount, true, true, // limit_permutation_column); // } else if (i == 0) { - // row += round_component_type::get_rows_amount(witness_amount, 0, true, false, + // row += round_component_type::get_rows_amount(witness_amount, true, false, // limit_permutation_column); // } else { - // row += round_component_type::get_rows_amount(witness_amount, 0, false, false, + // row += round_component_type::get_rows_amount(witness_amount, false, false, // limit_permutation_column); // } // } @@ -508,24 +510,24 @@ namespace nil { return result; } - static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t lookup_column_amount, + static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { std::size_t num_round_calls = calculate_num_round_calls(num_blocks); std::size_t res = - padding_component_type::get_rows_amount(witness_amount, lookup_column_amount, num_blocks, + padding_component_type::get_rows_amount(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); // + round_tt_rows for (std::size_t i = 0; i < num_round_calls; i++) { if (i == num_round_calls - 1) { - res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, true, + res += round_component_type::get_rows_amount(witness_amount, true, true, limit_permutation_column); } else { - res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, true, + res += round_component_type::get_rows_amount(witness_amount, true, false, limit_permutation_column); } for (std::size_t j = 1; j < 24; ++j) { - res += round_component_type::get_rows_amount(witness_amount, lookup_column_amount, false, + res += round_component_type::get_rows_amount(witness_amount, false, false, limit_permutation_column); } } @@ -570,11 +572,12 @@ namespace nil { keccak(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_, std::size_t lpc_ = 7) : - component_type(witness, constant, public_input, get_manifest()), + component_type(witness, constant, public_input, + get_manifest(num_blocks_, num_bits_, range_check_input_, lpc_)), num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), limit_permutation_column(lpc_), - padding(witness, constant, public_input, num_blocks_, num_bits_, range_check_input_, lpc_), num_round_calls(calculate_num_round_calls(num_blocks_)), + padding(witness, constant, public_input, num_blocks_, num_bits_, range_check_input_, lpc_), round_tt(witness, constant, public_input, true, true, lpc_), round_tf(witness, constant, public_input, true, false, lpc_), round_ff(witness, constant, public_input, false, false, lpc_) { @@ -624,17 +627,11 @@ namespace nil { using component_type = keccak_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; - using gate_type = typename crypto3::zk::snark::plonk_gate; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; - using lookup_gate_type = - typename crypto3::zk::snark::plonk_gate; - using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; std::vector selector_indexes; auto gates_configuration = component.gates_configuration; - std::size_t gate_index = 0; - std::size_t lookup_gate_index = 0; for (auto config : gates_configuration) { std::vector lookup_constraints_0; @@ -677,10 +674,8 @@ namespace nil { } selector_indexes.push_back(bp.add_gate({constraint_0, constraint_1})); selector_indexes.push_back(bp.add_gate({constraint_2})); - gate_index++; selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); - lookup_gate_index += 2; } return selector_indexes; @@ -701,7 +696,6 @@ namespace nil { std::uint32_t cur_row = start_row_index; std::size_t config_index = 0; - std::size_t prev_index = 0; auto config = component.full_configuration; auto padded_message = @@ -719,7 +713,6 @@ namespace nil { (config[config_index - 1].last_coordinate.column > 0); std::array inner_state; - auto prev_row = cur_row; auto gate_map_tf = component.round_tf.gates_configuration_map; std::vector rotate_rows_tf; @@ -930,7 +923,6 @@ namespace nil { std::vector integral_chunks; std::vector integral_sparse_chunks; integral_type mask = (integral_type(1) << chunk_size) - 1; - integral_type sparse_mask = (integral_type(1) << (chunk_size * 3)) - 1; integral_type power = 1; for (std::size_t j = 0; j < num_chunks; ++j) { @@ -1061,9 +1053,6 @@ namespace nil { const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = keccak_component; - using integral_type = typename BlueprintFieldType::integral_type; - std::size_t row = start_row_index + 4; for (std::size_t i = 0; i < 24; ++i) { assignment.constant(component.C(0), row + i) = component.pack(component.round_constant[i]); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index bf4aeda8a..0fa9cdf90 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -145,7 +145,6 @@ namespace nil { }; static gate_manifest get_gate_manifest(std::size_t witness_amount, - std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, @@ -155,7 +154,12 @@ namespace nil { return manifest; } - static manifest_type get_manifest() { + static manifest_type get_manifest( + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column = 7 + ) { static manifest_type manifest = manifest_type(std::shared_ptr( new nil::blueprint::manifest_single_value_param(9)), @@ -166,13 +170,13 @@ namespace nil { static const std::size_t lookup_rows = 65536; static const std::size_t num_chunks = 8; - const std::size_t limit_permutation_column = 7; - const bool range_check_input; - const std::size_t num_blocks; const std::size_t num_bits; - std::size_t shift = calculate_shift(num_blocks, num_bits); - std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks, shift); + const bool range_check_input; + const std::size_t limit_permutation_column = 7; + + const std::size_t shift = calculate_shift(num_blocks, num_bits); + const std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks, shift); const integral_type padding_delimiter = integral_type(1) << 56; @@ -189,7 +193,7 @@ namespace nil { std::vector gates_rows = calculate_gates_rows(this->witness_amount()); const std::size_t rows_amount = - get_rows_amount(this->witness_amount(), 0, num_blocks, num_bits, range_check_input, limit_permutation_column); + get_rows_amount(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input); struct input_type { @@ -225,8 +229,11 @@ namespace nil { } } - std::vector all_vars() const { - return padded_message; + std::vector> all_vars() { + std::vector> res; + res.reserve(padded_message.size()); + res.insert(res.end(), padded_message.begin(), padded_message.end()); + return res; } }; @@ -628,8 +635,8 @@ namespace nil { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); return map.size() * 2 + range_check_input + 2; } + static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t lookup_column_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, @@ -653,7 +660,8 @@ namespace nil { keccak_padding(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_ = true, std::size_t limit_permutation_column_ = 7) : - component_type(witness, constant, public_input, get_manifest()), + component_type(witness, constant, public_input, + get_manifest(num_blocks_, num_bits_, range_check_input_, limit_permutation_column_)), num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), limit_permutation_column(limit_permutation_column_) {}; @@ -663,7 +671,8 @@ namespace nil { std::initializer_list public_inputs, std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_ = true, std::size_t limit_permutation_column_ = 7) : - component_type(witnesses, constants, public_inputs, get_manifest()), + component_type(witnesses, constants, public_inputs, + get_manifest(num_blocks_, num_bits_, range_check_input_, limit_permutation_column_)), num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), limit_permutation_column(limit_permutation_column_) {}; @@ -688,15 +697,11 @@ namespace nil { using component_type = padding_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; - using gate_type = typename crypto3::zk::snark::plonk_gate; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; - using lookup_gate_type = typename crypto3::zk::snark::plonk_gate; - using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; std::vector selector_indexes; auto gates_configuration = component.gates_configuration; - std::size_t config_index = 0; std::size_t gate_index = 0; std::size_t lookup_gate_index = 0; int32_t row_shift = (component.shift == 0 || component.witness_amount() == 15) ? 0 : 1; @@ -827,7 +832,6 @@ namespace nil { std::size_t strow = start_row_index; std::size_t config_index = 0; std::size_t input_index = 0; - std::size_t witness_amount = component.witness_amount(); std::size_t conf_index_for_input = 0; if (component.shift != 0) { @@ -872,7 +876,6 @@ namespace nil { const std::uint32_t start_row_index) { using component_type = padding_component; - using var = typename component_type::var; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); assignment.enable_selector(selector_indexes[0], start_row_index + 1); @@ -927,7 +930,6 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; std::size_t config_index = 0; - std::size_t witness_amount = component.witness_amount(); // range_check shift integral_type mask_range_check = (integral_type(1) << 8) - 1; integral_type shift = component.shift; @@ -1029,7 +1031,6 @@ namespace nil { const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - using component_type = padding_component; using value_type = typename BlueprintFieldType::value_type; assignment.constant(component.C(0), start_row_index) = 0; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 6524b567d..1c93bb0ba 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -158,7 +158,6 @@ namespace nil { }; static gate_manifest get_gate_manifest(std::size_t witness_amount, - std::size_t lookup_column_amount, bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { @@ -167,7 +166,12 @@ namespace nil { return manifest; } - static manifest_type get_manifest() { + static manifest_type get_manifest( + bool xor_with_mes, + bool last_round_call, + std::size_t limit_permutation_column, + std::size_t lpc_ = 7 + ) { static manifest_type manifest = manifest_type(std::shared_ptr(new manifest_range_param(9, 15)), false); return manifest; @@ -285,7 +289,7 @@ namespace nil { const std::size_t rotate_buff = calculate_buff(this->witness_amount(), lookup_rows); const std::size_t rows_amount = - get_rows_amount(this->witness_amount(), 0, xor_with_mes, last_round_call, limit_permutation_column); + get_rows_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); // full configuration is precalculated, then used in other functions const std::size_t full_configuration_size = 17 * xor_with_mes + 85; @@ -340,8 +344,8 @@ namespace nil { } } - std::vector all_vars() const { - std::vector result; + std::vector> all_vars() { + std::vector> result; result.insert(result.end(), inner_state.begin(), inner_state.end()); return result; } @@ -899,7 +903,6 @@ namespace nil { std::size_t limit_permutation_column) { auto full_configuration = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); - auto rows_amount = full_configuration.back().last_coordinate.row + 1; std::vector> result; auto gates_configuration_map = configure_map(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); @@ -996,7 +999,6 @@ namespace nil { } static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t lookup_column_amount, bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { @@ -1051,7 +1053,8 @@ namespace nil { keccak_round(WitnessContainerType witness, ConstantContainerType constant, PublicInputContainerType public_input, bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : - component_type(witness, constant, public_input, get_manifest()), + component_type(witness, constant, public_input, + get_manifest(xor_with_mes_, last_round_call_, lpc_)), xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { // check_params(); }; @@ -1065,7 +1068,8 @@ namespace nil { bool xor_with_mes_ = false, bool last_round_call_ = false, std::size_t lpc_ = 7) : - component_type(witnesses, constants, public_inputs, get_manifest()), + component_type(witnesses, constants, public_inputs, + get_manifest(xor_with_mes_, last_round_call_, lpc_)), xor_with_mes(xor_with_mes_), last_round_call(last_round_call_), limit_permutation_column(lpc_) { // check_params(); }; @@ -1086,19 +1090,13 @@ namespace nil { using component_type = keccak_round_component; using var = typename component_type::var; using constraint_type = crypto3::zk::snark::plonk_constraint; - using gate_type = typename crypto3::zk::snark::plonk_gate; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; - using lookup_gate_type = - typename crypto3::zk::snark::plonk_gate; - using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; using configuration = typename component_type::configuration; auto gate_map = component.gates_configuration_map; auto gate_config = component.gates_configuration; auto lookup_gate_config = component.lookup_gates_configuration; - std::size_t gate_index = 0; - std::size_t lookup_gate_index = 0; std::vector selector_indexes; std::vector constraints; @@ -1602,8 +1600,6 @@ namespace nil { std::size_t prev_index = 0; auto config = component.full_configuration; - std::size_t num_copy_constr = 0; - if (component.xor_with_mes) { // inner_state ^ chunk for (int i = 0; i < 17 - component.last_round_call; ++i) { @@ -1615,7 +1611,6 @@ namespace nil { {instance_input.padded_message_chunk[i], var(component.W(config[i].copy_to[1].column), static_cast(config[i].copy_to[1].row + start_row_index), false)}); - num_copy_constr += 2; } config_index += 16; if (component.last_round_call) { @@ -1632,7 +1627,6 @@ namespace nil { var::column_type::constant), var(component.W(config[config_index].copy_to[2].column), static_cast(config[config_index].copy_to[2].row + start_row_index), false)}); - num_copy_constr += 3; } config_index += 1; @@ -1644,7 +1638,6 @@ namespace nil { {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); - num_copy_constr += 1; } for (int i = 17; i < 25; ++i) { bp.add_copy_constraint( @@ -1652,7 +1645,6 @@ namespace nil { {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); - num_copy_constr += 1; } config_index += 5; prev_index += 17; @@ -1663,7 +1655,6 @@ namespace nil { {component.W(config[config_index + i % 5].copy_to[i / 5].column), static_cast(config[config_index + i % 5].copy_to[i / 5].row + start_row_index), false}}); - num_copy_constr += 1; } config_index += 5; } @@ -1679,7 +1670,6 @@ namespace nil { var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); - num_copy_constr += 2; } config_index += 5; prev_index += 5; @@ -1701,7 +1691,6 @@ namespace nil { static_cast(config[prev_index + (x + 4) % 5].copy_to[0].row + start_row_index), false}, {component.W(config[config_index + i].copy_to[2].column), static_cast(config[config_index + i].copy_to[2].row + start_row_index), false}}); - num_copy_constr += 3; } config_index += 25; prev_index += 5; @@ -1868,7 +1857,6 @@ namespace nil { using component_type = keccak_round_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - using var = typename component_type::var; std::size_t strow = start_row_index; int config_index = 0; @@ -2106,7 +2094,6 @@ namespace nil { std::array A_2; for (int index = 0; index < 25; ++index) { int x = index % 5; - int y = index / 5; value_type sum = A_1[index] + C_rot[(x + 1) % 5] + C[(x + 4) % 5]; integral_type integral_sum = integral_type(sum.data); auto chunk_size = component.normalize4_chunk_size; @@ -2158,8 +2145,6 @@ namespace nil { 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1}; B[0] = A_2[0]; for (int index = 1; index < 25; ++index) { - int x = index % 5; - int y = index / 5; int r = 3 * component.rho_offsets[index]; int minus_r = 192 - r; integral_type integral_A = integral_type(A_2[perm[index - 1]].data); diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index 424268b5c..d2fc8783a 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -120,9 +120,6 @@ namespace nil { virtual std::size_t get_rows_number(){ return 256; } }; protected: - std::shared_ptr binary_xor_table; - std::shared_ptr keccak_pack_table; - bool reserved_all; class binary_and_table_type : public lookup_table_definition{ public: @@ -357,7 +354,7 @@ namespace nil { virtual std::size_t get_columns_number(){ return 1; } virtual std::size_t get_rows_number(){ return 129; } }; - + class normalize_base8_table_type : public lookup_table_definition{ std::size_t base; virtual std::array to_base(std::size_t base, typename BlueprintFieldType::integral_type num) { @@ -371,7 +368,7 @@ namespace nil { power <<= 3; } return {result, normalized_result}; - } + } public: normalize_base8_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { this->subtables["full"] = {{0,1}, 0, 65536}; @@ -400,7 +397,6 @@ namespace nil { typename BlueprintFieldType::integral_type result = 0; typename BlueprintFieldType::integral_type chi_result = 0; typename BlueprintFieldType::integral_type power = 1; - typename BlueprintFieldType::integral_type mask = 7; while (num > 0) { result = result + (num % base) * power; chi_result = chi_result + table[int(num % base)] * power; @@ -429,7 +425,7 @@ namespace nil { virtual std::size_t get_columns_number(){ return 2; } virtual std::size_t get_rows_number(){ return 65536; } }; - + public: using bimap_type = boost::bimap, boost::bimaps::set_of>; using left_reserved_type = typename bimap_type::left_map; @@ -450,7 +446,7 @@ namespace nil { tables["keccak_sign_bit_table"] = std::shared_ptr(new sparse_values_base8_sign_bit_table()); tables["keccak_normalize3_table"] = std::shared_ptr(new normalize_base8_table_type(3)); tables["keccak_normalize4_table"] = std::shared_ptr(new normalize_base8_table_type(4)); - tables["keccak_normalize6_table"] = std::shared_ptr(new normalize_base8_table_type(6)); + tables["keccak_normalize6_table"] = std::shared_ptr(new normalize_base8_table_type(6)); tables["keccak_chi_table"] = std::shared_ptr(new chi_table_type()); } diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 093759bd6..d50f574b4 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -59,7 +59,6 @@ const int r[5][5] = {{0, 36, 3, 41, 18}, template std::size_t number_bits(typename BlueprintFieldType::value_type value) { - using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; integral_type integral_value = integral_type(value.data); @@ -303,7 +302,7 @@ std::array value_type(0x80000001), value_type(0x8000000080008008)}; - std::size_t i = 0, j, x, y; + std::size_t i = 0, j; std::array padded_message_chunk; // Absorbing for (i = 0; i < padded_message.size(); i++) { @@ -350,8 +349,6 @@ auto test_keccak_inner(std::vector mess using hash_type = nil::crypto3::hashes::keccak_1600<256>; constexpr std::size_t Lambda = 1; - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; using component_type = nil::blueprint::components::keccak; using var = nil::crypto3::zk::snark::plonk_variable; @@ -486,7 +483,7 @@ void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = tr integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; ; value_type message_zero = - value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + value_type((integral_type(dis(gen)) & mask_zero) | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 73f122322..23f27e310 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -112,8 +112,6 @@ auto test_keccak_padding_inner(std::vector; constexpr std::size_t Lambda = 1; - using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; using component_type = nil::blueprint::components::keccak_padding; using var = typename component_type::var; @@ -158,7 +156,6 @@ auto test_keccak_padding_inner(std::vector void test_keccak_padding_0() { using value_type = typename BlueprintFieldType::value_type; - using integral_type = typename BlueprintFieldType::integral_type; std::vector message = {0}; const std::size_t num_blocks = 1; @@ -203,7 +200,7 @@ void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero } integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; value_type message_zero = - value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + value_type((integral_type(dis(gen)) & mask_zero) | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); @@ -237,7 +234,7 @@ void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits } integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; value_type message_zero = - value_type(integral_type(dis(gen)) & mask_zero | (integral_type(1) << (power_for_mask - 1))); + value_type((integral_type(dis(gen)) & mask_zero) | (integral_type(1) << (power_for_mask - 1))); std::vector message; message.push_back(message_zero); for (std::size_t i = 1; i < message_size; i++) { @@ -268,7 +265,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { for (std::size_t i = 1; i < 100; i++) { test_keccak_padding_1(i); test_keccak_padding_random(i); - test_keccak_padding_random(i, false); + test_keccak_padding_random(i, false); test_keccak_padding_random(i, true, false); test_keccak_padding_random(i, false, false); } @@ -288,8 +285,8 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test with no result_check asserts + // using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_to_fail_keccak_padding_random(10, false); // test_to_fail_keccak_padding_random(16, false, false); diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 66ba5423f..091d30095 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -221,6 +221,9 @@ auto test_keccak_round_inner(std::array void test_keccak_round_not_random() { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wimplicitly-unsigned-literal" + using value_type = typename BlueprintFieldType::value_type; std::array padded_message_chunk = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; @@ -334,6 +337,9 @@ void test_keccak_round_not_random() { 16959053435453822517, 12224711289652453635, 9342009439668884831, 4879704952849025062, 140226327413610143, 424854978622500449, 7259519967065370866, 7004910057750291985, 13293599522548616907, 10105770293752443592, 10668034807192757780, 1747952066141424100, 1654286879329379778, 8500057116360352059, 16929593379567477321}; + + #pragma clang diagnostic pop + for (int i = 0; i < 25; ++i) { expected_result[i] = to_sparse(expected_result[i]); } @@ -388,7 +394,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + // using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_not_random(); // test_keccak_round_random(); // test_keccak_round_random(); diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index c0ad265ce..b51a5a369 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -187,10 +187,9 @@ namespace nil { blueprint::connectedness_check_type connectedness_check, ComponentStaticInfoArgs... component_static_info_args) { using component_type = ComponentType; + blueprint::circuit> bp; + blueprint::assignment> assignment(desc); - blueprint::circuit bp; - blueprint::assignment assignment; - if constexpr( nil::blueprint::use_lookups() ){ auto lookup_tables = component_instance.component_lookup_tables(); for(auto &[k,v]:lookup_tables){ @@ -200,7 +199,11 @@ namespace nil { static boost::random::mt19937 gen; static boost::random::uniform_int_distribution<> dist(0, 100); - std::size_t start_row = 0;//dist(gen); + std::size_t start_row = 0; // dist(gen); + // resize to ensure that if the component is empty by default (e.g. a component which only uses batching) + if (start_row != 0) { + assignment.witness(0, start_row - 1) = 0; + } if constexpr (PrivateInput) { for (std::size_t i = 0; i < public_input.size(); i++) { @@ -212,81 +215,96 @@ namespace nil { } } + blueprint::components::generate_circuit( + component_instance, bp, assignment, instance_input, start_row); auto component_result = boost::get( - blueprint::components::generate_empty_assignments( - component_instance, assignment, instance_input, start_row)); - // assignment.export_table(std::cout); - // bp.export_circuit(std::cout); - result_check(assignment, component_result); - - if constexpr (!PrivateInput) { - bool is_connected; - if (connectedness_check == detail::connectedness_check_type::STRONG) { - is_connected = check_strong_connectedness( - assignment, - bp, - instance_input.all_vars(), - component_result.all_vars(), start_row, component_instance.rows_amount); - } else if (connectedness_check == detail::connectedness_check_type::WEAK) { - is_connected = check_weak_connectedness( - assignment, - bp, - instance_input.all_vars(), - component_result.all_vars(), start_row, component_instance.rows_amount); - } else if (connectedness_check == detail::connectedness_check_type::NONE) { - is_connected = true; - std::cout << "WARNING: connectedness check disabled" << std::endl; - } - - // Uncomment the following if you want to output a visual representation of the connectedness graph. - // I recommend turning off the starting row randomization - - // auto zones = blueprint::detail::generate_connectedness_zones( - // assignment, bp, instance_input.all_vars(), start_row, component_instance.rows_amount); - // blueprint::detail::export_connectedness_zones( - // zones, assignment, instance_input.all_vars(), start_row, component_instance.rows_amount, std::cout); + assigner(component_instance, assignment, instance_input, start_row)); - BOOST_ASSERT_MSG(is_connected, - "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); + // Stretched components do not have a manifest, as they are dynamically generated. + if constexpr (!blueprint::components::is_component_stretcher< + BlueprintFieldType, ComponentType>::value) { + BOOST_ASSERT_MSG(bp.num_gates() + bp.num_lookup_gates() == + component_type::get_gate_manifest(component_instance.witness_amount(), + component_static_info_args...).get_gates_amount(), + "Component total gates amount does not match actual gates amount."); } - zk::snark::plonk_table_description desc; - desc.usable_rows_amount = assignment.rows_amount(); - if (start_row + component_instance.rows_amount >= public_input.size()) { BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == component_instance.rows_amount, "Component rows amount does not match actual rows amount."); // Stretched components do not have a manifest, as they are dynamically generated. if constexpr (!blueprint::components::is_component_stretcher< - BlueprintFieldType, ArithmetizationParams, ComponentType>::value) { + BlueprintFieldType, ComponentType>::value) { BOOST_ASSERT_MSG(assignment.rows_amount() - start_row == - component_type::get_rows_amount(component_instance.witness_amount(), 0, + component_type::get_rows_amount(component_instance.witness_amount(), component_static_info_args...), "Static component rows amount does not match actual rows amount."); } } - // Stretched components do not have a manifest, as they are dynamically generated. - if constexpr (!blueprint::components::is_component_stretcher< - BlueprintFieldType, ArithmetizationParams, ComponentType>::value) { - BOOST_ASSERT_MSG(bp.num_gates() + bp.num_lookup_gates()== - component_type::get_gate_manifest(component_instance.witness_amount(), 0, - component_static_info_args...).get_gates_amount(), - "Component total gates amount does not match actual gates amount."); + + const std::size_t rows_after_component_batching = + assignment.finalize_component_batches(bp, start_row + component_instance.rows_amount); + const std::size_t rows_after_const_batching = + assignment.finalize_constant_batches(bp, 0, std::max(start_row, 1)); + const std::size_t rows_after_batching = std::max(rows_after_component_batching, rows_after_const_batching); + for (auto variable : component_result.all_vars()) { + if (assignment.get_batch_variable_map().count(variable)) { + variable.get() = assignment.get_batch_variable_map().at(variable); + } + } + + result_check(assignment, component_result); + + if constexpr (!PrivateInput) { + bool is_connected = check_connectedness( + assignment, + bp, + instance_input.all_vars(), + component_result.all_vars(), start_row, rows_after_batching - start_row, + connectedness_check); + if (connectedness_check.t == blueprint::connectedness_check_type::type::NONE) { + std::cout << "WARNING: Connectedness check is disabled." << std::endl; + } + + // Uncomment the following if you want to output a visual representation of the connectedness graph. + // I recommend turning off the starting row randomization + // If the whole of public_input isn't shown, increase the end row + + // auto zones = blueprint::detail::generate_connectedness_zones( + // assignment, bp, instance_input.all_vars(), start_row, rows_after_batching - start_row); + // blueprint::detail::export_connectedness_zones( + // zones, assignment, instance_input.all_vars(), start_row, rows_after_batching - start_row, std::cout); + + // BOOST_ASSERT_MSG(is_connected, + // "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); } + desc.usable_rows_amount = assignment.rows_amount(); - if(nil::blueprint::use_lookups()){ + if constexpr (nil::blueprint::use_lookups()) { // Components with lookups may use constant columns. // But now all constants are placed in the first column. - // So we reserve the first column for non-lookup constants. + // So we reserve the first column for non-lookup constants. // Rather universal for testing // We may start from zero if component doesn't use ordinary constants. std::vector lookup_columns_indices; - for( std::size_t i = 1; i < ArithmetizationParams::constant_columns; i++ ) lookup_columns_indices.push_back(i); - desc.usable_rows_amount = zk::snark::detail::pack_lookup_tables( + for(std::size_t i = 1; i < assignment.constants_amount(); i++) { + lookup_columns_indices.push_back(i); + } + + std::size_t cur_selector_id = 0; + for(const auto &gate: bp.gates()){ + cur_selector_id = std::max(cur_selector_id, gate.selector_index); + } + for(const auto &lookup_gate: bp.lookup_gates()){ + cur_selector_id = std::max(cur_selector_id, lookup_gate.tag_index); + } + cur_selector_id++; + desc.usable_rows_amount = zk::snark::pack_lookup_tables_horizontal( bp.get_reserved_indices(), bp.get_reserved_tables(), - bp, assignment, lookup_columns_indices, - desc.usable_rows_amount + bp, assignment, lookup_columns_indices, cur_selector_id, + desc.usable_rows_amount, + 500000 ); } desc.rows_amount = zk::snark::basic_padding(assignment); @@ -297,12 +315,57 @@ namespace nil { profiling(assignment); #endif + //assignment.export_table(std::cout); + //bp.export_circuit(std::cout); assert(blueprint::is_satisfied(bp, assignment) == expected_to_pass); return std::make_tuple(desc, bp, assignment); } + template< + typename ComponentType, typename BlueprintFieldType, typename Hash, + std::size_t Lambda, typename PublicInputContainerType, typename FunctorResultCheck, bool PrivateInput, + typename... ComponentStaticInfoArgs> + auto prepare_empty_component(ComponentType component_instance, + const zk::snark::plonk_table_description &desc, + const PublicInputContainerType &public_input, + const FunctorResultCheck &result_check, + typename ComponentType::input_type instance_input, + blueprint::connectedness_check_type connectedness_check, + ComponentStaticInfoArgs... component_static_info_args) { + using component_type = ComponentType; + + blueprint::circuit> bp; + blueprint::assignment> assignment(desc); + + static boost::random::mt19937 gen; + static boost::random::uniform_int_distribution<> dist(0, 100); + std::size_t start_row = dist(gen); + + if constexpr (PrivateInput) { + for (std::size_t i = 0; i < public_input.size(); i++) { + assignment.private_storage(i) = public_input[i]; + } + } else { + for (std::size_t i = 0; i < public_input.size(); i++) { + assignment.public_input(0, i) = public_input[i]; + } + } + + auto component_result = boost::get( + blueprint::components::generate_empty_assignments( + component_instance, assignment, instance_input, start_row)); + // assignment.export_table(std::cout); + // bp.export_circuit(std::cout); + result_check(assignment, component_result); + + BOOST_ASSERT(bp.num_gates() == 0); + BOOST_ASSERT(bp.num_lookup_gates() == 0); + + return std::make_tuple(desc, bp, assignment); + } + template @@ -350,7 +413,7 @@ namespace nil { // How to define it from crypto3 cmake? //#define BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED -#ifdef BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED2 +#ifdef BLUEPRINT_PLACEHOLDER_PROOF_GEN_ENABLED using circuit_params = typename nil::crypto3::zk::snark::placeholder_circuit_params; using lpc_params_type = typename nil::crypto3::zk::commitments::list_polynomial_commitment_params< Hash, Hash, 2 From e6622b4bb7aaf6d6078be92f300d17f6e782fcc9 Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Tue, 30 Apr 2024 13:39:19 +0400 Subject: [PATCH 36/48] run_tests.yml rebase fix. --- .github/workflows/run_tests.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 91846bef5..7f520514b 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -78,6 +78,18 @@ jobs: blueprint_verifiers_placeholder_f1_loop_test, blueprint_verifiers_placeholder_f3_loop_test, blueprint_verifiers_placeholder_gate_component_test, + blueprint_verifiers_flexible_pow_factor_test, + blueprint_proxy_test, + blueprint_mock_mocked_components_test, + blueprint_component_batch_test, + blueprint_verifiers_placeholder_expression_evaluation_component_test, + blueprint_verifiers_placeholder_final_polynomial_check_test, + blueprint_verifiers_flexible_swap_test, + blueprint_verifiers_flexible_additions_test, + blueprint_verifiers_flexible_multiplications_test, + blueprint_verifiers_flexible_poseidon_test, + blueprint_verifiers_flexible_constant_pow_test, + blueprint_verifiers_placeholder_verifier_test, blueprint_hashes_plonk_keccak_round_test, blueprint_hashes_plonk_keccak_padding_test, blueprint_hashes_plonk_keccak_test, From d6312e5bf6dc844874a31331859177b627b89941 Mon Sep 17 00:00:00 2001 From: Valeh Date: Tue, 30 Apr 2024 15:43:13 +0300 Subject: [PATCH 37/48] keccak connectedness attempt --- .../blueprint/components/hashes/keccak/keccak_component.hpp | 2 +- include/nil/blueprint/utils/connectedness_check.hpp | 4 ++-- test/hashes/plonk/keccak.cpp | 4 ++-- test/hashes/plonk/keccak_padding.cpp | 4 ++-- test/hashes/plonk/keccak_round.cpp | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index cabfb9d19..c47c566df 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -673,7 +673,7 @@ namespace nil { static_cast(conf.constraints[0][i].row))}}); } selector_indexes.push_back(bp.add_gate({constraint_0, constraint_1})); - selector_indexes.push_back(bp.add_gate({constraint_2})); + selector_indexes.push_back(bp.add_gate({constraint_2, constraint_3})); selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_0)); selector_indexes.push_back(bp.add_lookup_gate(lookup_constraints_1)); } diff --git a/include/nil/blueprint/utils/connectedness_check.hpp b/include/nil/blueprint/utils/connectedness_check.hpp index 85740d99b..1148a6150 100644 --- a/include/nil/blueprint/utils/connectedness_check.hpp +++ b/include/nil/blueprint/utils/connectedness_check.hpp @@ -82,8 +82,8 @@ namespace nil { const std::size_t end_row = start_row_index + rows_amount; nil::blueprint::assignment> output_assignment( - assignment.witnesses_amount(), assignment.constants_amount(), - assignment.public_inputs_amount(), assignment.selectors_amount() + assignment.witnesses_amount(), assignment.public_inputs_amount(), + assignment.constants_amount(), assignment.selectors_amount() ); // We do '+1' in all the assignments to separate the unassigned cells (0 by default) diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index d50f574b4..05b1501b3 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -389,7 +389,7 @@ auto test_keccak_inner(std::vector mess nil::crypto3::test_component( component_instance, desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::NONE, num_blocks, num_bits, range_check_input, + nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, limit_permutation_column); } @@ -536,7 +536,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_pallas) { // test_keccak_round_random(1); // test_keccak_0(136); test_keccak_0(136); - test_keccak_hello_world(); + // test_keccak_hello_world(); // test_keccak_round_random(); } diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 23f27e310..1f16cd46a 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -286,9 +286,9 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { // test with no result_check asserts - // using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_to_fail_keccak_padding_random(10, false); + test_to_fail_keccak_padding_random(10, false); // test_to_fail_keccak_padding_random(16, false, false); // test_to_fail_keccak_padding_random(11, false, false, false); // test_to_fail_keccak_padding_random(100, true); diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 091d30095..e493fd461 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -106,7 +106,7 @@ std::array sparse_round_function(st } } if (last_round_call) { - value_type last_round_const = to_sparse(value_type(0x80)); + value_type last_round_const = to_sparse(value_type(0x8000000000000000)); integral_type last_round_const_integral = integral_type(last_round_const.data); inner_state_integral[1][3] = inner_state_integral[1][3] ^ padded_message_chunk_integral[16] ^ last_round_const_integral; } @@ -385,8 +385,8 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; // test_keccak_round_not_random(); // xor_with_mes, last_round_call - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); test_keccak_round_random(); // test_keccak_round_random(); // test_keccak_round_random(); From ece7eb60513d85ae9d210c537f4c9e1c48bf7c13 Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Tue, 30 Apr 2024 18:02:30 +0400 Subject: [PATCH 38/48] Fixed out-of-memory errors in keccak round. --- .../components/hashes/keccak/keccak_round.hpp | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 1c93bb0ba..fde60d4de 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -882,12 +882,14 @@ namespace nil { while (cur_constr < pairs.size()) { configuration c; while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && - pairs[cur_constr].first >= cur_row) { + pairs[cur_constr].first >= cur_row) { c.constraints.push_back(cur_config.constraints[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; } - cur_row = pairs[cur_constr].first; + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } cur_result.push_back(c); } result.push_back(cur_result); @@ -958,7 +960,9 @@ namespace nil { ++cur_constr; found = true; } - cur_row = pairs[cur_constr].first; + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } if (found) { cur_result.push_back(c); } @@ -1025,19 +1029,6 @@ namespace nil { return num_cells / witness_amount + bool(num_cells % witness_amount); } - // std::vector> component_custom_lookup_tables(){ - // std::vector> result = {}; - // normalize3_table = std::shared_ptr(new normalize_table_type(3)); - // normalize4_table = std::shared_ptr(new normalize_table_type(4)); - // normalize6_table = std::shared_ptr(new normalize_table_type(6)); - // chi_table = std::shared_ptr(new chi_table_type()); - // result.push_back(normalize3_table); - // result.push_back(normalize4_table); - // result.push_back(normalize6_table); - // result.push_back(chi_table); - // return result; - // } - std::map component_lookup_tables() { std::map lookup_tables; lookup_tables["keccak_normalize3_table/full"] = 0; // REQUIRED_TABLE From 0929ce080922a9f6ca2bf1c2d1c8c5e8645b113d Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Tue, 30 Apr 2024 22:47:48 +0400 Subject: [PATCH 39/48] WIP saving progress. --- .../hashes/keccak/keccak_component.hpp | 4 ++- .../hashes/keccak/keccak_padding.hpp | 4 ++- include/nil/blueprint/lookup_library.hpp | 9 +++-- test/hashes/plonk/keccak.cpp | 3 +- test/hashes/plonk/keccak_round.cpp | 35 +++++++++---------- test/test_plonk_component.hpp | 4 +-- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index c47c566df..01567274e 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -487,7 +487,9 @@ namespace nil { c.first_coordinate = {cur_row, 0}; ++cur_constr; } - cur_row = pairs[cur_constr].first; + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } cur_result.push_back(c); } result.push_back(cur_result); diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 0fa9cdf90..4b97d1626 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -586,7 +586,9 @@ namespace nil { c.first_coordinate = {cur_row, 0}; ++cur_constr; } - cur_row = pairs[cur_constr].first; + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } cur_result.push_back(c); } result.push_back(cur_result); diff --git a/include/nil/blueprint/lookup_library.hpp b/include/nil/blueprint/lookup_library.hpp index d2fc8783a..8027226ff 100644 --- a/include/nil/blueprint/lookup_library.hpp +++ b/include/nil/blueprint/lookup_library.hpp @@ -370,9 +370,12 @@ namespace nil { return {result, normalized_result}; } public: - normalize_base8_table_type(std::size_t base_): lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { - this->subtables["full"] = {{0,1}, 0, 65536}; + normalize_base8_table_type(std::size_t base_) + : lookup_table_definition("keccak_normalize" + std::to_string(base_) + "_table"), base(base_) { + + this->subtables["full"] = {{0,1}, 0, 65535}; } + virtual void generate(){ this->_table.resize(2); std::vector value_sizes = {8}; @@ -407,7 +410,7 @@ namespace nil { } public: chi_table_type(): lookup_table_definition("keccak_chi_table") { - this->subtables["full"] = {{0,1}, 0, 65536}; + this->subtables["full"] = {{0,1}, 0, 65535}; } virtual void generate(){ this->_table.resize(2); diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 05b1501b3..5f66cbed6 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -389,7 +389,8 @@ auto test_keccak_inner(std::vector mess nil::crypto3::test_component( component_instance, desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::STRONG, num_blocks, num_bits, range_check_input, + {nil::blueprint::connectedness_check_type::type::STRONG, + nil::blueprint::connectedness_check_type::island_type::NONE}, num_blocks, num_bits, range_check_input, limit_permutation_column); } diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index e493fd461..23435107f 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -161,8 +161,8 @@ auto test_keccak_round_inner(std::array expected_result) { constexpr std::size_t PublicInputColumns = 1; - constexpr std::size_t ConstantColumns = 3; - constexpr std::size_t SelectorColumns = 30; + constexpr std::size_t ConstantColumns = 30; + constexpr std::size_t SelectorColumns = 50; nil::crypto3::zk::snark::plonk_table_description desc( WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; @@ -215,7 +215,7 @@ auto test_keccak_round_inner(std::array( boost::get(component_instance), desc, public_input, result_check, instance_input, - nil::blueprint::connectedness_check_type::type::NONE, + xor_with_mes ? nil::blueprint::connectedness_check_type::type::STRONG : nil::blueprint::connectedness_check_type::type::NONE, xor_with_mes, last_round_call, last_perm_col); } @@ -383,25 +383,24 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_not_random(); - // xor_with_mes, last_round_call - // test_keccak_round_random(); - // test_keccak_round_random(); + test_keccak_round_not_random(); + test_keccak_round_random(); + test_keccak_round_random(); test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { - // using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_not_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); - // test_keccak_round_random(); + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + test_keccak_round_not_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); + test_keccak_round_random(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index b51a5a369..8ac794c0d 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -275,8 +275,8 @@ namespace nil { // blueprint::detail::export_connectedness_zones( // zones, assignment, instance_input.all_vars(), start_row, rows_after_batching - start_row, std::cout); - // BOOST_ASSERT_MSG(is_connected, - // "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); + BOOST_ASSERT_MSG(is_connected, + "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); } desc.usable_rows_amount = assignment.rows_amount(); From 019904f6a6d4fea6f086b88028fff4daf7e024b6 Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Wed, 1 May 2024 01:43:27 +0400 Subject: [PATCH 40/48] Moved configuration out of keccak files. --- .../hashes/keccak/keccak_padding.hpp | 78 +------------ .../components/hashes/keccak/keccak_round.hpp | 78 +------------ include/nil/blueprint/configuration.hpp | 110 ++++++++++++++++++ test/hashes/plonk/keccak_padding.cpp | 2 +- 4 files changed, 121 insertions(+), 147 deletions(-) create mode 100644 include/nil/blueprint/configuration.hpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 4b97d1626..322e2c540 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -53,74 +54,6 @@ namespace nil { using integral_type = typename BlueprintFieldType::integral_type; public: - struct coordinates { - std::size_t row; - std::size_t column; - - coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - coordinates(std::vector vec) : row(vec[0]), column(vec[1]) {}; - bool operator==(const coordinates &other) const { - return row == other.row && column == other.column; - } - bool operator<(const coordinates &other) const { - return row < other.row || (row == other.row && column < other.column); - } - }; - - struct configuration { - // In constraints we use such notation: constr[0] - result, - // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. - coordinates first_coordinate; - coordinates last_coordinate; - std::vector copy_to; - std::vector> constraints; - std::vector> lookups; - coordinates copy_from; - - configuration() = default; - configuration(std::pair first_coordinate_, - std::pair last_coordinate_, - std::vector> copy_to_, - std::vector>> constraints_, - std::vector>> lookups_, - std::pair copy_from_) { - first_coordinate = coordinates(first_coordinate_); - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to.push_back(coordinates(copy_to_[i])); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - std::vector constr; - for (std::size_t j = 0; j < constraints_[i].size(); ++j) { - constr.push_back(coordinates(constraints_[i][j])); - } - constraints.push_back(constr); - } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - std::vector lookup; - for (std::size_t j = 0; j < lookups_[i].size(); ++j) { - lookup.push_back(coordinates(lookups_[i][j])); - } - lookups.push_back(lookup); - } - copy_from = coordinates(copy_from_); - }; - bool operator== (const configuration& other) const { - return first_coordinate == other.first_coordinate && - last_coordinate == other.last_coordinate && - copy_to == other.copy_to && - constraints == other.constraints && - lookups == other.lookups && - copy_from == other.copy_from; - } - bool operator< (const configuration& other) const { - return first_coordinate < other.first_coordinate || - (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); - } - }; - using var = typename component_type::var; using manifest_type = nil::blueprint::plonk_component_manifest; @@ -573,7 +506,7 @@ namespace nil { min = std::min(min, constr[j].row); max = std::max(max, constr[j].row); } - BOOST_ASSERT(max - min <= 2); + BOOST_ASSERT(max <= 2 + min); pairs.push_back({min, max}); } std::vector cur_result; @@ -581,7 +514,8 @@ namespace nil { std::size_t cur_constr = 0; while (cur_constr < pairs.size()) { configuration c; - while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && pairs[cur_constr].first >= cur_row) { + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { c.constraints.push_back(cur_config.constraints[cur_constr]); c.first_coordinate = {cur_row, 0}; ++cur_constr; @@ -831,7 +765,7 @@ namespace nil { using component_type = padding_component; using var = typename component_type::var; - std::size_t strow = start_row_index; + const std::size_t strow = start_row_index; std::size_t config_index = 0; std::size_t input_index = 0; @@ -925,7 +859,7 @@ namespace nil { const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - std::size_t strow = start_row_index; + const std::size_t strow = start_row_index; using component_type = padding_component; using value_type = typename BlueprintFieldType::value_type; diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index fde60d4de..de28049de 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -177,76 +178,6 @@ namespace nil { return manifest; } - struct configuration { - struct coordinates { - std::size_t row; - std::size_t column; - - coordinates() = default; - coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; - coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; - bool operator==(const coordinates &other) const { - return row == other.row && column == other.column; - } - bool operator<(const coordinates &other) const { - return row < other.row || (row == other.row && column < other.column); - } - }; - - // In constraints we use such notation: constr[0] - result, - // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. - coordinates first_coordinate; - coordinates last_coordinate; - std::vector copy_to; - std::vector> constraints; - std::vector> lookups; - coordinates copy_from; - std::string name; - - configuration() = default; - configuration(std::pair first_coordinate_, - std::pair - last_coordinate_, - std::vector> - copy_to_, - std::vector>> - constraints_, - std::vector>> - lookups_, - std::pair - copy_from_) { - first_coordinate = coordinates(first_coordinate_); - last_coordinate = coordinates(last_coordinate_); - for (std::size_t i = 0; i < copy_to_.size(); ++i) { - copy_to.push_back(coordinates(copy_to_[i])); - } - for (std::size_t i = 0; i < constraints_.size(); ++i) { - std::vector constr; - for (std::size_t j = 0; j < constraints_[i].size(); ++j) { - constr.push_back(coordinates(constraints_[i][j])); - } - constraints.push_back(constr); - } - for (std::size_t i = 0; i < lookups_.size(); ++i) { - std::vector lookup; - for (std::size_t j = 0; j < lookups_[i].size(); ++j) { - lookup.push_back(coordinates(lookups_[i][j])); - } - lookups.push_back(lookup); - } - copy_from = coordinates(copy_from_); - }; - bool operator==(const configuration &other) const { - return first_coordinate == other.first_coordinate && last_coordinate == other.last_coordinate && - copy_to == other.copy_to && constraints == other.constraints && - lookups == other.lookups && copy_from == other.copy_from; - } - bool operator<(const configuration &other) const { - return first_coordinate < other.first_coordinate || - (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); - } - }; - using var = typename component_type::var; static const std::size_t lookup_rows = 65536; @@ -873,7 +804,7 @@ namespace nil { min = std::min(min, constr[j].row); max = std::max(max, constr[j].row); } - BOOST_ASSERT(max - min <= 2); + BOOST_ASSERT(max <= 2 + min); pairs.push_back({min, max}); } std::vector cur_result; @@ -942,7 +873,7 @@ namespace nil { min = std::min(min, constr[j].row); max = std::max(max, constr[j].row); } - BOOST_ASSERT(max - min <= 2); + BOOST_ASSERT(max <= 2 + min); pairs.push_back({min, max}); } @@ -1083,7 +1014,6 @@ namespace nil { using constraint_type = crypto3::zk::snark::plonk_constraint; using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; using integral_type = typename BlueprintFieldType::integral_type; - using configuration = typename component_type::configuration; auto gate_map = component.gates_configuration_map; auto gate_config = component.gates_configuration; @@ -1848,7 +1778,7 @@ namespace nil { using component_type = keccak_round_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - std::size_t strow = start_row_index; + const std::size_t strow = start_row_index; int config_index = 0; diff --git a/include/nil/blueprint/configuration.hpp b/include/nil/blueprint/configuration.hpp new file mode 100644 index 000000000..53a35fac6 --- /dev/null +++ b/include/nil/blueprint/configuration.hpp @@ -0,0 +1,110 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// 2024 Valeh Farzaliyev +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#pragma once + +#include +#include + +namespace nil { + namespace blueprint { + struct configuration { + struct coordinates { + std::size_t row; + std::size_t column; + + coordinates() = default; + coordinates(std::size_t row_, std::size_t column_) : row(row_), column(column_) {}; + coordinates(std::pair pair) : row(pair.first), column(pair.second) {}; + + bool operator==(const coordinates &other) const { + return row == other.row && column == other.column; + } + + bool operator<(const coordinates &other) const { + return row < other.row || (row == other.row && column < other.column); + } + }; + + // In constraints we use such notation: constr[0] - result, + // constr[1]... - arguments for lookup, linear elements for regular constraints in correct order. + coordinates first_coordinate; + coordinates last_coordinate; + std::vector copy_to; + std::vector> constraints; + std::vector> lookups; + coordinates copy_from; + std::string name; + + configuration() = default; + configuration( + std::pair + first_coordinate_, + std::pair + last_coordinate_, + std::vector> + copy_to_, + std::vector>> + constraints_, + std::vector>> + lookups_, + std::pair + copy_from_ + ) { + first_coordinate = coordinates(first_coordinate_); + last_coordinate = coordinates(last_coordinate_); + for (std::size_t i = 0; i < copy_to_.size(); ++i) { + copy_to.push_back(coordinates(copy_to_[i])); + } + for (std::size_t i = 0; i < constraints_.size(); ++i) { + std::vector constr; + for (std::size_t j = 0; j < constraints_[i].size(); ++j) { + constr.push_back(coordinates(constraints_[i][j])); + } + constraints.push_back(constr); + } + for (std::size_t i = 0; i < lookups_.size(); ++i) { + std::vector lookup; + for (std::size_t j = 0; j < lookups_[i].size(); ++j) { + lookup.push_back(coordinates(lookups_[i][j])); + } + lookups.push_back(lookup); + } + copy_from = coordinates(copy_from_); + }; + + bool operator==(const configuration &other) const { + return first_coordinate == other.first_coordinate && last_coordinate == other.last_coordinate && + copy_to == other.copy_to && constraints == other.constraints && + lookups == other.lookups && copy_from == other.copy_from; + } + + bool operator<(const configuration &other) const { + return first_coordinate < other.first_coordinate || + (first_coordinate == other.first_coordinate && last_coordinate < other.last_coordinate); + } + }; + } // namespace blueprint +} // namespace nil diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index 1f16cd46a..bc6d43ced 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -288,7 +288,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { // test with no result_check asserts using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_to_fail_keccak_padding_random(10, false); + // test_to_fail_keccak_padding_random(10, false); // test_to_fail_keccak_padding_random(16, false, false); // test_to_fail_keccak_padding_random(11, false, false, false); // test_to_fail_keccak_padding_random(100, true); From 73838c365655527cee8dae5f5f52f87dd5e7192f Mon Sep 17 00:00:00 2001 From: Valeh Date: Tue, 7 May 2024 07:32:50 +0300 Subject: [PATCH 41/48] keccak connectedness solved --- .../hashes/keccak/keccak_component.hpp | 230 +++++++----------- .../hashes/keccak/keccak_padding.hpp | 115 +++------ .../components/hashes/keccak/keccak_round.hpp | 40 +-- test/hashes/plonk/keccak.cpp | 121 ++------- 4 files changed, 170 insertions(+), 336 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp index 01567274e..60059f358 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_component.hpp @@ -51,10 +51,6 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; - static std::size_t calculate_num_round_calls(std::size_t num_blocks) { - return (num_blocks + (17 - num_blocks % 17)) / 17; - } - public: using var = typename component_type::var; @@ -95,10 +91,10 @@ namespace nil { gate_manifest manifest = gate_manifest(gate_manifest_type( witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column)); - manifest.merge_with(padding_component_type::get_gate_manifest( - witness_amount, num_blocks, num_bits, range_check_input)); - manifest.merge_with(round_component_type::get_gate_manifest(witness_amount, - true, true, limit_permutation_column)); + manifest.merge_with(padding_component_type::get_gate_manifest(witness_amount, num_blocks, num_bits, + range_check_input)); + manifest.merge_with( + round_component_type::get_gate_manifest(witness_amount, true, true, limit_permutation_column)); // manifest.merge_with(round_component_type::get_gate_manifest( // witness_amount, lookup_column_amount, true, false, limit_permutation_column)); // manifest.merge_with(round_component_type::get_gate_manifest( @@ -107,19 +103,17 @@ namespace nil { return manifest; } - static manifest_type get_manifest( - std::size_t num_blocks, std::size_t num_bits, - bool range_check_input, std::size_t lpc = 7 - ) { + static manifest_type get_manifest(std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + std::size_t lpc = 7) { static manifest_type manifest = manifest_type(std::shared_ptr(new manifest_range_param(9, 15)), false) - .merge_with(padding_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)) - .merge_with(round_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)); + .merge_with( + padding_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)) + .merge_with( + round_component_type::get_manifest(num_blocks, num_bits, range_check_input, lpc)); return manifest; } - using configuration = typename padding_component_type::configuration; - const std::size_t lookup_rows = 65536; const std::size_t witnesses = this->witness_amount(); @@ -128,15 +122,8 @@ namespace nil { const bool range_check_input; const std::size_t limit_permutation_column = 7; - std::size_t round_tt_rows = 0; - std::size_t round_tf_rows = 0; - std::size_t round_ff_rows = 0; - std::size_t round_tt_gates = 0; - std::size_t round_tf_gates = 0; - std::size_t round_ff_gates = 0; - - const std::size_t num_round_calls = calculate_num_round_calls(num_blocks); - const std::size_t num_configs = 5 + num_blocks + (17 - num_blocks % 17); + const std::size_t num_round_calls = calculate_num_round_calls(num_blocks, num_bits); + const std::size_t num_configs = 4 + calculate_padded_length(num_blocks, num_bits); const std::size_t pack_chunk_size = 8; const std::size_t pack_num_chunks = 8; @@ -199,28 +186,33 @@ namespace nil { }; struct result_type { - std::array final_inner_state; + std::array final_inner_state; result_type(const keccak &component, std::size_t start_row_index) { auto offset = component.full_configuration[component.num_configs - 1].last_coordinate.row + (component.full_configuration[component.num_configs - 1].last_coordinate.column > 0); - for (std::size_t i = 0; i < 5; ++i) { + for (std::size_t i = 0; i < 4; ++i) { final_inner_state[i] = var(component.W( - component.full_configuration[component.num_configs - 5 + i].copy_from.column), + component.full_configuration[component.num_configs - 4 + i].copy_from.column), start_row_index + component.rows_amount - offset + - component.full_configuration[component.num_configs - 5 + i].copy_from.row, + component.full_configuration[component.num_configs - 4 + i].copy_from.row, false); } } std::vector> all_vars() { - return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3], - final_inner_state[4]}; + return {final_inner_state[0], final_inner_state[1], final_inner_state[2], final_inner_state[3]}; } }; - static std::size_t get_rows_amount_round_tt() { - return 0; + + static std::size_t calculate_padded_length(std::size_t num_blocks, std::size_t num_bits){ + std::size_t shift = padding_component_type::calculate_shift(num_blocks, num_bits); + return num_blocks + padding_component_type::calculate_num_padding_zeros(num_blocks, shift); + } + + static std::size_t calculate_num_round_calls(std::size_t num_blocks, std::size_t num_bits) { + return (calculate_padded_length(num_blocks, num_bits)) / 17; } integral_type pack(const integral_type &const_input) const { @@ -351,25 +343,9 @@ namespace nil { row++; } - // rounds - // for (std::size_t index = 0; index < num_round_calls; ++index) { - // for (std::size_t i = 0; i < 24; ++i) { - // if (index == num_round_calls - 1 && i == 0) { - // row += round_component_type::get_rows_amount(witness_amount, true, true, - // limit_permutation_column); - // } else if (i == 0) { - // row += round_component_type::get_rows_amount(witness_amount, true, false, - // limit_permutation_column); - // } else { - // row += round_component_type::get_rows_amount(witness_amount, false, false, - // limit_permutation_column); - // } - // } - // } - row = 0; // from sparse representation - for (std::size_t i = 0; i < 5; ++i) { + for (std::size_t i = 0; i < 4; ++i) { result.push_back(configure_pack_unpack(witness_amount, row, column, pack_cells, pack_num_chunks, pack_buff, limit_permutation_column)); row = result.back().last_coordinate.row; @@ -406,32 +382,29 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column) { - std::size_t num_configs = 5 + num_blocks + (17 - num_blocks % 17); - std::size_t num_round_calls = calculate_num_round_calls(num_blocks); + std::size_t num_configs = 4 + calculate_padded_length(num_blocks, num_bits); + std::size_t num_round_calls = calculate_num_round_calls(num_blocks, num_bits); auto config = configure_all(witness_amount, num_configs, num_round_calls, limit_permutation_column); std::size_t row = 0, column = 0; - std::size_t row_shift = 0; // padding_component_type::get_rows_amount( - // witness_amount, 0, num_blocks, num_bits, range_check_input, limit_permutation_column); - std::map> config_map; - for (std::size_t i = 0; i < config.size() - 5; ++i) { + for (std::size_t i = 0; i < config.size() - 4; ++i) { row = config[i].first_coordinate.row; column = config[i].first_coordinate.column; if (config_map.find(column) != config_map.end()) { - config_map[column].push_back(row + row_shift); + config_map[column].push_back(row); } else { - config_map[column] = {row + row_shift}; + config_map[column] = {row}; } } - // row_shift += config[config.size() - 6].last_coordinate.row; - for (std::size_t i = config.size() - 5; i < config.size(); ++i) { + + for (std::size_t i = config.size() - 4; i < config.size(); ++i) { row = config[i].first_coordinate.row; column = config[i].first_coordinate.column + 10 * witness_amount; if (config_map.find(column) != config_map.end()) { - config_map[column].push_back(row + row_shift); + config_map[column].push_back(row); } else { - config_map[column] = {row + row_shift}; + config_map[column] = {row}; } } @@ -512,32 +485,35 @@ namespace nil { return result; } - static std::size_t get_rows_amount(std::size_t witness_amount, - std::size_t num_blocks, std::size_t num_bits, bool range_check_input, + static std::size_t get_rows_amount(std::size_t witness_amount, std::size_t num_blocks, + std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - std::size_t num_round_calls = calculate_num_round_calls(num_blocks); - std::size_t res = - padding_component_type::get_rows_amount(witness_amount, num_blocks, - num_bits, range_check_input, limit_permutation_column); - // + round_tt_rows + std::size_t num_round_calls = calculate_num_round_calls(num_blocks, num_bits); + std::size_t res = padding_component_type::get_rows_amount( + witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + + auto round_tt_rows = + round_component_type::get_rows_amount(witness_amount, true, true, limit_permutation_column); + auto round_tf_rows = + round_component_type::get_rows_amount(witness_amount, true, false, limit_permutation_column); + auto round_ff_rows = + round_component_type::get_rows_amount(witness_amount, false, false, limit_permutation_column); + for (std::size_t i = 0; i < num_round_calls; i++) { if (i == num_round_calls - 1) { - res += round_component_type::get_rows_amount(witness_amount, true, - true, limit_permutation_column); + res += round_tt_rows; } else { - res += round_component_type::get_rows_amount(witness_amount, true, - false, limit_permutation_column); + res += round_tf_rows; } for (std::size_t j = 1; j < 24; ++j) { - res += round_component_type::get_rows_amount(witness_amount, false, - false, limit_permutation_column); + res += round_ff_rows; } } auto config = configure_all(witness_amount, num_blocks, num_round_calls, limit_permutation_column); auto index = config.size() - 1; res += config[index].last_coordinate.row + (config[index].last_coordinate.column > 0); - res += config[index - 5].last_coordinate.row + (config[index - 5].last_coordinate.column > 0); + res += config[index - 4].last_coordinate.row + (config[index - 4].last_coordinate.column > 0); return res; } static std::size_t get_gates_amount(std::size_t witness_amount, std::size_t num_blocks, @@ -547,10 +523,7 @@ namespace nil { auto config = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); for (auto c : config) { - if (c.first >= 10 * witness_amount) - res += 2; - else - res += 2; + res += 2; } return res; } @@ -577,20 +550,11 @@ namespace nil { component_type(witness, constant, public_input, get_manifest(num_blocks_, num_bits_, range_check_input_, lpc_)), num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), - limit_permutation_column(lpc_), - num_round_calls(calculate_num_round_calls(num_blocks_)), + limit_permutation_column(lpc_), num_round_calls(calculate_num_round_calls(num_blocks_, num_bits_)), padding(witness, constant, public_input, num_blocks_, num_bits_, range_check_input_, lpc_), round_tt(witness, constant, public_input, true, true, lpc_), round_tf(witness, constant, public_input, true, false, lpc_), - round_ff(witness, constant, public_input, false, false, lpc_) { - - round_tt_rows = round_tt.rows_amount; - round_tf_rows = round_tf.rows_amount; - round_ff_rows = round_ff.rows_amount; - round_tt_gates = round_tt.gates_amount; - round_tf_gates = round_tf.gates_amount; - round_ff_gates = round_ff.gates_amount; - }; + round_ff(witness, constant, public_input, false, false, lpc_) {}; keccak(std::initializer_list witnesses, std::initializer_list constants, @@ -601,18 +565,10 @@ namespace nil { num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_), limit_permutation_column(lpc_), padding(witnesses, constants, public_inputs, num_blocks_, num_bits_, range_check_input_, lpc_), - num_round_calls(calculate_num_round_calls(num_blocks_)), + num_round_calls(calculate_num_round_calls(num_blocks_, num_bits_)), round_tt(witnesses, constants, public_inputs, true, true, lpc_), round_tf(witnesses, constants, public_inputs, true, false, lpc_), - round_ff(witnesses, constants, public_inputs, false, false, lpc_) { - - round_tt_rows = round_tt.rows_amount; - round_tf_rows = round_tf.rows_amount; - round_ff_rows = round_ff.rows_amount; - round_tt_gates = round_tt.gates_amount; - round_tf_gates = round_tf.gates_amount; - round_ff_gates = round_ff.gates_amount; - }; + round_ff(witnesses, constants, public_inputs, false, false, lpc_) {}; }; template @@ -716,23 +672,23 @@ namespace nil { std::array inner_state; - auto gate_map_tf = component.round_tf.gates_configuration_map; - std::vector rotate_rows_tf; - for (auto g : gate_map_tf) { - if (g.first.first == 7) { - rotate_rows_tf.insert(rotate_rows_tf.end(), g.second.begin(), g.second.end()); - } - } - std::sort(rotate_rows_tf.begin(), rotate_rows_tf.end()); - - auto gate_map_ff = component.round_ff.gates_configuration_map; - std::vector rotate_rows_ff; - for (auto g : gate_map_ff) { - if (g.first.first == 7) { - rotate_rows_ff.insert(rotate_rows_ff.end(), g.second.begin(), g.second.end()); - } - } - std::sort(rotate_rows_ff.begin(), rotate_rows_ff.end()); + // auto gate_map_tf = component.round_tf.gates_configuration_map; + // std::vector rotate_rows_tf; + // for (auto g : gate_map_tf) { + // if (g.first.first == 7) { + // rotate_rows_tf.insert(rotate_rows_tf.end(), g.second.begin(), g.second.end()); + // } + // } + // std::sort(rotate_rows_tf.begin(), rotate_rows_tf.end()); + + // auto gate_map_ff = component.round_ff.gates_configuration_map; + // std::vector rotate_rows_ff; + // for (auto g : gate_map_ff) { + // if (g.first.first == 7) { + // rotate_rows_ff.insert(rotate_rows_ff.end(), g.second.begin(), g.second.end()); + // } + // } + // std::sort(rotate_rows_ff.begin(), rotate_rows_ff.end()); for (int i = 0; i < component.num_round_calls; i++) { for (int j = 0; j < 24; j++) { @@ -763,7 +719,7 @@ namespace nil { } } - for (std::size_t i = 0; i < 5; i++) { + for (std::size_t i = 0; i < 4; i++) { bp.add_copy_constraint( {inner_state[i], var(component.W(config[config_index].copy_to[0].column), static_cast(config[config_index].copy_to[0].row + cur_row), false)}); @@ -773,7 +729,7 @@ namespace nil { cur_row += config[config_index - 1].last_coordinate.row + (config[config_index - 1].last_coordinate.column > 0); - // BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); + BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); } template @@ -784,6 +740,8 @@ namespace nil { const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { + BOOST_ASSERT(instance_input.message.size() == component.num_blocks); + using component_type = keccak_component; using padding_type = typename component_type::padding_component_type; using round_type = typename component_type::round_component_type; @@ -792,19 +750,10 @@ namespace nil { generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); std::size_t row = start_row_index; - std::vector witnesses; - for (std::size_t i = 0; i < component.witnesses; ++i) { - witnesses.push_back(i); - } - std::vector zero_column = {0}; - - padding_type padding_component_instance(witnesses, zero_column, zero_column, component.num_blocks, - component.num_bits, component.range_check_input, - component.limit_permutation_column); typename padding_type::input_type padding_input = {instance_input.message}; typename padding_type::result_type padding_result = - generate_circuit(padding_component_instance, bp, assignment, padding_input, row); - row += padding_component_instance.rows_amount; + generate_circuit(component.padding, bp, assignment, padding_input, row); + row += component.padding.rows_amount; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); @@ -850,7 +799,7 @@ namespace nil { for (std::size_t j = 0; j < 24; ++j) { typename round_type::input_type round_input = { inner_state, pmc, - var(component.C(0), start_row_index + j + 4, false, var::column_type::constant)}; + var(component.C(0), start_row_index + j + 2, false, var::column_type::constant)}; if (i == component.num_round_calls - 1 && j == 0) { typename round_type::result_type round_result = generate_circuit(component.round_tt, bp, assignment, round_input, row); @@ -871,7 +820,6 @@ namespace nil { offset += 17; } - std::cout << "after rounds row: " << row << std::endl; // sel_ind = 0; for (auto config : config_map) { if (config.first >= 10 * component.witnesses) { @@ -898,6 +846,8 @@ namespace nil { const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { + BOOST_ASSERT(instance_input.message.size() == component.num_blocks); + std::size_t cur_row = start_row_index; using component_type = keccak_component; @@ -950,7 +900,7 @@ namespace nil { // cur_row << std::endl; sparse_padded_message_coords[index] = var(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row, false); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_chunks[j - 1]); @@ -974,6 +924,7 @@ namespace nil { for (std::size_t i = 0; i < component.num_round_calls; ++i) { std::copy(sparse_padded_message_coords.begin() + offset, sparse_padded_message_coords.begin() + offset + 17, pmc.begin()); + for (auto &el : pmc) { std::cout << component.unpack(integral_type(var_value(assignment, el).data)) << ","; } @@ -982,7 +933,7 @@ namespace nil { for (std::size_t j = 0; j < 24; ++j) { typename round_type::input_type round_input = { inner_state, pmc, - var(component.C(0), start_row_index + j + 4, false, var::column_type::constant)}; + var(component.C(0), start_row_index + j + 2, false, var::column_type::constant)}; if (i == component.num_round_calls - 1 && j == 0) { typename round_type::result_type round_result = generate_assignments(component.round_tt, assignment, round_input, cur_row); @@ -1004,7 +955,7 @@ namespace nil { } // from sparse - for (std::size_t index = 0; index < 5; ++index) { + for (std::size_t index = 0; index < 4; ++index) { value_type sparse_value = var_value(assignment, inner_state[index]); integral_type sparse = integral_type(sparse_value.data); integral_type regular = component.unpack(sparse); @@ -1027,7 +978,7 @@ namespace nil { cur_config.constraints[0][0].row + cur_row) = sparse_value; assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + cur_row) = value_type(regular); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + cur_row) = value_type(integral_chunks[j - 1]); @@ -1041,8 +992,7 @@ namespace nil { cur_row += component.full_configuration[config_index - 1].last_coordinate.row + (component.full_configuration[config_index - 1].last_coordinate.column > 0); - // BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); - std::cout << cur_row << " vs " << component.rows_amount << std::endl; + BOOST_ASSERT(cur_row == start_row_index + component.rows_amount); return typename component_type::result_type(component, start_row_index); } @@ -1055,7 +1005,7 @@ namespace nil { const typename keccak_component::input_type &instance_input, const std::uint32_t start_row_index) { - std::size_t row = start_row_index + 4; + std::size_t row = start_row_index + 2; for (std::size_t i = 0; i < 24; ++i) { assignment.constant(component.C(0), row + i) = component.pack(component.round_constant[i]); } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 322e2c540..8c0dd57cd 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -154,7 +154,7 @@ namespace nil { config.copy_to.back().row + start_row_index, false); } if(component.shift == 0){ - padded_message[size] = var(component.C(0), start_row_index + 3, false, var::column_type::constant); + padded_message[size] = var(component.C(0), start_row_index + 1, false, var::column_type::constant); } for (std::size_t i = size + (component.shift == 0); i < size + component.num_padding_zeros; ++i) { @@ -206,13 +206,6 @@ namespace nil { } return 0; } - static int32_t calculate_row_shift(std::size_t num_blocks, std::size_t num_bits) { - auto shift = calculate_shift(num_blocks, num_bits); - if (shift == 0) { - return 0; - } - return 1; - } static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column, std::size_t row, std::size_t column, @@ -374,26 +367,13 @@ namespace nil { } return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells, buff); } - static configuration configure_shift(std::size_t witness_amount, std::size_t row, std::size_t column) { - - std::pair first_coordinate = {row, column}; - std::size_t last_row = row, - last_column = column; - std::pair cell_copy_from = first_coordinate; - std::vector>> constraints = {{cell_copy_from}}; - for (std::size_t i = 0; i < 8; ++i) { - constraints[0].push_back({last_row + (last_column / witness_amount), - (last_column++) % witness_amount}); - } - return configuration(first_coordinate, {row + 1, 0}, {}, constraints, {}, cell_copy_from); - } static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { std::vector result; // result.push_back(configure_shift(witness_amount, 0, 0)); - std::size_t row = 1, + std::size_t row = 0, column = 0; if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { @@ -454,7 +434,6 @@ namespace nil { auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); std::size_t row = 0, column = 0; - int32_t row_shift = (shift == 0 || witness_amount == 15) ? 0 : 1; std::map> config_map; @@ -462,9 +441,9 @@ namespace nil { row = config[i].first_coordinate.row; column = config[i].first_coordinate.column; if (config_map.find(column) != config_map.end()) { - config_map[column].push_back(row + row_shift); + config_map[column].push_back(row ); } else { - config_map[column] = {row + row_shift}; + config_map[column] = {row }; } } @@ -569,7 +548,7 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column = 7) { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - return map.size() * 2 + range_check_input + 2; + return map.size() * 2 + range_check_input; } static std::size_t get_rows_amount(std::size_t witness_amount, @@ -579,7 +558,7 @@ namespace nil { std::size_t limit_permutation_column) { auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); auto res = confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); - if (res < 4) res = 4; + if (res < 2) res = 2; return res; } @@ -640,24 +619,10 @@ namespace nil { auto gates_configuration = component.gates_configuration; std::size_t gate_index = 0; std::size_t lookup_gate_index = 0; - int32_t row_shift = (component.shift == 0 || component.witness_amount() == 15) ? 0 : 1; std::vector cur_constraints; std::vector cur_lookup_constraints; - // range_check shift num_blocks * 64 - num_bits; - cur_constraints.push_back(var(component.W(0), -1) - + var(component.C(0), 1, true, var::column_type::constant) - - 64 * var(component.C(0), 0, true, var::column_type::constant)); - cur_constraints.push_back(var(component.W(0), -1)); - for (std::size_t i = 1; i < 9; ++i) { - cur_constraints[1] -= var(component.W(i), -1) * (integral_type(1) << ((i-1) * 8)); - cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(i), -1)}}); - } - selector_indexes.push_back(bp.add_gate(cur_constraints)); - gate_index++; - selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); - lookup_gate_index++; + cur_constraints.clear(); cur_lookup_constraints.clear(); @@ -666,21 +631,21 @@ namespace nil { auto conf = gates_configuration[0][0]; for (std::size_t i = 1; i < 8; ++i) { cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift)}}); + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); } cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_sign_bit_table/full"), - {var(component.W(conf.constraints[0][8].column), static_cast(conf.constraints[0][8].row) - row_shift)}}); + {var(component.W(conf.constraints[0][8].column), static_cast(conf.constraints[0][8].row))}}); selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); lookup_gate_index++; cur_lookup_constraints.clear(); for (auto confs : gates_configuration) { auto conf = confs[0]; - constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift); + constraint_type constraint = var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row)); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row)) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row) - row_shift)}}); + {var(component.W(conf.constraints[0][i].column), static_cast(conf.constraints[0][i].row))}}); } selector_indexes.push_back(bp.add_gate(constraint)); gate_index++; @@ -694,14 +659,14 @@ namespace nil { auto conf = gates_configuration[0][0]; for (std::size_t i = 1; i < 8; ++i) { cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row))}}); } cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_sign_bit_table/full"), - {var(component.W(conf.constraints[2][8].column), static_cast(conf.constraints[2][8].row) - row_shift)}}); + {var(component.W(conf.constraints[2][8].column), static_cast(conf.constraints[2][8].row))}}); // chunk, range_check for (std::size_t i = 1; i < 9; ++i) { cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift)}}); + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row))}}); } selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); lookup_gate_index++; @@ -711,33 +676,33 @@ namespace nil { auto conf = confs[0]; // chunk, first, second cur_constraints.push_back(constraint_type( - var(component.W(conf.constraints[0][0].column), static_cast(conf.constraints[0][0].row) - row_shift) - - var(component.W(conf.constraints[0][1].column), static_cast(conf.constraints[0][1].row) - row_shift) * + var(component.W(conf.constraints[0][0].column), static_cast(conf.constraints[0][0].row)) - + var(component.W(conf.constraints[0][1].column), static_cast(conf.constraints[0][1].row)) * (integral_type(1) << (64 - component.shift)) - - var(component.W(conf.constraints[0][2].column), static_cast(conf.constraints[0][2].row) - row_shift))); + var(component.W(conf.constraints[0][2].column), static_cast(conf.constraints[0][2].row)))); // sum, relay, first cur_constraints.push_back( - var(component.W(conf.constraints[1][0].column), static_cast(conf.constraints[1][0].row) - row_shift) - - var(component.W(conf.constraints[1][1].column), static_cast(conf.constraints[1][1].row) - row_shift) * + var(component.W(conf.constraints[1][0].column), static_cast(conf.constraints[1][0].row)) - + var(component.W(conf.constraints[1][1].column), static_cast(conf.constraints[1][1].row)) * (integral_type(1) << component.shift) - - var(component.W(conf.constraints[1][2].column), static_cast(conf.constraints[1][2].row) - row_shift)); + var(component.W(conf.constraints[1][2].column), static_cast(conf.constraints[1][2].row))); // sum, range_check - constraint_type constraint = var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row) - row_shift); + constraint_type constraint = var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row)); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row)) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row) - row_shift)}}); + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row))}}); } cur_constraints.push_back(constraint); if (component.range_check_input) { // chunk, range_check - constraint = var(component.W(conf.constraints[3][0].column), static_cast(conf.constraints[3][0].row) - row_shift); + constraint = var(component.W(conf.constraints[3][0].column), static_cast(conf.constraints[3][0].row)); for (std::size_t i = 1; i < 9; ++i) { - constraint -= var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift) + constraint -= var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row)) * (integral_type(1) << ((i-1) * 8)); cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), - {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row) - row_shift)}}); + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row))}}); } cur_constraints.push_back(constraint); } @@ -771,7 +736,7 @@ namespace nil { std::size_t conf_index_for_input = 0; if (component.shift != 0) { - bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow + 1, false)}); + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); conf_index_for_input = 1; } @@ -791,7 +756,7 @@ namespace nil { } if (component.shift != 0) { auto config = component.full_configuration[config_index++]; - bp.add_copy_constraint({var(component.C(0), start_row_index + 3, false, var::column_type::constant), + bp.add_copy_constraint({var(component.C(0), start_row_index + 1, false, var::column_type::constant), var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); } else { @@ -814,10 +779,9 @@ namespace nil { using component_type = padding_component; auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); - assignment.enable_selector(selector_indexes[0], start_row_index + 1); - assignment.enable_selector(selector_indexes[1], start_row_index + 1); + auto gc_map = component.gates_configuration_map; - std::size_t sel_ind = 2; + std::size_t sel_ind = 0; auto gc_iter = gc_map.begin(); if (gc_iter != gc_map.end()) { @@ -865,20 +829,11 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + BOOST_ASSERT(component.num_blocks == instance_input.message.size()); + std::size_t config_index = 0; // range_check shift integral_type mask_range_check = (integral_type(1) << 8) - 1; - integral_type shift = component.shift; - std::vector shift_range_check; - for (std::size_t i = 0; i < 7; ++i) { - shift_range_check.push_back(shift & mask_range_check); - shift >>= 8; - } - shift_range_check.push_back(shift); - assignment.witness(component.W(0), strow) = component.shift; - for (int j = 1; j < 9; ++j) { - assignment.witness(component.W(j), strow) = value_type(shift_range_check[j - 1]); - } if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); @@ -970,9 +925,7 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; assignment.constant(component.C(0), start_row_index) = 0; - assignment.constant(component.C(0), start_row_index + 1) = component.num_blocks; - assignment.constant(component.C(0), start_row_index + 2) = component.num_bits; - assignment.constant(component.C(0), start_row_index + 3) = value_type(component.padding_delimiter); + assignment.constant(component.C(0), start_row_index + 1) = value_type(component.padding_delimiter); } } // namespace components diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index de28049de..2aa33835e 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -1057,7 +1057,7 @@ namespace nil { constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize3_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize3_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1077,7 +1077,7 @@ namespace nil { constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize3_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize3_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1115,7 +1115,7 @@ namespace nil { constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize4_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize4_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1135,7 +1135,7 @@ namespace nil { constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize4_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize4_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1179,7 +1179,7 @@ namespace nil { constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize6_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize6_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1199,7 +1199,7 @@ namespace nil { constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.normalize6_num_chunks; ++k) { + for (std::size_t k = 0; k < component.normalize6_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1281,7 +1281,7 @@ namespace nil { constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.rotate_num_chunks; ++k) { + for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1321,7 +1321,7 @@ namespace nil { constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.rotate_num_chunks; ++k) { + for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1379,7 +1379,7 @@ namespace nil { constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.chi_num_chunks; ++k) { + for (std::size_t k = 0; k < component.chi_num_chunks; ++k) { constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1399,7 +1399,7 @@ namespace nil { constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); - for (int k = 0; k < component.chi_num_chunks; ++k) { + for (std::size_t k = 0; k < component.chi_num_chunks; ++k) { constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * @@ -1414,7 +1414,7 @@ namespace nil { } if (gm.first.first == 7) { for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { - for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { + for (std::size_t j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { lookup_constraint_type lookup_constraint = { lookup_tables_indices.at(cur_lookup_table_name), {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), @@ -1429,7 +1429,7 @@ namespace nil { continue; } for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { - for (int j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { + for (std::size_t j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { lookup_constraint_type lookup_constraint = { lookup_tables_indices.at(cur_lookup_table_name), {var(component.W(cur_lookup_config_vec[i].lookups[j][0].column), @@ -1816,7 +1816,7 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); @@ -1859,7 +1859,7 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); @@ -1922,7 +1922,7 @@ namespace nil { cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); @@ -1992,7 +1992,7 @@ namespace nil { cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); @@ -2044,7 +2044,7 @@ namespace nil { cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = A_2[index]; - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); @@ -2109,7 +2109,7 @@ namespace nil { cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].column), cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(integral_small_chunks[j - 1]); @@ -2160,7 +2160,7 @@ namespace nil { cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_chi_sum); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); @@ -2202,7 +2202,7 @@ namespace nil { cur_config.constraints[1][0].row + strow) = sum; assignment.witness(component.W(cur_config.constraints[2][0].column), cur_config.constraints[2][0].row + strow) = value_type(integral_normalized_sum); - for (int j = 1; j < num_chunks + 1; ++j) { + for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[1][j].column), cur_config.constraints[1][j].row + strow) = value_type(integral_chunks[j - 1]); diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 5f66cbed6..8b7beab67 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -140,8 +140,6 @@ std::vector std::size_t shift = 64 * message.size() - num_bits; if (shift > 0) { - // message[message.size() - 1] = message[message.size() - 1] * 2 + value_type(1); - // shift--; integral_type relay_value = integral_type(message[0].data); for (int i = 1; i < message.size(); ++i) { integral_type mask = (integral_type(1) << (64 - shift)) - 1; @@ -163,7 +161,6 @@ std::vector while (result.size() % 17 != 0) { result.push_back(value_type(0)); } - // result[result.size() - 1] += value_type(1); for (int i = 0; i < result.size(); i++) { result[i] = to_le_bytes(result[i]); @@ -215,15 +212,6 @@ std::array inner_state_integral[1][3] ^ padded_message_chunk_integral[16] ^ last_round_const_integral; } } - // std::cout << "["; - // for (int x = 0; x < 5; ++x) { - // std::cout << "["; - // for (int y = 0; y < 5; ++y) { - // std::cout << unpack(inner_state_integral[x][y]).data << ","; - // } - // std::cout << "],"; - // } - // std::cout << "]\n"; // theta std::array C; @@ -268,12 +256,12 @@ std::array } template -std::array +std::array keccak_function(std::vector message, std::size_t num_bits) { using value_type = typename BlueprintFieldType::value_type; - std::array hash; + std::array hash; std::vector padded_message = padding_function(message, num_bits); std::array inner_state; @@ -305,11 +293,6 @@ std::array std::size_t i = 0, j; std::array padded_message_chunk; // Absorbing - for (i = 0; i < padded_message.size(); i++) { - std::cout << padded_message[i].data << ","; - } - std::cout << std::endl; - std::size_t p17 = padded_message.size() / 17; for (i = 0; i < p17; i++) { for (j = 0; j < 17; j++) @@ -328,7 +311,7 @@ std::array } } - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) { hash[i] = unpack(inner_state[i]); } @@ -337,7 +320,7 @@ std::array template auto test_keccak_inner(std::vector message, - std::array expected_result, std::size_t num_blocks, + std::array expected_result, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; @@ -366,7 +349,6 @@ auto test_keccak_inner(std::vector mess typename component_type::input_type instance_input = {message_vars}; auto result_check = [expected_result](AssignmentType &assignment, typename component_type::result_type &real_res) { - std::cout << "sizes: " << expected_result.size() << " " << real_res.final_inner_state.size() << std::endl; assert(expected_result.size() == real_res.final_inner_state.size()); for (int i = 0; i < expected_result.size(); ++i) { std::cout << "res:\n" @@ -389,9 +371,8 @@ auto test_keccak_inner(std::vector mess nil::crypto3::test_component( component_instance, desc, public_input, result_check, instance_input, - {nil::blueprint::connectedness_check_type::type::STRONG, - nil::blueprint::connectedness_check_type::island_type::NONE}, num_blocks, num_bits, range_check_input, - limit_permutation_column); + nil::blueprint::connectedness_check_type::type::STRONG, + num_blocks, num_bits, range_check_input, limit_permutation_column); } // works @@ -411,23 +392,7 @@ void test_keccak_0(std::size_t num_bytes = 1) { const bool range_check_input = true; const std::size_t limit_permutation_column = 7; - std::array expected_result = keccak_function(message, num_bits); - - std::cout << expected_result[0].data << " " << expected_result[1].data << " " << expected_result[2].data << " " - << expected_result[3].data << std::endl; - - // std::cout << std::hex << message[0].data << std::endl; - integral_type result = integral_type(expected_result[0].data); - result = (result << 64) + integral_type(expected_result[1].data); - result = (result << 64) + integral_type(expected_result[2].data); - result = (result << 64) + integral_type(expected_result[3].data); - - // std::cout << std::hex << expected_result[0].data << std::endl; - // std::cout << std::hex << expected_result[1].data << std::endl; - // std::cout << std::hex << expected_result[2].data << std::endl; - // std::cout << std::hex << expected_result[3].data << std::endl; - - // std::cout << std::hex << result << std::endl; + std::array expected_result = keccak_function(message, num_bits); test_keccak_inner(message, expected_result, num_blocks, num_bits, range_check_input, limit_permutation_column); @@ -444,23 +409,7 @@ void test_keccak_hello_world() { const bool range_check_input = false; const std::size_t limit_permutation_column = 7; - std::array expected_result = keccak_function(message, num_bits); - - std::cout << expected_result[0].data << " " << expected_result[1].data << " " << expected_result[2].data << " " - << expected_result[3].data << std::endl; - - // std::cout << std::hex << message[0].data << std::endl; - integral_type result = integral_type(expected_result[0].data); - result = (result << 64) + integral_type(expected_result[1].data); - result = (result << 64) + integral_type(expected_result[2].data); - result = (result << 64) + integral_type(expected_result[3].data); - - // std::cout << std::hex << expected_result[0].data << std::endl; - // std::cout << std::hex << expected_result[1].data << std::endl; - // std::cout << std::hex << expected_result[2].data << std::endl; - // std::cout << std::hex << expected_result[3].data << std::endl; - - // std::cout << std::hex << result << std::endl; + std::array expected_result = keccak_function(message, num_bits); test_keccak_inner(message, expected_result, num_blocks, num_bits, range_check_input, limit_permutation_column); @@ -494,55 +443,37 @@ void test_keccak_random(std::size_t message_size = 1, bool random_mask_zero = tr std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); std::size_t num_blocks = message_size; - std::vector expected_result = { - value_type(integral_type(1) << 63), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector expected_result = keccak_function(message, num_bits); test_keccak_inner(message, expected_result, num_blocks, num_bits, range_check_input, limit_permutation_column); } -// template -// void test_keccak_padding_random() { -// using value_type = typename BlueprintFieldType::value_type; -// using integral_type = typename BlueprintFieldType::integral_type; -// std::random_device rd; -// std::mt19937 gen(rd()); -// std::uniform_int_distribution dis; +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) -// integral_type mask = (integral_type(1) << 64) - 1; -// integral_type mask_zero = (integral_type(1) << 60) - 1; -// std::vector message = {value_type(integral_type(dis(gen)) & mask_zero), -// value_type(integral_type(dis(gen)) & mask), -// value_type(integral_type(dis(gen)) & mask)}; -// std::size_t num_bits = 64 * (message.size() - 1) + number_bits(message[0]); -// std::size_t num_blocks = message.size(); +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_pallas) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; -// for (int i = 0; i < message.size(); ++i) { -// std::cout << "message: " << message[i].data << std::endl; -// } + test_keccak_0(136); + test_keccak_0(1); + test_keccak_hello_world(); +} -// auto expected_result = padding_function(message, num_bits); +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { + using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; -// test_keccak_padding_inner -// (message, expected_result, num_blocks, num_bits); -// } + test_keccak_0(136); + test_keccak_0(1); + test_keccak_hello_world(); +} -BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_bn254) { + using field_type = nil::crypto3::algebra::curves::alt_bn128_254::base_field_type; -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_pallas) { - // using field_type = nil::crypto3::algebra::curves::alt_bn128_254::base_field_type; - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - // test_keccak_round_random(1); - // test_keccak_0(136); test_keccak_0(136); - // test_keccak_hello_world(); - // test_keccak_round_random(); + test_keccak_0(1); + test_keccak_hello_world(); } -// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { -// using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; -// } - BOOST_AUTO_TEST_SUITE_END() From 79d876d4e81eeb102dd39dd623acb2d1ce805f4d Mon Sep 17 00:00:00 2001 From: Maksim Nikolaev Date: Thu, 20 Jun 2024 08:12:23 +0000 Subject: [PATCH 42/48] constraints updates, don't work yet --- .../hashes/keccak/keccak_padding.hpp | 298 +++++++++++++++++- .../components/hashes/keccak/keccak_round.hpp | 250 +++++++++++++-- test/hashes/plonk/keccak_padding.cpp | 46 +-- test/hashes/plonk/keccak_round.cpp | 30 +- 4 files changed, 546 insertions(+), 78 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index 8c0dd57cd..ece502d5d 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -123,6 +123,9 @@ namespace nil { const std::vector> gates_configuration = configure_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::vector> output_gates_configuration = + configure_output_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + std::vector gates_rows = calculate_gates_rows(this->witness_amount()); const std::size_t rows_amount = @@ -146,20 +149,33 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { - auto size = component.full_configuration.size(); + auto size = component.full_configuration.size() - 1; + std::cout << "size: " << size << std::endl; padded_message.resize(size + component.num_padding_zeros); - for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + for (std::size_t i = 0; i < padded_message.size() - 17; ++i) { auto config = component.full_configuration[i]; padded_message[i] = var(component.W(config.copy_to.back().column), config.copy_to.back().row + start_row_index, false); } - if(component.shift == 0){ - padded_message[size] = var(component.C(0), start_row_index + 1, false, var::column_type::constant); - } - - for (std::size_t i = size + (component.shift == 0); i < size + component.num_padding_zeros; ++i) { - padded_message[i] = var(component.C(0), start_row_index, false, var::column_type::constant); + std::cout << "padded_message.size(): " << padded_message.size() << std::endl; + for (std::size_t i = 0; i < 17; ++i) { + padded_message[padded_message.size() - 17 + i] = var(component.W(component.full_configuration.back().copy_to[i].column), + component.full_configuration.back().copy_to[i].row + start_row_index, false); } + std::cout << "padded_message: " << padded_message.size() << std::endl; + + // for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { + // auto config = component.full_configuration[i]; + // padded_message[i] = var(component.W(config.copy_to.back().column), + // config.copy_to.back().row + start_row_index, false); + // } + // if(component.shift == 0){ + // padded_message[size] = var(component.C(0), start_row_index + 1, false, var::column_type::constant); + // } + + // for (std::size_t i = size + (component.shift == 0); i < size + component.num_padding_zeros; ++i) { + // padded_message[i] = var(component.C(0), start_row_index, false, var::column_type::constant); + // } } std::vector> all_vars() { @@ -368,6 +384,70 @@ namespace nil { return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells, buff); } + static configuration configure_output(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t limit_permutation_column, + std::size_t row, std::size_t column) { + + if (column > 0) { + row += 1; + column = 0; + } + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + std::size_t shift = calculate_shift(num_blocks, num_bits); + + // relay, chunk, sum; second + std::vector> copy_to; + std::pair cell_copy_from; + + std::vector> selectors; + std::pair almost_sum; //((34-sum)*sum-1) + std::pair delta; + std::vector> values; + + for (std::size_t i = 0; i < 17; i++) { + values.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + copy_to.push_back(values.back()); + + } + delta = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + for (std::size_t i = 0; i < 17; i++) { + selectors.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + + } + almost_sum = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + + std::vector>> constraints; + std::vector>> lookups(1); + + // //s_i(s_i - 1)(s_i - 2)=0 + // for (std::size_t i = 0; i < 17; i++) { + // constraints.push_back({selectors[i]}); + // } + // // ((34-sum)*sum-1)-almost_sum=0 + // constraints.push_back({almost_sum}); + // //s_i(s_i - 2)s_i+1=0 && (s_i+1 - s_i + 1)(s_i+1 - s_i)=0 + // for (std::size_t i = 0; i < 17 - 1; i++) { + // constraints.push_back({selectors[i], selectors[i + 1]}); + // } + //s_i(s_i - 2)(w_i*delta - 1)=0 && (s_i - 1)(s_i - 2)w_i=0 + for (std::size_t i = 0; i < 17; i++) { + constraints.push_back({selectors[i], values[i], delta}); + } + + lookups[0].push_back(almost_sum); + std::cout << "almost_sum: " << almost_sum.first << " " << almost_sum.second << std::endl; + + last_row = almost_sum.first; + last_column = almost_sum.second; + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + } + static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { @@ -389,6 +469,7 @@ namespace nil { conf.last_coordinate = {row, column}; result.push_back(conf); } + result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column, row, column)); return result; } @@ -400,6 +481,7 @@ namespace nil { row = conf.last_coordinate.row; column = conf.last_coordinate.column; } + result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column, row, column)); // std::cout << "num_cofigs: " << result.size() << "\n"; // for (std::size_t i = 0; i < result.size(); ++i) { @@ -459,11 +541,70 @@ namespace nil { return config_map; } + static std::vector> configure_output_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + std::vector> result; + + configuration cur_config = configure_output(witness_amount, num_blocks, num_bits, + range_check_input, limit_permutation_column, + 0, 0); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max <= 2 + min); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } + cur_result.push_back(c); + } + cur_result.back().lookups = cur_config.lookups; + result.push_back(cur_result); + + std::cout << "output gates:\n"; + for (std::size_t i = 0; i < result.size(); ++i) { + std::cout << "config " << i << ":\n"; + for (auto cur_config : result[i]) { + std::cout << "gate:\n"; + for (int j = 0; j < cur_config.constraints.size(); ++j) { + for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + } + std::cout << std::endl; + } + } + } + + return result; + } + static std::vector> configure_gates(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { + // auto output_gates = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { return {}; } @@ -539,6 +680,15 @@ namespace nil { res.push_back(cur_row); cur_row += incr; } + + auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + auto output = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + auto row = config.back().last_coordinate.row; + if (config.back().last_coordinate.column == 0) row--; + if (output.size() == 2) { + res.push_back(row - 2); + } + res.push_back(row - 1); return res; } @@ -548,7 +698,10 @@ namespace nil { bool range_check_input, std::size_t limit_permutation_column = 7) { auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); - return map.size() * 2 + range_check_input; + auto res = map.size() * 2 + range_check_input; + auto output = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); + res += output[0].size() + 1; + return res; } static std::size_t get_rows_amount(std::size_t witness_amount, @@ -714,7 +867,84 @@ namespace nil { cur_lookup_constraints.clear(); } } + + auto output_gates = component.output_gates_configuration[0]; + std::size_t idx[2] = {0, 0}; + std::size_t shifts[2] = {1, 1}; + std::cout << "output_gates.size(): " << output_gates.size() << std::endl; + if (output_gates.size() > 1) { + idx[1] = 1; + shifts[1] = 2; + } + std::cout << "here0 " << std::endl; + // (s_i - 1)(s_i - 2)w_i=0 && s_i(s_i - 2)(w_i*delta - 1)=0 + for (auto constr : output_gates[idx[0]].constraints) { + cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 1) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 2) * + var(constr[1].column, static_cast(constr[1].row) - shifts[0])); + cur_constraints.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[0]) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 2) * + (var(constr[1].column, static_cast(constr[1].row) - shifts[0]) * var(constr[2].column, static_cast(constr[2].row) - shifts[0]) - 1)); + } + std::cout << "here1 " << std::endl; + if (output_gates.size() > 1) { + std::cout << "here2 " << std::endl; + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + cur_constraints.clear(); + } + std::cout << "here3 " << std::endl; + for (auto constr : output_gates[idx[1]].constraints) { + cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 1) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * + var(constr[1].column, static_cast(constr[1].row) - shifts[1])); + cur_constraints.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[1]) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * + (var(constr[1].column, static_cast(constr[1].row) - shifts[1]) * var(constr[2].column, static_cast(constr[2].row) - shifts[1]) - 1)); + } + std::cout << "here4 " << std::endl; + std::vector s_i; + for (std::size_t i = 0; i < 2; ++i) { + for (auto constr : output_gates[idx[i]].constraints) { + std::cout << "gt: " << static_cast(constr[0].row) - shifts[1] << " " << constr[0].column << std::endl; + s_i.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[1])); + } + } + std::cout << "here40 " << std::endl; + // s_i(s_i - 1)(s_i - 2)=0 + for (std::size_t i = 0; i < 17; ++i) { + cur_constraints.push_back(s_i[i] * (s_i[i] - 1) * (s_i[i] - 2)); + } + std::cout << "here10 " << std::endl; + // s_i(s_i - 2)s_i+1=0 && (s_i+1 - s_i + 1)(s_i+1 - s_i)=0 + for (std::size_t i = 0; i < 16; ++i) { + cur_constraints.push_back(s_i[i] * (s_i[i] - 2) * s_i[i+1]); + cur_constraints.push_back((s_i[i+1] - s_i[i] + 1) * (s_i[i+1] - s_i[i])); + } + std::cout << "here11 " << std::endl; + // sum + constraint_type sum = s_i[0]; + for (std::size_t i = 1; i < s_i.size(); ++i) { + sum += s_i[i]; + } + std::cout << "here12 " << std::endl; + cur_constraints.push_back((34 - sum) * sum - 1 - var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])); + + std::cout << "here5 " << std::endl; + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + cur_constraints.clear(); + + std::cout << "here6 " << std::endl; + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])}}); + + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); + BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); + std::cout << "gates_amount: " << component.gates_amount << std::endl; return selector_indexes; } @@ -740,7 +970,7 @@ namespace nil { conf_index_for_input = 1; } - while (config_index < component.full_configuration.size() - 1) { + while (config_index < component.full_configuration.size() - 2) { auto config = component.full_configuration[config_index]; bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(config.copy_to[conf_index_for_input].column), @@ -765,6 +995,20 @@ namespace nil { var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); } + + auto config = component.full_configuration[config_index]; + std::size_t idx = 0; + for (int i = 0; i < 17 - component.num_padding_zeros; ++i) { + idx++; + // TODO + // auto prev_config = component.full_configuration[config_index - 17 + i]; + // bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), + // var(component.W(prev_config.copy_from.column), prev_config.copy_from.row + strow, false)}); + } + for (int i = 0; i < component.num_padding_zeros; ++i) { + bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), + var(component.C(0), start_row_index, false, var::column_type::constant)}); + } } template @@ -775,6 +1019,7 @@ namespace nil { &assignment, const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { + std::cout << "circuit:\n"; using component_type = padding_component; @@ -808,9 +1053,21 @@ namespace nil { sel_ind += 2; } } + auto output = component.full_configuration.back(); + auto output_gates = component.output_gates_configuration[0]; + std::cout << "output gates: " << start_row_index << '\n'; + std::cout << "output gates: " << output.first_coordinate.row << '\n'; + std::cout << "output gates: " << output.first_coordinate.row + 1 + start_row_index << '\n'; + assignment.enable_selector(selector_indexes[sel_ind++], output.first_coordinate.row + 1 + start_row_index); + if (output_gates.size() > 1) { + assignment.enable_selector(selector_indexes[sel_ind], output.first_coordinate.row + 2 + start_row_index); + } + std::cout << "help me0" << '\n'; generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + std::cout << "help me1" << '\n'; generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); + std::cout << "help me2" << '\n'; return typename component_type::result_type(component, start_row_index); } @@ -834,6 +1091,7 @@ namespace nil { std::size_t config_index = 0; // range_check shift integral_type mask_range_check = (integral_type(1) << 8) - 1; + std::vector output_values; if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); @@ -847,6 +1105,7 @@ namespace nil { std::array chunk_parts = {integral_chunk >> (64 - component.shift), integral_chunk & mask}; integral_type sum = (relay_chunk << component.shift) + chunk_parts[0]; + output_values.push_back(value_type(sum)); std::vector sum_range_check; integral_type sum_to_check = sum; @@ -887,7 +1146,7 @@ namespace nil { config_index++; } } else { - for (std::size_t index = 0; index < component.full_configuration.size(); ++index) { + for (std::size_t index = 0; index < component.num_blocks; ++index) { auto cur_config = component.full_configuration[index]; if (component.range_check_input) { @@ -907,9 +1166,26 @@ namespace nil { assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = var_value(assignment, instance_input.message[index]); + output_values.push_back(var_value(assignment, instance_input.message[index])); } } + auto config = component.full_configuration.back(); + std::size_t idx = 0; + value_type last_nonzero = value_type(1); + for (int i = 0; i < output_values.size(); ++i) { + last_nonzero = output_values[i]; + assignment.witness(component.W(config.copy_to[idx].column), config.copy_to[idx].row + strow) = last_nonzero; + assignment.witness(component.W(config.constraints[idx][0].column), config.constraints[idx++][0].row + strow) = (i == output_values.size() - 1) ? value_type(1) : value_type(2); + } + assignment.witness(component.W(config.constraints[idx - 1][2].column), config.constraints[idx - 1][2].row + strow) = value_type(1) / last_nonzero; + for (int i = 0; i < component.num_padding_zeros; ++i) { + assignment.witness(component.W(config.copy_to[idx].column), config.copy_to[idx].row + strow) = value_type(0); + assignment.witness(component.W(config.constraints[idx][0].column), config.constraints[idx++][0].row + strow) = value_type(0); + } + value_type sum_s = value_type((17 - component.num_padding_zeros) * 2 - 1); + assignment.witness(component.W(config.lookups[0][0].column), config.lookups[0][0].row + strow) = sum_s * (value_type(34) - sum_s) - value_type(1); + return typename component_type::result_type(component, start_row_index); } diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 2aa33835e..6b3ce5902 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -64,7 +64,7 @@ namespace nil { static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base = 0) { if (base == 0) - return 8; + return 24; std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -82,7 +82,7 @@ namespace nil { } static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 0) { if (base == 0) - return 24; + return 24 + 1 * (1 + 8); std::size_t res = base == 3 ? 2 + 2 : base == 4 ? 3 + 2 : base == 6 ? 5 + 2 : 5; res += 2 * calculate_num_chunks(num_rows, base); return res; @@ -92,7 +92,7 @@ namespace nil { std::size_t buff = 0; std::size_t cells = calculate_num_cells(num_rows, base); if (base == 0) { - return 3 * witness_amount - cells; + return (10 * witness_amount - cells) % witness_amount; } if (base == 6) { return witness_amount * ((cells - 1) / witness_amount + 1) - cells; @@ -199,19 +199,19 @@ namespace nil { const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); const std::size_t normalize6_chunk_size = calculate_chunk_size(lookup_rows, 6); const std::size_t chi_chunk_size = calculate_chunk_size(lookup_rows, 5); - const std::size_t rotate_chunk_size = 24; + const std::size_t rotate_chunk_size = calculate_chunk_size(lookup_rows); const std::size_t normalize3_num_chunks = calculate_num_chunks(lookup_rows, 3); const std::size_t normalize4_num_chunks = calculate_num_chunks(lookup_rows, 4); const std::size_t normalize6_num_chunks = calculate_num_chunks(lookup_rows, 6); const std::size_t chi_num_chunks = calculate_num_chunks(lookup_rows, 5); - const std::size_t rotate_num_chunks = 8; + const std::size_t rotate_num_chunks = calculate_num_chunks(lookup_rows); const std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); const std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); const std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); const std::size_t chi_cells = calculate_num_cells(lookup_rows, 5); - const std::size_t rotate_cells = 24; + const std::size_t rotate_cells = calculate_num_cells(lookup_rows); const std::size_t xor2_buff = calculate_buff(this->witness_amount(), lookup_rows, 3); const std::size_t xor3_buff = calculate_buff(this->witness_amount(), lookup_rows, 4); @@ -463,12 +463,14 @@ namespace nil { // bound_big = big_part - sparse((1 << (64 - r)) - 1) + sparse((1 << 64) - 1); // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) // 1 << 192 = (1 << (192 - 3 * r)) * (1 << (3 * r)) + // small_part = small_part_chunk0 + small_part_chunk1 * 2^chunk_size + ... + small_part_chunkk * 2^(k*chunk_size) + // big_part = big_part_chunk0 + big_part_chunk1 * 2^chunk_size + ... + big_part_chunkk * 2^(k*chunk_size) std::pair first_coordinate = {row, column}; std::size_t last_row = row, last_column = column; - std::size_t num_chunks = 8; - std::size_t num_cells = 24; + std::size_t num_chunks = calculate_num_chunks(lookup_rows); + std::size_t num_cells = calculate_num_cells(lookup_rows); std::vector> copy_to; std::pair cell_copy_from; @@ -538,14 +540,135 @@ namespace nil { constraints[2].push_back(constraints[6][0]); constraints[4].push_back(constraints[6][1]); + constraints.push_back({cells[cell_index++]}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[7].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[7].back()); + lookups[1].push_back(constraints[7].back()); + } + // constraints.push_back({cells[cell_index++]}); + // for (std::size_t j = 0; j < num_chunks; ++j) { + // constraints[8].push_back(cells[cell_index++]); + // // lookups[0].push_back(constraints[8].back()); + // // lookups[1].push_back(constraints[8].back()); + // } + + std::cout << constraints[7].back().first << " " << constraints[7].back().second << std::endl; + std::cout << "cell " << cells.back().first << " " << cells.back().second << std::endl; last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; + std::cout << "last row: " << last_row << " last column: " << last_column << std::endl; return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } + + // static configuration configure_additional_rot(std::size_t witness_amount, std::size_t limit_permutation_column, + // std::size_t row, std::size_t column) { + // // regular constraints: + // // small_part = small_part_chunk0 + small_part_chunk1 * 2^chunk_size + ... + small_part_chunkk * 2^(k*chunk_size) + // // big_part = big_part_chunk0 + big_part_chunk1 * 2^chunk_size + ... + big_part_chunkk * 2^(k*chunk_size) + + // std::pair first_coordinate = {row, column}; + + // std::size_t last_row = row, last_column = column; + // std::size_t num_chunks = calculate_num_chunks(lookup_rows); + // std::size_t num_cells = 2 * (1 + 8); + + // std::vector> copy_to; + // std::pair cell_copy_from; + // std::vector>> constraints; + + // if (2 + column > limit_permutation_column) { + // copy_to.push_back({last_row + 1, 0}); + // cell_copy_from = {last_row + 1, 1}; + // } else { + // copy_to.push_back( + // {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); + // cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + // } + + // std::vector> cells; + // if (2 + column > limit_permutation_column) { + // for (int i = column; i < witness_amount; ++i) { + // cells.push_back({row, i}); + // } + // std::size_t cells_left = num_cells - witness_amount + column; + // std::size_t cur_row = row + 1, cur_column = 2; + // while (cur_column < cells_left) { + // cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + // } + // } else { + // std::size_t cur_row = row, cur_column = column + 2; + // while (cur_column - column < num_cells) { + // cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + // } + // } + // std::size_t cell_index = 0; + // auto rot_const = cells[cell_index++]; + // auto minus_rot_const = cells[cell_index++]; + + // constraints.push_back({copy_to[0]}); + // constraints[0].push_back(cells[cell_index++]); + // constraints[0].push_back(cells[cell_index++]); + + // constraints.push_back({cell_copy_from}); + // constraints[1].push_back(constraints[0][2]); + // constraints[1].push_back(constraints[0][1]); + + // std::vector>> lookups( + // 2, std::vector>()); + + // constraints.push_back({cells[cell_index++]}); + // constraints[2].push_back(constraints[0][1]); + // constraints.push_back({constraints[2][0]}); + // for (std::size_t j = 0; j < num_chunks; ++j) { + // constraints[3].push_back(cells[cell_index++]); + // lookups[0].push_back(constraints[3].back()); + // lookups[1].push_back(constraints[3].back()); + // } + + // constraints.push_back({cells[cell_index++]}); + // constraints[4].push_back(constraints[0][2]); + // constraints.push_back({constraints[4][0]}); + // for (std::size_t j = 0; j < num_chunks; ++j) { + // constraints[5].push_back(cells[cell_index++]); + // lookups[0].push_back(constraints[5].back()); + // lookups[1].push_back(constraints[5].back()); + // } + // constraints.push_back({rot_const, minus_rot_const}); + + // constraints[0].push_back(constraints[6][1]); + // constraints[1].push_back(constraints[6][0]); + // constraints[2].push_back(constraints[6][0]); + // constraints[4].push_back(constraints[6][1]); + + // constraints.push_back({cells[cell_index++]}); + // for (std::size_t j = 0; j < num_chunks; ++j) { + // constraints[7].push_back(cells[cell_index++]); + // lookups[0].push_back(constraints[7].back()); + // lookups[1].push_back(constraints[7].back()); + // } + // // constraints.push_back({cells[cell_index++]}); + // // for (std::size_t j = 0; j < num_chunks; ++j) { + // // constraints[8].push_back(cells[cell_index++]); + // // // lookups[0].push_back(constraints[8].back()); + // // // lookups[1].push_back(constraints[8].back()); + // // } + + // std::cout << constraints[7].back().first << " " << constraints[7].back().second << std::endl; + // std::cout << "cell " << cells.back().first << " " << cells.back().second << std::endl; + // last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); + // last_row = cells.back().first + (last_column / witness_amount); + // last_column %= witness_amount; + // std::cout << "last row: " << last_row << " last column: " << last_column << std::endl; + + // return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + // cell_copy_from); + // } + static std::vector configure_all(std::size_t witness_amount, bool xor_with_mes, bool last_round_call, @@ -779,22 +902,22 @@ namespace nil { break; } - // std::cout << "\nconfig:\n"; - // std::cout << config.first.first << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << - // " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << - // std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << - // std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << - // std::endl; - // } - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << - // cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } + std::cout << "\nconfig:\n"; + std::cout << config.first.first << "\n"; + std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << + " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << + std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << + std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { + std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << + std::endl; + } + for (int j = 0; j < cur_config.constraints.size(); ++j) { + for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + std::cout << cur_config.constraints[j][k].row << " " << + cur_config.constraints[j][k].column << ", "; + } + std::cout << std::endl; + } std::vector> pairs; for (auto constr : cur_config.constraints) { @@ -1346,6 +1469,46 @@ namespace nil { cur_config_vec[i].first_coordinate.row - 1) - (integral_type(1) << 192)); + j++; + cur_len = cur_config_vec[i].constraints.size(); + if (j >= cur_len) { + selector_indexes.push_back(bp.add_gate(cur_constraints)); + cur_constraints.clear(); + } + i += j / cur_len; + j %= cur_len; + + constraint_type constraint_3 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); + for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { + constraint_3 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.rotate_chunk_size)); + } + cur_constraints.push_back(constraint_3); + + // j++; + // cur_len = cur_config_vec[i].constraints.size(); + // if (j >= cur_len) { + // selector_indexes.push_back(bp.add_gate(cur_constraints)); + // cur_constraints.clear(); + // } + // i += j / cur_len; + // j %= cur_len; + + // constraint_type constraint_4 = var(cur_config_vec[i].constraints[j][0].column, + // cur_config_vec[i].constraints[j][0].row - + // cur_config_vec[i].first_coordinate.row - 1); + // for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { + // constraint_4 -= var(cur_config_vec[i].constraints[j][k + 1].column, + // cur_config_vec[i].constraints[j][k + 1].row - + // cur_config_vec[i].first_coordinate.row - 1) * + // (integral_type(1) << (k * component.rotate_chunk_size)); + // } + // cur_constraints.push_back(constraint_4); + selector_indexes.push_back(bp.add_gate(cur_constraints)); cur_lookup_table_name = "keccak_pack_table/range_check_sparse"; @@ -1954,8 +2117,8 @@ namespace nil { integral_type bigger_part = integral_C & ((integral_type(1) << 189) - 1); integral_type integral_C_rot = (bigger_part << 3) + smaller_part; C_rot[index] = value_type(integral_C_rot); - // integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); - // integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); + auto copy_smaller_part = smaller_part; + auto copy_bigger_part = bigger_part; integral_type bound_smaller = smaller_part + for_bound_smaller; integral_type bound_bigger = bigger_part + for_bound_bigger; auto copy_bound_smaller = bound_smaller; @@ -1966,10 +2129,18 @@ namespace nil { std::vector integral_big_chunks; integral_type mask = (integral_type(1) << chunk_size) - 1; for (std::size_t j = 0; j < num_chunks; ++j) { - integral_small_chunks.push_back(bound_smaller & mask); - bound_smaller >>= chunk_size; - integral_big_chunks.push_back(bound_bigger & mask); - bound_bigger >>= chunk_size; + integral_small_chunks.push_back(copy_bound_smaller & mask); + copy_bound_smaller >>= chunk_size; + integral_big_chunks.push_back(copy_bound_bigger & mask); + copy_bound_bigger >>= chunk_size; + } + std::vector integral_smaller_chunks; + std::vector integral_bigger_chunks; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_smaller_chunks.push_back(copy_smaller_part & mask); + copy_smaller_part >>= chunk_size; + integral_bigger_chunks.push_back(copy_bigger_part & mask); + copy_bigger_part >>= chunk_size; } // auto check = integral_big_chunks[0]; // auto power = integral_type(1); @@ -1989,9 +2160,9 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].column), - cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); + cur_config.constraints[3][0].row + strow) = value_type(bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].column), - cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); + cur_config.constraints[5][0].row + strow) = value_type(bound_bigger); for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = @@ -2004,6 +2175,21 @@ namespace nil { cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << 3); assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); + + assignment.witness(component.W(cur_config.constraints[7][0].column), + cur_config.constraints[7][0].row + strow) = value_type(smaller_part); + // assignment.witness(component.W(cur_config.constraints[8][0].column), + // cur_config.constraints[8][0].row + strow) = value_type(bigger_part); + std::cout << "smaller_part: " << smaller_part << '\n'; + for (std::size_t j = 1; j < num_chunks + 1; ++j) { + std::cout << "integral_smaller_chunks[j - 1]: " << integral_smaller_chunks[j - 1] << '\n'; + assignment.witness(component.W(cur_config.constraints[7][j].column), + cur_config.constraints[7][j].row + strow) = + value_type(integral_smaller_chunks[j - 1]); + // assignment.witness(component.W(cur_config.constraints[8][j].column), + // cur_config.constraints[8][j].row + strow) = + // value_type(integral_bigger_chunks[j - 1]); + } } config_index += 5; // std::cout << "C_rot:\n"; diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index bc6d43ced..c7e95560c 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -104,7 +104,7 @@ auto test_keccak_padding_inner(std::vector desc(WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; @@ -127,10 +127,15 @@ auto test_keccak_padding_inner(std::vector(); - for (std::size_t i = 1; i < 100; i++) { - test_keccak_padding_1(i); - test_keccak_padding_random(i); - test_keccak_padding_random(i, false); - test_keccak_padding_random(i, true, false); - test_keccak_padding_random(i, false, false); - } -} +// test_keccak_padding_0(); +// for (std::size_t i = 1; i < 100; i++) { +// test_keccak_padding_1(i); +// test_keccak_padding_random(i); +// test_keccak_padding_random(i, false); +// test_keccak_padding_random(i, true, false); +// test_keccak_padding_random(i, false, false); +// } +// } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - test_keccak_padding_0(); - for (std::size_t i = 1; i < 100; i++) { - test_keccak_padding_1(i); - test_keccak_padding_random(i); - test_keccak_padding_random(i, false); - test_keccak_padding_random(i, true, false); - test_keccak_padding_random(i, false, false); - } + // test_keccak_padding_0(); + test_keccak_padding_random(18); + // for (std::size_t i = 1; i < 100; i++) { + // test_keccak_padding_1(i); + // test_keccak_padding_random(i); + // test_keccak_padding_random(i, false); + // test_keccak_padding_random(i, true, false); + // test_keccak_padding_random(i, false, false); + // } } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { diff --git a/test/hashes/plonk/keccak_round.cpp b/test/hashes/plonk/keccak_round.cpp index 23435107f..7a45bcffe 100644 --- a/test/hashes/plonk/keccak_round.cpp +++ b/test/hashes/plonk/keccak_round.cpp @@ -384,23 +384,23 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; test_keccak_round_not_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); + // test_keccak_round_random(); test_keccak_round_random(); } -BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { - using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; - test_keccak_round_not_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); - test_keccak_round_random(); -} +// BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_diff_perm_cols) { +// using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; +// test_keccak_round_not_random(); +// test_keccak_round_random(); +// test_keccak_round_random(); +// test_keccak_round_random(); +// test_keccak_round_random(); +// test_keccak_round_random(); +// test_keccak_round_random(); +// } BOOST_AUTO_TEST_SUITE_END() From 9a6224f209863a1199ad59df2d3baa2dd033f304 Mon Sep 17 00:00:00 2001 From: ChernyshovaP <42933210+tshchelovek@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:44:13 +0200 Subject: [PATCH 43/48] Update keccak_round.hpp --- .../components/hashes/keccak/keccak_round.hpp | 509 ++++++++---------- 1 file changed, 227 insertions(+), 282 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp index 6b3ce5902..1495a12f1 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_round.hpp @@ -64,7 +64,7 @@ namespace nil { static std::size_t calculate_chunk_size(std::size_t num_rows, std::size_t base = 0) { if (base == 0) - return 24; + return 8; std::size_t chunk_size = 0; std::size_t power = base; while (power < num_rows) { @@ -82,7 +82,7 @@ namespace nil { } static std::size_t calculate_num_cells(std::size_t num_rows, std::size_t base = 0) { if (base == 0) - return 24 + 1 * (1 + 8); + return 24; std::size_t res = base == 3 ? 2 + 2 : base == 4 ? 3 + 2 : base == 6 ? 5 + 2 : 5; res += 2 * calculate_num_chunks(num_rows, base); return res; @@ -92,7 +92,7 @@ namespace nil { std::size_t buff = 0; std::size_t cells = calculate_num_cells(num_rows, base); if (base == 0) { - return (10 * witness_amount - cells) % witness_amount; + return 3 * witness_amount - cells; } if (base == 6) { return witness_amount * ((cells - 1) / witness_amount + 1) - cells; @@ -199,19 +199,19 @@ namespace nil { const std::size_t normalize4_chunk_size = calculate_chunk_size(lookup_rows, 4); const std::size_t normalize6_chunk_size = calculate_chunk_size(lookup_rows, 6); const std::size_t chi_chunk_size = calculate_chunk_size(lookup_rows, 5); - const std::size_t rotate_chunk_size = calculate_chunk_size(lookup_rows); + const std::size_t rotate_chunk_size = 24; const std::size_t normalize3_num_chunks = calculate_num_chunks(lookup_rows, 3); const std::size_t normalize4_num_chunks = calculate_num_chunks(lookup_rows, 4); const std::size_t normalize6_num_chunks = calculate_num_chunks(lookup_rows, 6); const std::size_t chi_num_chunks = calculate_num_chunks(lookup_rows, 5); - const std::size_t rotate_num_chunks = calculate_num_chunks(lookup_rows); + const std::size_t rotate_num_chunks = 8; const std::size_t xor2_cells = calculate_num_cells(lookup_rows, 3); const std::size_t xor3_cells = calculate_num_cells(lookup_rows, 4); const std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); const std::size_t chi_cells = calculate_num_cells(lookup_rows, 5); - const std::size_t rotate_cells = calculate_num_cells(lookup_rows); + const std::size_t rotate_cells = 24; const std::size_t xor2_buff = calculate_buff(this->witness_amount(), lookup_rows, 3); const std::size_t xor3_buff = calculate_buff(this->witness_amount(), lookup_rows, 4); @@ -223,7 +223,7 @@ namespace nil { get_rows_amount(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); // full configuration is precalculated, then used in other functions - const std::size_t full_configuration_size = 17 * xor_with_mes + 85; + const std::size_t full_configuration_size = 17 * xor_with_mes + 85 + 29; std::vector full_configuration = configure_all(this->witness_amount(), xor_with_mes, last_round_call, limit_permutation_column); // number represents relative selector index for each constraint @@ -264,7 +264,7 @@ namespace nil { std::array inner_state; result_type(const keccak_round &component, std::size_t start_row_index) { - std::size_t num_config = component.full_configuration.size() - 1; + std::size_t num_config = component.full_configuration.size() - 30; inner_state[0] = var(component.W(component.full_configuration[num_config].copy_from.column), component.full_configuration[num_config].copy_from.row + start_row_index, false); @@ -463,14 +463,12 @@ namespace nil { // bound_big = big_part - sparse((1 << (64 - r)) - 1) + sparse((1 << 64) - 1); // bound_big = big_chunk0 + big_chunk1 * 2^chunk_size + ... + big_chunkk * 2^(k*chunk_size) // 1 << 192 = (1 << (192 - 3 * r)) * (1 << (3 * r)) - // small_part = small_part_chunk0 + small_part_chunk1 * 2^chunk_size + ... + small_part_chunkk * 2^(k*chunk_size) - // big_part = big_part_chunk0 + big_part_chunk1 * 2^chunk_size + ... + big_part_chunkk * 2^(k*chunk_size) std::pair first_coordinate = {row, column}; std::size_t last_row = row, last_column = column; - std::size_t num_chunks = calculate_num_chunks(lookup_rows); - std::size_t num_cells = calculate_num_cells(lookup_rows); + std::size_t num_chunks = 8; + std::size_t num_cells = 24; std::vector> copy_to; std::pair cell_copy_from; @@ -540,140 +538,80 @@ namespace nil { constraints[2].push_back(constraints[6][0]); constraints[4].push_back(constraints[6][1]); - constraints.push_back({cells[cell_index++]}); - for (std::size_t j = 0; j < num_chunks; ++j) { - constraints[7].push_back(cells[cell_index++]); - lookups[0].push_back(constraints[7].back()); - lookups[1].push_back(constraints[7].back()); - } - // constraints.push_back({cells[cell_index++]}); - // for (std::size_t j = 0; j < num_chunks; ++j) { - // constraints[8].push_back(cells[cell_index++]); - // // lookups[0].push_back(constraints[8].back()); - // // lookups[1].push_back(constraints[8].back()); - // } - - std::cout << constraints[7].back().first << " " << constraints[7].back().second << std::endl; - std::cout << "cell " << cells.back().first << " " << cells.back().second << std::endl; last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); last_row = cells.back().first + (last_column / witness_amount); last_column %= witness_amount; - std::cout << "last row: " << last_row << " last column: " << last_column << std::endl; return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } - // static configuration configure_additional_rot(std::size_t witness_amount, std::size_t limit_permutation_column, - // std::size_t row, std::size_t column) { - // // regular constraints: - // // small_part = small_part_chunk0 + small_part_chunk1 * 2^chunk_size + ... + small_part_chunkk * 2^(k*chunk_size) - // // big_part = big_part_chunk0 + big_part_chunk1 * 2^chunk_size + ... + big_part_chunkk * 2^(k*chunk_size) - - // std::pair first_coordinate = {row, column}; - - // std::size_t last_row = row, last_column = column; - // std::size_t num_chunks = calculate_num_chunks(lookup_rows); - // std::size_t num_cells = 2 * (1 + 8); - - // std::vector> copy_to; - // std::pair cell_copy_from; - // std::vector>> constraints; - - // if (2 + column > limit_permutation_column) { - // copy_to.push_back({last_row + 1, 0}); - // cell_copy_from = {last_row + 1, 1}; - // } else { - // copy_to.push_back( - // {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); - // cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; - // } - - // std::vector> cells; - // if (2 + column > limit_permutation_column) { - // for (int i = column; i < witness_amount; ++i) { - // cells.push_back({row, i}); - // } - // std::size_t cells_left = num_cells - witness_amount + column; - // std::size_t cur_row = row + 1, cur_column = 2; - // while (cur_column < cells_left) { - // cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); - // } - // } else { - // std::size_t cur_row = row, cur_column = column + 2; - // while (cur_column - column < num_cells) { - // cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); - // } - // } - // std::size_t cell_index = 0; - // auto rot_const = cells[cell_index++]; - // auto minus_rot_const = cells[cell_index++]; - - // constraints.push_back({copy_to[0]}); - // constraints[0].push_back(cells[cell_index++]); - // constraints[0].push_back(cells[cell_index++]); - - // constraints.push_back({cell_copy_from}); - // constraints[1].push_back(constraints[0][2]); - // constraints[1].push_back(constraints[0][1]); - - // std::vector>> lookups( - // 2, std::vector>()); - - // constraints.push_back({cells[cell_index++]}); - // constraints[2].push_back(constraints[0][1]); - // constraints.push_back({constraints[2][0]}); - // for (std::size_t j = 0; j < num_chunks; ++j) { - // constraints[3].push_back(cells[cell_index++]); - // lookups[0].push_back(constraints[3].back()); - // lookups[1].push_back(constraints[3].back()); - // } - - // constraints.push_back({cells[cell_index++]}); - // constraints[4].push_back(constraints[0][2]); - // constraints.push_back({constraints[4][0]}); - // for (std::size_t j = 0; j < num_chunks; ++j) { - // constraints[5].push_back(cells[cell_index++]); - // lookups[0].push_back(constraints[5].back()); - // lookups[1].push_back(constraints[5].back()); - // } - // constraints.push_back({rot_const, minus_rot_const}); - - // constraints[0].push_back(constraints[6][1]); - // constraints[1].push_back(constraints[6][0]); - // constraints[2].push_back(constraints[6][0]); - // constraints[4].push_back(constraints[6][1]); - - // constraints.push_back({cells[cell_index++]}); - // for (std::size_t j = 0; j < num_chunks; ++j) { - // constraints[7].push_back(cells[cell_index++]); - // lookups[0].push_back(constraints[7].back()); - // lookups[1].push_back(constraints[7].back()); - // } - // // constraints.push_back({cells[cell_index++]}); - // // for (std::size_t j = 0; j < num_chunks; ++j) { - // // constraints[8].push_back(cells[cell_index++]); - // // // lookups[0].push_back(constraints[8].back()); - // // // lookups[1].push_back(constraints[8].back()); - // // } - - // std::cout << constraints[7].back().first << " " << constraints[7].back().second << std::endl; - // std::cout << "cell " << cells.back().first << " " << cells.back().second << std::endl; - // last_column = cells.back().second + 1 + calculate_buff(witness_amount, num_chunks); - // last_row = cells.back().first + (last_column / witness_amount); - // last_column %= witness_amount; - // std::cout << "last row: " << last_row << " last column: " << last_column << std::endl; - - // return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, - // cell_copy_from); - // } + static configuration configure_additional_rot(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column) { + // regular constraints: + // small_part = small_part_chunk0 + small_part_chunk1 * 2^chunk_size + ... + small_part_chunkk * 2^(k*chunk_size) + // big_part = big_part_chunk0 + big_part_chunk1 * 2^chunk_size + ... + big_part_chunkk * 2^(k*chunk_size) + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, last_column = column; + std::size_t num_chunks = calculate_num_chunks(lookup_rows); + std::size_t num_cells = 2 * (1 + 8); + std::size_t buff = (10 * witness_amount - num_cells) % witness_amount; + + std::vector> copy_to; + std::pair cell_copy_from; + std::vector>> constraints; + + if (2 + column > limit_permutation_column) { + copy_to.push_back({last_row + 1, 0}); + cell_copy_from = {last_row + 1, 1}; + } else { + copy_to.push_back( + {last_row + (last_column / witness_amount), (last_column++) % witness_amount}); + cell_copy_from = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + } + + std::vector> cells; + std::size_t cur_row = row, cur_column = 0; + while (cur_column < num_cells) { + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + } + std::size_t cell_index = 0; + + std::vector>> lookups( + 2, std::vector>()); + + constraints.push_back({cells[cell_index++]}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[0].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[0].back()); + lookups[1].push_back(constraints[0].back()); + } + constraints.push_back({cells[cell_index++]}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[1].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[1].back()); + lookups[1].push_back(constraints[1].back()); + } + for (int i = 0; i < 2; ++i) { + copy_to.push_back(constraints[i][0]); + } + + last_column = cells.back().second + 1 + buff; + last_row = cells.back().first + (last_column / witness_amount); + last_column %= witness_amount; + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + cell_copy_from); + } static std::vector configure_all(std::size_t witness_amount, bool xor_with_mes, bool last_round_call, std::size_t limit_permutation_column) { - std::size_t full_configuration_size = 17 * xor_with_mes + 85; + std::size_t full_configuration_size = 17 * xor_with_mes + 85 + 29; auto result = std::vector(full_configuration_size); std::size_t row = 0, column = 0; std::size_t cur_config = 0; @@ -730,6 +668,20 @@ namespace nil { } // iota result[cur_config] = configure_xor(witness_amount, limit_permutation_column, row, column, 2); + row = result[cur_config].last_coordinate.row; + column = result[cur_config++].last_coordinate.column; + if (column != 0) { + row++; + column = 0; + } + + // rot range checks 24+5 + for (int i = 0; i < 29; ++i) { + result[cur_config] = configure_additional_rot(witness_amount, limit_permutation_column, row, column); + row = result[cur_config].last_coordinate.row; + column = result[cur_config].last_coordinate.column; + cur_config++; + } // for (int i = 0; i < result.size(); ++i) { // std::cout << "\n config: " << result[i].name << std::endl; @@ -857,13 +809,25 @@ namespace nil { } // iota row = config[cur_config].first_coordinate.row; - column = config[cur_config].first_coordinate.column; + column = config[cur_config++].first_coordinate.column; std::pair zero_config = {2, column}; if (config_map.find(zero_config) != config_map.end()) { config_map[zero_config].push_back(row); } else { config_map[zero_config] = {row}; } + // additional rot range checks + for (int i = 0; i < 29; ++i) { + row = config[cur_config].first_coordinate.row; + column = config[cur_config].first_coordinate.column; + std::pair zero_config = {10, column}; + if (config_map.find(zero_config) != config_map.end()) { + config_map[zero_config].push_back(row); + } else { + config_map[zero_config] = {row}; + } + cur_config++; + } return config_map; } @@ -900,24 +864,28 @@ namespace nil { cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; + case 10: + cur_config = + configure_additional_rot(witness_amount, limit_permutation_column, 0, config.first.second); + break; } - std::cout << "\nconfig:\n"; - std::cout << config.first.first << "\n"; - std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << - " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << - std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << - std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { - std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << - std::endl; - } - for (int j = 0; j < cur_config.constraints.size(); ++j) { - for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - std::cout << cur_config.constraints[j][k].row << " " << - cur_config.constraints[j][k].column << ", "; - } - std::cout << std::endl; - } + // std::cout << "\nconfig:\n"; + // std::cout << config.first.first << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << + // " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << + // std::endl; std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << + // std::endl; for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << + // std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << + // cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } std::vector> pairs; for (auto constr : cur_config.constraints) { @@ -986,6 +954,10 @@ namespace nil { cur_config = configure_chi(witness_amount, limit_permutation_column, 0, config.first.second); break; + case 10: + cur_config = + configure_additional_rot(witness_amount, limit_permutation_column, 0, config.first.second); + break; } std::vector> pairs; @@ -1065,11 +1037,13 @@ namespace nil { std::size_t xor5_cells = calculate_num_cells(lookup_rows, 6); std::size_t chi_cells = calculate_num_cells(lookup_rows, 5); std::size_t rotate_cells = calculate_num_cells(lookup_rows); + std::size_t additional_rotate_cells = 2 * (1 + 8); std::size_t xor2_buff = calculate_buff(witness_amount, lookup_rows, 3); std::size_t xor3_buff = calculate_buff(witness_amount, lookup_rows, 4); std::size_t xor5_buff = calculate_buff(witness_amount, lookup_rows, 6); std::size_t chi_buff = calculate_buff(witness_amount, lookup_rows, 5); std::size_t rotate_buff = calculate_buff(witness_amount, lookup_rows); + std::size_t additional_rotate_buff = (10 * witness_amount - additional_rotate_cells) % witness_amount; std::size_t num_cells = (xor3_cells + xor3_buff) * last_round_call * xor_with_mes + // xor with last message chunk @@ -1079,8 +1053,11 @@ namespace nil { 25 * (xor3_cells + xor3_buff) + // theta 24 * (rotate_cells + rotate_buff) + // rho/phi 25 * (chi_cells + chi_buff) + // chi - xor2_cells; // iota - return num_cells / witness_amount + bool(num_cells % witness_amount); + xor2_cells + xor2_buff + // iota + 29 * (additional_rotate_cells + additional_rotate_buff); // additional rotate + // return num_cells / witness_amount + bool(num_cells % witness_amount); + auto config = configure_all(witness_amount, xor_with_mes, last_round_call, limit_permutation_column); + return config.back().last_coordinate.row + (config.back().last_coordinate.column > 0); } std::map component_lookup_tables() { @@ -1469,6 +1446,25 @@ namespace nil { cur_config_vec[i].first_coordinate.row - 1) - (integral_type(1) << 192)); + selector_indexes.push_back(bp.add_gate(cur_constraints)); + + cur_lookup_table_name = "keccak_pack_table/range_check_sparse"; + break; + } + case 10: { + std::size_t true_first_row = cur_config_vec[i].first_coordinate.row; + + constraint_type constraint_1 = var(cur_config_vec[i].constraints[j][0].column, + cur_config_vec[i].constraints[j][0].row - + cur_config_vec[i].first_coordinate.row - 1); + for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { + constraint_1 -= var(cur_config_vec[i].constraints[j][k + 1].column, + cur_config_vec[i].constraints[j][k + 1].row - + cur_config_vec[i].first_coordinate.row - 1) * + (integral_type(1) << (k * component.rotate_chunk_size)); + } + cur_constraints.push_back(constraint_1); + j++; cur_len = cur_config_vec[i].constraints.size(); if (j >= cur_len) { @@ -1478,38 +1474,19 @@ namespace nil { i += j / cur_len; j %= cur_len; - constraint_type constraint_3 = var(cur_config_vec[i].constraints[j][0].column, + constraint_type constraint_2 = var(cur_config_vec[i].constraints[j][0].column, cur_config_vec[i].constraints[j][0].row - cur_config_vec[i].first_coordinate.row - 1); for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { - constraint_3 -= var(cur_config_vec[i].constraints[j][k + 1].column, + constraint_2 -= var(cur_config_vec[i].constraints[j][k + 1].column, cur_config_vec[i].constraints[j][k + 1].row - cur_config_vec[i].first_coordinate.row - 1) * (integral_type(1) << (k * component.rotate_chunk_size)); } - cur_constraints.push_back(constraint_3); - - // j++; - // cur_len = cur_config_vec[i].constraints.size(); - // if (j >= cur_len) { - // selector_indexes.push_back(bp.add_gate(cur_constraints)); - // cur_constraints.clear(); - // } - // i += j / cur_len; - // j %= cur_len; - - // constraint_type constraint_4 = var(cur_config_vec[i].constraints[j][0].column, - // cur_config_vec[i].constraints[j][0].row - - // cur_config_vec[i].first_coordinate.row - 1); - // for (std::size_t k = 0; k < component.rotate_num_chunks; ++k) { - // constraint_4 -= var(cur_config_vec[i].constraints[j][k + 1].column, - // cur_config_vec[i].constraints[j][k + 1].row - - // cur_config_vec[i].first_coordinate.row - 1) * - // (integral_type(1) << (k * component.rotate_chunk_size)); - // } - // cur_constraints.push_back(constraint_4); + cur_constraints.push_back(constraint_2); selector_indexes.push_back(bp.add_gate(cur_constraints)); + std::cout << selector_indexes.back() << std::endl; cur_lookup_table_name = "keccak_pack_table/range_check_sparse"; break; @@ -1575,7 +1552,7 @@ namespace nil { break; } } - if (gm.first.first == 7) { + if (gm.first.first >= 7) { for (std::size_t i = 0; i < cur_lookup_config_vec.size(); ++i) { for (std::size_t j = 0; j < cur_lookup_config_vec[i].lookups.size(); ++j) { lookup_constraint_type lookup_constraint = { @@ -1608,64 +1585,6 @@ namespace nil { } index++; } - // lookup gates - index = 0; - // for (auto gm: gate_map) { - // std::vector cur_lookup_config_vec = lookup_gate_config[index]; - // std::vector cur_lookup_constraints; - // std::string cur_lookup_table_name; - // std::cout << "lookups: " << gm.first.first << std::endl; - // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { - // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { - // for (int k = 0; k < cur_config_vec[i].lookups[j].size(); ++k) { - // std::cout << static_cast(cur_config_vec[i].lookups[j][k].row) - - // static_cast(cur_config_vec[i].first_coordinate.row) - 1 << " " << - // cur_config_vec[i].lookups[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - // } - // switch (gm.first.first) { - // case 2: - // { - // cur_lookup_table_name = "keccak_normalize3_table/full"; - // break; - // } - // case 3: { - // cur_lookup_table_name = "keccak_normalize4_table/full"; - // break; - // } - // case 5: { - // cur_lookup_table_name = "keccak_normalize6_table/full"; - // break; - // } - // case 7: { - // // TODO: add pack table - // cur_lookup_table_name = "keccak_chi_table/full"; - // break; - // } - // case 0: { - // cur_lookup_table_name = "keccak_chi_table/full"; - // break; - // } - // } - // for (std::size_t i = 0; i < cur_config_vec.size(); ++i) { - // for (int j = 0; j < cur_config_vec[i].lookups.size(); ++j) { - // lookup_constraint_type lookup_constraint = - // {lookup_tables_indices.at(cur_lookup_table_name), - // {var(component.W(cur_config_vec[i].lookups[j][0].column), - // static_cast(cur_config_vec[i].lookups[j][0].row) - // - static_cast(cur_config_vec[i].first_coordinate.row) - 1), - // var(component.W(cur_config_vec[i].lookups[j][1].column), - // static_cast(cur_config_vec[i].lookups[j][1].row) - // - static_cast(cur_config_vec[i].first_coordinate.row) - 1)}}; - // cur_constraints.push_back(lookup_constraint); - // } - // selector_indexes.push_back(bp.add_lookup_gate(cur_constraints)); - // cur_constraints.clear(); - // } - // index++; - // } return selector_indexes; } @@ -1683,6 +1602,7 @@ namespace nil { std::size_t config_index = 0; std::size_t prev_index = 0; auto config = component.full_configuration; + std::vector additional_rot_vars; if (component.xor_with_mes) { // inner_state ^ chunk @@ -1754,6 +1674,12 @@ namespace nil { var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); + additional_rot_vars.push_back( + var(component.W(config[config_index + i].constraints[0][1].column), + static_cast(config[config_index + i].constraints[0][1].row + start_row_index), false)); + additional_rot_vars.push_back( + var(component.W(config[config_index + i].constraints[0][2].column), + static_cast(config[config_index + i].constraints[0][2].row + start_row_index), false)); } config_index += 5; prev_index += 5; @@ -1794,6 +1720,12 @@ namespace nil { var(component.C(0), static_cast(config[config_index + i].first_coordinate.row + start_row_index), false, var::column_type::constant)}); + additional_rot_vars.push_back( + var(component.W(config[config_index + i].constraints[0][1].column), + static_cast(config[config_index + i].constraints[0][1].row + start_row_index), false)); + additional_rot_vars.push_back( + var(component.W(config[config_index + i].constraints[0][2].column), + static_cast(config[config_index + i].constraints[0][2].row + start_row_index), false)); } // chi @@ -1836,6 +1768,19 @@ namespace nil { {instance_input.round_constant, {component.W(config[config_index].copy_to[1].column), static_cast(config[config_index].copy_to[1].row + start_row_index), false}}); + config_index += 1; + + // additional rot constraints + for (std::size_t i = 0; i < 29; ++i) { + bp.add_copy_constraint( + {additional_rot_vars[2 * i], + {component.W(config[config_index + i].constraints[0][0].column), + static_cast(config[config_index + i].constraints[0][0].row + start_row_index), false}}); + bp.add_copy_constraint( + {additional_rot_vars[2 * i + 1], + {component.W(config[config_index + i].constraints[1][0].column), + static_cast(config[config_index + i].constraints[1][0].row + start_row_index), false}}); + } } template @@ -1890,38 +1835,23 @@ namespace nil { generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); std::size_t ind = 0; std::size_t index = 0; - // for (auto g : component.gates_configuration_map) { - // for (auto j : g.second) { - // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << - // ", j: " << j << '\n'; assignment.enable_selector(selector_indexes[index], - // start_row_index + j + 1); - // } - // std::cout << '\n'; - // index++; - // } + for (auto g : component.gates_configuration_map) { - // std::cout << "g.first.first: " << g.first.first << ", g.first.second: " << g.first.second << - // '\n'; if (g.first.first == 5) continue; for (std::size_t i = 0; i < component.gates_configuration[ind].size(); ++i) { for (auto j : g.second) { - // std::cout << j + component.gates_configuration[ind][i].first_coordinate.row + 1 << ' '; assignment.enable_selector( selector_indexes[index], start_row_index + j + component.gates_configuration[ind][i].first_coordinate.row + 1); } - // std::cout << '\n'; index++; } for (std::size_t i = 0; i < component.lookup_gates_configuration[ind].size(); ++i) { for (auto j : g.second) { - // std::cout << start_row_index + j + - // component.lookup_gates_configuration[ind][i].first_coordinate.row + 1 << ' '; assignment.enable_selector( selector_indexes[index], start_row_index + j + component.lookup_gates_configuration[ind][i].first_coordinate.row + 1); } - // std::cout << '\n'; index++; } ind++; @@ -2101,6 +2031,8 @@ namespace nil { // } // std::cout << "\n"; + std::vector additional_rot_chunks; + // ROT std::array C_rot; integral_type for_bound_smaller = component.calculate_sparse((integral_type(1) << 64) - 1) - @@ -2117,8 +2049,10 @@ namespace nil { integral_type bigger_part = integral_C & ((integral_type(1) << 189) - 1); integral_type integral_C_rot = (bigger_part << 3) + smaller_part; C_rot[index] = value_type(integral_C_rot); - auto copy_smaller_part = smaller_part; - auto copy_bigger_part = bigger_part; + additional_rot_chunks.push_back(smaller_part); + additional_rot_chunks.push_back(bigger_part); + // integral_type bound_smaller = smaller_part - (integral_type(1) << 3) + (integral_type(1) << 192); + // integral_type bound_bigger = bigger_part - (integral_type(1) << 189) + (integral_type(1) << 192); integral_type bound_smaller = smaller_part + for_bound_smaller; integral_type bound_bigger = bigger_part + for_bound_bigger; auto copy_bound_smaller = bound_smaller; @@ -2129,18 +2063,10 @@ namespace nil { std::vector integral_big_chunks; integral_type mask = (integral_type(1) << chunk_size) - 1; for (std::size_t j = 0; j < num_chunks; ++j) { - integral_small_chunks.push_back(copy_bound_smaller & mask); - copy_bound_smaller >>= chunk_size; - integral_big_chunks.push_back(copy_bound_bigger & mask); - copy_bound_bigger >>= chunk_size; - } - std::vector integral_smaller_chunks; - std::vector integral_bigger_chunks; - for (std::size_t j = 0; j < num_chunks; ++j) { - integral_smaller_chunks.push_back(copy_smaller_part & mask); - copy_smaller_part >>= chunk_size; - integral_bigger_chunks.push_back(copy_bigger_part & mask); - copy_bigger_part >>= chunk_size; + integral_small_chunks.push_back(bound_smaller & mask); + bound_smaller >>= chunk_size; + integral_big_chunks.push_back(bound_bigger & mask); + bound_bigger >>= chunk_size; } // auto check = integral_big_chunks[0]; // auto power = integral_type(1); @@ -2160,9 +2086,9 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[0][2].column), cur_config.constraints[0][2].row + strow) = value_type(bigger_part); assignment.witness(component.W(cur_config.constraints[3][0].column), - cur_config.constraints[3][0].row + strow) = value_type(bound_smaller); + cur_config.constraints[3][0].row + strow) = value_type(copy_bound_smaller); assignment.witness(component.W(cur_config.constraints[5][0].column), - cur_config.constraints[5][0].row + strow) = value_type(bound_bigger); + cur_config.constraints[5][0].row + strow) = value_type(copy_bound_bigger); for (std::size_t j = 1; j < num_chunks + 1; ++j) { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = @@ -2175,21 +2101,6 @@ namespace nil { cur_config.constraints[6][0].row + strow) = value_type(integral_type(1) << 3); assignment.witness(component.W(cur_config.constraints[6][1].column), cur_config.constraints[6][1].row + strow) = value_type(integral_type(1) << 189); - - assignment.witness(component.W(cur_config.constraints[7][0].column), - cur_config.constraints[7][0].row + strow) = value_type(smaller_part); - // assignment.witness(component.W(cur_config.constraints[8][0].column), - // cur_config.constraints[8][0].row + strow) = value_type(bigger_part); - std::cout << "smaller_part: " << smaller_part << '\n'; - for (std::size_t j = 1; j < num_chunks + 1; ++j) { - std::cout << "integral_smaller_chunks[j - 1]: " << integral_smaller_chunks[j - 1] << '\n'; - assignment.witness(component.W(cur_config.constraints[7][j].column), - cur_config.constraints[7][j].row + strow) = - value_type(integral_smaller_chunks[j - 1]); - // assignment.witness(component.W(cur_config.constraints[8][j].column), - // cur_config.constraints[8][j].row + strow) = - // value_type(integral_bigger_chunks[j - 1]); - } } config_index += 5; // std::cout << "C_rot:\n"; @@ -2259,6 +2170,8 @@ namespace nil { integral_type bigger_part = integral_A & ((integral_type(1) << minus_r) - 1); integral_type integral_A_rot = (bigger_part << r) + smaller_part; B[perm[index]] = value_type(integral_A_rot); + additional_rot_chunks.push_back(smaller_part); + additional_rot_chunks.push_back(bigger_part); // integral_type bound_smaller = smaller_part - (integral_type(1) << r) + (integral_type(1) << 192); // integral_type bound_bigger = bigger_part - (integral_type(1) << minus_r) + (integral_type(1) << // 192); @@ -2379,7 +2292,7 @@ namespace nil { } A_4 = value_type(integral_normalized_sum); - auto cur_config = component.full_configuration[config_index]; + auto cur_config = component.full_configuration[config_index++]; assignment.witness(component.W(cur_config.copy_to[0].column), cur_config.copy_to[0].row + strow) = A_3[0]; assignment.witness(component.W(cur_config.copy_to[1].column), cur_config.copy_to[1].row + strow) = @@ -2396,6 +2309,7 @@ namespace nil { cur_config.constraints[2][j].row + strow) = value_type(integral_normalized_chunks[j - 1]); } + } // std::cout << "result:\n" << A_4.data << " "; // for (int i = 1; i < 25; ++i) { @@ -2403,6 +2317,37 @@ namespace nil { // } // std::cout << "\n"; + for (std::size_t i = 0; i < 29; ++i) { + auto chunk_size = component.rotate_chunk_size; + auto num_chunks = component.rotate_num_chunks; + auto copy_bound_smaller = additional_rot_chunks[2 * i]; + auto copy_bound_bigger = additional_rot_chunks[2 * i + 1]; + std::vector integral_small_chunks; + std::vector integral_big_chunks; + integral_type mask = (integral_type(1) << chunk_size) - 1; + for (std::size_t j = 0; j < num_chunks; ++j) { + integral_small_chunks.push_back(copy_bound_smaller & mask); + copy_bound_smaller >>= chunk_size; + integral_big_chunks.push_back(copy_bound_bigger & mask); + copy_bound_bigger >>= chunk_size; + } + + auto cur_config = component.full_configuration[config_index++]; + assignment.witness(component.W(cur_config.constraints[0][0].column), + cur_config.constraints[0][0].row + strow) = value_type(additional_rot_chunks[2 * i]); + assignment.witness(component.W(cur_config.constraints[1][0].column), + cur_config.constraints[1][0].row + strow) = value_type(additional_rot_chunks[2 * i + 1]); + for (std::size_t j = 1; j < num_chunks + 1; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), + cur_config.constraints[0][j].row + strow) = + value_type(integral_small_chunks[j - 1]); + assignment.witness(component.W(cur_config.constraints[1][j].column), + cur_config.constraints[1][j].row + strow) = + value_type(integral_big_chunks[j - 1]); + } + // std::cout << "last conf: " << cur_config.constraints[0][num_chunks].column << ' ' << cur_config.constraints[0][num_chunks].row << '\n'; + } + return typename component_type::result_type(component, start_row_index); } @@ -2410,4 +2355,4 @@ namespace nil { } // namespace blueprint } // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_ROUND_HPP From baa4103200e44edd27e19290c327195fbc6e32d6 Mon Sep 17 00:00:00 2001 From: ChernyshovaP <42933210+tshchelovek@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:47:30 +0200 Subject: [PATCH 44/48] Added constraints to keccak_padding --- .../hashes/keccak/keccak_padding.hpp | 394 +++++++++++------- 1 file changed, 241 insertions(+), 153 deletions(-) diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp index ece502d5d..b22eb317a 100644 --- a/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding.hpp @@ -125,6 +125,8 @@ namespace nil { const std::vector> output_gates_configuration = configure_output_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); + const std::vector> inner_range_check_gates_configuration = + configure_inner_range_check_gates(this->witness_amount(), num_blocks, num_bits, range_check_input, limit_permutation_column); std::vector gates_rows = calculate_gates_rows(this->witness_amount()); @@ -149,33 +151,18 @@ namespace nil { std::vector padded_message; result_type(const keccak_padding &component, std::size_t start_row_index) { - auto size = component.full_configuration.size() - 1; - std::cout << "size: " << size << std::endl; + auto size = component.full_configuration.size() - 1 - component.num_blocks * (component.shift != 0); padded_message.resize(size + component.num_padding_zeros); for (std::size_t i = 0; i < padded_message.size() - 17; ++i) { auto config = component.full_configuration[i]; padded_message[i] = var(component.W(config.copy_to.back().column), config.copy_to.back().row + start_row_index, false); } - std::cout << "padded_message.size(): " << padded_message.size() << std::endl; + auto output_config = component.full_configuration[component.num_blocks]; for (std::size_t i = 0; i < 17; ++i) { - padded_message[padded_message.size() - 17 + i] = var(component.W(component.full_configuration.back().copy_to[i].column), - component.full_configuration.back().copy_to[i].row + start_row_index, false); + padded_message[padded_message.size() - 17 + i] = var(component.W(output_config.copy_to[i].column), + output_config.copy_to[i].row + start_row_index, false); } - std::cout << "padded_message: " << padded_message.size() << std::endl; - - // for (std::size_t i = 0; i < component.full_configuration.size(); ++i) { - // auto config = component.full_configuration[i]; - // padded_message[i] = var(component.W(config.copy_to.back().column), - // config.copy_to.back().row + start_row_index, false); - // } - // if(component.shift == 0){ - // padded_message[size] = var(component.C(0), start_row_index + 1, false, var::column_type::constant); - // } - - // for (std::size_t i = size + (component.shift == 0); i < size + component.num_padding_zeros; ++i) { - // padded_message[i] = var(component.C(0), start_row_index, false, var::column_type::constant); - // } } std::vector> all_vars() { @@ -246,7 +233,7 @@ namespace nil { (last_column++) % witness_amount}); } if (!range_check_input) { - return configuration(first_coordinate, {last_row, last_column}, copy_to, {}, {}, {}); + return configuration(first_coordinate, {last_row, last_column}, copy_to, {}, {}, copy_to[0]); } std::vector>> constraints; @@ -260,22 +247,9 @@ namespace nil { last_row += last_column / witness_amount; last_column %= witness_amount; - auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); - - // std::cout << "config: " << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; - // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; - // } - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - - return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, {}); + auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, copy_to[0]); + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, copy_to[0]); } static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t row, std::size_t column, @@ -359,19 +333,6 @@ namespace nil { auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); - // std::cout << "config: " << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; - // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; - // } - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } static configuration configure_inner(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, @@ -424,30 +385,80 @@ namespace nil { std::vector>> constraints; std::vector>> lookups(1); - // //s_i(s_i - 1)(s_i - 2)=0 - // for (std::size_t i = 0; i < 17; i++) { - // constraints.push_back({selectors[i]}); - // } - // // ((34-sum)*sum-1)-almost_sum=0 - // constraints.push_back({almost_sum}); - // //s_i(s_i - 2)s_i+1=0 && (s_i+1 - s_i + 1)(s_i+1 - s_i)=0 - // for (std::size_t i = 0; i < 17 - 1; i++) { - // constraints.push_back({selectors[i], selectors[i + 1]}); - // } //s_i(s_i - 2)(w_i*delta - 1)=0 && (s_i - 1)(s_i - 2)w_i=0 for (std::size_t i = 0; i < 17; i++) { constraints.push_back({selectors[i], values[i], delta}); } lookups[0].push_back(almost_sum); - std::cout << "almost_sum: " << almost_sum.first << " " << almost_sum.second << std::endl; last_row = almost_sum.first; last_column = almost_sum.second; + if (last_column != 0) { + last_row += 1; + last_column = 0; + } return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); } + static configuration configure_inner_range_checks(std::size_t witness_amount, std::size_t limit_permutation_column, + std::size_t row, std::size_t column) { + // regular constraints: + // copy_first * 2^k - first = 0 + // first = first_chunk0 + first_chunk1 * 2^chunk_size + ... + first_chunkk * 2^(k*chunk_size) + // copy_second * 2^(64-k) - second = 0 + // second = second_chunk0 + second_chunk1 * 2^chunk_size + ... + second_chunkk * 2^(k*chunk_size) + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, last_column = column; + std::size_t num_chunks = 8; + std::size_t num_cells = 2 * (2 + 8); + std::size_t buff = (10 * witness_amount - num_cells) % witness_amount; + + std::vector> copy_to; + std::pair cell_copy_from; + std::vector>> constraints; + + std::vector> cells; + std::size_t cur_row = row, cur_column = 0; + while (cur_column < num_cells) { + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + } + std::size_t cell_index = 0; + + std::vector>> lookups(1); + + constraints.push_back({cells[cell_index++]}); + constraints[0].push_back(cells[cell_index++]); + + constraints.push_back({constraints[0].back()}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[1].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[1].back()); + } + + constraints.push_back({cells[cell_index++]}); + constraints[2].push_back(cells[cell_index++]); + + constraints.push_back({constraints[2].back()}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[3].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[3].back()); + } + for (int i = 0; i < 2; ++i) { + copy_to.push_back(constraints[2 * i][0]); + } + + last_column = cells.back().second + 1 + buff; + last_row = cells.back().first + (last_column / witness_amount); + last_column %= witness_amount; + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + cell_copy_from); + } + static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { @@ -482,23 +493,19 @@ namespace nil { column = conf.last_coordinate.column; } result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column, row, column)); + + if (calculate_shift(num_blocks, num_bits) == 0) { + return result; + } - // std::cout << "num_cofigs: " << result.size() << "\n"; - // for (std::size_t i = 0; i < result.size(); ++i) { - // auto cur_config = result[i]; - // std::cout << "config: " << i << "\n"; - // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; - // std::cout << "cf: " << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; - // for (int j = 0; j < cur_config.copy_to.size(); ++j) { - // std::cout << "ct: " << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; - // } - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - // } + row = result.back().last_coordinate.row; + column = result.back().last_coordinate.column; + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner_range_checks(witness_amount, limit_permutation_column, row, column); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } return result; } @@ -529,15 +536,6 @@ namespace nil { } } - // std::cout << "MAP\n"; - // for (auto c : config_map) { - // std::cout << c.first << ": "; - // for (auto r : c.second) { - // std::cout << r << " "; - // } - // std::cout << std::endl; - // } - return config_map; } @@ -581,19 +579,46 @@ namespace nil { cur_result.back().lookups = cur_config.lookups; result.push_back(cur_result); - std::cout << "output gates:\n"; - for (std::size_t i = 0; i < result.size(); ++i) { - std::cout << "config " << i << ":\n"; - for (auto cur_config : result[i]) { - std::cout << "gate:\n"; - for (int j = 0; j < cur_config.constraints.size(); ++j) { - for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - } - std::cout << std::endl; - } + return result; + } + + static std::vector> configure_inner_range_check_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input, + std::size_t limit_permutation_column) { + std::vector> result; + + configuration cur_config = configure_inner_range_checks(witness_amount, limit_permutation_column, 0, 0); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max <= 2 + min); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; } + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } + cur_result.push_back(c); } + cur_result.back().lookups = cur_config.lookups; + result.push_back(cur_result); return result; } @@ -603,7 +628,6 @@ namespace nil { std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { - // auto output_gates = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { return {}; @@ -648,19 +672,6 @@ namespace nil { result.push_back(cur_result); } - // for (std::size_t i = 0; i < result.size(); ++i) { - // std::cout << "config " << i << ":\n"; - // for (auto cur_config : result[i]) { - // std::cout << "gate:\n"; - // for (int j = 0; j < cur_config.constraints.size(); ++j) { - // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { - // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; - // } - // std::cout << std::endl; - // } - // } - // } - return result; } @@ -701,6 +712,8 @@ namespace nil { auto res = map.size() * 2 + range_check_input; auto output = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input, limit_permutation_column); res += output[0].size() + 1; + auto shift = calculate_shift(num_blocks, num_bits); + if (shift != 0) res += 2; return res; } @@ -859,6 +872,7 @@ namespace nil { } cur_constraints.push_back(constraint); } + selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); @@ -871,12 +885,10 @@ namespace nil { auto output_gates = component.output_gates_configuration[0]; std::size_t idx[2] = {0, 0}; std::size_t shifts[2] = {1, 1}; - std::cout << "output_gates.size(): " << output_gates.size() << std::endl; if (output_gates.size() > 1) { idx[1] = 1; shifts[1] = 2; } - std::cout << "here0 " << std::endl; // (s_i - 1)(s_i - 2)w_i=0 && s_i(s_i - 2)(w_i*delta - 1)=0 for (auto constr : output_gates[idx[0]].constraints) { cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 1) * @@ -886,14 +898,11 @@ namespace nil { (var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 2) * (var(constr[1].column, static_cast(constr[1].row) - shifts[0]) * var(constr[2].column, static_cast(constr[2].row) - shifts[0]) - 1)); } - std::cout << "here1 " << std::endl; if (output_gates.size() > 1) { - std::cout << "here2 " << std::endl; selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); } - std::cout << "here3 " << std::endl; for (auto constr : output_gates[idx[1]].constraints) { cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 1) * (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * @@ -902,40 +911,32 @@ namespace nil { (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * (var(constr[1].column, static_cast(constr[1].row) - shifts[1]) * var(constr[2].column, static_cast(constr[2].row) - shifts[1]) - 1)); } - std::cout << "here4 " << std::endl; std::vector s_i; for (std::size_t i = 0; i < 2; ++i) { for (auto constr : output_gates[idx[i]].constraints) { - std::cout << "gt: " << static_cast(constr[0].row) - shifts[1] << " " << constr[0].column << std::endl; s_i.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[1])); } } - std::cout << "here40 " << std::endl; // s_i(s_i - 1)(s_i - 2)=0 for (std::size_t i = 0; i < 17; ++i) { cur_constraints.push_back(s_i[i] * (s_i[i] - 1) * (s_i[i] - 2)); } - std::cout << "here10 " << std::endl; // s_i(s_i - 2)s_i+1=0 && (s_i+1 - s_i + 1)(s_i+1 - s_i)=0 for (std::size_t i = 0; i < 16; ++i) { cur_constraints.push_back(s_i[i] * (s_i[i] - 2) * s_i[i+1]); cur_constraints.push_back((s_i[i+1] - s_i[i] + 1) * (s_i[i+1] - s_i[i])); } - std::cout << "here11 " << std::endl; // sum constraint_type sum = s_i[0]; - for (std::size_t i = 1; i < s_i.size(); ++i) { + for (std::size_t i = 1; i < 17; ++i) { sum += s_i[i]; } - std::cout << "here12 " << std::endl; cur_constraints.push_back((34 - sum) * sum - 1 - var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])); - std::cout << "here5 " << std::endl; selector_indexes.push_back(bp.add_gate(cur_constraints)); gate_index++; cur_constraints.clear(); - std::cout << "here6 " << std::endl; cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), {var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])}}); @@ -943,8 +944,35 @@ namespace nil { lookup_gate_index++; cur_lookup_constraints.clear(); + if (component.shift != 0) { + auto conf = component.inner_range_check_gates_configuration[0][0]; + int row_shift = 0; + if (conf.last_coordinate.row - conf.first_coordinate.row == 2) row_shift = 1; + + cur_constraints.push_back(var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift) * + (integral_type(1) << (64 - component.shift)) - + var(conf.constraints[0][1].column, static_cast(conf.constraints[0][1].row) - row_shift)); + cur_constraints.push_back(var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row) - row_shift) * + (integral_type(1) << component.shift) - + var(conf.constraints[2][1].column, static_cast(conf.constraints[2][1].row) - row_shift)); + for (std::size_t j = 0; j < 2; ++j) { + constraint_type constraint = var(conf.constraints[2 * j + 1][0].column, static_cast(conf.constraints[2 * j + 1][0].row) - row_shift); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(conf.constraints[2 * j + 1][i].column, static_cast(conf.constraints[2 * j + 1][i].row) - row_shift) + * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(conf.constraints[2 * j + 1][i].column, static_cast(conf.constraints[2 * j + 1][i].row) - row_shift)}}); + } + cur_constraints.push_back(constraint); + } + + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + } + BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); - std::cout << "gates_amount: " << component.gates_amount << std::endl; return selector_indexes; } @@ -963,6 +991,8 @@ namespace nil { const std::size_t strow = start_row_index; std::size_t config_index = 0; std::size_t input_index = 0; + std::vector> first_second_chunks; + std::array fs_chunk; std::size_t conf_index_for_input = 0; if (component.shift != 0) { @@ -970,7 +1000,7 @@ namespace nil { conf_index_for_input = 1; } - while (config_index < component.full_configuration.size() - 2) { + while (config_index < component.num_blocks - 1) { auto config = component.full_configuration[config_index]; bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(config.copy_to[conf_index_for_input].column), @@ -981,6 +1011,10 @@ namespace nil { config.copy_from.row + strow, false), var(component.W(next_config.copy_to[0].column), next_config.copy_to[0].row + strow, false)}); + first_second_chunks.push_back({var(component.W(config.constraints[0][1].column), + config.constraints[0][1].row + strow, false), + var(component.W(config.constraints[0][2].column), + config.constraints[0][2].row + strow, false)}); } config_index++; } @@ -989,6 +1023,10 @@ namespace nil { bp.add_copy_constraint({var(component.C(0), start_row_index + 1, false, var::column_type::constant), var(component.W(config.copy_to[conf_index_for_input].column), config.copy_to[conf_index_for_input].row + strow, false)}); + first_second_chunks.push_back({var(component.W(config.constraints[0][1].column), + config.constraints[0][1].row + strow, false), + var(component.W(config.constraints[0][2].column), + config.constraints[0][2].row + strow, false)}); } else { auto config = component.full_configuration[config_index++]; bp.add_copy_constraint({instance_input.message[input_index++], @@ -998,17 +1036,30 @@ namespace nil { auto config = component.full_configuration[config_index]; std::size_t idx = 0; - for (int i = 0; i < 17 - component.num_padding_zeros; ++i) { - idx++; - // TODO - // auto prev_config = component.full_configuration[config_index - 17 + i]; - // bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), - // var(component.W(prev_config.copy_from.column), prev_config.copy_from.row + strow, false)}); + std::size_t prev_offset = (component.shift != 0) * 2; + for (int i = 17 - component.num_padding_zeros; i > 0; --i) { + auto prev_config = component.full_configuration[config_index - i]; + bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), + var(component.W(prev_config.copy_to[prev_offset].column), prev_config.copy_to[prev_offset].row + strow, false)}); + } + config_index++; + + if (component.shift == 0) { + bp.add_copy_constraint({var(component.C(0), start_row_index + 1, false, var::column_type::constant), + var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false)}); } - for (int i = 0; i < component.num_padding_zeros; ++i) { + for (int i = 0; i < component.num_padding_zeros - (component.shift == 0); ++i) { bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), var(component.C(0), start_row_index, false, var::column_type::constant)}); } + + if (component.shift != 0) { + for (int i = 0; i < component.num_blocks; ++i) { + config = component.full_configuration[config_index++]; + bp.add_copy_constraint({first_second_chunks[i][0], var(component.W(config.constraints[0][0].column), config.constraints[0][0].row + strow, false)}); + bp.add_copy_constraint({first_second_chunks[i][1], var(component.W(config.constraints[2][0].column), config.constraints[2][0].row + strow, false)}); + } + } } template @@ -1019,7 +1070,6 @@ namespace nil { &assignment, const typename padding_component::input_type &instance_input, const std::uint32_t start_row_index) { - std::cout << "circuit:\n"; using component_type = padding_component; @@ -1053,21 +1103,25 @@ namespace nil { sel_ind += 2; } } - auto output = component.full_configuration.back(); + auto output = component.full_configuration[component.num_blocks]; auto output_gates = component.output_gates_configuration[0]; - std::cout << "output gates: " << start_row_index << '\n'; - std::cout << "output gates: " << output.first_coordinate.row << '\n'; - std::cout << "output gates: " << output.first_coordinate.row + 1 + start_row_index << '\n'; assignment.enable_selector(selector_indexes[sel_ind++], output.first_coordinate.row + 1 + start_row_index); if (output_gates.size() > 1) { - assignment.enable_selector(selector_indexes[sel_ind], output.first_coordinate.row + 2 + start_row_index); + assignment.enable_selector(selector_indexes[sel_ind++], output.first_coordinate.row + 2 + start_row_index); + } + + if (component.shift != 0) { + int row_shift = 0; + auto conf = component.full_configuration[component.num_blocks + 1]; + if (conf.last_coordinate.row - conf.first_coordinate.row == 2) row_shift = 1; + for (std::size_t i = 1; i < component.num_blocks + 1; ++i) { + conf = component.full_configuration[component.num_blocks + i]; + assignment.enable_selector(selector_indexes[sel_ind], conf.first_coordinate.row + start_row_index + row_shift); + } } - std::cout << "help me0" << '\n'; generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); - std::cout << "help me1" << '\n'; generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); - std::cout << "help me2" << '\n'; return typename component_type::result_type(component, start_row_index); } @@ -1085,6 +1139,7 @@ namespace nil { using component_type = padding_component; using value_type = typename BlueprintFieldType::value_type; using integral_type = typename BlueprintFieldType::integral_type; + using var = typename component_type::var; BOOST_ASSERT(component.num_blocks == instance_input.message.size()); @@ -1092,6 +1147,8 @@ namespace nil { // range_check shift integral_type mask_range_check = (integral_type(1) << 8) - 1; std::vector output_values; + std::vector> non_shifted_chunk_parts; + std::vector> shifted_chunk_parts; if (component.shift != 0) { integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); @@ -1104,6 +1161,8 @@ namespace nil { integral_type mask = (integral_type(1) << (64 - component.shift)) - 1; std::array chunk_parts = {integral_chunk >> (64 - component.shift), integral_chunk & mask}; + non_shifted_chunk_parts.push_back(chunk_parts); + shifted_chunk_parts.push_back({chunk_parts[0] << (64 - component.shift), chunk_parts[1] << component.shift}); integral_type sum = (relay_chunk << component.shift) + chunk_parts[0]; output_values.push_back(value_type(sum)); @@ -1142,6 +1201,7 @@ namespace nil { assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(chunk_range_check[j - 1]); } } + relay_chunk = chunk_parts[1]; config_index++; } @@ -1167,25 +1227,53 @@ namespace nil { cur_config.copy_to[0].row + strow) = var_value(assignment, instance_input.message[index]); output_values.push_back(var_value(assignment, instance_input.message[index])); + config_index++; } + output_values.push_back(value_type(component.padding_delimiter)); } - auto config = component.full_configuration.back(); + // output + auto cur_config = component.full_configuration[config_index++]; std::size_t idx = 0; value_type last_nonzero = value_type(1); - for (int i = 0; i < output_values.size(); ++i) { + value_type sum_s = value_type(0); + for (std::size_t i = output_values.size() - ((output_values.size() - 1) % 17 + 1); i < output_values.size(); ++i) { last_nonzero = output_values[i]; - assignment.witness(component.W(config.copy_to[idx].column), config.copy_to[idx].row + strow) = last_nonzero; - assignment.witness(component.W(config.constraints[idx][0].column), config.constraints[idx++][0].row + strow) = (i == output_values.size() - 1) ? value_type(1) : value_type(2); + assignment.witness(component.W(cur_config.copy_to[idx].column), cur_config.copy_to[idx].row + strow) = last_nonzero; + value_type s = (i == output_values.size() - 1) ? value_type(1) : value_type(2); + assignment.witness(component.W(cur_config.constraints[idx][0].column), cur_config.constraints[idx++][0].row + strow) = s; + sum_s += s; } - assignment.witness(component.W(config.constraints[idx - 1][2].column), config.constraints[idx - 1][2].row + strow) = value_type(1) / last_nonzero; - for (int i = 0; i < component.num_padding_zeros; ++i) { - assignment.witness(component.W(config.copy_to[idx].column), config.copy_to[idx].row + strow) = value_type(0); - assignment.witness(component.W(config.constraints[idx][0].column), config.constraints[idx++][0].row + strow) = value_type(0); + assignment.witness(component.W(cur_config.constraints[idx - 1][2].column), cur_config.constraints[idx - 1][2].row + strow) = value_type(1) / last_nonzero; + for (int i = 0; i < component.num_padding_zeros - (component.shift == 0); ++i) { + assignment.witness(component.W(cur_config.copy_to[idx].column), cur_config.copy_to[idx].row + strow) = value_type(0); + assignment.witness(component.W(cur_config.constraints[idx][0].column), cur_config.constraints[idx++][0].row + strow) = value_type(0); } - value_type sum_s = value_type((17 - component.num_padding_zeros) * 2 - 1); - assignment.witness(component.W(config.lookups[0][0].column), config.lookups[0][0].row + strow) = sum_s * (value_type(34) - sum_s) - value_type(1); + assignment.witness(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row + strow) = sum_s * (value_type(34) - sum_s) - value_type(1); + if (component.shift != 0) { + // additional range_check + integral_type mask_range_check = (integral_type(1) << 8) - 1; + for (std::size_t i = 0; i < shifted_chunk_parts.size(); ++i) { + cur_config = component.full_configuration[config_index++]; + for (std::size_t j = 0; j < 2; ++j) { + assignment.witness(component.W(cur_config.constraints[2 * j][0].column), cur_config.constraints[2 * j][0].row + strow) = value_type(non_shifted_chunk_parts[i][j]); + assignment.witness(component.W(cur_config.constraints[2 * j][1].column), cur_config.constraints[2 * j][1].row + strow) = value_type(shifted_chunk_parts[i][j]); + + integral_type chunk_to_check = shifted_chunk_parts[i][j]; + std::vector chunk_range_check; + for (std::size_t i = 0; i < 8; ++i) { + chunk_range_check.push_back(chunk_to_check & mask_range_check); + chunk_to_check >>= 8; + } + // chunk range_check + for (int k = 1; k < 9; ++k) { + assignment.witness(component.W(cur_config.constraints[2 * j + 1][k].column), cur_config.constraints[2 * j + 1][k].row + strow) = value_type(chunk_range_check[k - 1]); + } + } + } + } + return typename component_type::result_type(component, start_row_index); } @@ -1208,4 +1296,4 @@ namespace nil { } // namespace blueprint } // namespace nil -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP \ No newline at end of file +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP From f4478e98b780a28eb741e6d07d252d24810a7e72 Mon Sep 17 00:00:00 2001 From: ChernyshovaP <42933210+tshchelovek@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:49:35 +0200 Subject: [PATCH 45/48] uncommented keccak_padding.cpp --- test/hashes/plonk/keccak_padding.cpp | 50 ++++++++++++---------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/test/hashes/plonk/keccak_padding.cpp b/test/hashes/plonk/keccak_padding.cpp index c7e95560c..8ac918216 100644 --- a/test/hashes/plonk/keccak_padding.cpp +++ b/test/hashes/plonk/keccak_padding.cpp @@ -127,15 +127,8 @@ auto test_keccak_padding_inner(std::vector(); -// for (std::size_t i = 1; i < 100; i++) { -// test_keccak_padding_1(i); -// test_keccak_padding_random(i); -// test_keccak_padding_random(i, false); -// test_keccak_padding_random(i, true, false); -// test_keccak_padding_random(i, false, false); -// } -// } + test_keccak_padding_0(); + test_keccak_padding_random(2, true, false); + for (std::size_t i = 1; i < 100; i++) { + test_keccak_padding_1(i); + test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); + } +} BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; - // test_keccak_padding_0(); - test_keccak_padding_random(18); - // for (std::size_t i = 1; i < 100; i++) { - // test_keccak_padding_1(i); - // test_keccak_padding_random(i); - // test_keccak_padding_random(i, false); - // test_keccak_padding_random(i, true, false); - // test_keccak_padding_random(i, false, false); - // } + test_keccak_padding_0(); + test_keccak_padding_random(10); + for (std::size_t i = 80; i < 100; i++) { + test_keccak_padding_1(i); + test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); + } } BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { @@ -318,4 +312,4 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { // test_to_fail_keccak_padding_random(5, false, true); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From d627f77c5001c7b1f2b4b107b51eca9bb13bd623 Mon Sep 17 00:00:00 2001 From: tshchelovek Date: Thu, 15 Aug 2024 17:30:00 +0000 Subject: [PATCH 46/48] keccak_padding without templates, not finished --- .../keccak/keccak_padding_no_template.hpp | 1334 +++++++++++++++++ .../plonk/keccak_padding_no_template.cpp | 324 ++++ 2 files changed, 1658 insertions(+) create mode 100644 include/nil/blueprint/components/hashes/keccak/keccak_padding_no_template.hpp create mode 100644 test/hashes/plonk/keccak_padding_no_template.cpp diff --git a/include/nil/blueprint/components/hashes/keccak/keccak_padding_no_template.hpp b/include/nil/blueprint/components/hashes/keccak/keccak_padding_no_template.hpp new file mode 100644 index 000000000..ec28bf97b --- /dev/null +++ b/include/nil/blueprint/components/hashes/keccak/keccak_padding_no_template.hpp @@ -0,0 +1,1334 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// 2024 Valeh Farzaliyev +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP +#define CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace nil { + namespace blueprint { + namespace components { + template + class keccak_padding; + + template + class keccak_padding> + : public plonk_component { + + using component_type = plonk_component; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + public: + using var = typename component_type::var; + using manifest_type = nil::blueprint::plonk_component_manifest; + + using exp_component_type = plonk_exponentiation; + exp_component_type exp_component; + + class gate_manifest_type : public component_gate_manifest { + public: + std::size_t witness_amount; + std::size_t num_blocks; + std::size_t num_bits; + bool range_check_input; + static constexpr const std::size_t clamp = 15; + + gate_manifest_type(std::size_t witness_amount_, std::size_t num_blocks_, std::size_t num_bits_, + bool range_check_input_) : + witness_amount(std::min(witness_amount_, clamp)), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_) {}; + + std::uint32_t gates_amount() const override { + return keccak_padding::get_gates_amount(witness_amount, num_blocks, num_bits, range_check_input); + } + }; + + static gate_manifest get_gate_manifest(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + gate_manifest manifest = + gate_manifest(gate_manifest_type(witness_amount, num_blocks, num_bits, range_check_input)); + manifest.merge_with(exp_component_type::get_gate_manifest(witness_amount)); + return manifest; + } + + static manifest_type get_manifest( + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input + ) { + static manifest_type manifest = + manifest_type(std::shared_ptr( + new nil::blueprint::manifest_single_value_param(9)), + true); + manifest.merge_with(exp_component_type::get_manifest()); + return manifest; + } + + static const std::size_t lookup_rows = 65536; + static const std::size_t num_chunks = 8; + const std::size_t WA = this->witness_amount(); + + const std::size_t num_blocks; + const std::size_t num_bits; + const bool range_check_input; + + const std::size_t shift = calculate_shift(num_blocks, num_bits); + const std::size_t num_padding_zeros = calculate_num_padding_zeros(num_blocks, shift); + + const integral_type padding_delimiter = integral_type(1) << 56; + + const std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + + const std::vector full_configuration = + configure_all(this->witness_amount(), num_blocks, num_bits, range_check_input); + const std::map> gates_configuration_map = + configure_map(this->witness_amount(), num_blocks, num_bits, range_check_input); + const std::vector> gates_configuration = + configure_gates(this->witness_amount(), num_blocks, num_bits, range_check_input); + + const std::vector> output_gates_configuration = + configure_output_gates(this->witness_amount(), num_blocks, num_bits, range_check_input); + const std::vector> inner_range_check_gates_configuration = + configure_inner_range_check_gates(this->witness_amount(), num_blocks, num_bits, range_check_input); + + std::vector gates_rows = calculate_gates_rows(this->witness_amount()); + + const std::size_t rows_amount = + get_rows_amount(this->witness_amount(), num_blocks, num_bits, range_check_input); + const std::size_t gates_amount = get_gates_amount(this->witness_amount(), num_blocks, num_bits, range_check_input); + + struct input_type { + // initial message = message[0] * 2^(64 * (num_blocks - 1)) + ... + message[num_blocks - 2] * 2^64 + + // message[num_blocks - 1] all message[i] are 64-bit for i > 0 message[0] is <= 64-bit + std::vector message; + var var_num_blocks; + var var_bit_shift; + + std::vector> all_vars() { + std::vector> res; + res.reserve(message.size()); + res.insert(res.end(), message.begin(), message.end()); + res.push_back(var_num_blocks); + res.push_back(var_bit_shift); + return res; + } + }; + + struct result_type { + std::vector padded_message; + + result_type(const keccak_padding &component, std::size_t start_row_index) { + std::size_t row = start_row_index + component.exp_component.rows_amount; + auto size = component.full_configuration.size() - 1 - component.num_blocks; + padded_message.resize(size + component.num_padding_zeros); + for (std::size_t i = 0; i < padded_message.size() - 17; ++i) { + auto config = component.full_configuration[i]; + padded_message[i] = var(component.W(config.copy_to.back().column), + config.copy_to.back().row + row, false); + } + auto output_config = component.full_configuration[component.num_blocks]; + for (std::size_t i = 0; i < 17; ++i) { + padded_message[padded_message.size() - 17 + i] = var(component.W(output_config.copy_to[i].column), + output_config.copy_to[i].row + row, false); + } + } + + std::vector> all_vars() { + std::vector> res; + res.reserve(padded_message.size()); + res.insert(res.end(), padded_message.begin(), padded_message.end()); + return res; + } + }; + + static std::size_t calculate_shift(std::size_t num_blocks, std::size_t num_bits) { + // assert(num_blocks * 64 >= num_bits); + return num_blocks * 64 - num_bits; + } + static std::size_t calculate_num_padding_zeros(std::size_t num_blocks, std::size_t shift) { + if (num_blocks % 17 == 0){ + if(shift == 0 ){ + return 17; + } + return 0; + } + return 17 - num_blocks % 17; + } + static std::size_t calculate_num_cells(std::size_t num_blocks, std::size_t num_bits, bool range_check_input) { + // if (calculate_shift(num_blocks, num_bits) == 0 && range_check_input) { + // return 1 + 8; // chunk, chunk range_check + // } + std::size_t res = 1 // relay + + 1 // chunk = first * 2^k + second + + 2 // first, second + + 1 // sum = relay * 2^(64-k) + first + + 8; // sum range_check + if (range_check_input) { + res += 8; // chunk range_check + } + return res; + } + + static configuration configure_inner_no_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t row, std::size_t column, + std::size_t num_cells) { + + if (column > 0) { + row += 1; + column = 0; + } + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + std::size_t limit_permutation_column = 7; + + // chunk + std::vector> copy_to; + if (column > limit_permutation_column) { + copy_to.push_back({last_row + 1, 0}); + } else { + copy_to.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + } + if (!range_check_input) { + return configuration(first_coordinate, {last_row, last_column}, copy_to, {}, {}, copy_to[0]); + } + + std::vector>> constraints; + // chunk range_check + constraints.push_back({copy_to[0]}); + for (int i = 0; i < 8; ++i) { + constraints[0].push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + } + + last_row += last_column / witness_amount; + last_column %= witness_amount; + + auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, copy_to[0]); + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, {}, copy_to[0]); + } + static configuration configure_inner_with_padding(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, std::size_t row, std::size_t column, + std::size_t num_cells) { + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + std::size_t buff = (10 * witness_amount - num_cells) % witness_amount; + + std::vector> cells; + while (last_column - column < num_cells) { + cells.push_back({last_row + (last_column / witness_amount), (last_column++) % witness_amount}); + } + std::size_t cell_index = 0; + + // relay, chunk, sum; second + std::vector> copy_to; + std::pair cell_copy_from; + for (int i = 0; i < 3; ++i) { + copy_to.push_back(cells[cell_index++]); + } + cell_copy_from = cells[cell_index++]; + + std::vector>> constraints; + std::vector>> lookups(1 + range_check_input); + // chunk, first, second + constraints.push_back({copy_to[1]}); + constraints[0].push_back(cells[cell_index++]); + constraints[0].push_back(cell_copy_from); + // sum, relay, first + constraints.push_back({copy_to[2]}); + constraints[1].push_back(copy_to[0]); + constraints[1].push_back(constraints[0][1]); + // sum range_check + constraints.push_back({constraints[1][0]}); + for (int i = 0; i < 8; ++i) { + constraints[2].push_back(cells[cell_index++]); + lookups[0].push_back(constraints.back().back()); + } + // chunk range_check + if (range_check_input) { + constraints.push_back({constraints[0][0]}); + for (int i = 0; i < 8; ++i) { + constraints[3].push_back(cells[cell_index++]); + lookups[1].push_back(constraints.back().back()); + } + } + + if (cell_copy_from.first > cells.back().first) { + cells.back() = cell_copy_from; + } + + last_column = cells.back().second + 1 + buff; + last_row = cells.back().first + (last_column >= witness_amount); + last_column %= witness_amount; + + auto cur_config = configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + + // std::cout << "config: " << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << '!' << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + } + static configuration configure_inner(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, + std::size_t row, std::size_t column, + std::size_t num_cells) { + // if (calculate_shift(num_blocks, num_bits) == 0) { + // return configure_inner_no_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells); + // } + return configure_inner_with_padding(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells); + } + + static configuration configure_output(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input, + std::size_t row, std::size_t column) { + + if (column > 0) { + row += 1; + column = 0; + } + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, + last_column = column; + std::size_t shift = calculate_shift(num_blocks, num_bits); + + // relay, chunk, sum; second + std::vector> copy_to; + std::pair cell_copy_from; + + std::vector> selectors; + std::pair almost_sum; //((34-sum)*sum-1) + std::pair delta; + std::vector> values; + + for (std::size_t i = 0; i < 17; i++) { + values.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + copy_to.push_back(values.back()); + + } + delta = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + for (std::size_t i = 0; i < 17; i++) { + selectors.push_back({last_row + (last_column / witness_amount), + (last_column++) % witness_amount}); + + } + almost_sum = {last_row + (last_column / witness_amount), (last_column++) % witness_amount}; + + std::vector>> constraints; + std::vector>> lookups(1); + + //s_i(s_i - 2)(w_i*delta - 1)=0 && (s_i - 1)(s_i - 2)w_i=0 + for (std::size_t i = 0; i < 17; i++) { + constraints.push_back({selectors[i], values[i], delta}); + } + + lookups[0].push_back(almost_sum); + + last_row = almost_sum.first; + last_column = almost_sum.second; + if (last_column != 0) { + last_row += 1; + last_column = 0; + } + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, cell_copy_from); + } + + static configuration configure_inner_range_checks(std::size_t witness_amount, + std::size_t row, std::size_t column) { + // regular constraints: + // copy_first * 2^k - first = 0 + // first = first_chunk0 + first_chunk1 * 2^chunk_size + ... + first_chunkk * 2^(k*chunk_size) + // copy_second * 2^(64-k) - second = 0 + // second = second_chunk0 + second_chunk1 * 2^chunk_size + ... + second_chunkk * 2^(k*chunk_size) + + std::pair first_coordinate = {row, column}; + + std::size_t last_row = row, last_column = column; + std::size_t num_chunks = 8; + std::size_t num_cells = 2 * (2 + 8); + std::size_t buff = (10 * witness_amount - num_cells) % witness_amount; + + std::vector> copy_to; + std::pair cell_copy_from; + std::vector>> constraints; + + std::vector> cells; + std::size_t cur_row = row, cur_column = 0; + while (cur_column < num_cells) { + cells.push_back({cur_row + (cur_column / witness_amount), (cur_column++) % witness_amount}); + } + std::size_t cell_index = 0; + + std::vector>> lookups(1); + + constraints.push_back({cells[cell_index++]}); + constraints[0].push_back(cells[cell_index++]); + + constraints.push_back({constraints[0].back()}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[1].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[1].back()); + } + + constraints.push_back({cells[cell_index++]}); + constraints[2].push_back(cells[cell_index++]); + + constraints.push_back({constraints[2].back()}); + for (std::size_t j = 0; j < num_chunks; ++j) { + constraints[3].push_back(cells[cell_index++]); + lookups[0].push_back(constraints[3].back()); + } + for (int i = 0; i < 2; ++i) { + copy_to.push_back(constraints[2 * i][0]); + } + + last_column = cells.back().second + 1 + buff; + last_row = cells.back().first + (last_column / witness_amount); + last_column %= witness_amount; + + return configuration(first_coordinate, {last_row, last_column}, copy_to, constraints, lookups, + cell_copy_from); + } + + static std::vector configure_all1(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input) { + + std::vector result; + std::size_t row = 0, + column = 0; + std::size_t limit_permutation_column = 7; + + if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { + for (std::size_t i = 0; i < num_blocks; ++i) { + configuration conf; + conf.copy_from = {row, column}; + conf.copy_to.push_back({row, column}); + column += 1; + if (column == limit_permutation_column) { + column = 0; + row += 1; + } + conf.last_coordinate = {row, column}; + result.push_back(conf); + } + result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, row, column)); + return result; + } + + std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } + result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, row, column)); + + if (calculate_shift(num_blocks, num_bits) == 0) { + return result; + } + + row = result.back().last_coordinate.row; + column = result.back().last_coordinate.column; + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner_range_checks(witness_amount, row, column); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } + + return result; + } + + static std::vector configure_all(std::size_t witness_amount, std::size_t num_blocks, std::size_t num_bits, + bool range_check_input) { + + std::vector result; + // result.push_back(configure_shift(witness_amount, 0, 0)); + std::size_t row = 0, + column = 0; + + std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner(witness_amount, num_blocks, num_bits, range_check_input, row, column, num_cells); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } + result.push_back(configure_output(witness_amount, num_blocks, num_bits, range_check_input, row, column)); + row = result.back().last_coordinate.row; + column = result.back().last_coordinate.column; + + for (std::size_t i = 0; i < num_blocks; ++i) { + auto conf = configure_inner_range_checks(witness_amount, row, column); + result.push_back(conf); + row = conf.last_coordinate.row; + column = conf.last_coordinate.column; + } + + std::cout << "num_cofigs: " << result.size() << "\n"; + // for (std::size_t i = 0; i < result.size(); ++i) { + // auto cur_config = result[i]; + // std::cout << "config: " << i << "\n"; + // std::cout << cur_config.first_coordinate.row << " " << cur_config.first_coordinate.column << " " << cur_config.last_coordinate.row << " " << cur_config.last_coordinate.column << std::endl; + // std::cout << "cf: " << cur_config.copy_from.row << " " << cur_config.copy_from.column << std::endl; + // for (int j = 0; j < cur_config.copy_to.size(); ++j) { + // std::cout << "ct: " << cur_config.copy_to[j].row << " " << cur_config.copy_to[j].column << std::endl; + // } + // for (int j = 0; j < cur_config.constraints.size(); ++j) { + // for (int k = 0; k < cur_config.constraints[j].size(); ++k) { + // std::cout << cur_config.constraints[j][k].row << " " << cur_config.constraints[j][k].column << ", "; + // } + // std::cout << std::endl; + // } + // } + + return result; + } + static std::map> configure_map(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + std::cout << "here 1\n"; + + auto shift = calculate_shift(num_blocks, num_bits); + if (shift == 0 && !range_check_input) { + return {}; + } + + auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input); + std::size_t row = 0, + column = 0; + std::cout << "here 2\n"; + + std::map> config_map; + + for (std::size_t i = 0; i < num_blocks; ++i) { + row = config[i].first_coordinate.row; + column = config[i].first_coordinate.column; + if (config_map.find(column) != config_map.end()) { + config_map[column].push_back(row ); + } else { + config_map[column] = {row }; + } + } + std::cout << "here 3\n"; + + return config_map; + } + + static std::vector> configure_output_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + std::vector> result; + + configuration cur_config = configure_output(witness_amount, num_blocks, num_bits, + range_check_input, + 0, 0); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max <= 2 + min); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } + cur_result.push_back(c); + } + cur_result.back().lookups = cur_config.lookups; + result.push_back(cur_result); + + return result; + } + + static std::vector> configure_inner_range_check_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + std::vector> result; + + configuration cur_config = configure_inner_range_checks(witness_amount, 0, 0); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + BOOST_ASSERT(max <= 2 + min); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } + cur_result.push_back(c); + } + cur_result.back().lookups = cur_config.lookups; + result.push_back(cur_result); + + return result; + } + + static std::vector> configure_gates(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + + // if (calculate_shift(num_blocks, num_bits) == 0 && !range_check_input) { + // return {}; + // } + std::cout << "configure gates\n"; + + std::vector> result; + auto gates_configuration_map = configure_map(witness_amount, num_blocks, num_bits, range_check_input); + std::size_t num_cells = calculate_num_cells(num_blocks, num_bits, range_check_input); + std::cout << "here2\n"; + + for (auto config: gates_configuration_map) { + configuration cur_config = configure_inner(witness_amount, num_blocks, num_bits, + range_check_input, + 0, config.first, num_cells); + std::vector> pairs; + for (auto constr : cur_config.constraints) { + std::size_t min = constr[0].row; + std::size_t max = constr.back().row; + for (std::size_t j = 0; j < constr.size(); ++j) { + min = std::min(min, constr[j].row); + max = std::max(max, constr[j].row); + } + std::cout << "minmax: " << min << " " << max << std::endl; + BOOST_ASSERT(max <= 2 + min); + pairs.push_back({min, max}); + } + std::vector cur_result; + std::size_t cur_row = 0; + std::size_t cur_constr = 0; + while (cur_constr < pairs.size()) { + configuration c; + while (cur_constr < pairs.size() && pairs[cur_constr].second <= cur_row + 2 && + pairs[cur_constr].first >= cur_row) { + c.constraints.push_back(cur_config.constraints[cur_constr]); + c.first_coordinate = {cur_row, 0}; + ++cur_constr; + } + if (cur_constr < pairs.size()) { + cur_row = pairs[cur_constr].first; + } + cur_result.push_back(c); + } + result.push_back(cur_result); + } + + return result; + } + + std::vector calculate_gates_rows(std::size_t witness_amount) { + std::vector res; + std::size_t incr = 3; + std::size_t block_per_gate = 5; + std::size_t first_block = 0; + if (witness_amount == 15) { + res.push_back(0); + incr = 2; + block_per_gate = 6; + first_block = 2; + } + std::size_t cur_row = 1; + for (std::size_t i = first_block; i < num_blocks; i += block_per_gate) { + res.push_back(cur_row); + cur_row += incr; + } + + auto config = configure_all(witness_amount, num_blocks, num_bits, range_check_input); + auto output = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input); + auto row = config.back().last_coordinate.row; + if (config.back().last_coordinate.column == 0) row--; + if (output.size() == 2) { + res.push_back(row - 2); + } + res.push_back(row - 1); + return res; + } + + static std::size_t get_gates_amount(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + auto map = configure_map(witness_amount, num_blocks, num_bits, range_check_input); + auto res = map.size() * 2 + range_check_input; + auto output = configure_output_gates(witness_amount, num_blocks, num_bits, range_check_input); + res += output[0].size() + 1; + res += 2; + return res; + } + + static std::size_t get_rows_amount(std::size_t witness_amount, + std::size_t num_blocks, + std::size_t num_bits, + bool range_check_input) { + auto confs = configure_all(witness_amount, num_blocks, num_bits, range_check_input); + auto res = confs.back().last_coordinate.row + 1 * (confs.back().last_coordinate.column != 0); + if (res < 2) res = 2; + + res += exp_component_type::get_rows_amount(witness_amount); + + return res; + } + + std::map component_lookup_tables(){ + std::map lookup_tables; + lookup_tables["keccak_pack_table/range_check"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_pack_table/64bit"] = 0; // REQUIRED_TABLE + lookup_tables["keccak_sign_bit_table/full"] = 0; // REQUIRED_TABLE + return lookup_tables; + } + + template + keccak_padding(WitnessContainerType witness, ConstantContainerType constant, + PublicInputContainerType public_input, std::size_t num_blocks_, + std::size_t num_bits_, + bool range_check_input_ = true) : + component_type(witness, constant, public_input, + get_manifest(num_blocks_, num_bits_, range_check_input_)), + exp_component(witness, constant, public_input), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_) {}; + + keccak_padding( + std::initializer_list witnesses, + std::initializer_list constants, + std::initializer_list + public_inputs, + std::size_t num_blocks_, std::size_t num_bits_, bool range_check_input_ = true) : + component_type(witnesses, constants, public_inputs, + get_manifest(num_blocks_, num_bits_, range_check_input_)), + exp_component(witnesses, constants, public_inputs), + num_blocks(num_blocks_), num_bits(num_bits_), range_check_input(range_check_input_) {}; + + using lookup_table_definition = + typename nil::crypto3::zk::snark::lookup_table_definition; + }; + + template + using padding_component = + keccak_padding>; + + template + std::vector generate_gates( + const padding_component &component, + circuit> &bp, + assignment> + &assignment, + const typename padding_component::input_type + &instance_input, + const typename lookup_library::left_reserved_type lookup_tables_indices) { + std::cout << "generate gatess\n"; + + using component_type = padding_component; + using var = typename component_type::var; + using constraint_type = crypto3::zk::snark::plonk_constraint; + using lookup_constraint_type = typename crypto3::zk::snark::plonk_lookup_constraint; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector selector_indexes; + auto gates_configuration = component.gates_configuration; + std::size_t gate_index = 0; + std::size_t lookup_gate_index = 0; + + std::vector cur_constraints; + std::vector cur_lookup_constraints; + + cur_constraints.clear(); + cur_lookup_constraints.clear(); + + { + if (component.range_check_input) { + auto conf = gates_configuration[0][0]; + for (std::size_t i = 1; i < 8; ++i) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row))}}); + } + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_sign_bit_table/full"), + {var(component.W(conf.constraints[2][8].column), static_cast(conf.constraints[2][8].row))}}); + // chunk, range_check + for (std::size_t i = 1; i < 9; ++i) { + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row))}}); + } + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); + } + for (auto confs : gates_configuration) { + auto conf = confs[0]; + // chunk, first, second + cur_constraints.push_back(constraint_type( + var(component.W(conf.constraints[0][0].column), static_cast(conf.constraints[0][0].row)) - + var(component.W(conf.constraints[0][1].column), static_cast(conf.constraints[0][1].row)) * + (integral_type(1) << (64 - component.shift)) - + var(component.W(conf.constraints[0][2].column), static_cast(conf.constraints[0][2].row)))); + // sum, relay, first + cur_constraints.push_back( + var(component.W(conf.constraints[1][0].column), static_cast(conf.constraints[1][0].row)) - + var(component.W(conf.constraints[1][1].column), static_cast(conf.constraints[1][1].row)) * + (integral_type(1) << component.shift) - + var(component.W(conf.constraints[1][2].column), static_cast(conf.constraints[1][2].row))); + // sum, range_check + constraint_type constraint = var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row)); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row)) + * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[2][i].column), static_cast(conf.constraints[2][i].row))}}); + } + cur_constraints.push_back(constraint); + if (component.range_check_input) { + // chunk, range_check + constraint = var(component.W(conf.constraints[3][0].column), static_cast(conf.constraints[3][0].row)); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row)) + * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(component.W(conf.constraints[3][i].column), static_cast(conf.constraints[3][i].row))}}); + } + cur_constraints.push_back(constraint); + } + + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + cur_constraints.clear(); + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); + } + } + + auto output_gates = component.output_gates_configuration[0]; + std::size_t idx[2] = {0, 0}; + std::size_t shifts[2] = {1, 1}; + if (output_gates.size() > 1) { + idx[1] = 1; + shifts[1] = 2; + } + // (s_i - 1)(s_i - 2)w_i=0 && s_i(s_i - 2)(w_i*delta - 1)=0 + for (auto constr : output_gates[idx[0]].constraints) { + cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 1) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 2) * + var(constr[1].column, static_cast(constr[1].row) - shifts[0])); + cur_constraints.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[0]) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[0]) - 2) * + (var(constr[1].column, static_cast(constr[1].row) - shifts[0]) * var(constr[2].column, static_cast(constr[2].row) - shifts[0]) - 1)); + } + if (output_gates.size() > 1) { + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + cur_constraints.clear(); + } + for (auto constr : output_gates[idx[1]].constraints) { + cur_constraints.push_back((var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 1) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * + var(constr[1].column, static_cast(constr[1].row) - shifts[1])); + cur_constraints.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[1]) * + (var(constr[0].column, static_cast(constr[0].row) - shifts[1]) - 2) * + (var(constr[1].column, static_cast(constr[1].row) - shifts[1]) * var(constr[2].column, static_cast(constr[2].row) - shifts[1]) - 1)); + } + std::vector s_i; + for (std::size_t i = 0; i < 2; ++i) { + for (auto constr : output_gates[idx[i]].constraints) { + s_i.push_back(var(constr[0].column, static_cast(constr[0].row) - shifts[1])); + } + } + // s_i(s_i - 1)(s_i - 2)=0 + for (std::size_t i = 0; i < 17; ++i) { + cur_constraints.push_back(s_i[i] * (s_i[i] - 1) * (s_i[i] - 2)); + } + // s_i(s_i - 2)s_i+1=0 && (s_i+1 - s_i + 1)(s_i+1 - s_i)=0 + for (std::size_t i = 0; i < 16; ++i) { + cur_constraints.push_back(s_i[i] * (s_i[i] - 2) * s_i[i+1]); + cur_constraints.push_back((s_i[i+1] - s_i[i] + 1) * (s_i[i+1] - s_i[i])); + } + // sum + constraint_type sum = s_i[0]; + for (std::size_t i = 1; i < 17; ++i) { + sum += s_i[i]; + } + cur_constraints.push_back((34 - sum) * sum - 1 - var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])); + + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + cur_constraints.clear(); + + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(output_gates[idx[1]].lookups[0][0].column, static_cast(output_gates[idx[1]].lookups[0][0].row) - shifts[1])}}); + + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + cur_lookup_constraints.clear(); + + { + auto conf = component.inner_range_check_gates_configuration[0][0]; + int row_shift = 0; + if (conf.last_coordinate.row - conf.first_coordinate.row == 2) row_shift = 1; + + cur_constraints.push_back(var(conf.constraints[0][0].column, static_cast(conf.constraints[0][0].row) - row_shift) * + (integral_type(1) << (64 - component.shift)) - + var(conf.constraints[0][1].column, static_cast(conf.constraints[0][1].row) - row_shift)); + cur_constraints.push_back(var(conf.constraints[2][0].column, static_cast(conf.constraints[2][0].row) - row_shift) * + (integral_type(1) << component.shift) - + var(conf.constraints[2][1].column, static_cast(conf.constraints[2][1].row) - row_shift)); + for (std::size_t j = 0; j < 2; ++j) { + constraint_type constraint = var(conf.constraints[2 * j + 1][0].column, static_cast(conf.constraints[2 * j + 1][0].row) - row_shift); + for (std::size_t i = 1; i < 9; ++i) { + constraint -= var(conf.constraints[2 * j + 1][i].column, static_cast(conf.constraints[2 * j + 1][i].row) - row_shift) + * (integral_type(1) << ((i-1) * 8)); + cur_lookup_constraints.push_back({lookup_tables_indices.at("keccak_pack_table/range_check"), + {var(conf.constraints[2 * j + 1][i].column, static_cast(conf.constraints[2 * j + 1][i].row) - row_shift)}}); + } + cur_constraints.push_back(constraint); + } + + selector_indexes.push_back(bp.add_gate(cur_constraints)); + gate_index++; + selector_indexes.push_back(bp.add_lookup_gate(cur_lookup_constraints)); + lookup_gate_index++; + } + + BOOST_ASSERT(gate_index + lookup_gate_index == component.gates_amount); + return selector_indexes; + } + + template + void generate_copy_constraints( + const padding_component &component, + circuit> &bp, + assignment> + &assignment, + const typename padding_component::input_type &instance_input, + const std::uint32_t start_row_index) { + std::cout << "generate copyy\n"; + + using component_type = padding_component; + using var = typename component_type::var; + + std::size_t strow = start_row_index + component.exp_component.rows_amount; + std::size_t config_index = 0; + std::size_t input_index = 0; + std::vector> first_second_chunks; + std::array fs_chunk; + + std::size_t conf_index_for_input = 0; + if (component.shift != 0) { + bp.add_copy_constraint({instance_input.message[input_index++], var(component.W(0), strow, false)}); + conf_index_for_input = 1; + } + + while (config_index < component.num_blocks - 1) { + auto config = component.full_configuration[config_index]; + bp.add_copy_constraint({instance_input.message[input_index++], + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); + if (component.shift != 0) { + auto next_config = component.full_configuration[config_index + 1]; + bp.add_copy_constraint({var(component.W(config.copy_from.column), + config.copy_from.row + strow, false), + var(component.W(next_config.copy_to[0].column), + next_config.copy_to[0].row + strow, false)}); + first_second_chunks.push_back({var(component.W(config.constraints[0][1].column), + config.constraints[0][1].row + strow, false), + var(component.W(config.constraints[0][2].column), + config.constraints[0][2].row + strow, false)}); + } + config_index++; + } + if (component.shift != 0) { + auto config = component.full_configuration[config_index++]; + bp.add_copy_constraint({var(component.C(0), strow + 1, false, var::column_type::constant), + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); + first_second_chunks.push_back({var(component.W(config.constraints[0][1].column), + config.constraints[0][1].row + strow, false), + var(component.W(config.constraints[0][2].column), + config.constraints[0][2].row + strow, false)}); + } else { + auto config = component.full_configuration[config_index++]; + bp.add_copy_constraint({instance_input.message[input_index++], + var(component.W(config.copy_to[conf_index_for_input].column), + config.copy_to[conf_index_for_input].row + strow, false)}); + } + + auto config = component.full_configuration[config_index]; + std::size_t idx = 0; + std::size_t prev_offset = (component.shift != 0) * 2; + for (int i = 17 - component.num_padding_zeros; i > 0; --i) { + auto prev_config = component.full_configuration[config_index - i]; + bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), + var(component.W(prev_config.copy_to[prev_offset].column), prev_config.copy_to[prev_offset].row + strow, false)}); + } + config_index++; + + if (component.shift == 0) { + bp.add_copy_constraint({var(component.C(0), strow + 1, false, var::column_type::constant), + var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false)}); + } + for (int i = 0; i < component.num_padding_zeros - (component.shift == 0); ++i) { + bp.add_copy_constraint({var(component.W(config.copy_to[idx].column), config.copy_to[idx++].row + strow, false), + var(component.C(0), strow, false, var::column_type::constant)}); + } + + if (component.shift != 0) { + for (int i = 0; i < component.num_blocks; ++i) { + config = component.full_configuration[config_index++]; + bp.add_copy_constraint({first_second_chunks[i][0], var(component.W(config.constraints[0][0].column), config.constraints[0][0].row + strow, false)}); + bp.add_copy_constraint({first_second_chunks[i][1], var(component.W(config.constraints[2][0].column), config.constraints[2][0].row + strow, false)}); + } + } + } + + template + typename padding_component::result_type generate_circuit( + const padding_component &component, + circuit> &bp, + assignment> + &assignment, + const typename padding_component::input_type &instance_input, + const std::uint32_t start_row_index) { + std::cout << "generate circuitt\n"; + + using component_type = padding_component; + using exp_type = typename component_type::exp_component_type; + using var = typename component_type::var; + + std::size_t strow = start_row_index; + typename exp_type::input_type exp_input = { + var(component.C(0), start_row_index, false, var::column_type::constant), + instance_input.var_bit_shift}; + typename exp_type::result_type exp_result = + generate_circuit(component.exp_component, bp, assignment, exp_input, strow); + strow += component.exp_component.rows_amount; + + auto selector_indexes = generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices()); + + auto gc_map = component.gates_configuration_map; + std::size_t sel_ind = 0; + auto gc_iter = gc_map.begin(); + + if (gc_iter != gc_map.end()) { + if (component.range_check_input) { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + strow); + sel_ind++; + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + strow); + } else { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[0] + strow); + assignment.enable_selector(selector_indexes[sel_ind + 1], gc_iter->second[0] + strow); + } + for (std::size_t i = 1; i < gc_iter->second.size(); ++i) { + assignment.enable_selector(selector_indexes[sel_ind], gc_iter->second[i] + strow); + assignment.enable_selector(selector_indexes[sel_ind + 1], gc_iter->second[i] + strow); + } + sel_ind += 2; + gc_iter++; + + for (; gc_iter != gc_map.end(); ++gc_iter) { + for (auto gate_row : gc_iter->second) { + assignment.enable_selector(selector_indexes[sel_ind], gate_row + strow); + assignment.enable_selector(selector_indexes[sel_ind + 1], gate_row + strow); + } + sel_ind += 2; + } + } + auto output = component.full_configuration[component.num_blocks]; + auto output_gates = component.output_gates_configuration[0]; + assignment.enable_selector(selector_indexes[sel_ind++], output.first_coordinate.row + 1 + strow); + if (output_gates.size() > 1) { + assignment.enable_selector(selector_indexes[sel_ind++], output.first_coordinate.row + 2 + strow); + } + + if (component.shift != 0) { + int row_shift = 0; + auto conf = component.full_configuration[component.num_blocks + 1]; + if (conf.last_coordinate.row - conf.first_coordinate.row == 2) row_shift = 1; + for (std::size_t i = 1; i < component.num_blocks + 1; ++i) { + conf = component.full_configuration[component.num_blocks + i]; + assignment.enable_selector(selector_indexes[sel_ind], conf.first_coordinate.row + strow + row_shift); + } + } + + generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); + generate_assignments_constant(component, bp, assignment, instance_input, start_row_index); + + return typename component_type::result_type(component, start_row_index); + } + + template + typename padding_component::result_type generate_assignments( + const padding_component &component, + assignment> + &assignment, + const typename padding_component::input_type &instance_input, + const std::uint32_t start_row_index) { + std::cout << "generate assignn\n"; + + std::size_t strow = start_row_index; + + using component_type = padding_component; + using exp_type = typename component_type::exp_component_type; + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + using var = typename component_type::var; + + // BOOST_ASSERT(component.num_blocks == instance_input.message.size()); + + typename exp_type::input_type exp_input = { + var(component.C(0), start_row_index, false, var::column_type::constant), + instance_input.var_bit_shift}; + typename exp_type::result_type exp_result = + generate_assignments(component.exp_component, assignment, exp_input, strow); + strow += component.exp_component.rows_amount; + + std::size_t config_index = 0; + // range_check shift + integral_type mask_range_check = (integral_type(1) << 8) - 1; + std::vector output_values; + std::vector> non_shifted_chunk_parts; + std::vector> shifted_chunk_parts; + + { + integral_type relay_chunk = integral_type(var_value(assignment, instance_input.message[0]).data); + for (std::size_t index = 1; index < component.num_blocks + 1; ++index) { + value_type chunk = value_type(component.padding_delimiter); + if (index < component.num_blocks) { + chunk = var_value(assignment, instance_input.message[index]); + } + std::cout << "chunk: " << chunk.data << std::endl; + integral_type integral_chunk = integral_type(chunk.data); + integral_type mask = (integral_type(1) << (64 - component.shift)) - 1; + std::array chunk_parts = {integral_chunk >> (64 - component.shift), + integral_chunk & mask}; + non_shifted_chunk_parts.push_back(chunk_parts); + shifted_chunk_parts.push_back({chunk_parts[0] << (64 - component.shift), chunk_parts[1] << component.shift}); + integral_type sum = (relay_chunk << component.shift) + chunk_parts[0]; + output_values.push_back(value_type(sum)); + std::cout << "sum: " << sum << std::endl; + + std::vector sum_range_check; + integral_type sum_to_check = sum; + for (std::size_t i = 0; i < 7; ++i) { + sum_range_check.push_back(sum_to_check & mask_range_check); + sum_to_check >>= 8; + } + sum_range_check.push_back(sum_to_check); + + auto cur_config = component.full_configuration[config_index]; + // chunk, first, second + assignment.witness(component.W(cur_config.constraints[0][0].column), cur_config.constraints[0][0].row + strow) = chunk; + for (int j = 1; j < 3; ++j) { + assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_parts[j - 1]); + } + // sum, relay, first + assignment.witness(component.W(cur_config.constraints[1][0].column), cur_config.constraints[1][0].row + strow) = value_type(sum); + assignment.witness(component.W(cur_config.constraints[1][1].column), cur_config.constraints[1][1].row + strow) = value_type(relay_chunk); + assignment.witness(component.W(cur_config.constraints[1][2].column), cur_config.constraints[1][2].row + strow) = value_type(chunk_parts[0]); + // sum range_check + for (int j = 1; j < 9; ++j) { + assignment.witness(component.W(cur_config.constraints[2][j].column), cur_config.constraints[2][j].row + strow) = value_type(sum_range_check[j - 1]); + } + if (component.range_check_input) { + std::vector chunk_range_check; + integral_type chunk_to_check = integral_chunk; + for (std::size_t i = 0; i < 7; ++i) { + chunk_range_check.push_back(chunk_to_check & mask_range_check); + chunk_to_check >>= 8; + } + chunk_range_check.push_back(chunk_to_check); + // chunk range_check + for (int j = 1; j < 9; ++j) { + assignment.witness(component.W(cur_config.constraints[3][j].column), cur_config.constraints[3][j].row + strow) = value_type(chunk_range_check[j - 1]); + } + } + + relay_chunk = chunk_parts[1]; + config_index++; + } + } + // } else { + // for (std::size_t index = 0; index < component.num_blocks; ++index) { + // auto cur_config = component.full_configuration[index]; + + // if (component.range_check_input) { + // integral_type chunk_to_check = integral_type(var_value(assignment, instance_input.message[index]).data); + // integral_type mask_range_check = (integral_type(1) << 8) - 1; + // std::vector chunk_range_check; + // for (std::size_t i = 0; i < 8; ++i) { + // chunk_range_check.push_back(chunk_to_check & mask_range_check); + // chunk_to_check >>= 8; + // } + // // chunk range_check + // for (int j = 1; j < 9; ++j) { + // assignment.witness(component.W(cur_config.constraints[0][j].column), cur_config.constraints[0][j].row + strow) = value_type(chunk_range_check[j - 1]); + // } + // } + + // assignment.witness(component.W(cur_config.copy_to[0].column), + // cur_config.copy_to[0].row + strow) = + // var_value(assignment, instance_input.message[index]); + // output_values.push_back(var_value(assignment, instance_input.message[index])); + // config_index++; + // } + // output_values.push_back(value_type(component.padding_delimiter)); + // } + + // output + auto cur_config = component.full_configuration[config_index++]; + std::size_t idx = 0; + value_type last_nonzero = value_type(1); + value_type sum_s = value_type(0); + for (std::size_t i = output_values.size() - ((output_values.size() - 1) % 17 + 1); i < output_values.size(); ++i) { + last_nonzero = output_values[i]; + assignment.witness(component.W(cur_config.copy_to[idx].column), cur_config.copy_to[idx].row + strow) = last_nonzero; + value_type s = (i == output_values.size() - 1) ? value_type(1) : value_type(2); + assignment.witness(component.W(cur_config.constraints[idx][0].column), cur_config.constraints[idx++][0].row + strow) = s; + sum_s += s; + } + assignment.witness(component.W(cur_config.constraints[idx - 1][2].column), cur_config.constraints[idx - 1][2].row + strow) = value_type(1) / last_nonzero; + for (int i = 0; i < component.num_padding_zeros - (component.shift == 0); ++i) { + assignment.witness(component.W(cur_config.copy_to[idx].column), cur_config.copy_to[idx].row + strow) = value_type(0); + assignment.witness(component.W(cur_config.constraints[idx][0].column), cur_config.constraints[idx++][0].row + strow) = value_type(0); + } + assignment.witness(component.W(cur_config.lookups[0][0].column), cur_config.lookups[0][0].row + strow) = sum_s * (value_type(34) - sum_s) - value_type(1); + + { + // additional range_check + integral_type mask_range_check = (integral_type(1) << 8) - 1; + for (std::size_t i = 0; i < shifted_chunk_parts.size(); ++i) { + cur_config = component.full_configuration[config_index++]; + for (std::size_t j = 0; j < 2; ++j) { + assignment.witness(component.W(cur_config.constraints[2 * j][0].column), cur_config.constraints[2 * j][0].row + strow) = value_type(non_shifted_chunk_parts[i][j]); + assignment.witness(component.W(cur_config.constraints[2 * j][1].column), cur_config.constraints[2 * j][1].row + strow) = value_type(shifted_chunk_parts[i][j]); + + integral_type chunk_to_check = shifted_chunk_parts[i][j]; + std::vector chunk_range_check; + for (std::size_t i = 0; i < 8; ++i) { + chunk_range_check.push_back(chunk_to_check & mask_range_check); + chunk_to_check >>= 8; + } + // chunk range_check + for (int k = 1; k < 9; ++k) { + assignment.witness(component.W(cur_config.constraints[2 * j + 1][k].column), cur_config.constraints[2 * j + 1][k].row + strow) = value_type(chunk_range_check[k - 1]); + } + } + } + } + + return typename component_type::result_type(component, start_row_index); + } + + template + void generate_assignments_constant( + const padding_component &component, + circuit> &bp, + assignment> + &assignment, + const typename padding_component::input_type &instance_input, + const std::uint32_t start_row_index) { + + using value_type = typename BlueprintFieldType::value_type; + + std::size_t row = start_row_index + component.exp_component.rows_amount; + + assignment.constant(component.C(0), row) = 0; + assignment.constant(component.C(0), row + 1) = value_type(component.padding_delimiter); + } + + } // namespace components + } // namespace blueprint +} // namespace nil + +#endif // CRYPTO3_BLUEPRINT_COMPONENTS_KECCAK_PADDING_HPP diff --git a/test/hashes/plonk/keccak_padding_no_template.cpp b/test/hashes/plonk/keccak_padding_no_template.cpp new file mode 100644 index 000000000..0fcbd3dbb --- /dev/null +++ b/test/hashes/plonk/keccak_padding_no_template.cpp @@ -0,0 +1,324 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Polina Chernyshova +// 2024 Valeh Farzaliyev +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE plonk_keccak_test + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +// #include +#include +// #include + +#include + +#include +#include + +#include + +#include "../../test_plonk_component.hpp" + +template +std::size_t number_bits(typename BlueprintFieldType::value_type value) { + using integral_type = typename BlueprintFieldType::integral_type; + + integral_type integral_value = integral_type(value.data); + std::size_t result = 0; + while (integral_value > 0) { + integral_value >>= 1; + ++result; + } + return result; +} + + +template +std::vector + padding_function(std::vector message, std::size_t num_bits) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector result; + std::size_t shift = 64 * message.size() - num_bits; + + if (shift > 0) { + integral_type relay_value = integral_type(message[0].data); + for (int i = 1; i < message.size(); ++i) { + integral_type mask = (integral_type(1) << (64 - shift)) - 1; + integral_type left_part = integral_type(message[i].data >> (64 - shift)); + integral_type right_part = integral_type(message[i].data) & mask; + result.push_back(value_type((relay_value << shift) + left_part)); + relay_value = right_part; + } + relay_value <<= shift; + relay_value += integral_type(1) << (shift - 8); + result.push_back(value_type(relay_value)); + } else { + for (int i = 0; i < message.size(); ++i) { + result.push_back(message[i]); + } + result.push_back(value_type(integral_type(1) << 56)); + } + while (result.size() % 17 != 0) { + result.push_back(value_type(0)); + } + + return result; +} + +template +auto test_keccak_padding_inner(std::vector message, + std::vector expected_result, + const std::size_t num_blocks, const std::size_t num_bits, + const bool range_check_input = true) { + constexpr std::size_t PublicInputColumns = 1; + constexpr std::size_t ConstantColumns = 3; + constexpr std::size_t SelectorColumns = 20; + nil::crypto3::zk::snark::plonk_table_description desc(WitnessesAmount, PublicInputColumns, + ConstantColumns, SelectorColumns); + using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; + using AssignmentType = nil::blueprint::assignment; + using hash_type = nil::crypto3::hashes::keccak_1600<256>; + constexpr std::size_t Lambda = 1; + + using component_type = nil::blueprint::components::keccak_padding; + using var = typename component_type::var; + + const std::size_t max_num_blocks = 200; + + std::vector public_input; + for (int i = 0; i < num_blocks; ++i) { + public_input.push_back(message[i]); + } + public_input.push_back(typename BlueprintFieldType::value_type(num_blocks)); + public_input.push_back(typename BlueprintFieldType::value_type(num_blocks * 64 - num_bits)); + + std::vector message_vars; + for (int i = 0; i < num_blocks; ++i) { + message_vars.push_back(var(0, i, false, var::column_type::public_input)); + } + var var_num_blocks = var(0, num_blocks, false, var::column_type::public_input); + var var_bit_shift = var(0, num_blocks + 1, false, var::column_type::public_input); + typename component_type::input_type instance_input = {message_vars, var_num_blocks, var_bit_shift}; + + auto result_check = [expected_result](AssignmentType &assignment, typename component_type::result_type &real_res) { + std::cout << "sizes: " << expected_result.size() << " " << real_res.padded_message.size() << std::endl; + assert(expected_result.size() == real_res.padded_message.size()); + for (int i = 0; i < real_res.padded_message.size(); ++i) { + std::cout << expected_result[i].data << " " << var_value(assignment, real_res.padded_message[i]).data << std::endl; + } + for (int i = 0; i < real_res.padded_message.size(); ++i) { + assert(expected_result[i] == var_value(assignment, real_res.padded_message[i])); + } + }; + + if (!(WitnessesAmount == 15 || WitnessesAmount == 9)) { + BOOST_ASSERT_MSG(false, "Please add support for WitnessesAmount that you passed here!"); + } + std::array witnesses; + for (std::uint32_t i = 0; i < WitnessesAmount; i++) { + witnesses[i] = i; + } + component_type component_instance = + component_type(witnesses, std::array {0}, std::array {0}, num_blocks, + num_bits, range_check_input); + + nil::crypto3::test_component( + component_instance, desc, public_input, result_check, instance_input, + nil::blueprint::connectedness_check_type::type::NONE, num_blocks, num_bits, range_check_input); +} + +// works +template +void test_keccak_padding_0() { + using value_type = typename BlueprintFieldType::value_type; + + std::vector message = {0}; + const std::size_t num_blocks = 1; + const std::size_t num_bits = 8; + + std::vector expected_result = {281474976710656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits); +} +template +void test_keccak_padding_1(std::size_t num_bits) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector message = {value_type(integral_type(1) << (num_bits - 1) % 64)}; + for (std::size_t i = 0; i < (num_bits - 1) / 64; i++) { + message.push_back(value_type(0)); + } + const std::size_t num_blocks = message.size(); + + auto expected_result = padding_function(message, num_bits); + + test_keccak_padding_inner(message, expected_result, + num_blocks, num_bits); +} + +template +void test_keccak_padding_random(std::size_t message_size, bool random_mask_zero = true, bool range_check_input = true) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; + + integral_type mask = (integral_type(1) << 64) - 1; + std::size_t power_for_mask = 64; + if (random_mask_zero) { + power_for_mask = dis(gen) % 63 + 1; + } + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; + value_type message_zero = + value_type((integral_type(dis(gen)) & mask_zero) | (integral_type(1) << (power_for_mask - 1))); + + std::vector message; + message.push_back(message_zero); + for (std::size_t i = 1; i < message_size; i++) { + message.push_back(value_type(integral_type(dis(gen)) & mask)); + } + assert(message_size == message.size()); + std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); + std::size_t num_blocks = message_size; + + auto expected_result = padding_function(message, num_bits); + + test_keccak_padding_inner( + message, expected_result, num_blocks, num_bits, range_check_input); +} + +template +void test_to_fail_keccak_padding_random(std::size_t message_size, bool more_bits, bool random_mask_zero = true, + bool range_check_input = true) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis; + + integral_type mask = (integral_type(1) << 64) - 1; + std::size_t power_for_mask = 64; + if (random_mask_zero) { + power_for_mask = dis(gen) % 63 + 1; + } + integral_type mask_zero = (integral_type(1) << power_for_mask) - 1; + value_type message_zero = + value_type((integral_type(dis(gen)) & mask_zero) | (integral_type(1) << (power_for_mask - 1))); + std::vector message; + message.push_back(message_zero); + for (std::size_t i = 1; i < message_size; i++) { + message.push_back(value_type(integral_type(dis(gen)) & mask)); + } + assert(message_size == message.size()); + std::size_t num_bits = 64 * (message_size - 1) + number_bits(message[0]); + std::size_t num_blocks = message_size; + + auto expected_result = padding_function(message, num_bits); + + if (more_bits) { + num_bits -= 1; + } else { + num_bits += 1; + } + + test_keccak_padding_inner( + message, expected_result, num_blocks, num_bits, range_check_input); +} + +BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas) { + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + + test_keccak_padding_0(); + // test_keccak_padding_random(2, true, false); + for (std::size_t i = 99; i < 100; i++) { + test_keccak_padding_1(i); + test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); + } +} + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_pallas_15) { + using field_type = nil::crypto3::algebra::curves::vesta::scalar_field_type; + +// test_keccak_padding_0(); +// test_keccak_padding_random(10); + for (std::size_t i = 80; i < 81; i++) { + test_keccak_padding_1(i); + test_keccak_padding_random(i); + test_keccak_padding_random(i, false); + test_keccak_padding_random(i, true, false); + test_keccak_padding_random(i, false, false); + } +} + +BOOST_AUTO_TEST_CASE(blueprint_plonk_hashes_keccak_round_to_fail) { + // test with no result_check asserts + using field_type = nil::crypto3::algebra::curves::pallas::base_field_type; + + // test_to_fail_keccak_padding_random(10, false); + // test_to_fail_keccak_padding_random(16, false, false); + // test_to_fail_keccak_padding_random(11, false, false, false); + // test_to_fail_keccak_padding_random(100, true); + // test_to_fail_keccak_padding_random(150, true, false); + // test_to_fail_keccak_padding_random(2, true, true, false); + // test_to_fail_keccak_padding_random(4, true, false, false); + + // test_to_fail_keccak_padding_random(10, false); + // test_to_fail_keccak_padding_random(16, false, false); + // test_to_fail_keccak_padding_random(11, false, false, false); + // test_to_fail_keccak_padding_random(100, true); + // test_to_fail_keccak_padding_random(150, true, false); + // test_to_fail_keccak_padding_random(2, true, true, false); + // test_to_fail_keccak_padding_random(4, true, false, false); + + // this doesn't break, because we switched off range check input + // test_to_fail_keccak_padding_random(5, false, true, false); + // test_to_fail_keccak_padding_random(5, false, true, false); + + // test_to_fail_keccak_padding_random(5, false, true); + // test_to_fail_keccak_padding_random(5, false, true); +} + +BOOST_AUTO_TEST_SUITE_END() From 7d4d35b75fe010507b987921f3cb3011b83a3ccf Mon Sep 17 00:00:00 2001 From: tshchelovek Date: Thu, 15 Aug 2024 17:30:49 +0000 Subject: [PATCH 47/48] cmakelists for no template --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 063ff2b43..4612aa5a0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -97,6 +97,7 @@ set(PLONK_TESTS_FILES "hashes/plonk/sha512_process" "hashes/plonk/keccak_round" "hashes/plonk/keccak_padding" + "hashes/plonk/keccak_padding_no_template" "hashes/plonk/keccak" "hashes/plonk/decomposition" "hashes/plonk/detail/sha_table_generators_base4" From 4c4b87c9a06af4b2886822b2780f717de2ff7e96 Mon Sep 17 00:00:00 2001 From: tshchelovek Date: Thu, 15 Aug 2024 17:31:31 +0000 Subject: [PATCH 48/48] functions for bytes to bit chunks added --- test/hashes/plonk/keccak.cpp | 84 +++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/test/hashes/plonk/keccak.cpp b/test/hashes/plonk/keccak.cpp index 8b7beab67..9b26c8018 100644 --- a/test/hashes/plonk/keccak.cpp +++ b/test/hashes/plonk/keccak.cpp @@ -38,7 +38,8 @@ #include #include -// #include +#include +#include #include // #include @@ -255,6 +256,77 @@ std::array return inner_state; } +template +std::vector + bytes_to_bit_chunks64(std::string bytes) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::vector bits; + std::cout << "bits:\n"; + for (auto byte : bytes) { + integral_type mask = integral_type(1) << 7; + for (int i = 0; i < 8; ++i) { + bits.push_back(int(byte & mask)); + mask >>= 1; + std::cout << bits.back(); + } + } + std::cout << std::endl; + std::size_t start_idx = 0; + while (start_idx + 1 < bits.size() && bits[start_idx] == 0) { + ++start_idx; + } + std::size_t end_idx = std::min(start_idx + 64, bits.size()); + + std::vector result; + while (end_idx <= bits.size()) { + integral_type value = 0; + for (std::size_t i = start_idx; i < end_idx; ++i) { + value = (value << 1) + bits[i]; + } + result.push_back(value_type(value)); + start_idx = end_idx; + end_idx = std::min(start_idx + 64, bits.size()); + } + + return result; +} + +template +std::string bit_chunks64_to_bytes(Container bit_chunks) { + using value_type = typename BlueprintFieldType::value_type; + using integral_type = typename BlueprintFieldType::integral_type; + + std::string result; + for (value_type chunk : bit_chunks) { + integral_type value = integral_type(chunk.data); + integral_type mask = integral_type(7) << 7; + for (int i = 0; i < 8; ++i) { + result.push_back(std::string(value & mask)); + mask >>= 3; + } + } + return result; +} + +template +std::vector + keccak_hash_call(std::vector message, std::size_t num_bits) { + using value_type = typename BlueprintFieldType::value_type; + + hashes::keccak_1600<224>::digest_type result = hash>(message.begin(), message.end()); + std::string result_str = std::to_string(result).data(); + std::cout << "Keccak hash call result string:\n" << result_str << std::endl; + + auto result_chunks = bytes_to_bit_chunks64(result_str); + std::cout << "Keccak hash call result chunks:\n"; + for (auto chunk : result_chunks) { + std::cout << chunk.data << std::endl; + } + return result_chunks; +} + template std::array keccak_function(std::vector message, std::size_t num_bits) { @@ -315,6 +387,14 @@ std::array hash[i] = unpack(inner_state[i]); } + std::cout << "Testing bits to bytes: " << bit_chunks64_to_bytes, BlueprintFieldType>(hash) << std::endl; + //check that computation is the same as keccak_1600_compressor + // auto check_result = keccak_hash_call(message, num_bits); + for (int i = 0; i < 4; ++i) { + std::cout << "hash:\n" + << hash[i].data << "\n"; + } + return hash; } @@ -324,7 +404,7 @@ auto test_keccak_inner(std::vector mess std::size_t num_bits, bool range_check_input, std::size_t limit_permutation_column) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 3; - constexpr std::size_t SelectorColumns = 30; + constexpr std::size_t SelectorColumns = 40; nil::crypto3::zk::snark::plonk_table_description desc(WitnessesAmount, PublicInputColumns, ConstantColumns, SelectorColumns); using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system;