Skip to content

Commit

Permalink
Implemented padding at the stage of block_to_field_wrapper
Browse files Browse the repository at this point in the history
Added example with non-byte input to poseidon

fix transcript test

Fix parallel version
  • Loading branch information
vo-nil committed Jan 21, 2025
1 parent 9384dab commit b222c43
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 27 deletions.
10 changes: 5 additions & 5 deletions crypto3/libs/hash/example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
58 changes: 57 additions & 1 deletion crypto3/libs/hash/example/hashes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#include <nil/crypto3/algebra/fields/bls12/scalar_field.hpp>
#include <type_traits>

#include <nil/crypto3/hash/detail/poseidon/poseidon_policy.hpp>
#include <nil/crypto3/hash/block_to_field_elements_wrapper.hpp>
#include "nil/crypto3/algebra/fields/pallas/scalar_field.hpp"

using namespace nil::crypto3::hashes;

template<typename hash_type, typename enable = void>
Expand Down Expand Up @@ -64,9 +68,60 @@ struct hash_usage_example<hash_type, typename std::enable_if<is_poseidon<hash_ty

typename policy::digest_type result = nil::crypto3::hash<hash_type>(field_input);
std::cout << result << std::endl;

}
};

template<typename hash_type>
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<uint8_t> hash_input(input.begin(), input.end());

typename policy::digest_type result = nil::crypto3::hash<hash_type>(
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<typename hash_type>
struct poseidon_int_vector_example
{
static void run()
{
using policy = typename hash_type::policy_type;
using field_type = typename policy::field_type;

std::vector<uint32_t> hash_input {
0xDEAD, 0xC001CAFE
};

typename policy::digest_type result = nil::crypto3::hash<hash_type>(
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;
Expand All @@ -86,8 +141,9 @@ int main() {
using policy = detail::poseidon_policy<field_type, security_bits, rate>;
using hash_type = poseidon<policy>;


hash_usage_example<hash_type>::run();
poseidon_bytes_vector_example<hash_type>::run();
poseidon_int_vector_example<hash_type>::run();

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace nil {
namespace crypto3 {
namespace hashes {

template<typename Field, typename Container, bool OverflowOnPurpose = false>
template<typename Field, typename Container, bool OverflowOnPurpose = false, bool Padding = true>
class block_to_field_elements_wrapper {
public:
static_assert(std::numeric_limits<typename Container::value_type>::is_specialized);
Expand Down Expand Up @@ -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<decltype(input_container_l_)>::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;
}
Expand Down Expand Up @@ -140,18 +147,19 @@ namespace nil {
typename Container::const_iterator input_container_end_;
};

template<typename Output, typename Container, bool OverflowOnPurpose, bool = algebra::is_field_element<Output>::value>
template<typename Output, typename Container, bool OverflowOnPurpose, bool Padding = true, bool = algebra::is_field_element<Output>::value>
struct conditional_block_to_field_elements_wrapper_helper {
using type = Container;
};

template<typename Output, typename Container, bool OverflowOnPurpose>
struct conditional_block_to_field_elements_wrapper_helper<Output, Container, OverflowOnPurpose, true> {
using type = block_to_field_elements_wrapper<typename Output::field_type, Container, OverflowOnPurpose>;
template<typename Output, typename Container, bool OverflowOnPurpose, bool Padding>
struct conditional_block_to_field_elements_wrapper_helper<Output, Container, OverflowOnPurpose, Padding, true> {
using type = block_to_field_elements_wrapper<typename Output::field_type, Container, OverflowOnPurpose, Padding>;
};

template<typename Output, typename Container, bool OverflowOnPurpose = false>
using conditional_block_to_field_elements_wrapper = typename conditional_block_to_field_elements_wrapper_helper<Output, Container, OverflowOnPurpose>::type;
template<typename Output, typename Container, bool OverflowOnPurpose = false, bool Padding = true>
using conditional_block_to_field_elements_wrapper =
typename conditional_block_to_field_elements_wrapper_helper<Output, Container, OverflowOnPurpose, Padding>::type;


} // namespace hashes
Expand Down
65 changes: 63 additions & 2 deletions crypto3/libs/hash/test/poseidon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <iostream>
Expand Down Expand Up @@ -99,6 +101,65 @@ 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<field_type>;
using hash_type = hashes::poseidon<policy>;

std::vector<uint8_t> hash_input1 {
0x00, 0x01, 0x02
};
std::vector<uint8_t> hash_input2 {
0x01, 0x02
};

typename policy::digest_type result1 = nil::crypto3::hash<hash_type>(
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<hash_type>(
nil::crypto3::hashes::conditional_block_to_field_elements_wrapper<
typename hash_type::word_type,
decltype(hash_input2)>
(hash_input2)
);

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<field_type>;
using hash_type = hashes::poseidon<policy>;

std::vector<uint8_t> hash_input1 {
0x00, 0x01, 0x02
};
std::vector<uint8_t> hash_input2 {
0x01, 0x02
};

typename policy::digest_type result1 = nil::crypto3::hash<hash_type>(
nil::crypto3::hashes::conditional_block_to_field_elements_wrapper<
typename hash_type::word_type,
decltype(hash_input1), true, false>
(hash_input1)
);

typename policy::digest_type result2 = nil::crypto3::hash<hash_type>(
nil::crypto3::hashes::conditional_block_to_field_elements_wrapper<
typename hash_type::word_type,
decltype(hash_input2), true, false>
(hash_input2)
);

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.
Expand Down Expand Up @@ -269,13 +330,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<typename field_type::value_type> field_input = {
0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD_big_uint255,
0x00000000000000000000000000000000000000000000000000000000000000EF_big_uint255,
0x00000000000000000000000000000000000000000000000000000000000001EF_big_uint255,
};

typename policy::digest_type d_uint8 = hash<hash_t>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<FieldType> &constraint_system,
std::shared_ptr<public_assignment_type> public_assignment,
Expand Down
7 changes: 3 additions & 4 deletions crypto3/libs/zk/test/transcript/transcript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
#include <nil/crypto3/marshalling/algebra/processing/mnt4.hpp>
#include <nil/crypto3/marshalling/algebra/processing/mnt6.hpp>


using namespace nil::crypto3;
using namespace nil::crypto3::zk;

Expand Down Expand Up @@ -90,9 +89,9 @@ BOOST_AUTO_TEST_CASE(zk_poseidon_transcript_init_test) {
auto ch2 = tr.challenge<field_type>();
int ch_int = tr.int_challenge<int>();

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<poseidon_type>(init_blob);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@

#include <nil/crypto3/zk/transcript/fiat_shamir.hpp>

#include <nil/crypto3/marshalling/algebra/processing/bls12.hpp>
#include <nil/crypto3/marshalling/algebra/processing/mnt4.hpp>
#include <nil/crypto3/marshalling/algebra/processing/mnt6.hpp>
#include <nil/crypto3/marshalling/algebra/processing/bls12.hpp>

using namespace nil::crypto3;
using namespace nil::crypto3::zk;
Expand Down Expand Up @@ -89,9 +89,9 @@ BOOST_AUTO_TEST_CASE(zk_poseidon_transcript_init_test) {
auto ch2 = tr.challenge<field_type>();
int ch_int = tr.int_challenge<int>();

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<poseidon_type>(init_blob);
Expand Down

0 comments on commit b222c43

Please sign in to comment.