Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed hash decomposition component. #280

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 132 additions & 74 deletions include/nil/blueprint/components/hashes/sha2/plonk/decomposition.hpp

Large diffs are not rendered by default.

24 changes: 0 additions & 24 deletions include/nil/blueprint/components/hashes/sha2/plonk/sha256.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,30 +149,6 @@ namespace nil {
using lookup_table_definition = typename
nil::crypto3::zk::snark::lookup_table_definition<BlueprintFieldType>;

std::vector<std::shared_ptr<lookup_table_definition>> component_custom_lookup_tables(){
std::vector<std::shared_ptr<lookup_table_definition>> result = {};

auto sparse_values_base4 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::sparse_values_base4_table());
result.push_back(sparse_values_base4);

auto sparse_values_base7 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::sparse_values_base7_table());
result.push_back(sparse_values_base7);

auto maj = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::maj_function_table());
result.push_back(maj);

auto reverse_sparse_sigmas_base4 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::reverse_sparse_sigmas_base4_table());
result.push_back(reverse_sparse_sigmas_base4);

auto reverse_sparse_sigmas_base7 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::reverse_sparse_sigmas_base7_table());
result.push_back(reverse_sparse_sigmas_base7);

auto ch = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::ch_function_table());
result.push_back(ch);

return result;
}

std::map<std::string, std::size_t> component_lookup_tables(){
std::map<std::string, std::size_t> lookup_tables;
lookup_tables["sha256_sparse_base4/full"] = 0; // REQUIRED_TABLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1213,9 +1213,13 @@ namespace nil {
&instance_input,
const std::size_t start_row_index) {

std::size_t row = start_row_index + 2;
using var = typename plonk_sha256_process<BlueprintFieldType>::var;
std::size_t row = start_row_index;
for (std::size_t i = 0; i < 8; ++i) {
bp.add_copy_constraint({var(component.W(i), row, false), instance_input.input_state[i]});
}

row = start_row_index + 2;
for (std::size_t i = 1; i <= 15; ++i) {
bp.add_copy_constraint(
{var(component.W(0), row + (i - 1) * 5 + 0, false), instance_input.input_words[i]});
Expand Down Expand Up @@ -1389,7 +1393,7 @@ namespace nil {
typename BlueprintFieldType::value_type h = input_state[7];

std::array<typename BlueprintFieldType::integral_type, 8> sparse_values {};
for (std::size_t i = 0; i < 4; i++) {
for (std::size_t i = 0; i < 8; i++) {
assignment.witness(component.W(i), row) = input_state[i];
typename BlueprintFieldType::integral_type integral_input_state_sparse =
typename BlueprintFieldType::integral_type(input_state[i].data);
Expand All @@ -1404,32 +1408,12 @@ namespace nil {
}

std::vector<std::size_t> input_state_sparse_sizes = {32};
const auto base = i < 4 ? plonk_sha256_process<BlueprintFieldType>::base4
: plonk_sha256_process<BlueprintFieldType>::base7;
std::array<std::vector<typename BlueprintFieldType::integral_type>, 2> input_state_sparse_chunks =
detail::split_and_sparse<BlueprintFieldType>(
input_state_sparse, input_state_sparse_sizes,
plonk_sha256_process<BlueprintFieldType>::base4);
assignment.witness(component.W(i), row + 1) = input_state_sparse_chunks[1][0];
sparse_values[i] = input_state_sparse_chunks[1][0];
}
for (std::size_t i = 4; i < 8; i++) {
assignment.witness(component.W(i), row) = input_state[i];
typename BlueprintFieldType::integral_type integral_input_state_sparse =
typename BlueprintFieldType::integral_type(input_state[i].data);
std::vector<bool> input_state_sparse(32);
{
nil::marshalling::status_type status;
std::vector<bool> input_state_sparse_all =
nil::marshalling::pack<nil::marshalling::option::big_endian>(integral_input_state_sparse,
status);
std::copy(input_state_sparse_all.end() - 32, input_state_sparse_all.end(),
input_state_sparse.begin());
}

std::vector<std::size_t> input_state_sparse_sizes = {32};
std::array<std::vector<typename BlueprintFieldType::integral_type>, 2> input_state_sparse_chunks =
detail::split_and_sparse<BlueprintFieldType>(
input_state_sparse, input_state_sparse_sizes,
plonk_sha256_process<BlueprintFieldType>::base7);
base);
assignment.witness(component.W(i), row + 1) = input_state_sparse_chunks[1][0];
sparse_values[i] = input_state_sparse_chunks[1][0];
}
Expand Down Expand Up @@ -1804,57 +1788,6 @@ namespace nil {
assignment.witness(component.W(6), row + i) = ( ((1 << 14) - 1) & (integral_a2 >> 28) );
assignment.witness(component.W(7), row + i) = integral_a2;
}
/*std::vector<std::size_t> value_sizes = {14};
// lookup table for sparse values with base = 4
for (typename CurveType::scalar_field_type::integral_type i = 0;
i < typename CurveType::scalar_field_type::integral_type(16384);
i++) {
std::vector<bool> value(14);
for (std::size_t j = 0; j < 14; j++) {
value[14 - j - 1] = multiprecision::bit_test(i, j);
}
std::array<std::vector<uint64_t>, 2> value_chunks =
detail::split_and_sparse<BlueprintFieldType>(value, value_sizes,
plonk_sha256_process<BlueprintFieldType>::base4);
assignment.constant(0)[start_row_index + std::size_t(i)] = value_chunks[0][0];
assignment.constant(1)[start_row_index + std::size_t(i)] = value_chunks[1][0];
}
// lookup table for sparse values with base = 7
for (typename CurveType::scalar_field_type::integral_type i = 0;
i < typename CurveType::scalar_field_type::integral_type(16384);
i++) {
std::vector<bool> value(14);
for (std::size_t j = 0; j < 14; j++) {
value[14 - j - 1] = multiprecision::bit_test(i, j);
}
std::array<std::vector<uint64_t>, 2> value_chunks =
detail::split_and_sparse<BlueprintFieldType>(value, value_sizes,
plonk_sha256_process<BlueprintFieldType>::base7);
assignment.constant(2)[start_row_index + std::size_t(i)] = value_chunks[0][0];
assignment.constant(3)[start_row_index + std::size_t(i)] = value_chunks[1][0];
}
// lookup table for maj function
value_sizes = {8};
for (typename CurveType::scalar_field_type::integral_type i = 0;
i < typename CurveType::scalar_field_type::integral_type(65535);
i++) {
static std::array<std::vector<typename CurveType::scalar_field_type::integral_type>, 2>
value = detail::reversed_sparse_and_split<BlueprintFieldType>(i, value_sizes,
plonk_sha256_process<BlueprintFieldType>::base4);
assignment.constant(4)[start_row_index + std::size_t(i)] = value[0][0];
assignment.constant(5)[start_row_index + std::size_t(i)] = i;
}

// lookup table for ch function
for (typename CurveType::scalar_field_type::integral_type i = 0;
i < typename CurveType::scalar_field_type::integral_type(5765041);
i++) {
static std::array<std::vector<typename CurveType::scalar_field_type::integral_type>, 2>
value = detail::reversed_sparse_and_split<BlueprintFieldType>(i, value_sizes,
plonk_sha256_process<BlueprintFieldType>::base7);
assignment.constant(4)[start_row_index + std::size_t(i)] = value[0][0];
assignment.constant(5)[start_row_index + std::size_t(i)] = i;
}*/

return typename plonk_sha256_process<BlueprintFieldType>::result_type(
component, start_row_index);
Expand Down
15 changes: 8 additions & 7 deletions include/nil/blueprint/utils/connectedness_check.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ namespace nil {
const std::size_t end_row = start_row_index + rows_amount;

nil::blueprint::assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>> 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)
// from the ones which actually got checked.
for (std::size_t witness_column = 0; witness_column < row_size; witness_column++) {
for (std::size_t witness_column = 0; witness_column < assignment.witnesses_amount(); witness_column++) {
std::size_t last_row =
std::min<std::size_t>(end_row, assignment.witness_column_size(witness_column));
for (std::size_t row = start_row_index; row < last_row; row++) {
Expand All @@ -114,15 +114,16 @@ namespace nil {
const auto output_value =
zones.find_set(copy_var_address<BlueprintFieldType>(
row_size, start_row_index, rows_amount, variable)) + 1;
switch (variable.type) {
const auto &variable_ref = variable.get();
switch (variable_ref.type) {
case var::column_type::constant:
output_assignment.constant(variable.index, variable.rotation) = output_value;
output_assignment.constant(variable_ref.index, variable_ref.rotation) = output_value;
break;
case var::column_type::public_input:
output_assignment.public_input(variable.index, variable.rotation) = output_value;
output_assignment.public_input(variable_ref.index, variable_ref.rotation) = output_value;
break;
case var::column_type::witness:
output_assignment.witness(variable.index, variable.rotation) = output_value;
output_assignment.witness(variable_ref.index, variable_ref.rotation) = output_value;
break;
case var::column_type::selector:
BOOST_ASSERT_MSG(false, "Selector variables should not be input variables.");
Expand Down
2 changes: 1 addition & 1 deletion include/nil/blueprint/utils/satisfiability_check.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,4 @@ namespace nil {

} // namespace blueprint
} // namespace nil
#endif // CRYPTO3_BLUEPRINT_UTILS_PLONK_SATISFIABILITY_CHECK_HPP
#endif // CRYPTO3_BLUEPRINT_UTILS_PLONK_SATISFIABILITY_CHECK_HPP
79 changes: 40 additions & 39 deletions test/hashes/plonk/decomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ void test_decomposition(std::vector<typename BlueprintFieldType::value_type> pub

constexpr std::size_t WitnessColumns = 9;
constexpr std::size_t PublicInputColumns = 1;
constexpr std::size_t ConstantColumns = 0;
constexpr std::size_t SelectorColumns = 1;
constexpr std::size_t ConstantColumns = 8;
constexpr std::size_t SelectorColumns = 3;
using hash_type = crypto3::hashes::keccak_1600<256>;
constexpr std::size_t Lambda = 40;

Expand All @@ -75,65 +75,66 @@ void test_decomposition(std::vector<typename BlueprintFieldType::value_type> pub

auto result_check = [&expected_res](AssignmentType &assignment,
typename component_type::result_type &real_res) {
// for (std::size_t i = 0; i < real_res.output.size(); i++){
// std::cout << var_value(assignment, real_res.output[i]).data << std::endl;
// }
// for (std::size_t i = 0; i < expected_res.size(); i++){
// std::cout << expected_res[i].data << std::endl;
// }
for (std::size_t i = 0; i < real_res.output.size(); i++){
assert(expected_res[i] == var_value(assignment, real_res.output[i]));
}
};
auto result_check_to_fail = [&expected_res](AssignmentType &assignment,
typename component_type::result_type &real_res) { };
auto result_check_to_fail = [](AssignmentType &assignment,
typename component_type::result_type &real_res) {};

component_type component_instance({0, 1, 2, 3, 4, 5, 6, 7, 8},{},{});

if (expected_to_pass) {
crypto3::test_component<component_type, BlueprintFieldType, hash_type, Lambda>(
component_instance, desc, public_input, result_check, instance_input);
crypto3::test_empty_component<component_type, BlueprintFieldType, hash_type, Lambda>(
component_instance, desc, public_input, result_check, instance_input);
component_instance, desc, public_input, result_check, instance_input,
nil::blueprint::connectedness_check_type::type::WEAK);
} else {
crypto3::test_component_to_fail<component_type, BlueprintFieldType, hash_type, Lambda>(
component_instance, desc, public_input, result_check_to_fail, instance_input);
component_instance, desc, public_input, result_check_to_fail, instance_input,
nil::blueprint::connectedness_check_type::type::WEAK);
}
}

BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite)

template<typename FieldType>
std::vector<typename FieldType::value_type> calculate_decomposition(std::vector<typename FieldType::value_type> data_value) {
std::array<typename FieldType::integral_type, 2> data = {
typename FieldType::integral_type(data_value[0].data),
typename FieldType::integral_type(data_value[1].data)};
std::array<typename FieldType::integral_type, 16> range_chunks;
std::size_t shift = 0;

for (std::size_t i = 0; i < 8; i++) {
range_chunks[i] = (data[0] >> shift) & ((1 << 16) - 1);
range_chunks[i + 8] = (data[1] >> shift) & ((1 << 16) - 1);
shift += 16;
}

std::array<typename FieldType::integral_type, 8> output;

output[0] = range_chunks[7] * (1 << 16) + range_chunks[6];
output[1] = range_chunks[5] * (1 << 16) + range_chunks[4];
output[2] = range_chunks[3] * (1 << 16) + range_chunks[2];
output[3] = range_chunks[1] * (1 << 16) + range_chunks[0];
output[4] = range_chunks[15] * (1 << 16) + range_chunks[14];
output[5] = range_chunks[13] * (1 << 16) + range_chunks[12];
output[6] = range_chunks[11] * (1 << 16) + range_chunks[10];
output[7] = range_chunks[9] * (1 << 16) + range_chunks[8];

std::vector<typename FieldType::value_type> output_value;

for (std::size_t i = 0; i < output.size(); i++){
output_value.push_back(typename FieldType::value_type(output[i]));
}

return output_value;
std::vector<typename FieldType::value_type> calculate_decomposition(
const std::vector<typename FieldType::value_type> &data_value) {

std::array<typename FieldType::integral_type, 2> data = {
typename FieldType::integral_type(data_value[0].data),
typename FieldType::integral_type(data_value[1].data)};
std::size_t shift = 0;
std::array<typename FieldType::integral_type, 8> output;
const typename FieldType::integral_type one = 1;

for (std::size_t i = 0; i < 4; i++, shift += 32) {
output[i + 4] = (data[0] >> shift) & ((one << 32) - 1);
output[i] = (data[1] >> shift) & ((one << 32) - 1);
}

std::vector<typename FieldType::value_type> output_value(output.size());

for (std::size_t i = 0; i < output.size(); i++){
output_value[output.size() - 1 - i] = typename FieldType::value_type(output[i]);
}
return output_value;
}

BOOST_AUTO_TEST_CASE(blueprint_plonk_decomposition_test0) {
using field_type = typename crypto3::algebra::curves::pallas::base_field_type;

test_decomposition<field_type>(
{0x1_cppui255, 0x2_cppui255},
calculate_decomposition<field_type>({0x1_cppui255, 0x2_cppui255}),
true);

test_decomposition<field_type>(
{0x8d741211e928fdd4d33a13970d0ce7f3_cppui255, 0x92f209334030f9ec8fa8a025e987a5dd_cppui255},
calculate_decomposition<field_type>({0x8d741211e928fdd4d33a13970d0ce7f3_cppui255, 0x92f209334030f9ec8fa8a025e987a5dd_cppui255}),
Expand Down
2 changes: 1 addition & 1 deletion test/hashes/plonk/sha256_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_sha256_process) {
constexpr std::size_t WitnessColumns = 9;
constexpr std::size_t PublicInputColumns = 1;
constexpr std::size_t ConstantColumns = 33;
constexpr std::size_t SelectorColumns = 50;
constexpr std::size_t SelectorColumns = 30;
using hash_type = nil::crypto3::hashes::keccak_1600<256>;
constexpr std::size_t Lambda = 1;

Expand Down
Loading