diff --git a/crypto3/libs/hash/example/CMakeLists.txt b/crypto3/libs/hash/example/CMakeLists.txt index c5a317cf18..57df5a7b1e 100644 --- a/crypto3/libs/hash/example/CMakeLists.txt +++ b/crypto3/libs/hash/example/CMakeLists.txt @@ -4,21 +4,21 @@ # http://www.boost.org/LICENSE_1_0.txt #---------------------------------------------------------------------------# -macro(define_algebra_example name) - add_executable(algebra_${name}_example ${name}.cpp) - target_link_libraries(algebra_${name}_example PRIVATE +macro(define_hash_example name) + add_executable(hash_${name}_example ${name}.cpp) + target_link_libraries(hash_${name}_example PRIVATE ${CMAKE_WORKSPACE_NAME}_hash crypto3::multiprecision Boost::random ) - set_target_properties(algebra_${name}_example PROPERTIES CXX_STANDARD 20) + set_target_properties(hash_${name}_example PROPERTIES CXX_STANDARD 20) endmacro() set(EXAMPLES_NAMES "hashes") foreach(EXAMPLE_NAME ${EXAMPLES_NAMES}) - define_algebra_example(${EXAMPLE_NAME}) + define_hash_example(${EXAMPLE_NAME}) endforeach() diff --git a/crypto3/libs/hash/example/hashes.cpp b/crypto3/libs/hash/example/hashes.cpp index 0b498e2765..3fd0f4432a 100644 --- a/crypto3/libs/hash/example/hashes.cpp +++ b/crypto3/libs/hash/example/hashes.cpp @@ -34,6 +34,10 @@ #include #include +#include +#include +#include "nil/crypto3/algebra/fields/pallas/scalar_field.hpp" + using namespace nil::crypto3::hashes; template @@ -64,9 +68,60 @@ struct hash_usage_example(field_input); std::cout << result << std::endl; + } }; +template +struct poseidon_bytes_vector_example +{ + static void run() + { + using policy = typename hash_type::policy_type; + using field_type = typename policy::field_type; + std::string input = + "Once upon a midnight dreary, while I pondered, weak and weary,\n" + "Over many a quaint and curious volume of forgotten lore—\n" + "While I nodded, nearly napping, suddenly there came a tapping,\n" + "As of some one gently rapping, rapping at my chamber door.\n" + "“’Tis some visitor,” I muttered, “tapping at my chamber door—\n" + " Only this and nothing more.”\n"; + + std::vector hash_input(input.begin(), input.end()); + + typename policy::digest_type result = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input)> + (hash_input) + ); + std::cout << result << std::endl; + } +}; + +template +struct poseidon_int_vector_example +{ + static void run() + { + using policy = typename hash_type::policy_type; + using field_type = typename policy::field_type; + + std::vector hash_input { + 0xDEAD, 0xC001CAFE + }; + + typename policy::digest_type result = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input)> + (hash_input) + ); + std::cout << result << std::endl; + } +}; + + int main() { std::cout << "SHA2-256" << std::endl; @@ -86,8 +141,9 @@ int main() { using policy = detail::poseidon_policy; using hash_type = poseidon; - hash_usage_example::run(); + poseidon_bytes_vector_example::run(); + poseidon_int_vector_example::run(); return 0; } diff --git a/crypto3/libs/hash/include/nil/crypto3/hash/block_to_field_elements_wrapper.hpp b/crypto3/libs/hash/include/nil/crypto3/hash/block_to_field_elements_wrapper.hpp index aa10d2a5ed..222a0fa28b 100644 --- a/crypto3/libs/hash/include/nil/crypto3/hash/block_to_field_elements_wrapper.hpp +++ b/crypto3/libs/hash/include/nil/crypto3/hash/block_to_field_elements_wrapper.hpp @@ -33,7 +33,7 @@ namespace nil { namespace crypto3 { namespace hashes { - template + template class block_to_field_elements_wrapper { public: static_assert(std::numeric_limits::is_specialized); @@ -106,12 +106,19 @@ namespace nil { field_element_.data = field_element_.data.base() << input_value_bits_; field_element_ += uint64_t(*tmp_iter++); } + if (tmp_iter == input_container_r_ && Padding) { + std::size_t element_size = sizeof(typename std::iterator_traits::value_type); + std::size_t bits_filled = 8 * element_size * std::distance(input_container_l_, tmp_iter); + /* This always adds 1 to higher bits without overflow as field element + * is filled with one byte less than a modulus width. */ + field_element_ += typename value_type::integral_type(1) << (bits_filled); + } element_filled_ = true; } void advance_container_iter() { for (std::size_t i = 0; i < container_elements_per_field_element_ && input_container_l_ != input_container_r_; ++i) { - input_container_l_++; + ++input_container_l_; } element_filled_ = false; } @@ -140,18 +147,19 @@ namespace nil { typename Container::const_iterator input_container_end_; }; - template::value> + template::value> struct conditional_block_to_field_elements_wrapper_helper { using type = Container; }; - template - struct conditional_block_to_field_elements_wrapper_helper { - using type = block_to_field_elements_wrapper; + template + struct conditional_block_to_field_elements_wrapper_helper { + using type = block_to_field_elements_wrapper; }; - template - using conditional_block_to_field_elements_wrapper = typename conditional_block_to_field_elements_wrapper_helper::type; + template + using conditional_block_to_field_elements_wrapper = + typename conditional_block_to_field_elements_wrapper_helper::type; } // namespace hashes diff --git a/crypto3/libs/hash/test/poseidon.cpp b/crypto3/libs/hash/test/poseidon.cpp index b475ed8294..45fd7c35a0 100644 --- a/crypto3/libs/hash/test/poseidon.cpp +++ b/crypto3/libs/hash/test/poseidon.cpp @@ -7,6 +7,8 @@ // http://www.boost.org/LICENSE_1_0.txt //---------------------------------------------------------------------------// +#include "nil/crypto3/algebra/fields/pallas/scalar_field.hpp" +#include "nil/crypto3/hash/detail/poseidon/poseidon_policy.hpp" #define BOOST_TEST_MODULE poseidon_test #include @@ -99,6 +101,77 @@ void test_poseidon_permutation( } BOOST_AUTO_TEST_SUITE(poseidon_tests) + +BOOST_AUTO_TEST_CASE(poseidon_with_padding_test) { + using field_type = fields::pallas_scalar_field; + using policy = pasta_poseidon_policy; + using hash_type = hashes::poseidon; + + std::vector hash_input1 { + 0x00, 0x01, 0x02 + }; + std::vector hash_input2 { + 0x01, 0x02 + }; + + /* Default behavior: input bytes converted into field elements and padded + * with lowest bit in the next higher block: + * 0x0000000000000000000000000000000000000000000000000000000001000102 + * and + * 0x0000000000000000000000000000000000000000000000000000000000010102 + */ + typename policy::digest_type result1 = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input1)> + (hash_input1) + ); + + typename policy::digest_type result2 = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input2)> + (hash_input2) + ); + + /* Results should not be equal */ + BOOST_CHECK_NE(result1, result2); +} + +BOOST_AUTO_TEST_CASE(poseidon_without_padding_test) { + using field_type = fields::pallas_scalar_field; + using policy = pasta_poseidon_policy; + using hash_type = hashes::poseidon; + + std::vector hash_input1 { + 0x00, 0x01, 0x02 + }; + std::vector hash_input2 { + 0x01, 0x02 + }; + + /* Explicit non-padding behavior: input bytes converted into field elements + * without padding, both inputs produce same element: + * 0x0000000000000000000000000000000000000000000000000000000000000102 + */ + typename policy::digest_type result1 = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input1), true, false /* padding */> + (hash_input1) + ); + + typename policy::digest_type result2 = nil::crypto3::hash( + nil::crypto3::hashes::conditional_block_to_field_elements_wrapper< + typename hash_type::word_type, + decltype(hash_input2), true, false /* padding */> + (hash_input2) + ); + + /* Results should be equal */ + BOOST_CHECK_EQUAL(result1, result2); +} + // Test data for Mina version was taken from https://github.com/o1-labs/proof-systems/blob/a36c088b3e81d17f5720abfff82a49cf9cb1ad5b/poseidon/src/tests/test_vectors/kimchi.json. // For some reason bytes in their test data are in Big Endian, while we need in Small Endian, I.E. you need to reverse the order of bytes to create our test data. @@ -269,13 +342,13 @@ BOOST_AUTO_TEST_SUITE(poseidon_tests) 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, // 256 bits up to this place, the last value should be moved to - // the next field element. + // the next field element and padded with one bit in the next byte. }; std::vector field_input = { 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD_big_uint255, - 0x00000000000000000000000000000000000000000000000000000000000000EF_big_uint255, + 0x00000000000000000000000000000000000000000000000000000000000001EF_big_uint255, }; typename policy::digest_type d_uint8 = hash( diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp index fbe87f708e..81cc8b9cf4 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp @@ -558,7 +558,6 @@ namespace nil { return result; } - // TODO: columns_with_copy_constraints -- It should be extracted from constraint_system static inline preprocessed_data_type process( const plonk_constraint_system &constraint_system, std::shared_ptr public_assignment, diff --git a/crypto3/libs/zk/test/transcript/transcript.cpp b/crypto3/libs/zk/test/transcript/transcript.cpp index 5ba4d986f9..b40e9417ec 100644 --- a/crypto3/libs/zk/test/transcript/transcript.cpp +++ b/crypto3/libs/zk/test/transcript/transcript.cpp @@ -49,7 +49,6 @@ #include #include - using namespace nil::crypto3; using namespace nil::crypto3::zk; @@ -90,9 +89,9 @@ BOOST_AUTO_TEST_CASE(zk_poseidon_transcript_init_test) { auto ch2 = tr.challenge(); int ch_int = tr.int_challenge(); - BOOST_CHECK_EQUAL(ch1.data, field_type::value_type(0x27B1BE8A820DE1A5E91A441F59F29D42D9DB9FC7778A0852819F331D5CD60B43_big_uint255).data); - BOOST_CHECK_EQUAL(ch2.data, field_type::value_type(0x12096E03B2ADEC9B317042D36F048C06AF123EED4A3FC040579E66DCE46C0AEE_big_uint255).data); - BOOST_CHECK_EQUAL(ch_int, 0x6296); + BOOST_CHECK_EQUAL(ch1.data, field_type::value_type(0x2c8488fd580563511086c59020975e49afd065fd26c451f6c1f9c5213798c928_big_uint255).data); + BOOST_CHECK_EQUAL(ch2.data, field_type::value_type(0x285f5407fb2f26a10fdcdc9357ecdc2b1415dc67b082f7c18964022bcb644ca7_big_uint255).data); + BOOST_CHECK_EQUAL(ch_int, 0x48f3); init_blob = {}; tr = transcript::fiat_shamir_heuristic_sequential(init_blob); diff --git a/parallel-crypto3/libs/parallel-containers/example/CMakeLists.txt b/parallel-crypto3/libs/parallel-containers/example/CMakeLists.txt index 1c949653b1..733b958c75 100644 --- a/parallel-crypto3/libs/parallel-containers/example/CMakeLists.txt +++ b/parallel-crypto3/libs/parallel-containers/example/CMakeLists.txt @@ -34,8 +34,8 @@ macro(define_containers_example example) add_executable(${target_name} ${example}.cpp) target_link_libraries(${target_name} PRIVATE - ${CMAKE_WORKSPACE_NAME}::algebra - ${CMAKE_WORKSPACE_NAME}::hash) + crypto3::algebra + crypto3::hash) set_target_properties(${target_name} PROPERTIES CXX_STANDARD 20) endmacro() diff --git a/parallel-crypto3/libs/parallel-zk/test/transcript/transcript.cpp b/parallel-crypto3/libs/parallel-zk/test/transcript/transcript.cpp index 41a0817216..b40e9417ec 100644 --- a/parallel-crypto3/libs/parallel-zk/test/transcript/transcript.cpp +++ b/parallel-crypto3/libs/parallel-zk/test/transcript/transcript.cpp @@ -45,9 +45,9 @@ #include +#include #include #include -#include using namespace nil::crypto3; using namespace nil::crypto3::zk; @@ -89,9 +89,9 @@ BOOST_AUTO_TEST_CASE(zk_poseidon_transcript_init_test) { auto ch2 = tr.challenge(); int ch_int = tr.int_challenge(); - BOOST_CHECK_EQUAL(ch1.data, field_type::value_type(0x27B1BE8A820DE1A5E91A441F59F29D42D9DB9FC7778A0852819F331D5CD60B43_big_uint255).data); - BOOST_CHECK_EQUAL(ch2.data, field_type::value_type(0x12096E03B2ADEC9B317042D36F048C06AF123EED4A3FC040579E66DCE46C0AEE_big_uint255).data); - BOOST_CHECK_EQUAL(ch_int, 0x6296); + BOOST_CHECK_EQUAL(ch1.data, field_type::value_type(0x2c8488fd580563511086c59020975e49afd065fd26c451f6c1f9c5213798c928_big_uint255).data); + BOOST_CHECK_EQUAL(ch2.data, field_type::value_type(0x285f5407fb2f26a10fdcdc9357ecdc2b1415dc67b082f7c18964022bcb644ca7_big_uint255).data); + BOOST_CHECK_EQUAL(ch_int, 0x48f3); init_blob = {}; tr = transcript::fiat_shamir_heuristic_sequential(init_blob);