From e1c732de44349c730ffad0449f6c5d30be0d3da3 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Fri, 27 Oct 2023 11:53:18 +0000 Subject: [PATCH 01/34] initial commit --- .../src/barretenberg/crypto/CMakeLists.txt | 1 + .../crypto/poseidon2/CMakeLists.txt | 1 + .../crypto/poseidon2/poseidon2.hpp | 140 ++++++ .../crypto/poseidon2/poseidon2.test.cpp | 32 ++ .../poseidon2/poseidon2_derive_params.hpp | 106 +++++ .../poseidon2_derive_params.test.cpp | 39 ++ .../crypto/poseidon2/poseidon2_params.hpp | 409 ++++++++++++++++++ .../ecc/fields/field_declarations.hpp | 12 + .../barretenberg/numeric/uint256/uint256.hpp | 44 +- .../numeric/uint256/uint256.test.cpp | 23 + 10 files changed, 802 insertions(+), 5 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp diff --git a/barretenberg/cpp/src/barretenberg/crypto/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/crypto/CMakeLists.txt index 87b519ba153..6efc1f82407 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/crypto/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(schnorr) add_subdirectory(sha256) add_subdirectory(ecdsa) add_subdirectory(aes128) +add_subdirectory(poseidon2) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt new file mode 100644 index 00000000000..f79d04fa8dc --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(crypto_poseidon2 crypto_blake3s ecc numeric) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp new file mode 100644 index 00000000000..5c5850125eb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp @@ -0,0 +1,140 @@ +#pragma once + +#include "poseidon2_params.hpp" + +#include "barretenberg/common/throw_or_abort.hpp" + +#include +#include +#include +#include + +namespace crypto { + +template class Poseidon2 { + public: + // todo make parameters configurable? + static constexpr size_t t = Params::t; + static constexpr size_t d = Params::d; + static constexpr size_t sbox_size = Params::sbox_size; // logp + static constexpr size_t rounds_f = Params::rounds_f; + static constexpr size_t rounds_p = Params::rounds_p; + static constexpr size_t NUM_ROUNDS = Params::rounds_f + Params::rounds_p; + + using FF = typename Params::FF; + using State = std::vector; + using RoundConstants = std::array; + using MatrixDiagonal = std::array; + using RoundConstantsContainer = std::array; + + static constexpr MatrixDiagonal internal_matrix_diagonal = + Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; + static constexpr RoundConstantsContainer round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; + // derive_round_constants(); + + static void matrix_multiplication_4x4(State& input) + { + /** + * hardcoded algorithm that evaluates matrix multiplication using the following MDS matrix: + * / \ + * | 5 7 1 3 | + * | 4 6 1 1 | + * | 1 3 5 7 | + * | 1 1 4 6 | + * \ / + */ + + auto t0 = input[0] + input[1]; // A + B + auto t1 = input[2] + input[3]; // C + D + auto t2 = input[1] + input[1]; // 2B + t2 += t1; // 2B + C + D + auto t3 = input[3] + input[3]; // 2C + t3 += t0; // 2C + A + B + auto t4 = t1 + t1; + t4 += t4; + t4 += t3; // 4D + 6C + A + B + auto t5 = t0 + t0; + t5 += t5; + t5 += t3; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 7C + 5D + auto t7 = t2 + t4; // A + 3B + 5D + 7C + input[0] = t6; + input[1] = t5; + input[2] = t7; + input[3] = t4; + } + + static void add_round_constants(State& input, const RoundConstants& rc) + { + for (size_t i = 0; i < t; ++i) { + input[i] += rc[i]; + } + } + + static void matrix_multiplication_internal(State& input) + { + // for t = 4 + auto sum = input[0]; + for (size_t i = 1; i < t; ++i) { + sum += input[i]; + } + for (size_t i = 0; i < t; ++i) { + input[i] *= internal_matrix_diagonal[i]; + input[i] += sum; + } + } + + static void matrix_multiplication_external(State& input) + { + if constexpr (t == 4) { + matrix_multiplication_4x4(input); + } else { + // erm panic + throw_or_abort("not supported"); + } + } + + static void apply_single_sbox(FF& input) + { + auto xx = input.sqr(); + auto xxxx = xx.sqr(); + input *= xxxx; + } + + static void apply_sbox(State& input) + { + for (auto& in : input) { + apply_single_sbox(in); + } + } + + static State permutation(State& input) + { + // deep copy + State current_state(input); + + // Apply 1st linear layer + matrix_multiplication_external(current_state); + + for (size_t i = 0; i < rounds_f; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(current_state); + } + + const size_t p_end = rounds_f + rounds_p; + for (size_t i = rounds_f; i < p_end; ++i) { + current_state[0] += round_constants[i][0]; + apply_single_sbox(current_state[0]); + matrix_multiplication_internal(current_state); + } + + for (size_t i = p_end; i < NUM_ROUNDS; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(current_state); + } + return current_state; + } +}; +} // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp new file mode 100644 index 00000000000..d4df515a546 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -0,0 +1,32 @@ +#include "poseidon2.hpp" +#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include + +using namespace barretenberg; + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +namespace poseidon2_tests { +TEST(Poseidon2, BasicTests) +{ + + barretenberg::fr a = barretenberg::fr::random_element(&engine); + barretenberg::fr b = barretenberg::fr::random_element(&engine); + barretenberg::fr c = barretenberg::fr::random_element(&engine); + barretenberg::fr d = barretenberg::fr::random_element(&engine); + + std::vector input1{ a, b, c, d }; + std::vector input2{ d, c, b, a }; + + auto r0 = crypto::Poseidon2::permutation(input1); + auto r1 = crypto::Poseidon2::permutation(input1); + auto r2 = crypto::Poseidon2::permutation(input2); + + EXPECT_EQ(r0, r1); + EXPECT_NE(r0, r2); +} + +} // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp new file mode 100644 index 00000000000..e87fa7cf89c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/crypto/blake3s/blake3s.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/numeric/uintx/uintx.hpp" + +#include +#include +#include +#include +#include + +namespace crypto { + +template +class Poseidon2DeriveParams { + public: + static constexpr size_t NUM_ROUNDS = rounds_f + rounds_p; + static constexpr size_t BLAKE3S_OUTPUT_SIZE = 32; + + using RoundConstants = std::array; + using MatrixDiagonal = std::array; + using RoundConstantsContainer = std::array; + + static FF hash_to_field_element(uint8_t* buffer, size_t buffer_size) + { + buffer[buffer_size - 1] = 0; + const auto hash_hi = blake3::blake3s_constexpr(buffer, buffer_size); + buffer[buffer_size - 1] = 1; + const auto hash_lo = blake3::blake3s_constexpr(buffer, buffer_size); + // custom serialize methods as common/serialize.hpp is not constexpr! + const auto read_uint256 = [](const uint8_t* in) { + const auto read_limb = [](const uint8_t* in, uint64_t& out) { + for (size_t i = 0; i < 8; ++i) { + out += static_cast(in[i]) << ((7 - i) * 8); + } + }; + uint256_t out = 0; + read_limb(&in[0], out.data[3]); + read_limb(&in[8], out.data[2]); + read_limb(&in[16], out.data[1]); + read_limb(&in[24], out.data[0]); + return out; + }; + // interpret 64 byte hash output as a uint512_t, reduce to Fq element + //(512 bits of entropy ensures result is not biased as 512 >> Fq::modulus.get_msb()) + return FF(uint512_t(read_uint256(&hash_lo[0]), read_uint256(&hash_hi[0]))); + } + + // n.b. this can be made constexpr but it will nuke compile times as compiler will evaluate this method call at + // compile time + static MatrixDiagonal generate_internal_matrix_diagonal() + { + // TODO: validate the values produced by this method are secure. See https://eprint.iacr.org/2023/323 + std::string seed = "Poseidon2 Internal Matrix Parameters"; + std::vector seed_bytes(seed.begin(), seed.end()); + auto seed_hash = blake3::blake3s_constexpr(&seed_bytes[0], seed_bytes.size()); + + std::array m_preimage; + m_preimage[BLAKE3S_OUTPUT_SIZE] = 0; + m_preimage[BLAKE3S_OUTPUT_SIZE + 1] = 0; + std::copy(seed_hash.begin(), seed_hash.end(), m_preimage.begin()); + + uint8_t count = 0; + MatrixDiagonal res; + for (size_t i = 0; i < t; ++i) { + m_preimage[BLAKE3S_OUTPUT_SIZE] = count++; + res[i] = hash_to_field_element(&seed_hash[0], 32); + } + return res; + } + + // n.b. this can be made constexpr but it will nuke compile times as compiler will evaluate this method call at + // compile time + static RoundConstantsContainer derive_round_constants() + { + std::string seed = "Gentlemen, a short view back to the past."; + std::vector seed_bytes(seed.begin(), seed.end()); + auto seed_hash = blake3::blake3s_constexpr(&seed_bytes[0], seed_bytes.size()); + constexpr size_t NUM_METADATA_BYTES = 7; + constexpr size_t PREIMAGE_SIZE = BLAKE3S_OUTPUT_SIZE + NUM_METADATA_BYTES; + + std::array rc_preimage; + std::copy(seed_hash.begin(), seed_hash.end(), rc_preimage.begin()); + + uint8_t rc_count = 0; + rc_preimage[BLAKE3S_OUTPUT_SIZE] = static_cast(t); + rc_preimage[BLAKE3S_OUTPUT_SIZE + 1] = static_cast(d); + rc_preimage[BLAKE3S_OUTPUT_SIZE + 2] = static_cast(rounds_f); + rc_preimage[BLAKE3S_OUTPUT_SIZE + 3] = static_cast(rounds_p); + rc_preimage[BLAKE3S_OUTPUT_SIZE + 4] = static_cast(sbox_size); + rc_preimage[BLAKE3S_OUTPUT_SIZE + 5] = rc_count; + rc_preimage[BLAKE3S_OUTPUT_SIZE + 6] = 0; + + RoundConstantsContainer round_constants; + for (size_t i = 0; i < NUM_ROUNDS; ++i) { + for (size_t j = 0; j < t; ++j) { + rc_preimage[BLAKE3S_OUTPUT_SIZE + 5] = rc_count++; + round_constants[i][j] = hash_to_field_element(&rc_preimage[0], PREIMAGE_SIZE); + } + } + return round_constants; + } +}; +} // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp new file mode 100644 index 00000000000..c85466985a9 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp @@ -0,0 +1,39 @@ +#include "poseidon2_derive_params.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "poseidon2_params.hpp" +#include + +using namespace barretenberg; +using namespace crypto; +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +namespace poseidon2_tests { +TEST(Poseidon2DeriveParams, ConsistencyCheckRoundConstants) +{ + auto generated_round_constants = + Poseidon2DeriveParams::derive_round_constants(); + auto expected_round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; + EXPECT_EQ(generated_round_constants, expected_round_constants); +} + +TEST(Poseidon2DeriveParams, ConsistencyCheckMatrixDiagonal) +{ + auto generated_internal_matrix_diagonal = + Poseidon2DeriveParams::generate_internal_matrix_diagonal(); + auto expected_internal_matrix_diagonal = Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; + EXPECT_EQ(generated_internal_matrix_diagonal, expected_internal_matrix_diagonal); +} + +} // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp new file mode 100644 index 00000000000..54f3a6a65ff --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp @@ -0,0 +1,409 @@ +#pragma once + +#include "barretenberg/ecc/curves/bn254/fr.hpp" + +namespace crypto { + +struct Poseidon2Bn254ScalarFieldParams { + using FF = barretenberg::fr; + static constexpr size_t t = 4; + static constexpr size_t d = 5; + static constexpr size_t rounds_f = 8; + static constexpr size_t rounds_p = 56; + static constexpr size_t sbox_size = 254; + + static constexpr std::array, rounds_f + rounds_p> round_constants{ + std::array{ + FF(std::string("0x15eea6dca2b448bd09150227f045553c94d4cd0502e0c5a24c588fe3e311fa67")), + FF(std::string("0x279df1af44823fa78173f97a9b3cdcc444c41f7a5fd25dac8252ad283fa5ec3f")), + FF(std::string("0x2e4aba940b2e5e9d60f7b558e840165eabae3e016bb14218f64a866963d666b7")), + FF(std::string("0x04323d044f25a2b19578b980d6c1589d639545d1dabc36ae965a70740a9c0857")), + }, + { + FF(std::string("0x1ad0d155c36e0233329934e15ac3d6467c3b05acbca17a1836cbfc7f0d660915")), + FF(std::string("0x07ec817c89206c5c4301973c5be04fe7b4c249859151779166d0a6bc4995d6e7")), + FF(std::string("0x0f7ffe28dc5258f8aa627156d9ce39467c740552d87e4b0e4cc696a3cf53cf36")), + FF(std::string("0x0a8ea6ce4988c432f594582361129f2c62dae142da5a057117b5fd6807257986")), + }, + { + FF(std::string("0x0308252835005ac66742d170cda29be20f224dd01e3a782c286414bc41d61218")), + FF(std::string("0x098e1a885f6b8d5fa1c4987ca12faa12e96408af06ec133342e7fb15914148dd")), + FF(std::string("0x220826e11ca209dbf03b948986a1e2767b6036473cfde7efd99e21f5ffc77dde")), + FF(std::string("0x15ab8985ee003841a897509e2baffa614ed80b401ade01c1c78e7d4ad41607de")), + }, + { + FF(std::string("0x064980ea9c8b32817c459209486d8b2533e29f53808161e7a650583da1690acc")), + FF(std::string("0x10c54b290c4040afa6454fb560ca3862c5535be8bc5da1c6a5be5344a03942c9")), + FF(std::string("0x2469f804e2a02b122d43c314d4fc1a1dd7bee08276da9138e705076583b90247")), + FF(std::string("0x19c3f8198fe7535dac3a2ea383aaffa39ddf30da0e1582bbcb07577475d2c0da")), + }, + { + FF(std::string("0x226caac408b4335f4ba9e927ea0127ab68fe0e0f0e9012609c4337ebcc63604b")), + FF(std::string("0x302d6600e481480955e13ad506ed7fe098f517bc5ee63b32c5bedad64cec9d78")), + FF(std::string("0x149754646e22efa13cfb34e1cfcf396bd3f91611a7d03edd1993098ebbcde8e0")), + FF(std::string("0x06f85232ebbf79f827857c165d221c6c66ac421e9b99274a174c0f2ff194432c")), + }, + { + FF(std::string("0x108f75e9efe231ba6396e0ee8c22472d3f71da8380b4be01ec4cb4b32232eb57")), + FF(std::string("0x0aee1b1783ba93af99e248aec6c41f937fe003185d0bc962aae3b080d187661b")), + FF(std::string("0x0bf3de9ada3a61ee25af9f448e055874b651d168f1009e22bb200c1b4d35324b")), + FF(std::string("0x18496105620a6c599c467a80a4d6f76313b7f793dfaff480c6d3ef1e361d328c")), + }, + { + FF(std::string("0x2bf6d9d2749f31152b6df0ebe61751b53b434160b454b49778e8343267d7f6a1")), + FF(std::string("0x026dd15b91c1ca7d869045ae68815dae60c5e4544fd438b7ef0b90319c005884")), + FF(std::string("0x0821a99692cd0c110e511829f7d918ed8980ccaa3e799315e914ab153b6303eb")), + FF(std::string("0x25018d135e760d8e196c44e271e7f6f22f09bbbaf36025f7a7880f177fde04b9")), + }, + { + FF(std::string("0x0aa5c1f043f4fe98ec82d081fa9741f846f833f900d31111d259a14b16fab4f2")), + FF(std::string("0x2023ce7ccb396c4c6d4054691f04d36be27d66d01eef8d63bc5aad175b1bd967")), + FF(std::string("0x0534b260e284e2f9b1c3aed425db75d9e458dec84fb78178673d31d20644fc98")), + FF(std::string("0x001bf1f59f36fa68545aaba439a1bca8ea4724b2895e6fb29f6db064467f1cc6")), + }, + { + FF(std::string("0x1a69a7401bbd7a4822930ae713a664bfd0f5ead08553e353d2f4498b80149baa")), + FF(std::string("0x125c28a74dad02056ffabe14f3544db6673289e6a6bc4132a3b183fd2ccf6b7b")), + FF(std::string("0x0c36495973a2a18285cedeb79118adf4585a0151e4ea25e836ee5591fe44f332")), + FF(std::string("0x1a376c8f32df8d253552a268f5957d62bf3b63f701c0c2dbbdcb293cc4bf1ec1")), + }, + { + FF(std::string("0x2b53585a0bc0789078d58374c129ab35e80e65ff0b9ecd002f0996d03e941049")), + FF(std::string("0x143354f143b3622a185a65b3f8e210cb91300d2f9d187058db94db23aacc0a64")), + FF(std::string("0x220ed9f1201fa741566e86c9491af4c63648d806262088b73c980240b2630d5b")), + FF(std::string("0x01df34ca136c47a5a016a9c6a13984a2e1200b047d8c345b477f3be24f1dfca6")), + }, + { + FF(std::string("0x0325e6449db3896bfa8c2bcdcabac9a4a0add91b9305e10b071f9681466d8a64")), + FF(std::string("0x1e4f12df40af7b3b3a7daab0d15e1b6c649bed50c6d85f0f469b9c680d6213aa")), + FF(std::string("0x259babe5dc5beb75821174d2ac2514c3ac75d9a252e919fa3d082f08f6fc255d")), + FF(std::string("0x0536d199068109873bd726373eaada568cbebe3b4723cf963954469fef87b03d")), + }, + { + FF(std::string("0x0f96c283774eb29f7a3e6ebf8d39b7580c6b87a4a8688c4e9954c985900c692a")), + FF(std::string("0x2a197e4a1585c27e4d0efb238aa87bc49146a5f9b10efd89b8e0e1e40a1f5397")), + FF(std::string("0x1334e3cea317028385e6359b7bb3b3a64958d8840e0c03c30673853f581f5762")), + FF(std::string("0x085335f63362d18d1807f03b7e7f33d12d80aa219e58e577fb51dc9fa4913b9d")), + }, + { + FF(std::string("0x24767a8fe8035513548f15f041d6d306e03a0974d70f550bf17d164c68545ddd")), + FF(std::string("0x05343763fc0c0c73d67623a34e695100fa591a9be834f34c971d7a1145e39a3b")), + FF(std::string("0x23a663071238e76485140982a4a7bb856f0cea6a3adf1f0a1e2a20a62be5d8a0")), + FF(std::string("0x10eb6ea7c892c9f530eb7c358f4595a602f3d6ead83a94c2430034a3ce67720e")), + }, + { + FF(std::string("0x22d77c228d29014470c28e3c6e4463f36d4a5d99e58271b2b762e34559ae252f")), + FF(std::string("0x14b7f0b968a5a59b13b66c60059ee0794e990715d64637516a6e414aa7c3eb4e")), + FF(std::string("0x03c56ae6f8cecce9636a751c3e0c9f8460f6b01dca3c488f0ad59cd8753621b7")), + FF(std::string("0x231ef5b2c2bd15606426bbf4a7a32270fd95cef340be77b69295c849712f7970")), + }, + { + FF(std::string("0x052cc6b97d8f8657fd1371eb099c2f0efe37166aa4be7e6b2f5ec18ecd7a2555")), + FF(std::string("0x08339e3b437b5c5fe7fc91bb7903901cab3634f4d71eeb999d4e1ec8dd7d5d34")), + FF(std::string("0x2b52dd66a2f030ffff2b1134cfab98aa0bd16706346457d9995f6bc579f63e0d")), + FF(std::string("0x2d770d6d74c1238b40e39bf1e0da9cf8540bd7461a84aab9b474a0ec581731c5")), + }, + { + FF(std::string("0x25fd2a2b1c65fe0bff324bd3ebc035d7806e374a1770ea9baca8115101afd9ec")), + FF(std::string("0x24b73f5aa558b9165a0e2db4280134e06b46740d9b05bcec07d5bfa5f9866f7b")), + FF(std::string("0x253dbd4522315578fec9b4d9ddbdd94797cb670c2b36cc8fc35ddb11da3574d8")), + FF(std::string("0x1678ac4331ce9d28dd63a303e2840c1a8c8df5cdf7982edd3e880bf9e3ff638c")), + }, + { + FF(std::string("0x299b57ed6ef793250bba6df0464aaaa40ee32fc0cdea661dc47f7167c788bc15")), + FF(std::string("0x0e8031d7f045796728ec86ef6be1105e317697b6817123c92c62cd0df3e134a0")), + FF(std::string("0x08bbc62c82e3192c7a71903385188fd2defe8d3821d83fc19a735821f58b53ed")), + FF(std::string("0x15246558ca9f8636072607ea90f89aaae31e5a095e71f62d40ecef3cf87fc56e")), + }, + { + FF(std::string("0x2c69fb396836afb10bcdee8830ef75edfd2de23bdb1f458cd4013b95b399df5a")), + FF(std::string("0x1332a20f8423504ac6dea46427bca87c692659ee456db4b631b329abac0428f8")), + FF(std::string("0x076099baa164eff4630a22beae8945ec96df7b84fd3e7c2135e38072e53dcb89")), + FF(std::string("0x0e612dcdcec52eac2c227596b8df9f8325785e9ccb4d8e595b164224ee232643")), + }, + { + FF(std::string("0x205123027e2e8e0d813daaa7e791ec129a4a89ba0f7e026dd6c591080495d6da")), + FF(std::string("0x126e7c36d80a9dc4fa9a868ec791b53d61a54e6e2f850bab00cb32cdc6d975d5")), + FF(std::string("0x2638520164de3f58a5f0ef7b6302cb0740d7c0e60c0e3feec89e137c0918ab1e")), + FF(std::string("0x2adf70f515c0d91851da22ef6fcef1c270f2cf28a15adbb4e8931c375fb1d152")), + }, + { + FF(std::string("0x12dc9813445d92702cefdccf3aed56487e5b13fba98d993a101e23d5c75c7fa5")), + FF(std::string("0x1f0c0639a5b5209dc4056aac7aafaaa759dde0c3b219f32fe6dd77596f7fef5b")), + FF(std::string("0x2bac8f37d86d3f562ad7f4a285a63fccb1de4745c78e29a7ada03c8d84584a0d")), + FF(std::string("0x2dc55bc6c7f6dd4a723daafef52a133602ae2e113566d1ed44deff0228536629")), + }, + { + FF(std::string("0x060e528735661c9f4aab45b097c326f53c374658041cfa1c8c6402581267ec60")), + FF(std::string("0x0655e8499681d25f19ce13c9361eecf7d89664d709fbac5edbd00826880526ff")), + FF(std::string("0x03d2045d3557086899658264d24baee7e842cbb213b36bf22db6e408881e194b")), + FF(std::string("0x1b3bebbee511ad923e5741b9ae9299e0b3a49a950e7b0b8eb35b5411e58fa83a")), + }, + { + FF(std::string("0x01635e56bfea75fdcf3fbf9ed4c103f99851d9553a696c3c02ff71bea3b934a4")), + FF(std::string("0x2edcb004d073cb39a73eef2a994653a732e7cc2aa5c33980be989d35268e7a85")), + FF(std::string("0x04c2258ac4f7f74cb2114477aef1ae61d541b919b362efafa0cc6ff1f3abe0c4")), + FF(std::string("0x2dae38722e7509f87cf5380638e40560584de28b0a180c3f654e145d83d4e5b6")), + }, + { + FF(std::string("0x2b1a7bccd6a282790bcc29f5f2d13c5f33dc5eee59af2939b3339f142324f102")), + FF(std::string("0x1768e953de2e58f7620005da9cc4a6863da49fb3c8369ec4d389ae1e74ac5525")), + FF(std::string("0x0d7cfced42afd96297631bb0332b3c90a772ca1c82187cffe43d90906684863f")), + FF(std::string("0x283f8070a0bca435614e8e3e786c120e637f235108fad44a8b1d55f15549ee50")), + }, + { + FF(std::string("0x17400a650edc03e961ec826cedeb0028c928d98bc30e758032afce5c6b9b4bcc")), + FF(std::string("0x0beb669dbb1fa32200d670275f0dfd51b016beef89ed28b2c605a9cee9e4897b")), + FF(std::string("0x08419d357edbd69de031dfe608761f7ff782cc8994b9c282760189d4ec7e01f6")), + FF(std::string("0x118bc2f4015b753019d60abb95037d582270a525d06c6341f35ddca22505f3b2")), + }, + { + FF(std::string("0x293f43e6aa59c0ac8337e25182b0810d0bbfbfb9dc33951d93645e0795b6e5b8")), + FF(std::string("0x25b16e33ab57889a409537da7ee0cd22db722d275e2aa4f5b2b7cae010f055c7")), + FF(std::string("0x1c35af9efbed4574315d523b2d25f8b9bdb0033346243486a99b0b5c49a7d1f3")), + FF(std::string("0x0c9cca6505f4e705fca5caff5283b2bcaf781d95ae388e52314e27f2f14e14b5")), + }, + { + FF(std::string("0x2f6985dc96c8f1ba0e338bd09d4624b28958a4114927158001d5d8d550cc3b71")), + FF(std::string("0x08e034f17598366a77cb0ad47ab55dc31df8e5d2893e13549d132f6428afe09a")), + FF(std::string("0x1651e97525932a9ebca8f072f8e6aa8740a3a351231c14d6061b3268e42e8c7e")), + FF(std::string("0x0f34ea4d29d247d4baf3ea9b9c9763e8ba263c46e0f25ea80df81999f51fbb8b")), + }, + { + FF(std::string("0x27f93f3a609b73ad1ffe2bf154899d8399c9accba6947507bd84bc4556168d7d")), + FF(std::string("0x2bd8b5f1a460e7dcf8b1f8e753b260d4d9460b8c86a3eb1d006d476a9cbe5650")), + FF(std::string("0x123515d8163c3825363d25a84e13bffaa0b5e20c9db01aa1ea6fa467aee0b5e4")), + FF(std::string("0x29676411a52008a07ed65c1fc2901a8adc3689d70ebac45532cf4f3cc8d30774")), + }, + { + FF(std::string("0x1bb60ab8bc36870aed66a594efb34ea24fb7d2d992ca58d4aeb31289c8cf0d65")), + FF(std::string("0x248f8f678b4a5c3a7ffae164c471d29dba9fa6a320b1e9809f64ae120d0bb22b")), + FF(std::string("0x05c08dff728cf1e6804ed5d84e6cabd4575f9bf2f89e9a2eccdb1fc8b83672cb")), + FF(std::string("0x0a5dc0217ebc7f6bbb10ea6261d4bed8fd2b8598be6a7e326e31cc3991135a6b")), + }, + { + FF(std::string("0x21ea154846c075ba1e2ec1d61ad4843bb263e2f05b9bdad67c8b989fe52c9377")), + FF(std::string("0x0592a7b6e9cc14efcff5e9530db734028610a38322e4ad5b2a60220d69e819bb")), + FF(std::string("0x01b98b71b6bf17a929d6557703eecae267893a625f923e497752d7befcaab460")), + FF(std::string("0x2b867342d1d0664b7411d4ab1056f337828ee7bf9db45871798051c56b869503")), + }, + { + FF(std::string("0x0a66788eaf35195b3d40246c836baf1412a9927185197ce2abd747760a809fad")), + FF(std::string("0x2a886be85416c3ef9748376da17b5178091817cb82a38b80ff7492f13ef3444b")), + FF(std::string("0x1dc519f87a75cb012b0a4e15aa8d8fff0da730e81b41c27411766d7587dde4ca")), + FF(std::string("0x2ef6492984f15978f5357c70cb6fd9e13cfc4e21ef6aee5d72b2b636da194bcb")), + }, + { + FF(std::string("0x062de010063d1072aac3b8f51dc0c462c5eaccb9142f931a7ab76a1ae3d5b7ae")), + FF(std::string("0x204baed49134a9764295715f195a04f609a93727157afe1993dc5daa29c46df5")), + FF(std::string("0x0649a9953bbb403ac0d2e9cd624cf9627f36ed8e15cb33d7514e883480234fab")), + FF(std::string("0x2abd88ffeb65a265128ffa3c42037d77934da139f4f04d4ba59790b163e9507e")), + }, + { + FF(std::string("0x18d333c846fa6c4ead13daa110e590ebbc288ea7394e52abfe6f247f99d0e23e")), + FF(std::string("0x2e8727a08f6964a4c758214db8d7cf5c88112176d6dfa3230824935788876509")), + FF(std::string("0x1ef52294254e9a07eea80611b6ae3d7e1b6e8a4b70515d723399f4dcd1e2a5f6")), + FF(std::string("0x11572d12ac653a3c0f22d5b7d20459e6aad41a9116a6adf35aa5e515f6b97399")), + }, + { + FF(std::string("0x09c871834f078d45549694f501a761e42a501c592bd3a4e1fb3e09ad8dd16df1")), + FF(std::string("0x246bbcaf77d39eaa09131e99ffb6d8a754aae3be7a2e3e88c11684f4bf7db342")), + FF(std::string("0x18ba724cfbc52564874d8443dcf08f3584233c2a14e59970059c17648af1c46b")), + FF(std::string("0x2676199c8c498f8b995e8d8089219e64faf4d644d918a8bbdf48f5aeef397ee2")), + }, + { + FF(std::string("0x25af0a7566280e5b679d22a6a543e5d1ee49afba262854cff833c6ab17d9b406")), + FF(std::string("0x0944ddaa67cef777788d34b3af061ca90138856b7b673732abbb7a729010d5e0")), + FF(std::string("0x2541565720337000bfa180c09d2b74f26dc75bc0092489afe6c7628867903fab")), + FF(std::string("0x1557f108c4f6a5e42e6b21b6ce3324111c3b197e746ed56a1b3011df4f3a78aa")), + }, + { + FF(std::string("0x02379e39dade80c2b3cdd994914cc7e3bbabe6f5451c457ea72e8061e6258cf6")), + FF(std::string("0x19283b8a618a8dab599629f322448c2d438a7ff0c8e3869fd48c1287af4682b2")), + FF(std::string("0x2ccdb0312609448eb09c8d49a8ebae3b47cc0476675753b908c244f82262bd46")), + FF(std::string("0x03ce886a32c134b13e508ad9c9470b47c66c28f6c07b6d7abf5d67e3d8cfe128")), + }, + { + FF(std::string("0x05105ee8f7d50a26d109a3854267be2bb0045dbfdec8493ae70bdab4e783815c")), + FF(std::string("0x2d5d51efb46deaf8c878b35c0d62ed2821127d533cc30c28b4259800d11722a8")), + FF(std::string("0x1074bc594f6b3665ccc365f9ff5cc21135d1f922e1db035cbbb452babe549599")), + FF(std::string("0x216aac7bdd7f0bfbdacc9d0a0202cdf964f1dd203f231b08a6138171a332af56")), + }, + { + FF(std::string("0x179773cd3f390ee479f96169df1866d8def0bda8b3a542924e82a61a30f5d734")), + FF(std::string("0x051ce7238a6fb317f56eba00b5eafbd8d83addd72de072f0e67e17918edab699")), + FF(std::string("0x2b50582527dc94f6c32a7a37cb59b783795e42ad4a50d60ad8c4cd9d32a4e5e8")), + FF(std::string("0x175bdedd785a09eb07d8d40c5c53407dc40bf4f85c29e451a1ab015b62d4d9e0")), + }, + { + FF(std::string("0x0ac575ed0014055981fb6db94e50ec901bb29474e93772f9aaf25e8c18fe6f1f")), + FF(std::string("0x1b8541ea21a9c9215a63b2b32192e6dbfd5102471c517e180440d719e98bef2e")), + FF(std::string("0x0deb999605c554a85c85e671ab63cb6989c44445a5f428d4f2688d48eba1a846")), + FF(std::string("0x19d5c93f224b85de28240ba4bb1de0f0bba3c08648957dff13b323a90cbe0a5b")), + }, + { + FF(std::string("0x2a6abea2a0828a230400d001108a16d95a8906e04db3577c602b009d6130677b")), + FF(std::string("0x1b6a2b82be46145b09c0f0ecfe2191b8896ba92c0bd67f8a9ff9e99fc0aaa41d")), + FF(std::string("0x03a0b2e64db36338004acf1bfbb756cc4e1df1a60272b4eb7240beec0fe9ff0a")), + FF(std::string("0x090da681d61c1e68e31625e3d1dd767e8996076333ecd2c0c32de18f93c8a7cc")), + }, + { + FF(std::string("0x00304b05b245d8a93c35dcc8a201623bc10c70a7a59809a9ae77fbb3592c448d")), + FF(std::string("0x2ccc7c443cc4ac2d908ac7cbc78f3432ffdace325957fc00cbcb36fd4220abca")), + FF(std::string("0x05bb83747d88579128e4f3ec624d239fc51da9fd20788970a1dcc1e0650b9742")), + FF(std::string("0x08789f0f2d902548599a592dc0e1902bb11d4f2344c7155919736dae577aede0")), + }, + { + FF(std::string("0x2d7e79f6ff0a354d849c9339102cc01d6fcab3bbcf2a19755ae6e78aab0c50fd")), + FF(std::string("0x23b130113a10a7b7bf6df003e9f895e2de67bf7be27bc802a9fa1552928cd126")), + FF(std::string("0x1907e748c911fce6a62574268653103ff1b7eb59539f29434873a8cc31f1c7dd")), + FF(std::string("0x2e68eba7243e7fb1a492512ee8a7041c84b0c840b74119f6c00d4cb5856054ae")), + }, + { + FF(std::string("0x08dadfd73dbd17a1a3834300b2d47e3645d270df6e0081d84cdf05fe71f9b86e")), + FF(std::string("0x2b194d668c4400df5a26a2c4067d923086d505d3d4a3bbcf59c292c84b0e7ca5")), + FF(std::string("0x2456e40dde7c6f74e1da3a2277b7210cdf00509166d6af184c78d33f79f43a48")), + FF(std::string("0x016009a0a16d27ed52230190747b3b6913966cbc0414156778e68c6b14fd1735")), + }, + { + FF(std::string("0x12ff5c523564441020205b85188e144c8157f689ec5069cc7d039803a7349ab4")), + FF(std::string("0x041578eda5a7678fbda568fbf40759426f5705e303f32c63ac474cb5f5f7ec6a")), + FF(std::string("0x05239591df2f6f81c1d26da5a2a0fbfca86d0efc99a38a63ce0a7d247a69af83")), + FF(std::string("0x250ddf97d92629ebea4aa32ecaf8b78e9dba508e113dd267327662a81833cfb4")), + }, + { + FF(std::string("0x2c6f9180b88371c9fbb0be3de33660ef305e29db740d1a58c932b81564ac1b85")), + FF(std::string("0x072c7948f6111a46e2cab1b8bdca315dd4d2d4ec9cbafb7fa93a4142a610de2a")), + FF(std::string("0x1d95394e6d3f4a54fac5db36c72e1ab50b5bfba092983a9e2bb314190c0ddbcf")), + FF(std::string("0x047dd6e2991a472698d3769e7fd4424e8d1bc7b8b71d4a302b5cc41e1a940b27")), + }, + { + FF(std::string("0x1d1bf8d0e8a7862fe9b96231ae07bc42563ba5921fdee16f209645884a46e6e3")), + FF(std::string("0x08a53afc4b57bc9202929dc6ed63b7c661d5c485cf6ae17161bce7938fc59af4")), + FF(std::string("0x0ff20cb119d82b8d20cf4d31b9f477758a0be7ecaf8812126f9b4ad464a6782c")), + FF(std::string("0x087b751afd7be2acd7923cb74430f27db98890e44c375c09ac535d3a8ee4349f")), + }, + { + FF(std::string("0x2df5483c1ce4c9de8401c7051392a30e0198a489d21449ddedf4048b50dac823")), + FF(std::string("0x284c153a3a910c030071783ee0baa88fd701dc61f31ed77463bd9b37cd34b782")), + FF(std::string("0x03e1a7a5affcca77d76dff3e43fca2c9aea3962775bf9f416dda6b9b70a553f4")), + FF(std::string("0x24be4f6d00f3088d5983848d39e43ebc8b940192cedfe9205ee84221427aaa38")), + }, + { + FF(std::string("0x29f50462b45601fc9cd5f46ebd7d6a659351898bea6e3403ce931fd3432d0290")), + FF(std::string("0x1ed2ff04f43127d837a5ca18a41163a9470c67d355ecebe5aff04366865ac132")), + FF(std::string("0x146cccc77351666008a6b776a7ebbc2a84aecb29bf20bddf2e4896da0bd3eb64")), + FF(std::string("0x0b91c204757074bcf1e106f7fb7bf26dd9836c2af828e50f5b3424668e6c3f49")), + }, + { + FF(std::string("0x0c46dafe7ba3db2a074471d38a67ae25a5cc91844f2efe41435dd6bd794c8889")), + FF(std::string("0x04a54a09f063d9aa4d123e0f4bbf948c1015b281adbd993df67be92639604e56")), + FF(std::string("0x0bf1f2a39d8f9002dfb81966bbde913d798ea554515b4b7cc985613d43bdc380")), + FF(std::string("0x0c12d5365ba60d32e6342537847154c0933d99d36342cf98a080a62db324723b")), + }, + { + FF(std::string("0x20dc243ef10af7a9a5822706cd8fc4d0beb65d68e6f08218bca636b566d90635")), + FF(std::string("0x22bac8e86894a619dc6bb337719964b56fee5217bda8c711500b8579196d6360")), + FF(std::string("0x1cfe092982f2d61d132e0b6fc4b678c97d1f80297d1b43e723024503e19da7a5")), + FF(std::string("0x2bb3ca88ab47d917625c22ce11260cba3dc9c5cc693ccc4722f7d06058b5c355")), + }, + { + FF(std::string("0x2289c7ff79446228f2b6a52e48a90d6d3ddec3d7ff5b548f39267ded5c175191")), + FF(std::string("0x09d963f5d895df0d2f1be27e0cd589c1e20f6219a31526fe9acdbb534de923fe")), + FF(std::string("0x07dc265e4f1736a3a07c0aa2d94d0f23742ecb90837c5ed87e8e1f4db3f49f3b")), + FF(std::string("0x18f75992411fbb0ec8a01ce2c0c81567ce8da36087ab92e483470d3f141e1176")), + }, + { + FF(std::string("0x2a7d09e28d6b184616502993130ee0b552d238da6867895ee7eb50fea033af26")), + FF(std::string("0x2b5e8bd12bd77ba2a3abfd4b56a8dc5e93b8c509110665113acbe97598e2514a")), + FF(std::string("0x2b4506470648cd32461b08692dfe4741571820e1e02674a4652305724c3024b9")), + FF(std::string("0x0a64cd1b197a31dac84de8bb0eb634fafd344155bdbac92719e8d34ed0accf64")), + }, + { + FF(std::string("0x0ebaacbd0edc01a28c88ea6cd8232a8fb5e0cbf7b7d46db954a59551269aae11")), + FF(std::string("0x1d3d7a5ba3d8d1728f3187401038cebf5adec7e95d5ec485aa82f58fd9339a68")), + FF(std::string("0x16b027c675b006b18560c236d7e0b4fe0c08061572911f467c8448a5e62a25a5")), + FF(std::string("0x20eb9f65f94084054d77a1fb220bdfe6fc2ab17ea04f99400834241b584949c6")), + }, + { + FF(std::string("0x11d15fbd5525aa70d44cbcb3879128652f4680034db3841db0254a60218fb29a")), + FF(std::string("0x1e4a6b228d2596a72e7535d24dd60a0c583eb2febd0d8bcd12396ebc425470eb")), + FF(std::string("0x21728fe5756ff55de1c9d5fc0d08f1b1318805a66f6637088fd2b20294911687")), + FF(std::string("0x1bda907f1c69a520fd37d6ddce8d3956c32e5aa10b24f2958ed7a6705bd1f37d")), + }, + { + FF(std::string("0x1c837c3290090ef4afd9d904ff67734f54b939fb719cc1038efa5db256c94d6d")), + FF(std::string("0x019e54db9c8ec7651ceda7bcf44b50b1255fb78d797e158e669de93adcb6e3b5")), + FF(std::string("0x261506c83aea562286a84681f6fa2449395c241e1cde0c69f8ca63783fbfca59")), + FF(std::string("0x08e04b821c976f6cec904c3aea5aaf05cb255722bbdcf7ee93b1de99846b3625")), + }, + { + FF(std::string("0x1e8d1ab72f9ca36a7ecd2ad9e93bb46a5b88830925dfa45fa8817c5ead9d8b54")), + FF(std::string("0x2f58fda0de317d3472baac058b7a0e8c5c590eaf0482dbe53ead518b2f313dbe")), + FF(std::string("0x0aaea80cc01cac944922c8a24532953790060ea0d48934da0ef75bc6574444d3")), + FF(std::string("0x2306ce71ff2352e0f1bf6e5f87cabb98ecdfb489ff3a99891ae203526d4d737b")), + }, + { + FF(std::string("0x06628eb6eef76ad7569e50e4b97b25f18d412426e9bfd45ec583cc1fe6272005")), + FF(std::string("0x284db95e0c26cd9b64fbd9e40aee8aeab14ff0429aa5775711a6ca4854076d27")), + FF(std::string("0x2328cd3fb4348135ab6acaccbc0e83a7c8272687d3c6454390a725af4a7f95de")), + FF(std::string("0x1d5815e60424ef674449982aa51687893b82363952d31cfe8bc24453ed153cb6")), + }, + { + FF(std::string("0x18c57f75efec583c1c0c440fffcf5f4377e4740ff3311e820a8b6d814e92c86a")), + FF(std::string("0x1b82f143fc2eebc22a600bb95a3af1506b68d813ffbf647bc479c3864170b338")), + FF(std::string("0x192470dde3a0806e90bc34f2190afd2dcb7df6629bad92e209d70c74a48c9d92")), + FF(std::string("0x0aa97a5b7d802d0caf9cb6d1c76486853bee852f1aadd85b52fd83e1147457a2")), + }, + { + FF(std::string("0x1b831d08854a1a109a745c5b16760cec73edd3d5317dcbe1cf24a6b0ddc2d79e")), + FF(std::string("0x096b1936ea537a6b03ce83d87823f2326a97e03c2b90c10476c3058001e6b471")), + FF(std::string("0x2c1ab915961a17681e0626196749ab54beaf01e1b29e01f1be2cba941d6d3eac")), + FF(std::string("0x19fc611ee693c8a12b73bd0eba61fa74ff4a476df46c221b3abe00af3ee82e61")), + }, + { + FF(std::string("0x205625df4943f819eedf11cb9736648f80437f3e0b3cd73a5a0b3b144e5b3569")), + FF(std::string("0x2eb23a5e85fbc502e6b24d08acaad160119e51498ef07df8079c2d47ff760d57")), + FF(std::string("0x0c725970a0e4c070a785efd46d63eb6523a7b4951e5270bdf549ae1a89dc0991")), + FF(std::string("0x15f2d2888ad658cecc3d7038de6541c7e620ac92e4d2c192eafd4fec2ba48e8f")), + }, + { + FF(std::string("0x01080c482028f2fdfb4c4247d07157bfa58d6d2fd6e0583fe87a1a8f3d96f112")), + FF(std::string("0x058e98dfe1751afb7478f2b93a4522e0e5bab006777fcc9903580542e549b66f")), + FF(std::string("0x21abaf2ff4b43316f52910454f957d485008403630f1bc68b63da871d3462d9a")), + FF(std::string("0x227acf3eaa5df73c3f01e2e34e571c2d69279194b0f2930fdd9adf3898753ec7")), + }, + { + FF(std::string("0x21e0c57ce891ea47b91b4757a41817a9f47b4a5a14632dd556ea0e5411f79f1f")), + FF(std::string("0x1a8ada480114c7e248cd5214511ee2b79b793f8e199eff986b3ae59297e9feb9")), + FF(std::string("0x082bc7a263ca5da12ee6e8aa048a7cdcd1ae4d4a16aacfd92b33991157c92db9")), + FF(std::string("0x178502779a89aa327096a62883989ac41e28a25caac6cfb7bd4ec32e343b08b1")), + }, + { + FF(std::string("0x0bdc3b7f3127210ac8871d1b8e3ec744d345dbbfe1508f8565b05896c9e50e8e")), + FF(std::string("0x146f2b581340685a19fc4175354475b04bae900f542ee1c6254c4b94d9e5c619")), + FF(std::string("0x0e2093f5fea23aa450f519e844a3ff5dd3c62bc5727b6016d8272bff4f8d18b4")), + FF(std::string("0x0bd958eab1a98cc6618245168d3f83c9f502450c15ce978e4ed8fa09b409d0cd")), + }, + { + FF(std::string("0x1d4fa3a009238083b8e844c9923bd6220460d55d47677d0dca26bb6ed30fb9c6")), + FF(std::string("0x219992a2ad3c2e2ed6a7b2b95556835e1bad915d26e886c8ee5d4b6edae81085")), + FF(std::string("0x0fccc34a26a433f005e9ab759b8029ee18e5e2f36aa10564684f3f359845c920")), + FF(std::string("0x1fb16829f9023a2c365f4f35b3e8e85fa9da87a1196a87941bd54b2e2f6a3c5a")), + }, + { + FF(std::string("0x2a62ca0cc5e850c6c4af48edf269e50bf2d812e5883622557c9c407694bfe1ea")), + FF(std::string("0x1d7e77f95174c41ea0c1368390eb4618cbc6cc3a5a5743cc03ee90a636022a76")), + FF(std::string("0x24dd714d441b7986af8dee276cd2606359cba9e4ead6034ac3bab018364a21c4")), + FF(std::string("0x11072894ca6d01e8d6536eacaa067940f59b1b6d27bebdb2c6f53ac887fee5dc")), + }, + }; + + static constexpr std::array internal_matrix_diagonal = { + FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), + FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), + FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), + FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), + }; +}; +} // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index c64b1e35196..9158291d4f9 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -106,6 +106,18 @@ template struct alignas(32) field { self_to_montgomery_form(); } + constexpr explicit field(std::string& input) noexcept + { + uint256_t value(input); + *this = field(value); + } + + constexpr explicit field(std::string_view input) noexcept + { + uint256_t value(input); + *this = field(value); + } + constexpr explicit operator uint32_t() const { field out = from_montgomery_form(); diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp index 70c80c811a9..eeb1e310d78 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp @@ -13,6 +13,7 @@ #include "../uint128/uint128.hpp" #include "barretenberg/common/serialize.hpp" +#include "barretenberg/common/throw_or_abort.hpp" #include #include #include @@ -35,14 +36,47 @@ class alignas(32) uint256_t { {} constexpr uint256_t(uint256_t&& other) noexcept = default; - explicit uint256_t(std::string const& str) noexcept + explicit constexpr uint256_t(std::string_view input) noexcept { - for (int i = 0; i < 4; ++i) { - std::stringstream ss; - ss << std::hex << str.substr(static_cast(i) * 16, 16); - ss >> data[3 - i]; + /* Quick and dirty conversion from a single character to its hex equivelent */ + constexpr auto HexCharToInt = [](uint8_t Input) { + bool valid = + (Input >= 'a' && Input <= 'f') || (Input >= 'A' && Input <= 'F') || (Input >= '0' && Input <= '9'); + if (!valid) { + throw_or_abort("Error, uint256 constructed from string_view with invalid hex parameter"); + } + uint8_t res = ((Input >= 'a') && (Input <= 'f')) ? (Input - 87) + : ((Input >= 'A') && (Input <= 'F')) ? (Input - 55) + : ((Input >= '0') && (Input <= '9')) ? (Input - 48) + : 0; + return res; + }; + + std::array limbs{ 0, 0, 0, 0 }; + size_t start_index = 0; + if (input.size() == 66 && input[0] == '0' && input[1] == 'x') { + start_index = 2; + } else if (input.size() != 64) { + throw_or_abort("Error, uint256 constructed from string_view with invalid length"); } + for (size_t j = 0; j < 4; ++j) { + + const size_t limb_index = start_index + j * 16; + for (size_t i = 0; i < 8; ++i) { + const size_t byte_index = limb_index + (i * 2); + uint8_t nibble_hi = HexCharToInt(static_cast(input[byte_index])); + uint8_t nibble_lo = HexCharToInt(static_cast(input[byte_index + 1])); + uint8_t byte = (nibble_hi * 16) + nibble_lo; + limbs[j] <<= 8; + limbs[j] += byte; + } + } + data[0] = limbs[3]; + data[1] = limbs[2]; + data[2] = limbs[1]; + data[3] = limbs[0]; } + explicit constexpr uint256_t(std::string const& str) noexcept { *this = uint256_t(std::string_view(str)); } static constexpr uint256_t from_uint128(const uint128_t a) noexcept { diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp index 386119b3864..9b76da65b02 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp @@ -8,6 +8,29 @@ auto& engine = numeric::random::get_debug_engine(); using namespace numeric; +TEST(uint256, TestStringConstructors) +{ + std::string input = "9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"; + constexpr std::string_view input2("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); + constexpr std::string_view input3("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); + const std::string input4("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); + + const uint256_t result1(input); + constexpr uint256_t result2(input2); + const uint256_t result3(input3); + const uint256_t result4(input4); + constexpr uint256_t expected{ + 0xabcdef0123456789, + 0xfedcba9876543210, + 0xa0b1c2d3e4f56789, + 0x9a807b615c4d3e2f, + }; + EXPECT_EQ(result1, result2); + EXPECT_EQ(result1, result3); + EXPECT_EQ(result1, result4); + EXPECT_EQ(result1, expected); +} + TEST(uint256, GetBit) { constexpr uint256_t a{ 0b0110011001110010011001100111001001100110011100100110011001110011, From ea12f99fd4319f49fdf5caef8bd448ca558ccc7d Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Fri, 27 Oct 2023 11:55:28 +0000 Subject: [PATCH 02/34] mmmmm constexpr --- .../barretenberg/crypto/poseidon2/poseidon2.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp index 5c5850125eb..fcac6dd78be 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp @@ -32,7 +32,7 @@ template class Poseidon2 { static constexpr RoundConstantsContainer round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; // derive_round_constants(); - static void matrix_multiplication_4x4(State& input) + static constexpr void matrix_multiplication_4x4(State& input) { /** * hardcoded algorithm that evaluates matrix multiplication using the following MDS matrix: @@ -64,14 +64,14 @@ template class Poseidon2 { input[3] = t4; } - static void add_round_constants(State& input, const RoundConstants& rc) + static constexpr void add_round_constants(State& input, const RoundConstants& rc) { for (size_t i = 0; i < t; ++i) { input[i] += rc[i]; } } - static void matrix_multiplication_internal(State& input) + static constexpr void matrix_multiplication_internal(State& input) { // for t = 4 auto sum = input[0]; @@ -84,7 +84,7 @@ template class Poseidon2 { } } - static void matrix_multiplication_external(State& input) + static constexpr void matrix_multiplication_external(State& input) { if constexpr (t == 4) { matrix_multiplication_4x4(input); @@ -94,21 +94,21 @@ template class Poseidon2 { } } - static void apply_single_sbox(FF& input) + static constexpr void apply_single_sbox(FF& input) { auto xx = input.sqr(); auto xxxx = xx.sqr(); input *= xxxx; } - static void apply_sbox(State& input) + static constexpr void apply_sbox(State& input) { for (auto& in : input) { apply_single_sbox(in); } } - static State permutation(State& input) + static constexpr State permutation(State& input) { // deep copy State current_state(input); From 95e657240e1fb991bfac3b99af74f1b7ddecc906 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Fri, 27 Oct 2023 11:57:38 +0000 Subject: [PATCH 03/34] wip --- barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp index fcac6dd78be..8064c1dc370 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp @@ -96,6 +96,7 @@ template class Poseidon2 { static constexpr void apply_single_sbox(FF& input) { + // hardcoded assumption that d = 5. should fix this or not make d configurable auto xx = input.sqr(); auto xxxx = xx.sqr(); input *= xxxx; From 8c3082835c5fc0a50d0d52f421cb039ed02ef7c0 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Fri, 27 Oct 2023 18:49:06 +0000 Subject: [PATCH 04/34] basic poseidon hash working --- .../crypto/poseidon2/poseidon2.hpp | 133 +---------------- .../crypto/poseidon2/poseidon2.test.cpp | 6 +- .../poseidon2/poseidon2_permutation.hpp | 141 ++++++++++++++++++ .../poseidon2/poseidon2_permutation.test.cpp | 32 ++++ .../crypto/poseidon2/sponge/sponge.hpp | 136 +++++++++++++++++ 5 files changed, 316 insertions(+), 132 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp index 8064c1dc370..15488e2d0b3 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp @@ -1,141 +1,16 @@ #pragma once #include "poseidon2_params.hpp" - -#include "barretenberg/common/throw_or_abort.hpp" - -#include -#include -#include -#include +#include "poseidon2_permutation.hpp" +#include "sponge/sponge.hpp" namespace crypto { template class Poseidon2 { public: - // todo make parameters configurable? - static constexpr size_t t = Params::t; - static constexpr size_t d = Params::d; - static constexpr size_t sbox_size = Params::sbox_size; // logp - static constexpr size_t rounds_f = Params::rounds_f; - static constexpr size_t rounds_p = Params::rounds_p; - static constexpr size_t NUM_ROUNDS = Params::rounds_f + Params::rounds_p; - using FF = typename Params::FF; - using State = std::vector; - using RoundConstants = std::array; - using MatrixDiagonal = std::array; - using RoundConstantsContainer = std::array; - - static constexpr MatrixDiagonal internal_matrix_diagonal = - Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; - static constexpr RoundConstantsContainer round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; - // derive_round_constants(); - - static constexpr void matrix_multiplication_4x4(State& input) - { - /** - * hardcoded algorithm that evaluates matrix multiplication using the following MDS matrix: - * / \ - * | 5 7 1 3 | - * | 4 6 1 1 | - * | 1 3 5 7 | - * | 1 1 4 6 | - * \ / - */ - - auto t0 = input[0] + input[1]; // A + B - auto t1 = input[2] + input[3]; // C + D - auto t2 = input[1] + input[1]; // 2B - t2 += t1; // 2B + C + D - auto t3 = input[3] + input[3]; // 2C - t3 += t0; // 2C + A + B - auto t4 = t1 + t1; - t4 += t4; - t4 += t3; // 4D + 6C + A + B - auto t5 = t0 + t0; - t5 += t5; - t5 += t3; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + 7C + 5D - auto t7 = t2 + t4; // A + 3B + 5D + 7C - input[0] = t6; - input[1] = t5; - input[2] = t7; - input[3] = t4; - } - - static constexpr void add_round_constants(State& input, const RoundConstants& rc) - { - for (size_t i = 0; i < t; ++i) { - input[i] += rc[i]; - } - } - - static constexpr void matrix_multiplication_internal(State& input) - { - // for t = 4 - auto sum = input[0]; - for (size_t i = 1; i < t; ++i) { - sum += input[i]; - } - for (size_t i = 0; i < t; ++i) { - input[i] *= internal_matrix_diagonal[i]; - input[i] += sum; - } - } - - static constexpr void matrix_multiplication_external(State& input) - { - if constexpr (t == 4) { - matrix_multiplication_4x4(input); - } else { - // erm panic - throw_or_abort("not supported"); - } - } - - static constexpr void apply_single_sbox(FF& input) - { - // hardcoded assumption that d = 5. should fix this or not make d configurable - auto xx = input.sqr(); - auto xxxx = xx.sqr(); - input *= xxxx; - } - - static constexpr void apply_sbox(State& input) - { - for (auto& in : input) { - apply_single_sbox(in); - } - } - - static constexpr State permutation(State& input) - { - // deep copy - State current_state(input); - - // Apply 1st linear layer - matrix_multiplication_external(current_state); - - for (size_t i = 0; i < rounds_f; ++i) { - add_round_constants(current_state, round_constants[i]); - apply_sbox(current_state); - matrix_multiplication_external(current_state); - } - - const size_t p_end = rounds_f + rounds_p; - for (size_t i = rounds_f; i < p_end; ++i) { - current_state[0] += round_constants[i][0]; - apply_single_sbox(current_state[0]); - matrix_multiplication_internal(current_state); - } - for (size_t i = p_end; i < NUM_ROUNDS; ++i) { - add_round_constants(current_state, round_constants[i]); - apply_sbox(current_state); - matrix_multiplication_external(current_state); - } - return current_state; - } + using Sponge = FieldSponge>; + static FF hash(std::span input) { return Sponge::hash_fixed_length(input); } }; } // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp index d4df515a546..84f82dd263b 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -21,9 +21,9 @@ TEST(Poseidon2, BasicTests) std::vector input1{ a, b, c, d }; std::vector input2{ d, c, b, a }; - auto r0 = crypto::Poseidon2::permutation(input1); - auto r1 = crypto::Poseidon2::permutation(input1); - auto r2 = crypto::Poseidon2::permutation(input2); + auto r0 = crypto::Poseidon2::hash(input1); + auto r1 = crypto::Poseidon2::hash(input1); + auto r2 = crypto::Poseidon2::hash(input2); EXPECT_EQ(r0, r1); EXPECT_NE(r0, r2); diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp new file mode 100644 index 00000000000..7a9486c7e68 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp @@ -0,0 +1,141 @@ +#pragma once + +#include "poseidon2_params.hpp" + +#include "barretenberg/common/throw_or_abort.hpp" + +#include +#include +#include +#include + +namespace crypto { + +template class Poseidon2Permutation { + public: + // todo make parameters configurable? + static constexpr size_t t = Params::t; + static constexpr size_t d = Params::d; + static constexpr size_t sbox_size = Params::sbox_size; // logp + static constexpr size_t rounds_f = Params::rounds_f; + static constexpr size_t rounds_p = Params::rounds_p; + static constexpr size_t NUM_ROUNDS = Params::rounds_f + Params::rounds_p; + + using FF = typename Params::FF; + using State = std::vector; + using RoundConstants = std::array; + using MatrixDiagonal = std::array; + using RoundConstantsContainer = std::array; + + static constexpr MatrixDiagonal internal_matrix_diagonal = + Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; + static constexpr RoundConstantsContainer round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; + // derive_round_constants(); + + static constexpr void matrix_multiplication_4x4(State& input) + { + /** + * hardcoded algorithm that evaluates matrix multiplication using the following MDS matrix: + * / \ + * | 5 7 1 3 | + * | 4 6 1 1 | + * | 1 3 5 7 | + * | 1 1 4 6 | + * \ / + */ + + auto t0 = input[0] + input[1]; // A + B + auto t1 = input[2] + input[3]; // C + D + auto t2 = input[1] + input[1]; // 2B + t2 += t1; // 2B + C + D + auto t3 = input[3] + input[3]; // 2C + t3 += t0; // 2C + A + B + auto t4 = t1 + t1; + t4 += t4; + t4 += t3; // 4D + 6C + A + B + auto t5 = t0 + t0; + t5 += t5; + t5 += t3; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 7C + 5D + auto t7 = t2 + t4; // A + 3B + 5D + 7C + input[0] = t6; + input[1] = t5; + input[2] = t7; + input[3] = t4; + } + + static constexpr void add_round_constants(State& input, const RoundConstants& rc) + { + for (size_t i = 0; i < t; ++i) { + input[i] += rc[i]; + } + } + + static constexpr void matrix_multiplication_internal(State& input) + { + // for t = 4 + auto sum = input[0]; + for (size_t i = 1; i < t; ++i) { + sum += input[i]; + } + for (size_t i = 0; i < t; ++i) { + input[i] *= internal_matrix_diagonal[i]; + input[i] += sum; + } + } + + static constexpr void matrix_multiplication_external(State& input) + { + if constexpr (t == 4) { + matrix_multiplication_4x4(input); + } else { + // erm panic + throw_or_abort("not supported"); + } + } + + static constexpr void apply_single_sbox(FF& input) + { + // hardcoded assumption that d = 5. should fix this or not make d configurable + auto xx = input.sqr(); + auto xxxx = xx.sqr(); + input *= xxxx; + } + + static constexpr void apply_sbox(State& input) + { + for (auto& in : input) { + apply_single_sbox(in); + } + } + + static constexpr State permutation(State& input) + { + // deep copy + State current_state(input); + + // Apply 1st linear layer + matrix_multiplication_external(current_state); + + for (size_t i = 0; i < rounds_f; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(current_state); + } + + const size_t p_end = rounds_f + rounds_p; + for (size_t i = rounds_f; i < p_end; ++i) { + current_state[0] += round_constants[i][0]; + apply_single_sbox(current_state[0]); + matrix_multiplication_internal(current_state); + } + + for (size_t i = p_end; i < NUM_ROUNDS; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(current_state); + } + return current_state; + } +}; +} // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp new file mode 100644 index 00000000000..eff17006bce --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp @@ -0,0 +1,32 @@ +#include "poseidon2_permutation.hpp" +#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include + +using namespace barretenberg; + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +namespace poseidon2_tests { +TEST(Poseidon2Permutation, BasicTests) +{ + + barretenberg::fr a = barretenberg::fr::random_element(&engine); + barretenberg::fr b = barretenberg::fr::random_element(&engine); + barretenberg::fr c = barretenberg::fr::random_element(&engine); + barretenberg::fr d = barretenberg::fr::random_element(&engine); + + std::vector input1{ a, b, c, d }; + std::vector input2{ d, c, b, a }; + + auto r0 = crypto::Poseidon2Permutation::permutation(input1); + auto r1 = crypto::Poseidon2Permutation::permutation(input1); + auto r2 = crypto::Poseidon2Permutation::permutation(input2); + + EXPECT_EQ(r0, r1); + EXPECT_NE(r0, r2); +} + +} // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp new file mode 100644 index 00000000000..51e45fad567 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp @@ -0,0 +1,136 @@ +#pragma once + +#include +#include +#include +#include + +#include "barretenberg/numeric/uint256/uint256.hpp" + +namespace crypto { + +/** + * @brief Implements a cryptographic sponge over prime fields. + * Implements the sponge specification from the Community Cryptographic Specification Project + * see https://github.com/C2SP/C2SP/blob/792c1254124f625d459bfe34417e8f6bdd02eb28/poseidon-sponge.md + * (Note: this spec was not accepted into the C2SP repo, we might want to reference something else!) + * + * @tparam FF + * @tparam rate + * @tparam capacity + * @tparam t + * @tparam Permutation + */ +template class FieldSponge { + public: + enum Mode { + ABSORB, + SQUEEZE, + }; + std::array state; + std::array cache; + size_t cache_size = 0; + Mode mode = Mode::ABSORB; + + FieldSponge(FF domain_iv = 0) + { + for (size_t i = 0; i < rate; ++i) { + state[i] = 0; + } + state[rate] = domain_iv; + } + + std::array perform_duplex() + { + for (size_t i = cache_size; i < rate; ++i) { + cache[i] = 0; + } + for (size_t i = 0; i < rate; ++i) { + state[i] += cache[i]; + } + // todo unify types between SPonge and permutation + std::vector in(state.begin(), state.end()); + auto res = Permutation::permutation(in); + std::array output; + for (size_t i = 0; i < t; ++i) { + state[i] = res[i]; + } + for (size_t i = 0; i < rate; ++i) { + output[i] = state[i]; + } + + return output; + } + + void absorb(const FF& input) + { + if (mode == Mode::ABSORB && cache_size == rate) { + perform_duplex(); + cache[0] = input; + cache_size = 1; + } else if (mode == Mode::ABSORB && cache_size < rate) { + cache[cache_size] = input; + cache_size += 1; + } else if (mode == Mode::SQUEEZE) { + cache[0] = input; + cache_size = 1; + mode = Mode::ABSORB; + } + } + + FF squeeze() + { + if (mode == Mode::SQUEEZE && cache_size == 0) { + mode = Mode::ABSORB; + cache_size = 0; + } + if (mode == Mode::ABSORB) { + auto new_output_elements = perform_duplex(); + mode = Mode::SQUEEZE; + for (size_t i = 0; i < rate; ++i) { + cache[i] = new_output_elements[i]; + } + cache_size = rate; + } + FF result = cache[0]; + for (size_t i = 1; i < cache_size; ++i) { + cache[i - 1] = cache[i]; + } + cache_size -= 1; + return result; + } + + template static std::array hash_internal(std::span input) + { + size_t in_len = input.size(); + const uint256_t iv = (static_cast(in_len) << 64) + out_len - 1; + FieldSponge sponge(iv); + + for (size_t i = 0; i < in_len; ++i) { + sponge.absorb(input[i]); + } + + if constexpr (is_variable_length) { + sponge.absorb(1); + } + + std::array output; + for (size_t i = 0; i < out_len; ++i) { + output[i] = sponge.squeeze(); + } + return output; + } + + template static std::array hash_fixed_length(std::span input) + { + return hash_internal(input); + } + static FF hash_fixed_length(std::span input) { return hash_fixed_length<1>(input)[0]; } + + template static std::array hash_variable_length(std::span input) + { + return hash_internal(input); + } + static FF hash_variable_length(std::span input) { return hash_variable_length<1>(input)[0]; } +}; +} // namespace crypto \ No newline at end of file From 86cf018009fc14c60b971313f18be64f42b2ba98 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 30 Oct 2023 08:36:01 +0000 Subject: [PATCH 05/34] added tests + comments --- .../crypto/poseidon2/poseidon2.test.cpp | 17 +++++++ .../poseidon2/poseidon2_permutation.hpp | 21 +++++++-- .../poseidon2/poseidon2_permutation.test.cpp | 26 ++++++++++- .../crypto/poseidon2/sponge/sponge.hpp | 45 ++++++++++++++++--- 4 files changed, 96 insertions(+), 13 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp index 84f82dd263b..c5f4f3e9dd3 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -29,4 +29,21 @@ TEST(Poseidon2, BasicTests) EXPECT_NE(r0, r2); } +// N.B. these hardcoded values were extracted from the algorithm being tested. These are NOT independent test vectors! +// TODO(@zac-williamson): find independent test vectors we can compare against! (very hard to find given flexibility of +// Poseidon's parametrisation) +TEST(Poseidon2, ConsistencyCheck) +{ + barretenberg::fr a(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr b(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr c(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr d(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + + std::array input{ a, b, c, d }; + auto result = crypto::Poseidon2::hash(input); + + barretenberg::fr expected(std::string_view("0x2f8f825d4ba3c0461bd4804e7e9490775b6f107e2eea15d6c74d370d465f7e6d")); + + EXPECT_EQ(result, expected); +} } // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp index 7a9486c7e68..4001ddf6a12 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp @@ -11,18 +11,32 @@ namespace crypto { +/** + * @brief Applies the Poseidon2 permutation function from https://eprint.iacr.org/2023/323 . + * This algorithm was implemented using https://github.com/HorizenLabs/poseidon2 as a reference. + * + * @tparam Params + */ template class Poseidon2Permutation { public: - // todo make parameters configurable? + // t = sponge permutation size (in field elements) + // t = rate + capacity + // capacity = 1 field element (256 bits) + // rate = number of field elements that can be compressed per permutation static constexpr size_t t = Params::t; + // d = degree of s-box polynomials. For a given field, `d` is the smallest element of `p` such that gdc(d, p - 1) = + // 1 (excluding 1) For bn254/grumpkin, d = 5 static constexpr size_t d = Params::d; - static constexpr size_t sbox_size = Params::sbox_size; // logp + // sbox size = number of bits in p + static constexpr size_t sbox_size = Params::sbox_size; + // number of full sbox rounds static constexpr size_t rounds_f = Params::rounds_f; + // number of partial sbox rounds static constexpr size_t rounds_p = Params::rounds_p; static constexpr size_t NUM_ROUNDS = Params::rounds_f + Params::rounds_p; using FF = typename Params::FF; - using State = std::vector; + using State = std::array; using RoundConstants = std::array; using MatrixDiagonal = std::array; using RoundConstantsContainer = std::array; @@ -30,7 +44,6 @@ template class Poseidon2Permutation { static constexpr MatrixDiagonal internal_matrix_diagonal = Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; static constexpr RoundConstantsContainer round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; - // derive_round_constants(); static constexpr void matrix_multiplication_4x4(State& input) { diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp index eff17006bce..4dab40cb728 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp @@ -18,8 +18,8 @@ TEST(Poseidon2Permutation, BasicTests) barretenberg::fr c = barretenberg::fr::random_element(&engine); barretenberg::fr d = barretenberg::fr::random_element(&engine); - std::vector input1{ a, b, c, d }; - std::vector input2{ d, c, b, a }; + std::array input1{ a, b, c, d }; + std::array input2{ d, c, b, a }; auto r0 = crypto::Poseidon2Permutation::permutation(input1); auto r1 = crypto::Poseidon2Permutation::permutation(input1); @@ -29,4 +29,26 @@ TEST(Poseidon2Permutation, BasicTests) EXPECT_NE(r0, r2); } +// N.B. these hardcoded values were extracted from the algorithm being tested. These are NOT independent test vectors! +// TODO(@zac-williamson): find independent test vectors we can compare against! (very hard to find given flexibility of +// Poseidon's parametrisation) +TEST(Poseidon2Permutation, ConsistencyCheck) +{ + barretenberg::fr a(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr b(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr c(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + barretenberg::fr d(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); + + std::array input{ a, b, c, d }; + auto result = crypto::Poseidon2Permutation::permutation(input); + + std::array expected{ + barretenberg::fr(std::string_view("0x0514d38493ec8da89f9e2b599bc20f96206ad0c94bc2751e6df03003009aa2ea")), + barretenberg::fr(std::string_view("0x0757d335371eacea287976a7b26729a74801720418bfdac37d852ac198b585ed")), + barretenberg::fr(std::string_view("0x19f5168edd96d2c8800d460908dde37c5dd36d56ae905faa8660182a2803c56c")), + barretenberg::fr(std::string_view("0x0096047284f80a35f2f9f95101a9287e99e1afb0866f19e86286a09bdb203685")), + }; + EXPECT_EQ(result, expected); +} + } // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp index 51e45fad567..d983a9824b2 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp @@ -15,6 +15,8 @@ namespace crypto { * see https://github.com/C2SP/C2SP/blob/792c1254124f625d459bfe34417e8f6bdd02eb28/poseidon-sponge.md * (Note: this spec was not accepted into the C2SP repo, we might want to reference something else!) * + * Note: If we ever use this sponge class for more than 1 hash functions, we should move this out of `poseidon2` + * and into its own directory * @tparam FF * @tparam rate * @tparam capacity @@ -23,11 +25,22 @@ namespace crypto { */ template class FieldSponge { public: + /** + * @brief Defines what phase of the sponge algorithm we are in. + * + * ABSORB: 'absorbing' field elements into the sponge + * SQUEEZE: compressing the sponge and extracting a field element + * + */ enum Mode { ABSORB, SQUEEZE, }; + + // sponge state. t = rate + capacity. capacity = 1 field element (~256 bits) std::array state; + + // cached elements that have been absorbed. std::array cache; size_t cache_size = 0; Mode mode = Mode::ABSORB; @@ -42,36 +55,37 @@ template perform_duplex() { + // zero-pad the cache for (size_t i = cache_size; i < rate; ++i) { cache[i] = 0; } + // add the cache into sponge state for (size_t i = 0; i < rate; ++i) { state[i] += cache[i]; } - // todo unify types between SPonge and permutation - std::vector in(state.begin(), state.end()); - auto res = Permutation::permutation(in); + state = Permutation::permutation(state); + // return `rate` number of field elements from the sponge state. std::array output; - for (size_t i = 0; i < t; ++i) { - state[i] = res[i]; - } for (size_t i = 0; i < rate; ++i) { output[i] = state[i]; } - return output; } void absorb(const FF& input) { if (mode == Mode::ABSORB && cache_size == rate) { + // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache perform_duplex(); cache[0] = input; cache_size = 1; } else if (mode == Mode::ABSORB && cache_size < rate) { + // If we're absorbing, and the cache is not full, add the input into the cache cache[cache_size] = input; cache_size += 1; } else if (mode == Mode::SQUEEZE) { + // If we're in squeeze mode, switch to absorb mode and add the input into the cache. + // N.B. I don't think this code path can be reached?! cache[0] = input; cache_size = 1; mode = Mode::ABSORB; @@ -81,10 +95,15 @@ template + */ template static std::array hash_internal(std::span input) { size_t in_len = input.size(); @@ -110,6 +138,9 @@ template Date: Mon, 30 Oct 2023 19:21:38 +0000 Subject: [PATCH 06/34] comments --- .../cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp | 4 ++-- .../src/barretenberg/crypto/poseidon2/poseidon2_params.hpp | 4 ++++ .../crypto/poseidon2/poseidon2_permutation.test.cpp | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp index c5f4f3e9dd3..d95456ade86 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -30,8 +30,8 @@ TEST(Poseidon2, BasicTests) } // N.B. these hardcoded values were extracted from the algorithm being tested. These are NOT independent test vectors! -// TODO(@zac-williamson): find independent test vectors we can compare against! (very hard to find given flexibility of -// Poseidon's parametrisation) +// TODO(@zac-williamson #3132): find independent test vectors we can compare against! (very hard to find given +// flexibility of Poseidon's parametrisation) TEST(Poseidon2, ConsistencyCheck) { barretenberg::fr a(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp index 54f3a6a65ff..8d674032771 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp @@ -12,6 +12,8 @@ struct Poseidon2Bn254ScalarFieldParams { static constexpr size_t rounds_p = 56; static constexpr size_t sbox_size = 254; + // generated in `poseidon2_derive_params.hpp`. N.B. does not use the method outlined in the poseidon2 paper + // (requires implementation of some extra 3rd party crypto). May need to change for #3132 static constexpr std::array, rounds_f + rounds_p> round_constants{ std::array{ FF(std::string("0x15eea6dca2b448bd09150227f045553c94d4cd0502e0c5a24c588fe3e311fa67")), @@ -399,6 +401,8 @@ struct Poseidon2Bn254ScalarFieldParams { }, }; + // generated in `poseidon2_derive_params.hpp`. N.B. does not use the method outlined in the poseidon2 paper + // (requires implementation of some extra 3rd party crypto). May need to change for #3132 static constexpr std::array internal_matrix_diagonal = { FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp index 4dab40cb728..20f0fc39e3a 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp @@ -30,8 +30,8 @@ TEST(Poseidon2Permutation, BasicTests) } // N.B. these hardcoded values were extracted from the algorithm being tested. These are NOT independent test vectors! -// TODO(@zac-williamson): find independent test vectors we can compare against! (very hard to find given flexibility of -// Poseidon's parametrisation) +// TODO(@zac-williamson #3132): find independent test vectors we can compare against! (very hard to find given +// flexibility of Poseidon's parametrisation) TEST(Poseidon2Permutation, ConsistencyCheck) { barretenberg::fr a(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); From 3dbd8df23e02cc287cd6d1e3d40a0f0a3cca7b6a Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 30 Oct 2023 19:30:19 +0000 Subject: [PATCH 07/34] removed string_view constructors --- .../src/barretenberg/crypto/poseidon2/poseidon2.test.cpp | 2 +- .../crypto/poseidon2/poseidon2_permutation.test.cpp | 8 ++++---- .../src/barretenberg/ecc/fields/field_declarations.hpp | 8 +------- .../cpp/src/barretenberg/numeric/uint256/uint256.hpp | 3 +-- .../cpp/src/barretenberg/numeric/uint256/uint256.test.cpp | 6 ++---- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp index d95456ade86..26f7fe3f513 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -42,7 +42,7 @@ TEST(Poseidon2, ConsistencyCheck) std::array input{ a, b, c, d }; auto result = crypto::Poseidon2::hash(input); - barretenberg::fr expected(std::string_view("0x2f8f825d4ba3c0461bd4804e7e9490775b6f107e2eea15d6c74d370d465f7e6d")); + barretenberg::fr expected(std::string("0x2f8f825d4ba3c0461bd4804e7e9490775b6f107e2eea15d6c74d370d465f7e6d")); EXPECT_EQ(result, expected); } diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp index 20f0fc39e3a..4bd45a6de68 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp @@ -43,10 +43,10 @@ TEST(Poseidon2Permutation, ConsistencyCheck) auto result = crypto::Poseidon2Permutation::permutation(input); std::array expected{ - barretenberg::fr(std::string_view("0x0514d38493ec8da89f9e2b599bc20f96206ad0c94bc2751e6df03003009aa2ea")), - barretenberg::fr(std::string_view("0x0757d335371eacea287976a7b26729a74801720418bfdac37d852ac198b585ed")), - barretenberg::fr(std::string_view("0x19f5168edd96d2c8800d460908dde37c5dd36d56ae905faa8660182a2803c56c")), - barretenberg::fr(std::string_view("0x0096047284f80a35f2f9f95101a9287e99e1afb0866f19e86286a09bdb203685")), + barretenberg::fr(std::string("0x0514d38493ec8da89f9e2b599bc20f96206ad0c94bc2751e6df03003009aa2ea")), + barretenberg::fr(std::string("0x0757d335371eacea287976a7b26729a74801720418bfdac37d852ac198b585ed")), + barretenberg::fr(std::string("0x19f5168edd96d2c8800d460908dde37c5dd36d56ae905faa8660182a2803c56c")), + barretenberg::fr(std::string("0x0096047284f80a35f2f9f95101a9287e99e1afb0866f19e86286a09bdb203685")), }; EXPECT_EQ(result, expected); } diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 9158291d4f9..a0446f17916 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -106,13 +106,7 @@ template struct alignas(32) field { self_to_montgomery_form(); } - constexpr explicit field(std::string& input) noexcept - { - uint256_t value(input); - *this = field(value); - } - - constexpr explicit field(std::string_view input) noexcept + constexpr explicit field(std::string input) noexcept { uint256_t value(input); *this = field(value); diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp index eeb1e310d78..955b340e942 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp @@ -36,7 +36,7 @@ class alignas(32) uint256_t { {} constexpr uint256_t(uint256_t&& other) noexcept = default; - explicit constexpr uint256_t(std::string_view input) noexcept + explicit constexpr uint256_t(std::string input) noexcept { /* Quick and dirty conversion from a single character to its hex equivelent */ constexpr auto HexCharToInt = [](uint8_t Input) { @@ -76,7 +76,6 @@ class alignas(32) uint256_t { data[2] = limbs[1]; data[3] = limbs[0]; } - explicit constexpr uint256_t(std::string const& str) noexcept { *this = uint256_t(std::string_view(str)); } static constexpr uint256_t from_uint128(const uint128_t a) noexcept { diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp index 9b76da65b02..28234d0c279 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.test.cpp @@ -11,13 +11,11 @@ using namespace numeric; TEST(uint256, TestStringConstructors) { std::string input = "9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"; - constexpr std::string_view input2("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); - constexpr std::string_view input3("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); const std::string input4("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); const uint256_t result1(input); - constexpr uint256_t result2(input2); - const uint256_t result3(input3); + constexpr uint256_t result2("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); + const uint256_t result3("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"); const uint256_t result4(input4); constexpr uint256_t expected{ 0xabcdef0123456789, From 3631294805c47de14dea211578525a361bcb1680 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 31 Oct 2023 11:05:52 +0000 Subject: [PATCH 08/34] poseidon2 parameters now consistent with definition in paper params use sage script derived from hoizen labs implementation --- .../crypto/poseidon2/poseidon2.test.cpp | 2 +- .../poseidon2/poseidon2_cpp_params.sage | 726 +++++++++++++++ .../poseidon2/poseidon2_derive_params.hpp | 106 --- .../poseidon2_derive_params.test.cpp | 39 - .../crypto/poseidon2/poseidon2_params.hpp | 823 +++++++++--------- .../poseidon2/poseidon2_permutation.hpp | 18 +- .../poseidon2/poseidon2_permutation.test.cpp | 19 +- 7 files changed, 1182 insertions(+), 551 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_cpp_params.sage delete mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp index 26f7fe3f513..33757efd2b1 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp @@ -42,7 +42,7 @@ TEST(Poseidon2, ConsistencyCheck) std::array input{ a, b, c, d }; auto result = crypto::Poseidon2::hash(input); - barretenberg::fr expected(std::string("0x2f8f825d4ba3c0461bd4804e7e9490775b6f107e2eea15d6c74d370d465f7e6d")); + barretenberg::fr expected(std::string("0x150c19ae11b3290c137c7a4d760d9482a6581d731535f560c3601d6a766b0937")); EXPECT_EQ(result, expected); } diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_cpp_params.sage b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_cpp_params.sage new file mode 100644 index 00000000000..c914d4988fa --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_cpp_params.sage @@ -0,0 +1,726 @@ +# Remark: Original sage script authored by Markus Schofnegger from Horizen Labs +# Original source: https://github.com/HorizenLabs/poseidon2/blob/main/poseidon2_rust_params.sage +# Licenced under MIT. +# Remark: This script contains functionality for GF(2^n), but currently works only over GF(p)! A few small adaptations are needed for GF(2^n). +from sage.rings.polynomial.polynomial_gf2x import GF2X_BuildIrred_list +from math import * +import itertools + +########################################################################### +# p = 18446744069414584321 # GoldiLocks +# p = 2013265921 # BabyBear +# p = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # BLS12-381 +p = 21888242871839275222246405745257275088548364400416034343698204186575808495617 # BN254/BN256 +# p = 28948022309329048855892746252171976963363056481941560715954676764349967630337 # Pasta (Pallas) +# p = 28948022309329048855892746252171976963363056481941647379679742748393362948097 # Pasta (Vesta) + +n = len(p.bits()) # bit +# t = 12 # GoldiLocks (t = 12 for sponge, t = 8 for compression) +# t = 16 # BabyBear (t = 24 for sponge, t = 16 for compression) +t = 4 # BN254/BN256, BLS12-381, Pallas, Vesta (t = 3 for sponge, t = 2 for compression) + +FIELD = 1 +SBOX = 0 +FIELD_SIZE = n +NUM_CELLS = t + +def get_alpha(p): + for alpha in range(3, p): + if gcd(alpha, p-1) == 1: + break + return alpha + +alpha = get_alpha(p) + +def get_sbox_cost(R_F, R_P, N, t): + return int(t * R_F + R_P) + +def get_size_cost(R_F, R_P, N, t): + n = ceil(float(N) / t) + return int((N * R_F) + (n * R_P)) + +def poseidon_calc_final_numbers_fixed(p, t, alpha, M, security_margin): + # [Min. S-boxes] Find best possible for t and N + n = ceil(log(p, 2)) + N = int(n * t) + cost_function = get_sbox_cost + ret_list = [] + (R_F, R_P) = find_FD_round_numbers(p, t, alpha, M, cost_function, security_margin) + min_sbox_cost = cost_function(R_F, R_P, N, t) + ret_list.append(R_F) + ret_list.append(R_P) + ret_list.append(min_sbox_cost) + + # [Min. Size] Find best possible for t and N + # Minimum number of S-boxes for fixed n results in minimum size also (round numbers are the same)! + min_size_cost = get_size_cost(R_F, R_P, N, t) + ret_list.append(min_size_cost) + + return ret_list # [R_F, R_P, min_sbox_cost, min_size_cost] + +def find_FD_round_numbers(p, t, alpha, M, cost_function, security_margin): + n = ceil(log(p, 2)) + N = int(n * t) + + sat_inequiv = sat_inequiv_alpha + + R_P = 0 + R_F = 0 + min_cost = float("inf") + max_cost_rf = 0 + # Brute-force approach + for R_P_t in range(1, 500): + for R_F_t in range(4, 100): + if R_F_t % 2 == 0: + if (sat_inequiv(p, t, R_F_t, R_P_t, alpha, M) == True): + if security_margin == True: + R_F_t += 2 + R_P_t = int(ceil(float(R_P_t) * 1.075)) + cost = cost_function(R_F_t, R_P_t, N, t) + if (cost < min_cost) or ((cost == min_cost) and (R_F_t < max_cost_rf)): + R_P = ceil(R_P_t) + R_F = ceil(R_F_t) + min_cost = cost + max_cost_rf = R_F + return (int(R_F), int(R_P)) + +def sat_inequiv_alpha(p, t, R_F, R_P, alpha, M): + N = int(FIELD_SIZE * NUM_CELLS) + + if alpha > 0: + R_F_1 = 6 if M <= ((floor(log(p, 2) - ((alpha-1)/2.0))) * (t + 1)) else 10 # Statistical + R_F_2 = 1 + ceil(log(2, alpha) * min(M, FIELD_SIZE)) + ceil(log(t, alpha)) - R_P # Interpolation + R_F_3 = (log(2, alpha) * min(M, log(p, 2))) - R_P # Groebner 1 + R_F_4 = t - 1 + log(2, alpha) * min(M / float(t + 1), log(p, 2) / float(2)) - R_P # Groebner 2 + R_F_5 = (t - 2 + (M / float(2 * log(alpha, 2))) - R_P) / float(t - 1) # Groebner 3 + R_F_max = max(ceil(R_F_1), ceil(R_F_2), ceil(R_F_3), ceil(R_F_4), ceil(R_F_5)) + + # Addition due to https://eprint.iacr.org/2023/537.pdf + r_temp = floor(t / 3.0) + over = (R_F - 1) * t + R_P + r_temp + r_temp * (R_F / 2.0) + R_P + alpha + under = r_temp * (R_F / 2.0) + R_P + alpha + binom_log = log(binomial(over, under), 2) + if binom_log == inf: + binom_log = M + 1 + cost_gb4 = ceil(2 * binom_log) # Paper uses 2.3727, we are more conservative here + + return ((R_F >= R_F_max) and (cost_gb4 >= M)) + else: + print("Invalid value for alpha!") + exit(1) + +R_F_FIXED, R_P_FIXED, _, _ = poseidon_calc_final_numbers_fixed(p, t, alpha, 128, True) +#print("+++ R_F = {0}, R_P = {1} +++".format(R_F_FIXED, R_P_FIXED)) + +# For STARK TODO +# r_p_mod = R_P_FIXED % NUM_CELLS +# if r_p_mod != 0: +# R_P_FIXED = R_P_FIXED + NUM_CELLS - r_p_mod + +########################################################################### + +INIT_SEQUENCE = [] + +PRIME_NUMBER = p +# if FIELD == 1 and len(sys.argv) != 8: +# print("Please specify a prime number (in hex format)!") +# exit() +# elif FIELD == 1 and len(sys.argv) == 8: +# PRIME_NUMBER = int(sys.argv[7], 16) # e.g. 0xa7, 0xFFFFFFFFFFFFFEFF, 0xa1a42c3efd6dbfe08daa6041b36322ef + +F = GF(PRIME_NUMBER) + +def grain_sr_generator(): + bit_sequence = INIT_SEQUENCE + for _ in range(0, 160): + new_bit = bit_sequence[62] ^^ bit_sequence[51] ^^ bit_sequence[38] ^^ bit_sequence[23] ^^ bit_sequence[13] ^^ bit_sequence[0] + bit_sequence.pop(0) + bit_sequence.append(new_bit) + + while True: + new_bit = bit_sequence[62] ^^ bit_sequence[51] ^^ bit_sequence[38] ^^ bit_sequence[23] ^^ bit_sequence[13] ^^ bit_sequence[0] + bit_sequence.pop(0) + bit_sequence.append(new_bit) + while new_bit == 0: + new_bit = bit_sequence[62] ^^ bit_sequence[51] ^^ bit_sequence[38] ^^ bit_sequence[23] ^^ bit_sequence[13] ^^ bit_sequence[0] + bit_sequence.pop(0) + bit_sequence.append(new_bit) + new_bit = bit_sequence[62] ^^ bit_sequence[51] ^^ bit_sequence[38] ^^ bit_sequence[23] ^^ bit_sequence[13] ^^ bit_sequence[0] + bit_sequence.pop(0) + bit_sequence.append(new_bit) + new_bit = bit_sequence[62] ^^ bit_sequence[51] ^^ bit_sequence[38] ^^ bit_sequence[23] ^^ bit_sequence[13] ^^ bit_sequence[0] + bit_sequence.pop(0) + bit_sequence.append(new_bit) + yield new_bit +grain_gen = grain_sr_generator() + +def grain_random_bits(num_bits): + random_bits = [next(grain_gen) for i in range(0, num_bits)] + # random_bits.reverse() ## Remove comment to start from least significant bit + random_int = int("".join(str(i) for i in random_bits), 2) + return random_int + +def init_generator(field, sbox, n, t, R_F, R_P): + # Generate initial sequence based on parameters + bit_list_field = [_ for _ in (bin(FIELD)[2:].zfill(2))] + bit_list_sbox = [_ for _ in (bin(SBOX)[2:].zfill(4))] + bit_list_n = [_ for _ in (bin(FIELD_SIZE)[2:].zfill(12))] + bit_list_t = [_ for _ in (bin(NUM_CELLS)[2:].zfill(12))] + bit_list_R_F = [_ for _ in (bin(R_F)[2:].zfill(10))] + bit_list_R_P = [_ for _ in (bin(R_P)[2:].zfill(10))] + bit_list_1 = [1] * 30 + global INIT_SEQUENCE + INIT_SEQUENCE = bit_list_field + bit_list_sbox + bit_list_n + bit_list_t + bit_list_R_F + bit_list_R_P + bit_list_1 + INIT_SEQUENCE = [int(_) for _ in INIT_SEQUENCE] + +def generate_constants(field, n, t, R_F, R_P, prime_number): + round_constants = [] + # num_constants = (R_F + R_P) * t # Poseidon + num_constants = (R_F * t) + R_P # Poseidon2 + + if field == 0: + for i in range(0, num_constants): + random_int = grain_random_bits(n) + round_constants.append(random_int) + elif field == 1: + for i in range(0, num_constants): + random_int = grain_random_bits(n) + while random_int >= prime_number: + # print("[Info] Round constant is not in prime field! Taking next one.") + random_int = grain_random_bits(n) + round_constants.append(random_int) + # Add (t-1) zeroes for Poseidon2 if partial round + if i >= ((R_F/2) * t) and i < (((R_F/2) * t) + R_P): + round_constants.extend([0] * (t-1)) + return round_constants + +def print_round_constants(round_constants, n, field): + print("Number of round constants:", len(round_constants)) + + if field == 0: + print("Round constants for GF(2^n):") + elif field == 1: + print("Round constants for GF(p):") + hex_length = int(ceil(float(n) / 4)) + 2 # +2 for "0x" + print(["{0:#0{1}x}".format(entry, hex_length) for entry in round_constants]) + +def create_mds_p(n, t): + M = matrix(F, t, t) + + # Sample random distinct indices and assign to xs and ys + while True: + flag = True + rand_list = [F(grain_random_bits(n)) for _ in range(0, 2*t)] + while len(rand_list) != len(set(rand_list)): # Check for duplicates + rand_list = [F(grain_random_bits(n)) for _ in range(0, 2*t)] + xs = rand_list[:t] + ys = rand_list[t:] + # xs = [F(ele) for ele in range(0, t)] + # ys = [F(ele) for ele in range(t, 2*t)] + for i in range(0, t): + for j in range(0, t): + if (flag == False) or ((xs[i] + ys[j]) == 0): + flag = False + else: + entry = (xs[i] + ys[j])^(-1) + M[i, j] = entry + if flag == False: + continue + return M + +def generate_vectorspace(round_num, M, M_round, NUM_CELLS): + t = NUM_CELLS + s = 1 + V = VectorSpace(F, t) + if round_num == 0: + return V + elif round_num == 1: + return V.subspace(V.basis()[s:]) + else: + mat_temp = matrix(F) + for i in range(0, round_num-1): + add_rows = [] + for j in range(0, s): + add_rows.append(M_round[i].rows()[j][s:]) + mat_temp = matrix(mat_temp.rows() + add_rows) + r_k = mat_temp.right_kernel() + extended_basis_vectors = [] + for vec in r_k.basis(): + extended_basis_vectors.append(vector([0]*s + list(vec))) + S = V.subspace(extended_basis_vectors) + + return S + +def subspace_times_matrix(subspace, M, NUM_CELLS): + t = NUM_CELLS + V = VectorSpace(F, t) + subspace_basis = subspace.basis() + new_basis = [] + for vec in subspace_basis: + new_basis.append(M * vec) + new_subspace = V.subspace(new_basis) + return new_subspace + +# Returns True if the matrix is considered secure, False otherwise +def algorithm_1(M, NUM_CELLS): + t = NUM_CELLS + s = 1 + r = floor((t - s) / float(s)) + + # Generate round matrices + M_round = [] + for j in range(0, t+1): + M_round.append(M^(j+1)) + + for i in range(1, r+1): + mat_test = M^i + entry = mat_test[0, 0] + mat_target = matrix.circulant(vector([entry] + ([F(0)] * (t-1)))) + + if (mat_test - mat_target) == matrix.circulant(vector([F(0)] * (t))): + return [False, 1] + + S = generate_vectorspace(i, M, M_round, t) + V = VectorSpace(F, t) + + basis_vectors= [] + for eigenspace in mat_test.eigenspaces_right(format='galois'): + if (eigenspace[0] not in F): + continue + vector_subspace = eigenspace[1] + intersection = S.intersection(vector_subspace) + basis_vectors += intersection.basis() + IS = V.subspace(basis_vectors) + + if IS.dimension() >= 1 and IS != V: + return [False, 2] + for j in range(1, i+1): + S_mat_mul = subspace_times_matrix(S, M^j, t) + if S == S_mat_mul: + print("S.basis():\n", S.basis()) + return [False, 3] + + return [True, 0] + +# Returns True if the matrix is considered secure, False otherwise +def algorithm_2(M, NUM_CELLS): + t = NUM_CELLS + s = 1 + + V = VectorSpace(F, t) + trail = [None, None] + test_next = False + I = range(0, s) + I_powerset = list(sage.misc.misc.powerset(I))[1:] + for I_s in I_powerset: + test_next = False + new_basis = [] + for l in I_s: + new_basis.append(V.basis()[l]) + IS = V.subspace(new_basis) + for i in range(s, t): + new_basis.append(V.basis()[i]) + full_iota_space = V.subspace(new_basis) + for l in I_s: + v = V.basis()[l] + while True: + delta = IS.dimension() + v = M * v + IS = V.subspace(IS.basis() + [v]) + if IS.dimension() == t or IS.intersection(full_iota_space) != IS: + test_next = True + break + if IS.dimension() <= delta: + break + if test_next == True: + break + if test_next == True: + continue + return [False, [IS, I_s]] + + return [True, None] + +# Returns True if the matrix is considered secure, False otherwise +def algorithm_3(M, NUM_CELLS): + t = NUM_CELLS + s = 1 + + V = VectorSpace(F, t) + + l = 4*t + for r in range(2, l+1): + next_r = False + res_alg_2 = algorithm_2(M^r, t) + if res_alg_2[0] == False: + return [False, None] + + # if res_alg_2[1] == None: + # continue + # IS = res_alg_2[1][0] + # I_s = res_alg_2[1][1] + # for j in range(1, r): + # IS = subspace_times_matrix(IS, M, t) + # I_j = [] + # for i in range(0, s): + # new_basis = [] + # for k in range(0, t): + # if k != i: + # new_basis.append(V.basis()[k]) + # iota_space = V.subspace(new_basis) + # if IS.intersection(iota_space) != iota_space: + # single_iota_space = V.subspace([V.basis()[i]]) + # if IS.intersection(single_iota_space) == single_iota_space: + # I_j.append(i) + # else: + # next_r = True + # break + # if next_r == True: + # break + # if next_r == True: + # continue + # return [False, [IS, I_j, r]] + + return [True, None] + +def check_minpoly_condition(M, NUM_CELLS): + max_period = 2*NUM_CELLS + all_fulfilled = True + M_temp = M + for i in range(1, max_period + 1): + if not ((M_temp.minimal_polynomial().degree() == NUM_CELLS) and (M_temp.minimal_polynomial().is_irreducible() == True)): + all_fulfilled = False + break + M_temp = M * M_temp + return all_fulfilled + +def generate_matrix(FIELD, FIELD_SIZE, NUM_CELLS): + if FIELD == 0: + print("Matrix generation not implemented for GF(2^n).") + exit(1) + elif FIELD == 1: + mds_matrix = create_mds_p(FIELD_SIZE, NUM_CELLS) + result_1 = algorithm_1(mds_matrix, NUM_CELLS) + result_2 = algorithm_2(mds_matrix, NUM_CELLS) + result_3 = algorithm_3(mds_matrix, NUM_CELLS) + while result_1[0] == False or result_2[0] == False or result_3[0] == False: + mds_matrix = create_mds_p(FIELD_SIZE, NUM_CELLS) + result_1 = algorithm_1(mds_matrix, NUM_CELLS) + result_2 = algorithm_2(mds_matrix, NUM_CELLS) + result_3 = algorithm_3(mds_matrix, NUM_CELLS) + return mds_matrix + +def generate_matrix_full(NUM_CELLS): + M = None + if t == 2: + M = matrix.circulant(vector([F(2), F(1)])) + elif t == 3: + M = matrix.circulant(vector([F(2), F(1), F(1)])) + elif t == 4: + M = matrix(F, [[F(5), F(7), F(1), F(3)], [F(4), F(6), F(1), F(1)], [F(1), F(3), F(5), F(7)], [F(1), F(1), F(4), F(6)]]) + elif (t % 4) == 0: + M = matrix(F, t, t) + # M_small = matrix.circulant(vector([F(3), F(2), F(1), F(1)])) + M_small = matrix(F, [[F(5), F(7), F(1), F(3)], [F(4), F(6), F(1), F(1)], [F(1), F(3), F(5), F(7)], [F(1), F(1), F(4), F(6)]]) + small_num = t // 4 + for i in range(0, small_num): + for j in range(0, small_num): + if i == j: + M[i*4:(i+1)*4,j*4:(j+1)*4] = 2* M_small + else: + M[i*4:(i+1)*4,j*4:(j+1)*4] = M_small + else: + print("Error: No matrix for these parameters.") + exit() + return M + +def generate_matrix_partial(FIELD, FIELD_SIZE, NUM_CELLS): ## TODO: Prioritize small entries + entry_max_bit_size = FIELD_SIZE + if FIELD == 0: + print("Matrix generation not implemented for GF(2^n).") + exit(1) + elif FIELD == 1: + M = None + if t == 2: + M = matrix(F, [[F(2), F(1)], [F(1), F(3)]]) + elif t == 3: + M = matrix(F, [[F(2), F(1), F(1)], [F(1), F(2), F(1)], [F(1), F(1), F(3)]]) + else: + M_circulant = matrix.circulant(vector([F(0)] + [F(1) for _ in range(0, NUM_CELLS - 1)])) + M_diagonal = matrix.diagonal([F(grain_random_bits(entry_max_bit_size)) for _ in range(0, NUM_CELLS)]) + M = M_circulant + M_diagonal + # while algorithm_1(M, NUM_CELLS)[0] == False or algorithm_2(M, NUM_CELLS)[0] == False or algorithm_3(M, NUM_CELLS)[0] == False: + while check_minpoly_condition(M, NUM_CELLS) == False: + M_diagonal = matrix.diagonal([F(grain_random_bits(entry_max_bit_size)) for _ in range(0, NUM_CELLS)]) + M = M_circulant + M_diagonal + + if(algorithm_1(M, NUM_CELLS)[0] == False or algorithm_2(M, NUM_CELLS)[0] == False or algorithm_3(M, NUM_CELLS)[0] == False): + print("Error: Generated partial matrix is not secure w.r.t. subspace trails.") + exit() + return M + +def generate_matrix_partial_small_entries(FIELD, FIELD_SIZE, NUM_CELLS): + if FIELD == 0: + print("Matrix generation not implemented for GF(2^n).") + exit(1) + elif FIELD == 1: + M_circulant = matrix.circulant(vector([F(0)] + [F(1) for _ in range(0, NUM_CELLS - 1)])) + combinations = list(itertools.product(range(2, 6), repeat=NUM_CELLS)) + for entry in combinations: + M = M_circulant + matrix.diagonal(vector(F, list(entry))) + print(M) + # if M.is_invertible() == False or algorithm_1(M, NUM_CELLS)[0] == False or algorithm_2(M, NUM_CELLS)[0] == False or algorithm_3(M, NUM_CELLS)[0] == False: + if M.is_invertible() == False or check_minpoly_condition(M, NUM_CELLS) == False: + continue + return M + +def matrix_partial_m_1(matrix_partial, NUM_CELLS): + M_circulant = matrix.identity(F, NUM_CELLS) + return matrix_partial - M_circulant + +def print_linear_layer(M, n, t): + print("n:", n) + print("t:", t) + print("N:", (n * t)) + print("Result Algorithm 1:\n", algorithm_1(M, NUM_CELLS)) + print("Result Algorithm 2:\n", algorithm_2(M, NUM_CELLS)) + print("Result Algorithm 3:\n", algorithm_3(M, NUM_CELLS)) + hex_length = int(ceil(float(n) / 4)) + 2 # +2 for "0x" + print("Prime number:", "0x" + hex(PRIME_NUMBER)) + matrix_string = "[" + for i in range(0, t): + matrix_string += str(["{0:#0{1}x}".format(int(entry), hex_length) for entry in M[i]]) + if i < (t-1): + matrix_string += "," + matrix_string += "]" + print("MDS matrix:\n", matrix_string) + +def calc_equivalent_matrices(MDS_matrix_field): + # Following idea: Split M into M' * M'', where M'' is "cheap" and M' can move before the partial nonlinear layer + # The "previous" matrix layer is then M * M'. Due to the construction of M', the M[0,0] and v values will be the same for the new M' (and I also, obviously) + # Thus: Compute the matrices, store the w_hat and v_hat values + + MDS_matrix_field_transpose = MDS_matrix_field.transpose() + + w_hat_collection = [] + v_collection = [] + v = MDS_matrix_field_transpose[[0], list(range(1,t))] + + M_mul = MDS_matrix_field_transpose + M_i = matrix(F, t, t) + for i in range(R_P_FIXED - 1, -1, -1): + M_hat = M_mul[list(range(1,t)), list(range(1,t))] + w = M_mul[list(range(1,t)), [0]] + v = M_mul[[0], list(range(1,t))] + v_collection.append(v.list()) + w_hat = M_hat.inverse() * w + w_hat_collection.append(w_hat.list()) + + # Generate new M_i, and multiplication M * M_i for "previous" round + M_i = matrix.identity(t) + M_i[list(range(1,t)), list(range(1,t))] = M_hat + M_mul = MDS_matrix_field_transpose * M_i + + return M_i, v_collection, w_hat_collection, MDS_matrix_field_transpose[0, 0] + +def calc_equivalent_constants(constants, MDS_matrix_field): + constants_temp = [constants[index:index+t] for index in range(0, len(constants), t)] + + MDS_matrix_field_transpose = MDS_matrix_field.transpose() + + # Start moving round constants up + # Calculate c_i' = M^(-1) * c_(i+1) + # Split c_i': Add c_i'[0] AFTER the S-box, add the rest to c_i + # I.e.: Store c_i'[0] for each of the partial rounds, and make c_i = c_i + c_i' (where now c_i'[0] = 0) + num_rounds = R_F_FIXED + R_P_FIXED + R_f = R_F_FIXED / 2 + for i in range(num_rounds - 2 - R_f, R_f - 1, -1): + inv_cip1 = list(vector(constants_temp[i+1]) * MDS_matrix_field_transpose.inverse()) + constants_temp[i] = list(vector(constants_temp[i]) + vector([0] + inv_cip1[1:])) + constants_temp[i+1] = [inv_cip1[0]] + [0] * (t-1) + + return constants_temp + +def poseidon(input_words, matrix, round_constants): + + R_f = int(R_F_FIXED / 2) + + round_constants_counter = 0 + + state_words = list(input_words) + + # First full rounds + for r in range(0, R_f): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + for i in range(0, t): + state_words[i] = (state_words[i])^alpha + state_words = list(matrix * vector(state_words)) + + # Middle partial rounds + for r in range(0, R_P_FIXED): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + state_words[0] = (state_words[0])^alpha + state_words = list(matrix * vector(state_words)) + + # Last full rounds + for r in range(0, R_f): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + for i in range(0, t): + state_words[i] = (state_words[i])^alpha + state_words = list(matrix * vector(state_words)) + + return state_words + +def poseidon2(input_words, matrix_full, matrix_partial, round_constants): + + R_f = int(R_F_FIXED / 2) + + round_constants_counter = 0 + + state_words = list(input_words) + + # First matrix mul + state_words = list(matrix_full * vector(state_words)) + + # First full rounds + for r in range(0, R_f): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + for i in range(0, t): + state_words[i] = (state_words[i])^alpha + state_words = list(matrix_full * vector(state_words)) + + # Middle partial rounds + for r in range(0, R_P_FIXED): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + state_words[0] = (state_words[0])^alpha + state_words = list(matrix_partial * vector(state_words)) + + # Last full rounds + for r in range(0, R_f): + # Round constants, nonlinear layer, matrix multiplication + for i in range(0, t): + state_words[i] = state_words[i] + round_constants[round_constants_counter] + round_constants_counter += 1 + for i in range(0, t): + state_words[i] = (state_words[i])^alpha + state_words = list(matrix_full * vector(state_words)) + + return state_words + +# Init +init_generator(FIELD, SBOX, FIELD_SIZE, NUM_CELLS, R_F_FIXED, R_P_FIXED) + +# Round constants +round_constants = generate_constants(FIELD, FIELD_SIZE, NUM_CELLS, R_F_FIXED, R_P_FIXED, PRIME_NUMBER) +# print_round_constants(round_constants, FIELD_SIZE, FIELD) + +# Matrix +# MDS = generate_matrix(FIELD, FIELD_SIZE, NUM_CELLS) +MATRIX_FULL = generate_matrix_full(NUM_CELLS) +MATRIX_PARTIAL = generate_matrix_partial(FIELD, FIELD_SIZE, NUM_CELLS) +MATRIX_PARTIAL_DIAGONAL_M_1 = [matrix_partial_m_1(MATRIX_PARTIAL, NUM_CELLS)[i,i] for i in range(0, NUM_CELLS)] + +def to_hex(value): + l = len(hex(p - 1)) + if l % 2 == 1: + l = l + 1 + value = hex(int(value))[2:] + value = "0x" + value.zfill(l - 2) + print("FF(std::string(\"{}\")),".format(value)) + + + +# # MDS +# print("pub static ref MDS{}: Vec> = vec![".format(t)) +# for vec in MDS: +# print("vec![", end="") +# for val in vec: +# to_hex(val) +# print("],") +# print("];") +# print() + +print("// poseidon2 paramters generated via sage script") +print("// original author: Markus Schofnegger from Horizen Labs") +print("// original source: https://github.com/HorizenLabs/poseidon2/blob/main/poseidon2_rust_params.sage") +print("#pragma once\n") + +print("#include \"barretenberg/ecc/curves/bn254/fr.hpp\"\n") + +print("namespace crypto {\n") + +print("struct Poseidon2Bn254ScalarFieldParams{\n") +print(" using FF = barretenberg::fr;") +print(" static constexpr size_t t = {};".format(t)) +print(" static constexpr size_t d = {};".format(alpha)) + +print(" static constexpr size_t rounds_f = {};".format(R_F_FIXED)) +print(" static constexpr size_t rounds_p = {};".format(R_P_FIXED)) +print(" static constexpr size_t sbox_size = {};".format(FIELD_SIZE)) + +# Efficient partial matrix (diagonal - 1) +print("static constexpr std::array internal_matrix_diagonal = {") +for val in MATRIX_PARTIAL_DIAGONAL_M_1: + to_hex(val) +print("};") +print() + +# Efficient partial matrix (full) +print("static constexpr std::array, t> internal_matrix = {") +for vec in MATRIX_PARTIAL: + print("std::array{") + for val in vec: + to_hex(val) + print("},") +print("};") +print() + +# Round constants +print("static constexpr std::array, rounds_f + rounds_p> round_constants{") +for (i,val) in enumerate(round_constants): + if i % t == 0: + print("std::array{") + to_hex(val) + if i % t == t - 1: + print("},") +print("};") +print() + +#print("pub static ref POSEIDON_{}_PARAMS: Arc> = Arc::new(PoseidonParams::new({}, {}, {}, {}, &MAT_DIAG{}_M_1, &RC{}));".format(t, t, alpha, R_F_FIXED, R_P_FIXED , t, t)) + + + +state_in = vector([F(i) for i in range(t)]) +# state_out = poseidon(state_in, MDS, round_constants) +state_out = poseidon2(state_in, MATRIX_FULL, MATRIX_PARTIAL, round_constants) + +for (i,val) in enumerate(state_in): + if i % t == 0: + print("static constexpr std::array TEST_VECTOR_INPUT{") + to_hex(val) + if i % t == t - 1: + print("};") + +for (i,val) in enumerate(state_out): + if i % t == 0: + print("static constexpr std::array TEST_VECTOR_OUTPUT{") + to_hex(val) + if i % t == t - 1: + print("};") + +print("};") +print("} // namespace crypto") \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp deleted file mode 100644 index e87fa7cf89c..00000000000 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/crypto/blake3s/blake3s.hpp" -#include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/numeric/uintx/uintx.hpp" - -#include -#include -#include -#include -#include - -namespace crypto { - -template -class Poseidon2DeriveParams { - public: - static constexpr size_t NUM_ROUNDS = rounds_f + rounds_p; - static constexpr size_t BLAKE3S_OUTPUT_SIZE = 32; - - using RoundConstants = std::array; - using MatrixDiagonal = std::array; - using RoundConstantsContainer = std::array; - - static FF hash_to_field_element(uint8_t* buffer, size_t buffer_size) - { - buffer[buffer_size - 1] = 0; - const auto hash_hi = blake3::blake3s_constexpr(buffer, buffer_size); - buffer[buffer_size - 1] = 1; - const auto hash_lo = blake3::blake3s_constexpr(buffer, buffer_size); - // custom serialize methods as common/serialize.hpp is not constexpr! - const auto read_uint256 = [](const uint8_t* in) { - const auto read_limb = [](const uint8_t* in, uint64_t& out) { - for (size_t i = 0; i < 8; ++i) { - out += static_cast(in[i]) << ((7 - i) * 8); - } - }; - uint256_t out = 0; - read_limb(&in[0], out.data[3]); - read_limb(&in[8], out.data[2]); - read_limb(&in[16], out.data[1]); - read_limb(&in[24], out.data[0]); - return out; - }; - // interpret 64 byte hash output as a uint512_t, reduce to Fq element - //(512 bits of entropy ensures result is not biased as 512 >> Fq::modulus.get_msb()) - return FF(uint512_t(read_uint256(&hash_lo[0]), read_uint256(&hash_hi[0]))); - } - - // n.b. this can be made constexpr but it will nuke compile times as compiler will evaluate this method call at - // compile time - static MatrixDiagonal generate_internal_matrix_diagonal() - { - // TODO: validate the values produced by this method are secure. See https://eprint.iacr.org/2023/323 - std::string seed = "Poseidon2 Internal Matrix Parameters"; - std::vector seed_bytes(seed.begin(), seed.end()); - auto seed_hash = blake3::blake3s_constexpr(&seed_bytes[0], seed_bytes.size()); - - std::array m_preimage; - m_preimage[BLAKE3S_OUTPUT_SIZE] = 0; - m_preimage[BLAKE3S_OUTPUT_SIZE + 1] = 0; - std::copy(seed_hash.begin(), seed_hash.end(), m_preimage.begin()); - - uint8_t count = 0; - MatrixDiagonal res; - for (size_t i = 0; i < t; ++i) { - m_preimage[BLAKE3S_OUTPUT_SIZE] = count++; - res[i] = hash_to_field_element(&seed_hash[0], 32); - } - return res; - } - - // n.b. this can be made constexpr but it will nuke compile times as compiler will evaluate this method call at - // compile time - static RoundConstantsContainer derive_round_constants() - { - std::string seed = "Gentlemen, a short view back to the past."; - std::vector seed_bytes(seed.begin(), seed.end()); - auto seed_hash = blake3::blake3s_constexpr(&seed_bytes[0], seed_bytes.size()); - constexpr size_t NUM_METADATA_BYTES = 7; - constexpr size_t PREIMAGE_SIZE = BLAKE3S_OUTPUT_SIZE + NUM_METADATA_BYTES; - - std::array rc_preimage; - std::copy(seed_hash.begin(), seed_hash.end(), rc_preimage.begin()); - - uint8_t rc_count = 0; - rc_preimage[BLAKE3S_OUTPUT_SIZE] = static_cast(t); - rc_preimage[BLAKE3S_OUTPUT_SIZE + 1] = static_cast(d); - rc_preimage[BLAKE3S_OUTPUT_SIZE + 2] = static_cast(rounds_f); - rc_preimage[BLAKE3S_OUTPUT_SIZE + 3] = static_cast(rounds_p); - rc_preimage[BLAKE3S_OUTPUT_SIZE + 4] = static_cast(sbox_size); - rc_preimage[BLAKE3S_OUTPUT_SIZE + 5] = rc_count; - rc_preimage[BLAKE3S_OUTPUT_SIZE + 6] = 0; - - RoundConstantsContainer round_constants; - for (size_t i = 0; i < NUM_ROUNDS; ++i) { - for (size_t j = 0; j < t; ++j) { - rc_preimage[BLAKE3S_OUTPUT_SIZE + 5] = rc_count++; - round_constants[i][j] = hash_to_field_element(&rc_preimage[0], PREIMAGE_SIZE); - } - } - return round_constants; - } -}; -} // namespace crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp deleted file mode 100644 index c85466985a9..00000000000 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_derive_params.test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "poseidon2_derive_params.hpp" -#include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "poseidon2_params.hpp" -#include - -using namespace barretenberg; -using namespace crypto; -namespace { -auto& engine = numeric::random::get_debug_engine(); -} - -namespace poseidon2_tests { -TEST(Poseidon2DeriveParams, ConsistencyCheckRoundConstants) -{ - auto generated_round_constants = - Poseidon2DeriveParams::derive_round_constants(); - auto expected_round_constants = Poseidon2Bn254ScalarFieldParams::round_constants; - EXPECT_EQ(generated_round_constants, expected_round_constants); -} - -TEST(Poseidon2DeriveParams, ConsistencyCheckMatrixDiagonal) -{ - auto generated_internal_matrix_diagonal = - Poseidon2DeriveParams::generate_internal_matrix_diagonal(); - auto expected_internal_matrix_diagonal = Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal; - EXPECT_EQ(generated_internal_matrix_diagonal, expected_internal_matrix_diagonal); -} - -} // namespace poseidon2_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp index 8d674032771..430d75f1fb6 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_params.hpp @@ -1,3 +1,6 @@ +// poseidon2 paramters generated via sage script +// original author: Markus Schofnegger from Horizen Labs +// original source: https://github.com/HorizenLabs/poseidon2/blob/main/poseidon2_rust_params.sage #pragma once #include "barretenberg/ecc/curves/bn254/fr.hpp" @@ -5,409 +8,445 @@ namespace crypto { struct Poseidon2Bn254ScalarFieldParams { + using FF = barretenberg::fr; static constexpr size_t t = 4; static constexpr size_t d = 5; static constexpr size_t rounds_f = 8; static constexpr size_t rounds_p = 56; static constexpr size_t sbox_size = 254; + static constexpr std::array internal_matrix_diagonal = { + FF(std::string("0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7")), + FF(std::string("0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b")), + FF(std::string("0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15")), + FF(std::string("0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b")), + }; + + static constexpr std::array, t> internal_matrix = { + std::array{ + FF(std::string("0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e8")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + }, + std::array{ + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740c")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + }, + std::array{ + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac16")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + }, + std::array{ + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428c")), + }, + }; - // generated in `poseidon2_derive_params.hpp`. N.B. does not use the method outlined in the poseidon2 paper - // (requires implementation of some extra 3rd party crypto). May need to change for #3132 static constexpr std::array, rounds_f + rounds_p> round_constants{ std::array{ - FF(std::string("0x15eea6dca2b448bd09150227f045553c94d4cd0502e0c5a24c588fe3e311fa67")), - FF(std::string("0x279df1af44823fa78173f97a9b3cdcc444c41f7a5fd25dac8252ad283fa5ec3f")), - FF(std::string("0x2e4aba940b2e5e9d60f7b558e840165eabae3e016bb14218f64a866963d666b7")), - FF(std::string("0x04323d044f25a2b19578b980d6c1589d639545d1dabc36ae965a70740a9c0857")), - }, - { - FF(std::string("0x1ad0d155c36e0233329934e15ac3d6467c3b05acbca17a1836cbfc7f0d660915")), - FF(std::string("0x07ec817c89206c5c4301973c5be04fe7b4c249859151779166d0a6bc4995d6e7")), - FF(std::string("0x0f7ffe28dc5258f8aa627156d9ce39467c740552d87e4b0e4cc696a3cf53cf36")), - FF(std::string("0x0a8ea6ce4988c432f594582361129f2c62dae142da5a057117b5fd6807257986")), - }, - { - FF(std::string("0x0308252835005ac66742d170cda29be20f224dd01e3a782c286414bc41d61218")), - FF(std::string("0x098e1a885f6b8d5fa1c4987ca12faa12e96408af06ec133342e7fb15914148dd")), - FF(std::string("0x220826e11ca209dbf03b948986a1e2767b6036473cfde7efd99e21f5ffc77dde")), - FF(std::string("0x15ab8985ee003841a897509e2baffa614ed80b401ade01c1c78e7d4ad41607de")), - }, - { - FF(std::string("0x064980ea9c8b32817c459209486d8b2533e29f53808161e7a650583da1690acc")), - FF(std::string("0x10c54b290c4040afa6454fb560ca3862c5535be8bc5da1c6a5be5344a03942c9")), - FF(std::string("0x2469f804e2a02b122d43c314d4fc1a1dd7bee08276da9138e705076583b90247")), - FF(std::string("0x19c3f8198fe7535dac3a2ea383aaffa39ddf30da0e1582bbcb07577475d2c0da")), - }, - { - FF(std::string("0x226caac408b4335f4ba9e927ea0127ab68fe0e0f0e9012609c4337ebcc63604b")), - FF(std::string("0x302d6600e481480955e13ad506ed7fe098f517bc5ee63b32c5bedad64cec9d78")), - FF(std::string("0x149754646e22efa13cfb34e1cfcf396bd3f91611a7d03edd1993098ebbcde8e0")), - FF(std::string("0x06f85232ebbf79f827857c165d221c6c66ac421e9b99274a174c0f2ff194432c")), - }, - { - FF(std::string("0x108f75e9efe231ba6396e0ee8c22472d3f71da8380b4be01ec4cb4b32232eb57")), - FF(std::string("0x0aee1b1783ba93af99e248aec6c41f937fe003185d0bc962aae3b080d187661b")), - FF(std::string("0x0bf3de9ada3a61ee25af9f448e055874b651d168f1009e22bb200c1b4d35324b")), - FF(std::string("0x18496105620a6c599c467a80a4d6f76313b7f793dfaff480c6d3ef1e361d328c")), - }, - { - FF(std::string("0x2bf6d9d2749f31152b6df0ebe61751b53b434160b454b49778e8343267d7f6a1")), - FF(std::string("0x026dd15b91c1ca7d869045ae68815dae60c5e4544fd438b7ef0b90319c005884")), - FF(std::string("0x0821a99692cd0c110e511829f7d918ed8980ccaa3e799315e914ab153b6303eb")), - FF(std::string("0x25018d135e760d8e196c44e271e7f6f22f09bbbaf36025f7a7880f177fde04b9")), - }, - { - FF(std::string("0x0aa5c1f043f4fe98ec82d081fa9741f846f833f900d31111d259a14b16fab4f2")), - FF(std::string("0x2023ce7ccb396c4c6d4054691f04d36be27d66d01eef8d63bc5aad175b1bd967")), - FF(std::string("0x0534b260e284e2f9b1c3aed425db75d9e458dec84fb78178673d31d20644fc98")), - FF(std::string("0x001bf1f59f36fa68545aaba439a1bca8ea4724b2895e6fb29f6db064467f1cc6")), - }, - { - FF(std::string("0x1a69a7401bbd7a4822930ae713a664bfd0f5ead08553e353d2f4498b80149baa")), - FF(std::string("0x125c28a74dad02056ffabe14f3544db6673289e6a6bc4132a3b183fd2ccf6b7b")), - FF(std::string("0x0c36495973a2a18285cedeb79118adf4585a0151e4ea25e836ee5591fe44f332")), - FF(std::string("0x1a376c8f32df8d253552a268f5957d62bf3b63f701c0c2dbbdcb293cc4bf1ec1")), - }, - { - FF(std::string("0x2b53585a0bc0789078d58374c129ab35e80e65ff0b9ecd002f0996d03e941049")), - FF(std::string("0x143354f143b3622a185a65b3f8e210cb91300d2f9d187058db94db23aacc0a64")), - FF(std::string("0x220ed9f1201fa741566e86c9491af4c63648d806262088b73c980240b2630d5b")), - FF(std::string("0x01df34ca136c47a5a016a9c6a13984a2e1200b047d8c345b477f3be24f1dfca6")), - }, - { - FF(std::string("0x0325e6449db3896bfa8c2bcdcabac9a4a0add91b9305e10b071f9681466d8a64")), - FF(std::string("0x1e4f12df40af7b3b3a7daab0d15e1b6c649bed50c6d85f0f469b9c680d6213aa")), - FF(std::string("0x259babe5dc5beb75821174d2ac2514c3ac75d9a252e919fa3d082f08f6fc255d")), - FF(std::string("0x0536d199068109873bd726373eaada568cbebe3b4723cf963954469fef87b03d")), - }, - { - FF(std::string("0x0f96c283774eb29f7a3e6ebf8d39b7580c6b87a4a8688c4e9954c985900c692a")), - FF(std::string("0x2a197e4a1585c27e4d0efb238aa87bc49146a5f9b10efd89b8e0e1e40a1f5397")), - FF(std::string("0x1334e3cea317028385e6359b7bb3b3a64958d8840e0c03c30673853f581f5762")), - FF(std::string("0x085335f63362d18d1807f03b7e7f33d12d80aa219e58e577fb51dc9fa4913b9d")), - }, - { - FF(std::string("0x24767a8fe8035513548f15f041d6d306e03a0974d70f550bf17d164c68545ddd")), - FF(std::string("0x05343763fc0c0c73d67623a34e695100fa591a9be834f34c971d7a1145e39a3b")), - FF(std::string("0x23a663071238e76485140982a4a7bb856f0cea6a3adf1f0a1e2a20a62be5d8a0")), - FF(std::string("0x10eb6ea7c892c9f530eb7c358f4595a602f3d6ead83a94c2430034a3ce67720e")), - }, - { - FF(std::string("0x22d77c228d29014470c28e3c6e4463f36d4a5d99e58271b2b762e34559ae252f")), - FF(std::string("0x14b7f0b968a5a59b13b66c60059ee0794e990715d64637516a6e414aa7c3eb4e")), - FF(std::string("0x03c56ae6f8cecce9636a751c3e0c9f8460f6b01dca3c488f0ad59cd8753621b7")), - FF(std::string("0x231ef5b2c2bd15606426bbf4a7a32270fd95cef340be77b69295c849712f7970")), - }, - { - FF(std::string("0x052cc6b97d8f8657fd1371eb099c2f0efe37166aa4be7e6b2f5ec18ecd7a2555")), - FF(std::string("0x08339e3b437b5c5fe7fc91bb7903901cab3634f4d71eeb999d4e1ec8dd7d5d34")), - FF(std::string("0x2b52dd66a2f030ffff2b1134cfab98aa0bd16706346457d9995f6bc579f63e0d")), - FF(std::string("0x2d770d6d74c1238b40e39bf1e0da9cf8540bd7461a84aab9b474a0ec581731c5")), - }, - { - FF(std::string("0x25fd2a2b1c65fe0bff324bd3ebc035d7806e374a1770ea9baca8115101afd9ec")), - FF(std::string("0x24b73f5aa558b9165a0e2db4280134e06b46740d9b05bcec07d5bfa5f9866f7b")), - FF(std::string("0x253dbd4522315578fec9b4d9ddbdd94797cb670c2b36cc8fc35ddb11da3574d8")), - FF(std::string("0x1678ac4331ce9d28dd63a303e2840c1a8c8df5cdf7982edd3e880bf9e3ff638c")), - }, - { - FF(std::string("0x299b57ed6ef793250bba6df0464aaaa40ee32fc0cdea661dc47f7167c788bc15")), - FF(std::string("0x0e8031d7f045796728ec86ef6be1105e317697b6817123c92c62cd0df3e134a0")), - FF(std::string("0x08bbc62c82e3192c7a71903385188fd2defe8d3821d83fc19a735821f58b53ed")), - FF(std::string("0x15246558ca9f8636072607ea90f89aaae31e5a095e71f62d40ecef3cf87fc56e")), - }, - { - FF(std::string("0x2c69fb396836afb10bcdee8830ef75edfd2de23bdb1f458cd4013b95b399df5a")), - FF(std::string("0x1332a20f8423504ac6dea46427bca87c692659ee456db4b631b329abac0428f8")), - FF(std::string("0x076099baa164eff4630a22beae8945ec96df7b84fd3e7c2135e38072e53dcb89")), - FF(std::string("0x0e612dcdcec52eac2c227596b8df9f8325785e9ccb4d8e595b164224ee232643")), - }, - { - FF(std::string("0x205123027e2e8e0d813daaa7e791ec129a4a89ba0f7e026dd6c591080495d6da")), - FF(std::string("0x126e7c36d80a9dc4fa9a868ec791b53d61a54e6e2f850bab00cb32cdc6d975d5")), - FF(std::string("0x2638520164de3f58a5f0ef7b6302cb0740d7c0e60c0e3feec89e137c0918ab1e")), - FF(std::string("0x2adf70f515c0d91851da22ef6fcef1c270f2cf28a15adbb4e8931c375fb1d152")), - }, - { - FF(std::string("0x12dc9813445d92702cefdccf3aed56487e5b13fba98d993a101e23d5c75c7fa5")), - FF(std::string("0x1f0c0639a5b5209dc4056aac7aafaaa759dde0c3b219f32fe6dd77596f7fef5b")), - FF(std::string("0x2bac8f37d86d3f562ad7f4a285a63fccb1de4745c78e29a7ada03c8d84584a0d")), - FF(std::string("0x2dc55bc6c7f6dd4a723daafef52a133602ae2e113566d1ed44deff0228536629")), - }, - { - FF(std::string("0x060e528735661c9f4aab45b097c326f53c374658041cfa1c8c6402581267ec60")), - FF(std::string("0x0655e8499681d25f19ce13c9361eecf7d89664d709fbac5edbd00826880526ff")), - FF(std::string("0x03d2045d3557086899658264d24baee7e842cbb213b36bf22db6e408881e194b")), - FF(std::string("0x1b3bebbee511ad923e5741b9ae9299e0b3a49a950e7b0b8eb35b5411e58fa83a")), - }, - { - FF(std::string("0x01635e56bfea75fdcf3fbf9ed4c103f99851d9553a696c3c02ff71bea3b934a4")), - FF(std::string("0x2edcb004d073cb39a73eef2a994653a732e7cc2aa5c33980be989d35268e7a85")), - FF(std::string("0x04c2258ac4f7f74cb2114477aef1ae61d541b919b362efafa0cc6ff1f3abe0c4")), - FF(std::string("0x2dae38722e7509f87cf5380638e40560584de28b0a180c3f654e145d83d4e5b6")), - }, - { - FF(std::string("0x2b1a7bccd6a282790bcc29f5f2d13c5f33dc5eee59af2939b3339f142324f102")), - FF(std::string("0x1768e953de2e58f7620005da9cc4a6863da49fb3c8369ec4d389ae1e74ac5525")), - FF(std::string("0x0d7cfced42afd96297631bb0332b3c90a772ca1c82187cffe43d90906684863f")), - FF(std::string("0x283f8070a0bca435614e8e3e786c120e637f235108fad44a8b1d55f15549ee50")), - }, - { - FF(std::string("0x17400a650edc03e961ec826cedeb0028c928d98bc30e758032afce5c6b9b4bcc")), - FF(std::string("0x0beb669dbb1fa32200d670275f0dfd51b016beef89ed28b2c605a9cee9e4897b")), - FF(std::string("0x08419d357edbd69de031dfe608761f7ff782cc8994b9c282760189d4ec7e01f6")), - FF(std::string("0x118bc2f4015b753019d60abb95037d582270a525d06c6341f35ddca22505f3b2")), - }, - { - FF(std::string("0x293f43e6aa59c0ac8337e25182b0810d0bbfbfb9dc33951d93645e0795b6e5b8")), - FF(std::string("0x25b16e33ab57889a409537da7ee0cd22db722d275e2aa4f5b2b7cae010f055c7")), - FF(std::string("0x1c35af9efbed4574315d523b2d25f8b9bdb0033346243486a99b0b5c49a7d1f3")), - FF(std::string("0x0c9cca6505f4e705fca5caff5283b2bcaf781d95ae388e52314e27f2f14e14b5")), - }, - { - FF(std::string("0x2f6985dc96c8f1ba0e338bd09d4624b28958a4114927158001d5d8d550cc3b71")), - FF(std::string("0x08e034f17598366a77cb0ad47ab55dc31df8e5d2893e13549d132f6428afe09a")), - FF(std::string("0x1651e97525932a9ebca8f072f8e6aa8740a3a351231c14d6061b3268e42e8c7e")), - FF(std::string("0x0f34ea4d29d247d4baf3ea9b9c9763e8ba263c46e0f25ea80df81999f51fbb8b")), - }, - { - FF(std::string("0x27f93f3a609b73ad1ffe2bf154899d8399c9accba6947507bd84bc4556168d7d")), - FF(std::string("0x2bd8b5f1a460e7dcf8b1f8e753b260d4d9460b8c86a3eb1d006d476a9cbe5650")), - FF(std::string("0x123515d8163c3825363d25a84e13bffaa0b5e20c9db01aa1ea6fa467aee0b5e4")), - FF(std::string("0x29676411a52008a07ed65c1fc2901a8adc3689d70ebac45532cf4f3cc8d30774")), - }, - { - FF(std::string("0x1bb60ab8bc36870aed66a594efb34ea24fb7d2d992ca58d4aeb31289c8cf0d65")), - FF(std::string("0x248f8f678b4a5c3a7ffae164c471d29dba9fa6a320b1e9809f64ae120d0bb22b")), - FF(std::string("0x05c08dff728cf1e6804ed5d84e6cabd4575f9bf2f89e9a2eccdb1fc8b83672cb")), - FF(std::string("0x0a5dc0217ebc7f6bbb10ea6261d4bed8fd2b8598be6a7e326e31cc3991135a6b")), - }, - { - FF(std::string("0x21ea154846c075ba1e2ec1d61ad4843bb263e2f05b9bdad67c8b989fe52c9377")), - FF(std::string("0x0592a7b6e9cc14efcff5e9530db734028610a38322e4ad5b2a60220d69e819bb")), - FF(std::string("0x01b98b71b6bf17a929d6557703eecae267893a625f923e497752d7befcaab460")), - FF(std::string("0x2b867342d1d0664b7411d4ab1056f337828ee7bf9db45871798051c56b869503")), - }, - { - FF(std::string("0x0a66788eaf35195b3d40246c836baf1412a9927185197ce2abd747760a809fad")), - FF(std::string("0x2a886be85416c3ef9748376da17b5178091817cb82a38b80ff7492f13ef3444b")), - FF(std::string("0x1dc519f87a75cb012b0a4e15aa8d8fff0da730e81b41c27411766d7587dde4ca")), - FF(std::string("0x2ef6492984f15978f5357c70cb6fd9e13cfc4e21ef6aee5d72b2b636da194bcb")), - }, - { - FF(std::string("0x062de010063d1072aac3b8f51dc0c462c5eaccb9142f931a7ab76a1ae3d5b7ae")), - FF(std::string("0x204baed49134a9764295715f195a04f609a93727157afe1993dc5daa29c46df5")), - FF(std::string("0x0649a9953bbb403ac0d2e9cd624cf9627f36ed8e15cb33d7514e883480234fab")), - FF(std::string("0x2abd88ffeb65a265128ffa3c42037d77934da139f4f04d4ba59790b163e9507e")), - }, - { - FF(std::string("0x18d333c846fa6c4ead13daa110e590ebbc288ea7394e52abfe6f247f99d0e23e")), - FF(std::string("0x2e8727a08f6964a4c758214db8d7cf5c88112176d6dfa3230824935788876509")), - FF(std::string("0x1ef52294254e9a07eea80611b6ae3d7e1b6e8a4b70515d723399f4dcd1e2a5f6")), - FF(std::string("0x11572d12ac653a3c0f22d5b7d20459e6aad41a9116a6adf35aa5e515f6b97399")), - }, - { - FF(std::string("0x09c871834f078d45549694f501a761e42a501c592bd3a4e1fb3e09ad8dd16df1")), - FF(std::string("0x246bbcaf77d39eaa09131e99ffb6d8a754aae3be7a2e3e88c11684f4bf7db342")), - FF(std::string("0x18ba724cfbc52564874d8443dcf08f3584233c2a14e59970059c17648af1c46b")), - FF(std::string("0x2676199c8c498f8b995e8d8089219e64faf4d644d918a8bbdf48f5aeef397ee2")), - }, - { - FF(std::string("0x25af0a7566280e5b679d22a6a543e5d1ee49afba262854cff833c6ab17d9b406")), - FF(std::string("0x0944ddaa67cef777788d34b3af061ca90138856b7b673732abbb7a729010d5e0")), - FF(std::string("0x2541565720337000bfa180c09d2b74f26dc75bc0092489afe6c7628867903fab")), - FF(std::string("0x1557f108c4f6a5e42e6b21b6ce3324111c3b197e746ed56a1b3011df4f3a78aa")), - }, - { - FF(std::string("0x02379e39dade80c2b3cdd994914cc7e3bbabe6f5451c457ea72e8061e6258cf6")), - FF(std::string("0x19283b8a618a8dab599629f322448c2d438a7ff0c8e3869fd48c1287af4682b2")), - FF(std::string("0x2ccdb0312609448eb09c8d49a8ebae3b47cc0476675753b908c244f82262bd46")), - FF(std::string("0x03ce886a32c134b13e508ad9c9470b47c66c28f6c07b6d7abf5d67e3d8cfe128")), - }, - { - FF(std::string("0x05105ee8f7d50a26d109a3854267be2bb0045dbfdec8493ae70bdab4e783815c")), - FF(std::string("0x2d5d51efb46deaf8c878b35c0d62ed2821127d533cc30c28b4259800d11722a8")), - FF(std::string("0x1074bc594f6b3665ccc365f9ff5cc21135d1f922e1db035cbbb452babe549599")), - FF(std::string("0x216aac7bdd7f0bfbdacc9d0a0202cdf964f1dd203f231b08a6138171a332af56")), - }, - { - FF(std::string("0x179773cd3f390ee479f96169df1866d8def0bda8b3a542924e82a61a30f5d734")), - FF(std::string("0x051ce7238a6fb317f56eba00b5eafbd8d83addd72de072f0e67e17918edab699")), - FF(std::string("0x2b50582527dc94f6c32a7a37cb59b783795e42ad4a50d60ad8c4cd9d32a4e5e8")), - FF(std::string("0x175bdedd785a09eb07d8d40c5c53407dc40bf4f85c29e451a1ab015b62d4d9e0")), - }, - { - FF(std::string("0x0ac575ed0014055981fb6db94e50ec901bb29474e93772f9aaf25e8c18fe6f1f")), - FF(std::string("0x1b8541ea21a9c9215a63b2b32192e6dbfd5102471c517e180440d719e98bef2e")), - FF(std::string("0x0deb999605c554a85c85e671ab63cb6989c44445a5f428d4f2688d48eba1a846")), - FF(std::string("0x19d5c93f224b85de28240ba4bb1de0f0bba3c08648957dff13b323a90cbe0a5b")), - }, - { - FF(std::string("0x2a6abea2a0828a230400d001108a16d95a8906e04db3577c602b009d6130677b")), - FF(std::string("0x1b6a2b82be46145b09c0f0ecfe2191b8896ba92c0bd67f8a9ff9e99fc0aaa41d")), - FF(std::string("0x03a0b2e64db36338004acf1bfbb756cc4e1df1a60272b4eb7240beec0fe9ff0a")), - FF(std::string("0x090da681d61c1e68e31625e3d1dd767e8996076333ecd2c0c32de18f93c8a7cc")), - }, - { - FF(std::string("0x00304b05b245d8a93c35dcc8a201623bc10c70a7a59809a9ae77fbb3592c448d")), - FF(std::string("0x2ccc7c443cc4ac2d908ac7cbc78f3432ffdace325957fc00cbcb36fd4220abca")), - FF(std::string("0x05bb83747d88579128e4f3ec624d239fc51da9fd20788970a1dcc1e0650b9742")), - FF(std::string("0x08789f0f2d902548599a592dc0e1902bb11d4f2344c7155919736dae577aede0")), - }, - { - FF(std::string("0x2d7e79f6ff0a354d849c9339102cc01d6fcab3bbcf2a19755ae6e78aab0c50fd")), - FF(std::string("0x23b130113a10a7b7bf6df003e9f895e2de67bf7be27bc802a9fa1552928cd126")), - FF(std::string("0x1907e748c911fce6a62574268653103ff1b7eb59539f29434873a8cc31f1c7dd")), - FF(std::string("0x2e68eba7243e7fb1a492512ee8a7041c84b0c840b74119f6c00d4cb5856054ae")), - }, - { - FF(std::string("0x08dadfd73dbd17a1a3834300b2d47e3645d270df6e0081d84cdf05fe71f9b86e")), - FF(std::string("0x2b194d668c4400df5a26a2c4067d923086d505d3d4a3bbcf59c292c84b0e7ca5")), - FF(std::string("0x2456e40dde7c6f74e1da3a2277b7210cdf00509166d6af184c78d33f79f43a48")), - FF(std::string("0x016009a0a16d27ed52230190747b3b6913966cbc0414156778e68c6b14fd1735")), - }, - { - FF(std::string("0x12ff5c523564441020205b85188e144c8157f689ec5069cc7d039803a7349ab4")), - FF(std::string("0x041578eda5a7678fbda568fbf40759426f5705e303f32c63ac474cb5f5f7ec6a")), - FF(std::string("0x05239591df2f6f81c1d26da5a2a0fbfca86d0efc99a38a63ce0a7d247a69af83")), - FF(std::string("0x250ddf97d92629ebea4aa32ecaf8b78e9dba508e113dd267327662a81833cfb4")), - }, - { - FF(std::string("0x2c6f9180b88371c9fbb0be3de33660ef305e29db740d1a58c932b81564ac1b85")), - FF(std::string("0x072c7948f6111a46e2cab1b8bdca315dd4d2d4ec9cbafb7fa93a4142a610de2a")), - FF(std::string("0x1d95394e6d3f4a54fac5db36c72e1ab50b5bfba092983a9e2bb314190c0ddbcf")), - FF(std::string("0x047dd6e2991a472698d3769e7fd4424e8d1bc7b8b71d4a302b5cc41e1a940b27")), - }, - { - FF(std::string("0x1d1bf8d0e8a7862fe9b96231ae07bc42563ba5921fdee16f209645884a46e6e3")), - FF(std::string("0x08a53afc4b57bc9202929dc6ed63b7c661d5c485cf6ae17161bce7938fc59af4")), - FF(std::string("0x0ff20cb119d82b8d20cf4d31b9f477758a0be7ecaf8812126f9b4ad464a6782c")), - FF(std::string("0x087b751afd7be2acd7923cb74430f27db98890e44c375c09ac535d3a8ee4349f")), - }, - { - FF(std::string("0x2df5483c1ce4c9de8401c7051392a30e0198a489d21449ddedf4048b50dac823")), - FF(std::string("0x284c153a3a910c030071783ee0baa88fd701dc61f31ed77463bd9b37cd34b782")), - FF(std::string("0x03e1a7a5affcca77d76dff3e43fca2c9aea3962775bf9f416dda6b9b70a553f4")), - FF(std::string("0x24be4f6d00f3088d5983848d39e43ebc8b940192cedfe9205ee84221427aaa38")), - }, - { - FF(std::string("0x29f50462b45601fc9cd5f46ebd7d6a659351898bea6e3403ce931fd3432d0290")), - FF(std::string("0x1ed2ff04f43127d837a5ca18a41163a9470c67d355ecebe5aff04366865ac132")), - FF(std::string("0x146cccc77351666008a6b776a7ebbc2a84aecb29bf20bddf2e4896da0bd3eb64")), - FF(std::string("0x0b91c204757074bcf1e106f7fb7bf26dd9836c2af828e50f5b3424668e6c3f49")), - }, - { - FF(std::string("0x0c46dafe7ba3db2a074471d38a67ae25a5cc91844f2efe41435dd6bd794c8889")), - FF(std::string("0x04a54a09f063d9aa4d123e0f4bbf948c1015b281adbd993df67be92639604e56")), - FF(std::string("0x0bf1f2a39d8f9002dfb81966bbde913d798ea554515b4b7cc985613d43bdc380")), - FF(std::string("0x0c12d5365ba60d32e6342537847154c0933d99d36342cf98a080a62db324723b")), - }, - { - FF(std::string("0x20dc243ef10af7a9a5822706cd8fc4d0beb65d68e6f08218bca636b566d90635")), - FF(std::string("0x22bac8e86894a619dc6bb337719964b56fee5217bda8c711500b8579196d6360")), - FF(std::string("0x1cfe092982f2d61d132e0b6fc4b678c97d1f80297d1b43e723024503e19da7a5")), - FF(std::string("0x2bb3ca88ab47d917625c22ce11260cba3dc9c5cc693ccc4722f7d06058b5c355")), - }, - { - FF(std::string("0x2289c7ff79446228f2b6a52e48a90d6d3ddec3d7ff5b548f39267ded5c175191")), - FF(std::string("0x09d963f5d895df0d2f1be27e0cd589c1e20f6219a31526fe9acdbb534de923fe")), - FF(std::string("0x07dc265e4f1736a3a07c0aa2d94d0f23742ecb90837c5ed87e8e1f4db3f49f3b")), - FF(std::string("0x18f75992411fbb0ec8a01ce2c0c81567ce8da36087ab92e483470d3f141e1176")), - }, - { - FF(std::string("0x2a7d09e28d6b184616502993130ee0b552d238da6867895ee7eb50fea033af26")), - FF(std::string("0x2b5e8bd12bd77ba2a3abfd4b56a8dc5e93b8c509110665113acbe97598e2514a")), - FF(std::string("0x2b4506470648cd32461b08692dfe4741571820e1e02674a4652305724c3024b9")), - FF(std::string("0x0a64cd1b197a31dac84de8bb0eb634fafd344155bdbac92719e8d34ed0accf64")), - }, - { - FF(std::string("0x0ebaacbd0edc01a28c88ea6cd8232a8fb5e0cbf7b7d46db954a59551269aae11")), - FF(std::string("0x1d3d7a5ba3d8d1728f3187401038cebf5adec7e95d5ec485aa82f58fd9339a68")), - FF(std::string("0x16b027c675b006b18560c236d7e0b4fe0c08061572911f467c8448a5e62a25a5")), - FF(std::string("0x20eb9f65f94084054d77a1fb220bdfe6fc2ab17ea04f99400834241b584949c6")), - }, - { - FF(std::string("0x11d15fbd5525aa70d44cbcb3879128652f4680034db3841db0254a60218fb29a")), - FF(std::string("0x1e4a6b228d2596a72e7535d24dd60a0c583eb2febd0d8bcd12396ebc425470eb")), - FF(std::string("0x21728fe5756ff55de1c9d5fc0d08f1b1318805a66f6637088fd2b20294911687")), - FF(std::string("0x1bda907f1c69a520fd37d6ddce8d3956c32e5aa10b24f2958ed7a6705bd1f37d")), - }, - { - FF(std::string("0x1c837c3290090ef4afd9d904ff67734f54b939fb719cc1038efa5db256c94d6d")), - FF(std::string("0x019e54db9c8ec7651ceda7bcf44b50b1255fb78d797e158e669de93adcb6e3b5")), - FF(std::string("0x261506c83aea562286a84681f6fa2449395c241e1cde0c69f8ca63783fbfca59")), - FF(std::string("0x08e04b821c976f6cec904c3aea5aaf05cb255722bbdcf7ee93b1de99846b3625")), - }, - { - FF(std::string("0x1e8d1ab72f9ca36a7ecd2ad9e93bb46a5b88830925dfa45fa8817c5ead9d8b54")), - FF(std::string("0x2f58fda0de317d3472baac058b7a0e8c5c590eaf0482dbe53ead518b2f313dbe")), - FF(std::string("0x0aaea80cc01cac944922c8a24532953790060ea0d48934da0ef75bc6574444d3")), - FF(std::string("0x2306ce71ff2352e0f1bf6e5f87cabb98ecdfb489ff3a99891ae203526d4d737b")), - }, - { - FF(std::string("0x06628eb6eef76ad7569e50e4b97b25f18d412426e9bfd45ec583cc1fe6272005")), - FF(std::string("0x284db95e0c26cd9b64fbd9e40aee8aeab14ff0429aa5775711a6ca4854076d27")), - FF(std::string("0x2328cd3fb4348135ab6acaccbc0e83a7c8272687d3c6454390a725af4a7f95de")), - FF(std::string("0x1d5815e60424ef674449982aa51687893b82363952d31cfe8bc24453ed153cb6")), - }, - { - FF(std::string("0x18c57f75efec583c1c0c440fffcf5f4377e4740ff3311e820a8b6d814e92c86a")), - FF(std::string("0x1b82f143fc2eebc22a600bb95a3af1506b68d813ffbf647bc479c3864170b338")), - FF(std::string("0x192470dde3a0806e90bc34f2190afd2dcb7df6629bad92e209d70c74a48c9d92")), - FF(std::string("0x0aa97a5b7d802d0caf9cb6d1c76486853bee852f1aadd85b52fd83e1147457a2")), - }, - { - FF(std::string("0x1b831d08854a1a109a745c5b16760cec73edd3d5317dcbe1cf24a6b0ddc2d79e")), - FF(std::string("0x096b1936ea537a6b03ce83d87823f2326a97e03c2b90c10476c3058001e6b471")), - FF(std::string("0x2c1ab915961a17681e0626196749ab54beaf01e1b29e01f1be2cba941d6d3eac")), - FF(std::string("0x19fc611ee693c8a12b73bd0eba61fa74ff4a476df46c221b3abe00af3ee82e61")), - }, - { - FF(std::string("0x205625df4943f819eedf11cb9736648f80437f3e0b3cd73a5a0b3b144e5b3569")), - FF(std::string("0x2eb23a5e85fbc502e6b24d08acaad160119e51498ef07df8079c2d47ff760d57")), - FF(std::string("0x0c725970a0e4c070a785efd46d63eb6523a7b4951e5270bdf549ae1a89dc0991")), - FF(std::string("0x15f2d2888ad658cecc3d7038de6541c7e620ac92e4d2c192eafd4fec2ba48e8f")), - }, - { - FF(std::string("0x01080c482028f2fdfb4c4247d07157bfa58d6d2fd6e0583fe87a1a8f3d96f112")), - FF(std::string("0x058e98dfe1751afb7478f2b93a4522e0e5bab006777fcc9903580542e549b66f")), - FF(std::string("0x21abaf2ff4b43316f52910454f957d485008403630f1bc68b63da871d3462d9a")), - FF(std::string("0x227acf3eaa5df73c3f01e2e34e571c2d69279194b0f2930fdd9adf3898753ec7")), - }, - { - FF(std::string("0x21e0c57ce891ea47b91b4757a41817a9f47b4a5a14632dd556ea0e5411f79f1f")), - FF(std::string("0x1a8ada480114c7e248cd5214511ee2b79b793f8e199eff986b3ae59297e9feb9")), - FF(std::string("0x082bc7a263ca5da12ee6e8aa048a7cdcd1ae4d4a16aacfd92b33991157c92db9")), - FF(std::string("0x178502779a89aa327096a62883989ac41e28a25caac6cfb7bd4ec32e343b08b1")), - }, - { - FF(std::string("0x0bdc3b7f3127210ac8871d1b8e3ec744d345dbbfe1508f8565b05896c9e50e8e")), - FF(std::string("0x146f2b581340685a19fc4175354475b04bae900f542ee1c6254c4b94d9e5c619")), - FF(std::string("0x0e2093f5fea23aa450f519e844a3ff5dd3c62bc5727b6016d8272bff4f8d18b4")), - FF(std::string("0x0bd958eab1a98cc6618245168d3f83c9f502450c15ce978e4ed8fa09b409d0cd")), - }, - { - FF(std::string("0x1d4fa3a009238083b8e844c9923bd6220460d55d47677d0dca26bb6ed30fb9c6")), - FF(std::string("0x219992a2ad3c2e2ed6a7b2b95556835e1bad915d26e886c8ee5d4b6edae81085")), - FF(std::string("0x0fccc34a26a433f005e9ab759b8029ee18e5e2f36aa10564684f3f359845c920")), - FF(std::string("0x1fb16829f9023a2c365f4f35b3e8e85fa9da87a1196a87941bd54b2e2f6a3c5a")), - }, - { - FF(std::string("0x2a62ca0cc5e850c6c4af48edf269e50bf2d812e5883622557c9c407694bfe1ea")), - FF(std::string("0x1d7e77f95174c41ea0c1368390eb4618cbc6cc3a5a5743cc03ee90a636022a76")), - FF(std::string("0x24dd714d441b7986af8dee276cd2606359cba9e4ead6034ac3bab018364a21c4")), - FF(std::string("0x11072894ca6d01e8d6536eacaa067940f59b1b6d27bebdb2c6f53ac887fee5dc")), + FF(std::string("0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5")), + FF(std::string("0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6")), + FF(std::string("0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa")), + FF(std::string("0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8")), + }, + std::array{ + FF(std::string("0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902")), + FF(std::string("0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e")), + FF(std::string("0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996")), + FF(std::string("0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e")), + }, + std::array{ + FF(std::string("0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738")), + FF(std::string("0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06")), + FF(std::string("0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549")), + FF(std::string("0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b")), + }, + std::array{ + FF(std::string("0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8")), + FF(std::string("0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f")), + FF(std::string("0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1")), + FF(std::string("0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447")), + }, + std::array{ + FF(std::string("0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + }, + std::array{ + FF(std::string("0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38")), + FF(std::string("0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5")), + FF(std::string("0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c")), + FF(std::string("0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f")), + }, + std::array{ + FF(std::string("0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a")), + FF(std::string("0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96")), + FF(std::string("0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce")), + FF(std::string("0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959")), + }, + std::array{ + FF(std::string("0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b")), + FF(std::string("0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4")), + FF(std::string("0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf")), + FF(std::string("0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455")), + }, + std::array{ + FF(std::string("0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335")), + FF(std::string("0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b")), + FF(std::string("0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df")), + FF(std::string("0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404")), }, }; - // generated in `poseidon2_derive_params.hpp`. N.B. does not use the method outlined in the poseidon2 paper - // (requires implementation of some extra 3rd party crypto). May need to change for #3132 - static constexpr std::array internal_matrix_diagonal = { - FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), - FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), - FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), - FF(std::string("0x056015c21fd75936e34c48b67888855f0ee8b5e54e173d7125251ec6e81957bd")), + static constexpr std::array TEST_VECTOR_INPUT{ + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000000")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000001")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000002")), + FF(std::string("0x0000000000000000000000000000000000000000000000000000000000000003")), + }; + static constexpr std::array TEST_VECTOR_OUTPUT{ + FF(std::string("0x01bd538c2ee014ed5141b29e9ae240bf8db3fe5b9a38629a9647cf8d76c01737")), + FF(std::string("0x239b62e7db98aa3a2a8f6a0d2fa1709e7a35959aa6c7034814d9daa90cbac662")), + FF(std::string("0x04cbb44c61d928ed06808456bf758cbf0c18d1e15a7b6dbc8245fa7515d5e3cb")), + FF(std::string("0x2e11c5cff2a22c64d01304b778d78f6998eff1ab73163a35603f54794c30847a")), }; }; -} // namespace crypto \ No newline at end of file +} // namespace crypto diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp index 4001ddf6a12..5f87fea543a 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp @@ -56,20 +56,19 @@ template class Poseidon2Permutation { * | 1 1 4 6 | * \ / */ - auto t0 = input[0] + input[1]; // A + B auto t1 = input[2] + input[3]; // C + D auto t2 = input[1] + input[1]; // 2B t2 += t1; // 2B + C + D - auto t3 = input[3] + input[3]; // 2C - t3 += t0; // 2C + A + B + auto t3 = input[3] + input[3]; // 2D + t3 += t0; // 2D + A + B auto t4 = t1 + t1; t4 += t4; - t4 += t3; // 4D + 6C + A + B + t4 += t3; // A + B + 4C + 6D auto t5 = t0 + t0; t5 += t5; - t5 += t3; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + 7C + 5D + t5 += t2; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 3C + D auto t7 = t2 + t4; // A + 3B + 5D + 7C input[0] = t6; input[1] = t5; @@ -130,14 +129,15 @@ template class Poseidon2Permutation { // Apply 1st linear layer matrix_multiplication_external(current_state); - for (size_t i = 0; i < rounds_f; ++i) { + constexpr size_t rounds_f_beginning = rounds_f / 2; + for (size_t i = 0; i < rounds_f_beginning; ++i) { add_round_constants(current_state, round_constants[i]); apply_sbox(current_state); matrix_multiplication_external(current_state); } - const size_t p_end = rounds_f + rounds_p; - for (size_t i = rounds_f; i < p_end; ++i) { + const size_t p_end = rounds_f_beginning + rounds_p; + for (size_t i = rounds_f_beginning; i < p_end; ++i) { current_state[0] += round_constants[i][0]; apply_single_sbox(current_state[0]); matrix_multiplication_internal(current_state); diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp index 4bd45a6de68..759a00c768a 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.test.cpp @@ -10,6 +10,17 @@ auto& engine = numeric::random::get_debug_engine(); } namespace poseidon2_tests { + +TEST(Poseidon2Permutation, TestVectors) +{ + + auto input = crypto::Poseidon2Bn254ScalarFieldParams::TEST_VECTOR_INPUT; + auto expected = crypto::Poseidon2Bn254ScalarFieldParams::TEST_VECTOR_OUTPUT; + auto result = crypto::Poseidon2Permutation::permutation(input); + + EXPECT_EQ(result, expected); +} + TEST(Poseidon2Permutation, BasicTests) { @@ -43,10 +54,10 @@ TEST(Poseidon2Permutation, ConsistencyCheck) auto result = crypto::Poseidon2Permutation::permutation(input); std::array expected{ - barretenberg::fr(std::string("0x0514d38493ec8da89f9e2b599bc20f96206ad0c94bc2751e6df03003009aa2ea")), - barretenberg::fr(std::string("0x0757d335371eacea287976a7b26729a74801720418bfdac37d852ac198b585ed")), - barretenberg::fr(std::string("0x19f5168edd96d2c8800d460908dde37c5dd36d56ae905faa8660182a2803c56c")), - barretenberg::fr(std::string("0x0096047284f80a35f2f9f95101a9287e99e1afb0866f19e86286a09bdb203685")), + barretenberg::fr(std::string("0x2bf1eaf87f7d27e8dc4056e9af975985bccc89077a21891d6c7b6ccce0631f95")), + barretenberg::fr(std::string("0x0c01fa1b8d0748becafbe452c0cb0231c38224ea824554c9362518eebdd5701f")), + barretenberg::fr(std::string("0x018555a8eb50cf07f64b019ebaf3af3c925c93e631f3ecd455db07bbb52bbdd3")), + barretenberg::fr(std::string("0x0cbea457c91c22c6c31fd89afd2541efc2edf31736b9f721e823b2165c90fd41")), }; EXPECT_EQ(result, expected); } From 910b3038a75908ed9ba4f85302b96dd00d57fb32 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 31 Oct 2023 18:37:03 +0000 Subject: [PATCH 09/34] fixed bug where constructing uint from a string that is too big! --- .../src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index 01adec035f0..0f8764c3bc8 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -114,7 +114,7 @@ TEST(ECDSASecp256r1, test_hardcoded) }; crypto::ecdsa::key_pair account; - account.private_key = curve_ct::fr(uint256_t("020202020202020202020202020202020202020202020202020202020202020202")); + account.private_key = curve_ct::fr(uint256_t("0202020202020202020202020202020202020202020202020202020202020202")); account.public_key = curve_ct::g1::one * account.private_key; From c7b41572787bf6dfcc8bf922aec26c6e22a6789a Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 7 Nov 2023 16:14:18 +0000 Subject: [PATCH 10/34] added cast to fix build error --- barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp index 955b340e942..2b38253963a 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp @@ -66,7 +66,7 @@ class alignas(32) uint256_t { const size_t byte_index = limb_index + (i * 2); uint8_t nibble_hi = HexCharToInt(static_cast(input[byte_index])); uint8_t nibble_lo = HexCharToInt(static_cast(input[byte_index + 1])); - uint8_t byte = (nibble_hi * 16) + nibble_lo; + uint8_t byte = static_cast((nibble_hi * 16) + nibble_lo); limbs[j] <<= 8; limbs[j] += byte; } From 7bcee209559457882e0e9760f56be59f53e86078 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 7 Nov 2023 16:15:20 +0000 Subject: [PATCH 11/34] benchmarking file for native impl --- .../crypto/poseidon2/poseidon2.bench.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.bench.cpp diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.bench.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.bench.cpp new file mode 100644 index 00000000000..603238bf6e8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.bench.cpp @@ -0,0 +1,29 @@ +#include "./poseidon2.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include + +using namespace benchmark; + +grumpkin::fq poseidon_function(const size_t count) +{ + std::vector inputs(count); + for (size_t i = 0; i < count; ++i) { + inputs[i] = grumpkin::fq::random_element(); + } + std::span tmp(inputs); + // hash count many field elements + inputs[0] = crypto::Poseidon2::hash(tmp); + return inputs[0]; +} + +void native_poseidon2_commitment_bench(State& state) noexcept +{ + for (auto _ : state) { + const size_t count = (static_cast(state.range(0))); + (poseidon_function(count)); + } +} +BENCHMARK(native_poseidon2_commitment_bench)->Arg(10)->Arg(1000)->Arg(10000); + +BENCHMARK_MAIN(); +// } // namespace crypto \ No newline at end of file From 672ab677a0fec89e7ce62c91f08ffe2286a62f6c Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 17:50:11 +0000 Subject: [PATCH 12/34] external poseidon2 round relation --- .../relations/poseidon2_relation.hpp | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp new file mode 100644 index 00000000000..5aec4ddaf60 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp @@ -0,0 +1,95 @@ +#pragma once +#include "relation_parameters.hpp" +#include "relation_types.hpp" + +namespace proof_system { + +template class Poseidon2ExternalRelationImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_LENGTHS{ + 7, // external poseidon2 round sub-relation for first value + 7, // external poseidon2 round sub-relation for second value + 7, // external poseidon2 round sub-relation for third value + 7, // external poseidon2 round sub-relation for fourth value + }; + + /** + * @brief Expression for the poseidon2 external gate. + * @details This relation is defined as: + * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - + * w_4_shift) ) = 0 + * where: + * t0 := w_1 + w_2 (1, 1, 0, 0) + * t1 := w_3 + w_4 (0, 0, 1, 1) + * t2 := w_2 + w_2 + t1 = 2 * w_2 + w_3 + w_4 (0, 2, 1, 1) + * t3 := w_4 + w_4 + t0 = w_1 + w_2 + 2 * w_4 (1, 1, 0, 2) + * t4 := 2 * (t1 + t1) + t3 = w_1 + w_2 + 4 * w_3 + 6 * w_4 (1, 1, 4, 6) + * t5 := 2 * (t0 + t0) + t2 = 4 * w_1 + 6 * w_2 + w_3 + w_4 (4, 6, 1, 1) + * t6 := t3 + t5 = 5 * w_1 + 7 * w_2 + 1 * w_3 + 3 * w_4 (5, 7, 1, 3) + * t7 := t2 + t4 (1, 3, 5, 7) + * + * @param evals transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& in, + const RelationParameters&, + const FF& scaling_factor) + { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + auto w_l = View(in.w_l); + auto w_r = View(in.w_r); + auto w_o = View(in.w_o); + auto w_4 = View(in.w_4); + auto w_l_shift = View(in.w_l_shift); + auto w_r_shift = View(in.w_r_shift); + auto w_o_shift = View(in.w_o_shift); + auto w_4_shift = View(in.w_4_shift); + auto q_pos2_ext = View(in.q_pos2_ext); + + auto t0 = w_l + w_r; // A + B + auto t1 = w_o + w_4; // C + D + auto t2 = w_r + w_r; // 2B + t2 += t1; // 2B + C + D + auto t3 = w_4 + w_4; // 2D + t3 += t0; // 2D + A + B + auto t4 = t1 + t1; + t4 += t4; + t4 += t3; // A + B + 4C + 6D + auto t5 = t0 + t0; + t5 += t5; + t5 += t2; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 3C + D + auto t7 = t2 + t4; // A + 3B + 5D + 7C + + { + auto tmp = q_pos2_ext * (t6 - w_l_shift); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t5 - w_r_shift); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t7 - w_o_shift); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t4 - w_4_shift); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + }; +}; + +template using Poseidon2ExternalRelation = Relation>; +} // namespace proof_system From 60eca169c977977269b3d6a2d992cb0cae4f7841 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 19:41:00 +0000 Subject: [PATCH 13/34] added ARC and SBox rounds to external --- .../relations/poseidon2_relation.hpp | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp index 5aec4ddaf60..075b6dfa64e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp @@ -18,16 +18,19 @@ template class Poseidon2ExternalRelationImpl { /** * @brief Expression for the poseidon2 external gate. * @details This relation is defined as: - * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - - * w_4_shift) ) = 0 - * where: - * t0 := w_1 + w_2 (1, 1, 0, 0) - * t1 := w_3 + w_4 (0, 0, 1, 1) - * t2 := w_2 + w_2 + t1 = 2 * w_2 + w_3 + w_4 (0, 2, 1, 1) - * t3 := w_4 + w_4 + t0 = w_1 + w_2 + 2 * w_4 (1, 1, 0, 2) - * t4 := 2 * (t1 + t1) + t3 = w_1 + w_2 + 4 * w_3 + 6 * w_4 (1, 1, 4, 6) - * t5 := 2 * (t0 + t0) + t2 = 4 * w_1 + 6 * w_2 + w_3 + w_4 (4, 6, 1, 1) - * t6 := t3 + t5 = 5 * w_1 + 7 * w_2 + 1 * w_3 + 3 * w_4 (5, 7, 1, 3) + * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + + * \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - w_4_shift) ) = 0 where: + * v1 := (w_1 + q_1)^5 + * v2 := (w_2 + q_2)^5 + * v3 := (w_3 + q_3)^5 + * v4 := (w_4 + q_4)^5 + * t0 := v1 + v2 (1, 1, 0, 0) + * t1 := v3 + v4 (0, 0, 1, 1) + * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) + * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) + * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) + * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) + * t6 := t3 + t5 = 5 * v1 + 7 * v2 + 1 * v3 + 3 * v4 (5, 7, 1, 3) * t7 := t2 + t4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` @@ -52,13 +55,38 @@ template class Poseidon2ExternalRelationImpl { auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); auto q_pos2_ext = View(in.q_pos2_ext); + auto q_l = View(in.q_l); + auto q_r = View(in.q_r); + auto q_o = View(in.q_o); + auto q_4 = View(in.q_4); - auto t0 = w_l + w_r; // A + B - auto t1 = w_o + w_4; // C + D - auto t2 = w_r + w_r; // 2B - t2 += t1; // 2B + C + D - auto t3 = w_4 + w_4; // 2D - t3 += t0; // 2D + A + B + // add round constants + w_l += q_l; + w_r += q_r; + w_o += q_o; + w_4 += q_4; + + // apply s-box round + auto v1 = w_l * w_l; + v1 *= v1; + v1 *= w_l; + auto v2 = w_r * w_r; + v2 *= v2; + v2 *= w_r; + auto v3 = w_o * w_o; + v3 *= v3; + v3 *= w_o; + auto v4 = w_4 * w_4; + v4 *= v4; + v4 *= w_4; + + // matrix mul with 14 additions + auto t0 = v1 + v2; // A + B + auto t1 = v3 + v4; // C + D + auto t2 = v2 + v2; // 2B + t2 += t1; // 2B + C + D + auto t3 = v4 + v4; // 2D + t3 += t0; // 2D + A + B auto t4 = t1 + t1; t4 += t4; t4 += t3; // A + B + 4C + 6D From d53bace32c6410482d9accaee1f45d3a99fb4f2c Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 20:11:33 +0000 Subject: [PATCH 14/34] created internal round relation --- ...on.hpp => poseidon2_external_relation.hpp} | 16 +-- .../relations/poseidon2_internal_relation.hpp | 106 ++++++++++++++++++ 2 files changed, 114 insertions(+), 8 deletions(-) rename barretenberg/cpp/src/barretenberg/relations/{poseidon2_relation.hpp => poseidon2_external_relation.hpp} (93%) create mode 100644 barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp similarity index 93% rename from barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp rename to barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 075b6dfa64e..1548812c03e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -24,14 +24,14 @@ template class Poseidon2ExternalRelationImpl { * v2 := (w_2 + q_2)^5 * v3 := (w_3 + q_3)^5 * v4 := (w_4 + q_4)^5 - * t0 := v1 + v2 (1, 1, 0, 0) - * t1 := v3 + v4 (0, 0, 1, 1) - * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) - * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) - * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) - * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) + * t0 := v1 + v2 (1, 1, 0, 0) + * t1 := v3 + v4 (0, 0, 1, 1) + * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) + * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) + * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) + * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) * t6 := t3 + t5 = 5 * v1 + 7 * v2 + 1 * v3 + 3 * v4 (5, 7, 1, 3) - * t7 := t2 + t4 (1, 3, 5, 7) + * t7 := t2 + t4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -60,7 +60,7 @@ template class Poseidon2ExternalRelationImpl { auto q_o = View(in.q_o); auto q_4 = View(in.q_4); - // add round constants + // add round constants which are loaded in selectors w_l += q_l; w_r += q_r; w_o += q_o; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp new file mode 100644 index 00000000000..c6b57349012 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -0,0 +1,106 @@ +#pragma once +#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" +#include "relation_parameters.hpp" +#include "relation_types.hpp" + +namespace proof_system { + +template class Poseidon2InternalRelationImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_LENGTHS{ + 7, // internal poseidon2 round sub-relation for first value + 7, // internal poseidon2 round sub-relation for second value + 7, // internal poseidon2 round sub-relation for third value + 7, // internal poseidon2 round sub-relation for fourth value + }; + + /** + * @brief Expression for the poseidon2 internal gate. + * @details This relation is defined as: + * q_pos2 * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) + + * \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where: + * v1 := (w_1 + q_1)^5 + * v2 := w_2 + * v3 := w_3 + * v4 := w_4 + * sum := v1 + v2 + v3 + v4 + * v1 := v1 * D1 + sum + * v2 := v2 * D2 + sum + * v3 := v3 * D3 + sum + * v4 := v4 * D4 + sum + * + * @param evals transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& in, + const RelationParameters&, + const FF& scaling_factor) + { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + auto w_l = View(in.w_l); + auto w_r = View(in.w_r); + auto w_o = View(in.w_o); + auto w_4 = View(in.w_4); + auto w_l_shift = View(in.w_l_shift); + auto w_r_shift = View(in.w_r_shift); + auto w_o_shift = View(in.w_o_shift); + auto w_4_shift = View(in.w_4_shift); + auto q_pos2_ext = View(in.q_pos2_ext); + auto q_l = View(in.q_l); + auto q_r = View(in.q_r); + auto q_o = View(in.q_o); + auto q_4 = View(in.q_4); + + // add round constants + w_l += q_l; + + // apply s-box round + auto v1 = w_l * w_l; + v1 *= v1; + v1 *= w_l; + auto v2 = w_r; + auto v3 = w_o; + auto v4 = w_4; + + // matrix mul with 4 muls and 7 additions + auto sum = v1 + v2 + v3 + v4; + { + v1 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + v1 += sum; + auto tmp = q_pos2_ext * (v1 - w_l_shift); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + { + v2 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + v2 += sum; + auto tmp = q_pos2_ext * (v2 - w_r_shift); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + { + v3 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + v3 += sum; + auto tmp = q_pos2_ext * (v3 - w_o_shift); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + { + v4 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + v4 += sum; + auto tmp = q_pos2_ext * (v4 - w_4_shift); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + }; +}; // namespace proof_system + +template using Poseidon2InternalRelation = Relation>; +} // namespace proof_system From d7367f2564542e778887d498376917ec923e0976 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 21 Nov 2023 20:36:27 +0000 Subject: [PATCH 15/34] added poseidon2 selectors to goblin_ultra flavor --- .../src/barretenberg/flavor/goblin_ultra.hpp | 174 ++++++++++-------- .../relations/poseidon2_external_relation.hpp | 10 +- .../relations/poseidon2_internal_relation.hpp | 11 +- 3 files changed, 112 insertions(+), 83 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index ad09352b917..21bece0d561 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -10,6 +10,8 @@ #include "barretenberg/relations/gen_perm_sort_relation.hpp" #include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" +#include "barretenberg/relations/poseidon2_external_relation.hpp" +#include "barretenberg/relations/poseidon2_internal_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -35,10 +37,10 @@ class GoblinUltra { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 53; + static constexpr size_t NUM_ALL_ENTITIES = 55; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 28; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 30; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 18; @@ -84,34 +86,36 @@ class GoblinUltra { */ class PrecomputedEntities : public PrecomputedEntities_ { public: - DataType q_m; // column 0 - DataType q_c; // column 1 - DataType q_l; // column 2 - DataType q_r; // column 3 - DataType q_o; // column 4 - DataType q_4; // column 5 - DataType q_arith; // column 6 - DataType q_sort; // column 7 - DataType q_elliptic; // column 8 - DataType q_aux; // column 9 - DataType q_lookup; // column 10 - DataType q_busread; // column 11 - DataType sigma_1; // column 12 - DataType sigma_2; // column 13 - DataType sigma_3; // column 14 - DataType sigma_4; // column 15 - DataType id_1; // column 16 - DataType id_2; // column 17 - DataType id_3; // column 18 - DataType id_4; // column 19 - DataType table_1; // column 20 - DataType table_2; // column 21 - DataType table_3; // column 22 - DataType table_4; // column 23 - DataType lagrange_first; // column 24 - DataType lagrange_last; // column 25 - DataType lagrange_ecc_op; // column 26 // indicator poly for ecc op gates - DataType databus_id; // column 27 // id polynomial, i.e. id_i = i + DataType q_m; // column 0 + DataType q_c; // column 1 + DataType q_l; // column 2 + DataType q_r; // column 3 + DataType q_o; // column 4 + DataType q_4; // column 5 + DataType q_arith; // column 6 + DataType q_sort; // column 7 + DataType q_elliptic; // column 8 + DataType q_aux; // column 9 + DataType q_lookup; // column 10 + DataType q_busread; // column 11 + DataType q_poseidon2_external; // column 12 + DataType q_poseidon2_internal; // column 13 + DataType sigma_1; // column 14 + DataType sigma_2; // column 15 + DataType sigma_3; // column 16 + DataType sigma_4; // column 17 + DataType id_1; // column 18 + DataType id_2; // column 19 + DataType id_3; // column 20 + DataType id_4; // column 21 + DataType table_1; // column 22 + DataType table_2; // column 23 + DataType table_3; // column 24 + DataType table_4; // column 25 + DataType lagrange_first; // column 26 + DataType lagrange_last; // column 27 + DataType lagrange_ecc_op; // column 28 // indicator poly for ecc op gates + DataType databus_id; // column 29 // id polynomial, i.e. id_i = i DEFINE_POINTER_VIEW(NUM_PRECOMPUTED_ENTITIES, &q_m, @@ -126,6 +130,8 @@ class GoblinUltra { &q_aux, &q_lookup, &q_busread, + &q_poseidon2_external, + &q_poseidon2_internal, &sigma_1, &sigma_2, &sigma_3, @@ -147,7 +153,20 @@ class GoblinUltra { std::vector get_selectors() override { - return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup, q_busread }; + return { q_m, + q_c, + q_l, + q_r, + q_o, + q_4, + q_arith, + q_sort, + q_elliptic, + q_aux, + q_lookup, + q_busread, + q_poseidon2_external, + q_poseidon2_internal }; }; std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3, sigma_4 }; }; std::vector get_id_polynomials() override { return { id_1, id_2, id_3, id_4 }; }; @@ -234,48 +253,49 @@ class GoblinUltra { DataType q_aux; // column 9 DataType q_lookup; // column 10 DataType q_busread; // column 11 - DataType sigma_1; // column 12 - DataType sigma_2; // column 13 - DataType sigma_3; // column 14 - DataType sigma_4; // column 15 - DataType id_1; // column 16 - DataType id_2; // column 17 - DataType id_3; // column 18 - DataType id_4; // column 19 - DataType table_1; // column 20 - DataType table_2; // column 21 - DataType table_3; // column 22 - DataType table_4; // column 23 - DataType lagrange_first; // column 24 - DataType lagrange_last; // column 25 - DataType lagrange_ecc_op; // column 26 - DataType databus_id; // column 27 - DataType w_l; // column 28 - DataType w_r; // column 29 - DataType w_o; // column 30 - DataType w_4; // column 31 - DataType sorted_accum; // column 32 - DataType z_perm; // column 33 - DataType z_lookup; // column 34 - DataType ecc_op_wire_1; // column 35 - DataType ecc_op_wire_2; // column 36 - DataType ecc_op_wire_3; // column 37 - DataType ecc_op_wire_4; // column 38 - DataType calldata; // column 39 - DataType calldata_read_counts; // column 40 - DataType lookup_inverses; // column 41 - DataType table_1_shift; // column 42 - DataType table_2_shift; // column 43 - DataType table_3_shift; // column 44 - DataType table_4_shift; // column 45 - DataType w_l_shift; // column 46 - DataType w_r_shift; // column 47 - DataType w_o_shift; // column 48 - DataType w_4_shift; // column 49 - DataType sorted_accum_shift; // column 50 - DataType z_perm_shift; // column 51 - DataType z_lookup_shift; // column 52 - + DataType q_poseidon2_external; // column 12 + DataType q_poseidon2_internal; // column 13 + DataType sigma_1; // column 14 + DataType sigma_2; // column 15 + DataType sigma_3; // column 16 + DataType sigma_4; // column 17 + DataType id_1; // column 18 + DataType id_2; // column 19 + DataType id_3; // column 20 + DataType id_4; // column 21 + DataType table_1; // column 22 + DataType table_2; // column 23 + DataType table_3; // column 24 + DataType table_4; // column 25 + DataType lagrange_first; // column 26 + DataType lagrange_last; // column 27 + DataType lagrange_ecc_op; // column 28 + DataType databus_id; // column 29 + DataType w_l; // column 30 + DataType w_r; // column 31 + DataType w_o; // column 32 + DataType w_4; // column 33 + DataType sorted_accum; // column 34 + DataType z_perm; // column 35 + DataType z_lookup; // column 36 + DataType ecc_op_wire_1; // column 37 + DataType ecc_op_wire_2; // column 38 + DataType ecc_op_wire_3; // column 39 + DataType ecc_op_wire_4; // column 40 + DataType calldata; // column 41 + DataType calldata_read_counts; // column 42 + DataType lookup_inverses; // column 43 + DataType table_1_shift; // column 44 + DataType table_2_shift; // column 45 + DataType table_3_shift; // column 46 + DataType table_4_shift; // column 47 + DataType w_l_shift; // column 48 + DataType w_r_shift; // column 49 + DataType w_o_shift; // column 50 + DataType w_4_shift; // column 51 + DataType sorted_accum_shift; // column 52 + DataType z_perm_shift; // column 53 + DataType z_lookup_shift; // column 54 // defines a method pointer_view that returns the following, with const and non-const variants DEFINE_POINTER_VIEW(NUM_ALL_ENTITIES, &q_c, @@ -290,6 +310,8 @@ class GoblinUltra { &q_aux, &q_lookup, &q_busread, + &q_poseidon2_external, + &q_poseidon2_internal, &sigma_1, &sigma_2, &sigma_3, @@ -352,6 +374,8 @@ class GoblinUltra { q_aux, q_lookup, q_busread, + q_poseidon2_external, + q_poseidon2_internal, sigma_1, sigma_2, sigma_3, @@ -519,6 +543,8 @@ class GoblinUltra { q_aux = "__Q_AUX"; q_lookup = "__Q_LOOKUP"; q_busread = "__Q_BUSREAD"; + q_poseidon2_external = "__Q_POSEIDON2_EXTERNAL"; + q_poseidon2_internal = "__Q_POSEIDON2_INTERNAL"; sigma_1 = "__SIGMA_1"; sigma_2 = "__SIGMA_2"; sigma_3 = "__SIGMA_3"; @@ -555,6 +581,8 @@ class GoblinUltra { q_aux = verification_key->q_aux; q_lookup = verification_key->q_lookup; q_busread = verification_key->q_busread; + q_poseidon2_external = verification_key->q_poseidon2_external; + q_poseidon2_internal = verification_key->q_poseidon2_internal; sigma_1 = verification_key->sigma_1; sigma_2 = verification_key->sigma_2; sigma_3 = verification_key->sigma_3; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 1548812c03e..d963b9b4ad0 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -54,11 +54,11 @@ template class Poseidon2ExternalRelationImpl { auto w_r_shift = View(in.w_r_shift); auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); - auto q_pos2_ext = View(in.q_pos2_ext); auto q_l = View(in.q_l); auto q_r = View(in.q_r); auto q_o = View(in.q_o); auto q_4 = View(in.q_4); + auto q_poseidon2_external = View(in.q_poseidon2_external); // add round constants which are loaded in selectors w_l += q_l; @@ -97,22 +97,22 @@ template class Poseidon2ExternalRelationImpl { auto t7 = t2 + t4; // A + 3B + 5D + 7C { - auto tmp = q_pos2_ext * (t6 - w_l_shift); + auto tmp = q_poseidon2_external * (t6 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t5 - w_r_shift); + auto tmp = q_poseidon2_external * (t5 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t7 - w_o_shift); + auto tmp = q_poseidon2_external * (t7 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t4 - w_4_shift); + auto tmp = q_poseidon2_external * (t4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index c6b57349012..f16c2d4abe5 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -30,6 +30,7 @@ template class Poseidon2InternalRelationImpl { * v2 := v2 * D2 + sum * v3 := v3 * D3 + sum * v4 := v4 * D4 + sum + * Di is the ith internal diagonal value - 1 of the internal matrix * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -52,11 +53,11 @@ template class Poseidon2InternalRelationImpl { auto w_r_shift = View(in.w_r_shift); auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); - auto q_pos2_ext = View(in.q_pos2_ext); auto q_l = View(in.q_l); auto q_r = View(in.q_r); auto q_o = View(in.q_o); auto q_4 = View(in.q_4); + auto q_poseidon2_internal = View(in.q_poseidon2_internal); // add round constants w_l += q_l; @@ -74,28 +75,28 @@ template class Poseidon2InternalRelationImpl { { v1 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; v1 += sum; - auto tmp = q_pos2_ext * (v1 - w_l_shift); + auto tmp = q_poseidon2_internal * (v1 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { v2 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; v2 += sum; - auto tmp = q_pos2_ext * (v2 - w_r_shift); + auto tmp = q_poseidon2_internal * (v2 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { v3 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; v3 += sum; - auto tmp = q_pos2_ext * (v3 - w_o_shift); + auto tmp = q_poseidon2_internal * (v3 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { v4 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; v4 += sum; - auto tmp = q_pos2_ext * (v4 - w_4_shift); + auto tmp = q_poseidon2_internal * (v4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } From 6249c2ef3dcc2db3254e80a35d7506a06a89dd6a Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 21 Nov 2023 21:34:24 +0000 Subject: [PATCH 16/34] adding selector patches to relations from merged refactoring --- .../src/barretenberg/flavor/goblin_ultra.hpp | 4 +- .../flavor/goblin_ultra_recursive.hpp | 186 ++++++++++-------- .../arithmetization/arithmetization.hpp | 11 +- .../relations/poseidon2_external_relation.hpp | 34 ++-- .../relations/poseidon2_internal_relation.hpp | 34 ++-- 5 files changed, 147 insertions(+), 122 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index 21bece0d561..53321d68a98 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -55,7 +55,9 @@ class GoblinUltra { proof_system::EllipticRelation, proof_system::AuxiliaryRelation, proof_system::EccOpQueueRelation, - proof_system::DatabusLookupRelation>; + proof_system::DatabusLookupRelation, + proof_system::Poseidon2ExternalRelation, + proof_system::Poseidon2InternalRelation>; using LogDerivLookupRelation = proof_system::DatabusLookupRelation; diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp index f37d26b3adc..7ab20ba19ee 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp @@ -10,15 +10,7 @@ #include "barretenberg/polynomials/evaluation_domain.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" -#include "barretenberg/relations/auxiliary_relation.hpp" -#include "barretenberg/relations/ecc_op_queue_relation.hpp" -#include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/gen_perm_sort_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" -#include "barretenberg/relations/permutation_relation.hpp" -#include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" -#include "barretenberg/transcript/transcript.hpp" #include #include #include @@ -61,10 +53,10 @@ template class GoblinUltraRecursive_ { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 53; + static constexpr size_t NUM_ALL_ENTITIES = 55; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 28; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 30; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 18; @@ -76,7 +68,9 @@ template class GoblinUltraRecursive_ { proof_system::EllipticRelation, proof_system::AuxiliaryRelation, proof_system::EccOpQueueRelation, - proof_system::DatabusLookupRelation>; + proof_system::DatabusLookupRelation, + proof_system::Poseidon2ExternalRelation, + proof_system::Poseidon2InternalRelation>; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); @@ -98,34 +92,36 @@ template class GoblinUltraRecursive_ { */ class PrecomputedEntities : public PrecomputedEntities_ { public: - DataType q_m; // column 0 - DataType q_c; // column 1 - DataType q_l; // column 2 - DataType q_r; // column 3 - DataType q_o; // column 4 - DataType q_4; // column 5 - DataType q_arith; // column 6 - DataType q_sort; // column 7 - DataType q_elliptic; // column 8 - DataType q_aux; // column 9 - DataType q_lookup; // column 10 - DataType q_busread; // column 11 - DataType sigma_1; // column 12 - DataType sigma_2; // column 13 - DataType sigma_3; // column 14 - DataType sigma_4; // column 15 - DataType id_1; // column 16 - DataType id_2; // column 17 - DataType id_3; // column 18 - DataType id_4; // column 19 - DataType table_1; // column 20 - DataType table_2; // column 21 - DataType table_3; // column 22 - DataType table_4; // column 23 - DataType lagrange_first; // column 24 - DataType lagrange_last; // column 25 - DataType lagrange_ecc_op; // column 26 // indicator poly for ecc op gates - DataType databus_id; // column 27 // id polynomial, i.e. id_i = i + DataType q_m; // column 0 + DataType q_c; // column 1 + DataType q_l; // column 2 + DataType q_r; // column 3 + DataType q_o; // column 4 + DataType q_4; // column 5 + DataType q_arith; // column 6 + DataType q_sort; // column 7 + DataType q_elliptic; // column 8 + DataType q_aux; // column 9 + DataType q_lookup; // column 10 + DataType q_busread; // column 11 + DataType q_poseidon2_external; // column 12 + DataType q_poseidon2_internal; // column 13 + DataType sigma_1; // column 14 + DataType sigma_2; // column 15 + DataType sigma_3; // column 16 + DataType sigma_4; // column 17 + DataType id_1; // column 18 + DataType id_2; // column 19 + DataType id_3; // column 20 + DataType id_4; // column 21 + DataType table_1; // column 22 + DataType table_2; // column 23 + DataType table_3; // column 24 + DataType table_4; // column 25 + DataType lagrange_first; // column 26 + DataType lagrange_last; // column 27 + DataType lagrange_ecc_op; // column 28 // indicator poly for ecc op gates + DataType databus_id; // column 29 // id polynomial, i.e. id_i = i DEFINE_POINTER_VIEW(NUM_PRECOMPUTED_ENTITIES, &q_m, @@ -140,6 +136,8 @@ template class GoblinUltraRecursive_ { &q_aux, &q_lookup, &q_busread, + &q_poseidon2_external, + &q_poseidon2_internal, &sigma_1, &sigma_2, &sigma_3, @@ -161,7 +159,20 @@ template class GoblinUltraRecursive_ { std::vector get_selectors() override { - return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup, q_busread }; + return { q_m, + q_c, + q_l, + q_r, + q_o, + q_4, + q_arith, + q_sort, + q_elliptic, + q_aux, + q_lookup, + q_busread, + q_poseidon2_external, + q_poseidon2_internal }; }; std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3, sigma_4 }; }; std::vector get_id_polynomials() override { return { id_1, id_2, id_3, id_4 }; }; @@ -248,48 +259,49 @@ template class GoblinUltraRecursive_ { DataType q_aux; // column 9 DataType q_lookup; // column 10 DataType q_busread; // column 11 - DataType sigma_1; // column 12 - DataType sigma_2; // column 13 - DataType sigma_3; // column 14 - DataType sigma_4; // column 15 - DataType id_1; // column 16 - DataType id_2; // column 17 - DataType id_3; // column 18 - DataType id_4; // column 19 - DataType table_1; // column 20 - DataType table_2; // column 21 - DataType table_3; // column 22 - DataType table_4; // column 23 - DataType lagrange_first; // column 24 - DataType lagrange_last; // column 25 - DataType lagrange_ecc_op; // column 26 - DataType databus_id; // column 27 - DataType w_l; // column 28 - DataType w_r; // column 29 - DataType w_o; // column 30 - DataType w_4; // column 31 - DataType sorted_accum; // column 32 - DataType z_perm; // column 33 - DataType z_lookup; // column 34 - DataType ecc_op_wire_1; // column 35 - DataType ecc_op_wire_2; // column 36 - DataType ecc_op_wire_3; // column 37 - DataType ecc_op_wire_4; // column 38 - DataType calldata; // column 39 - DataType calldata_read_counts; // column 40 - DataType lookup_inverses; // column 41 - DataType table_1_shift; // column 42 - DataType table_2_shift; // column 43 - DataType table_3_shift; // column 44 - DataType table_4_shift; // column 45 - DataType w_l_shift; // column 46 - DataType w_r_shift; // column 47 - DataType w_o_shift; // column 48 - DataType w_4_shift; // column 49 - DataType sorted_accum_shift; // column 50 - DataType z_perm_shift; // column 51 - DataType z_lookup_shift; // column 52 - + DataType q_poseidon2_external; // column 12 + DataType q_poseidon2_internal; // column 13 + DataType sigma_1; // column 14 + DataType sigma_2; // column 15 + DataType sigma_3; // column 16 + DataType sigma_4; // column 17 + DataType id_1; // column 18 + DataType id_2; // column 19 + DataType id_3; // column 20 + DataType id_4; // column 21 + DataType table_1; // column 22 + DataType table_2; // column 23 + DataType table_3; // column 24 + DataType table_4; // column 25 + DataType lagrange_first; // column 26 + DataType lagrange_last; // column 27 + DataType lagrange_ecc_op; // column 28 + DataType databus_id; // column 29 + DataType w_l; // column 30 + DataType w_r; // column 31 + DataType w_o; // column 32 + DataType w_4; // column 33 + DataType sorted_accum; // column 34 + DataType z_perm; // column 35 + DataType z_lookup; // column 36 + DataType ecc_op_wire_1; // column 37 + DataType ecc_op_wire_2; // column 38 + DataType ecc_op_wire_3; // column 39 + DataType ecc_op_wire_4; // column 40 + DataType calldata; // column 41 + DataType calldata_read_counts; // column 42 + DataType lookup_inverses; // column 43 + DataType table_1_shift; // column 44 + DataType table_2_shift; // column 45 + DataType table_3_shift; // column 46 + DataType table_4_shift; // column 47 + DataType w_l_shift; // column 48 + DataType w_r_shift; // column 49 + DataType w_o_shift; // column 50 + DataType w_4_shift; // column 51 + DataType sorted_accum_shift; // column 52 + DataType z_perm_shift; // column 53 + DataType z_lookup_shift; // column 54 // defines a method pointer_view that returns the following, with const and non-const variants DEFINE_POINTER_VIEW(NUM_ALL_ENTITIES, &q_c, @@ -304,6 +316,8 @@ template class GoblinUltraRecursive_ { &q_aux, &q_lookup, &q_busread, + &q_poseidon2_external, + &q_poseidon2_internal, &sigma_1, &sigma_2, &sigma_3, @@ -366,6 +380,8 @@ template class GoblinUltraRecursive_ { q_aux, q_lookup, q_busread, + q_poseidon2_external, + q_poseidon2_internal, sigma_1, sigma_2, sigma_3, @@ -441,6 +457,8 @@ template class GoblinUltraRecursive_ { this->q_aux = Commitment::from_witness(builder, native_key->q_aux); this->q_lookup = Commitment::from_witness(builder, native_key->q_lookup); this->q_busread = Commitment::from_witness(builder, native_key->q_busread); + this->q_poseidon2_external = Commitment::from_witness(builder, native_key->q_poseidon2_external); + this->q_poseidon2_internal = Commitment::from_witness(builder, native_key->q_poseidon2_internal); this->sigma_1 = Commitment::from_witness(builder, native_key->sigma_1); this->sigma_2 = Commitment::from_witness(builder, native_key->sigma_2); this->sigma_3 = Commitment::from_witness(builder, native_key->sigma_3); @@ -509,6 +527,8 @@ template class GoblinUltraRecursive_ { this->q_aux = "__Q_AUX"; this->q_lookup = "__Q_LOOKUP"; this->q_busread = "__Q_BUSREAD"; + this->q_poseidon2_external = "__Q_POSEIDON2_EXTERNAL"; + this->q_poseidon2_internal = "__Q_POSEIDON2_INTERNAL"; this->sigma_1 = "__SIGMA_1"; this->sigma_2 = "__SIGMA_2"; this->sigma_3 = "__SIGMA_3"; @@ -543,6 +563,8 @@ template class GoblinUltraRecursive_ { this->q_aux = verification_key->q_aux; this->q_lookup = verification_key->q_lookup; this->q_busread = verification_key->q_busread; + this->q_poseidon2_external = verification_key->q_poseidon2_external; + this->q_poseidon2_internal = verification_key->q_poseidon2_internal; this->sigma_1 = verification_key->sigma_1; this->sigma_2 = verification_key->sigma_2; this->sigma_3 = verification_key->sigma_3; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index c6dffdeaa3a..c396301f7ba 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -118,7 +118,7 @@ template class Ultra { template class UltraHonk { public: static constexpr size_t NUM_WIRES = 4; - static constexpr size_t NUM_SELECTORS = 12; + static constexpr size_t NUM_SELECTORS = 14; using FF = FF_; using SelectorType = std::vector>; @@ -138,6 +138,8 @@ template class UltraHonk { SelectorType& q_aux() { return selectors[9]; }; SelectorType& q_lookup_type() { return selectors[10]; }; SelectorType& q_busread() { return this->selectors[11]; }; + SelectorType& q_poseidon2_external() { return this->selectors[12]; }; + SelectorType& q_poseidon2_internal() { return this->selectors[13]; }; const auto& get() const { return selectors; }; @@ -154,7 +156,12 @@ template class UltraHonk { * Ultra arithmetization * */ - void pad_additional() { q_busread().emplace_back(0); }; + void pad_additional() + { + q_busread().emplace_back(0); + q_poseidon2_external().emplace_back(0); + q_poseidon2_internal().emplace_back(0); + }; // Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk) inline static const std::vector selector_names = {}; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index d963b9b4ad0..e6de96218d3 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -1,14 +1,12 @@ #pragma once -#include "relation_parameters.hpp" -#include "relation_types.hpp" - +#include "barretenberg/relations/relation_types.hpp" namespace proof_system { template class Poseidon2ExternalRelationImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 7, // external poseidon2 round sub-relation for first value 7, // external poseidon2 round sub-relation for second value 7, // external poseidon2 round sub-relation for third value @@ -38,10 +36,10 @@ template class Poseidon2ExternalRelationImpl { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - template + template void static accumulate(ContainerOverSubrelations& evals, const AllEntities& in, - const RelationParameters&, + const Parameters&, const FF& scaling_factor) { using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; @@ -61,24 +59,24 @@ template class Poseidon2ExternalRelationImpl { auto q_poseidon2_external = View(in.q_poseidon2_external); // add round constants which are loaded in selectors - w_l += q_l; - w_r += q_r; - w_o += q_o; - w_4 += q_4; + auto tmp1 = w_l + q_l; + auto tmp2 = w_r + q_r; + auto tmp3 = w_o + q_o; + auto tmp4 = w_4 + q_4; // apply s-box round - auto v1 = w_l * w_l; + auto v1 = tmp1 * tmp1; v1 *= v1; - v1 *= w_l; - auto v2 = w_r * w_r; + v1 *= tmp1; + auto v2 = tmp2 * tmp2; v2 *= v2; - v2 *= w_r; - auto v3 = w_o * w_o; + v2 *= tmp2; + auto v3 = tmp3 * tmp3; v3 *= v3; - v3 *= w_o; - auto v4 = w_4 * w_4; + v3 *= tmp3; + auto v4 = tmp4 * tmp4; v4 *= v4; - v4 *= w_4; + v4 *= tmp4; // matrix mul with 14 additions auto t0 = v1 + v2; // A + B diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index f16c2d4abe5..4458ba004b8 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -1,6 +1,5 @@ #pragma once #include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" -#include "relation_parameters.hpp" #include "relation_types.hpp" namespace proof_system { @@ -9,7 +8,7 @@ template class Poseidon2InternalRelationImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 7, // internal poseidon2 round sub-relation for first value 7, // internal poseidon2 round sub-relation for second value 7, // internal poseidon2 round sub-relation for third value @@ -37,10 +36,10 @@ template class Poseidon2InternalRelationImpl { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - template + template void static accumulate(ContainerOverSubrelations& evals, const AllEntities& in, - const RelationParameters&, + const Parameters&, const FF& scaling_factor) { using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; @@ -54,18 +53,15 @@ template class Poseidon2InternalRelationImpl { auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); auto q_l = View(in.q_l); - auto q_r = View(in.q_r); - auto q_o = View(in.q_o); - auto q_4 = View(in.q_4); auto q_poseidon2_internal = View(in.q_poseidon2_internal); // add round constants - w_l += q_l; + auto tmp1 = w_l + q_l; // apply s-box round - auto v1 = w_l * w_l; + auto v1 = tmp1 * tmp1; v1 *= v1; - v1 *= w_l; + v1 *= tmp1; auto v2 = w_r; auto v3 = w_o; auto v4 = w_4; @@ -80,23 +76,23 @@ template class Poseidon2InternalRelationImpl { std::get<0>(evals) += tmp; } { - v2 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; - v2 += sum; - auto tmp = q_poseidon2_internal * (v2 - w_r_shift); + auto tmp2 = v2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + tmp2 += sum; + auto tmp = q_poseidon2_internal * (tmp2 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - v3 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; - v3 += sum; - auto tmp = q_poseidon2_internal * (v3 - w_o_shift); + auto tmp3 = v3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + tmp3 += sum; + auto tmp = q_poseidon2_internal * (tmp3 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - v4 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; - v4 += sum; - auto tmp = q_poseidon2_internal * (v4 - w_4_shift); + auto tmp4 = v4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + tmp4 += sum; + auto tmp = q_poseidon2_internal * (tmp4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } From 8d2b7317c76154363073793e17c59cef7e3f57c9 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 21 Nov 2023 22:16:37 +0000 Subject: [PATCH 17/34] forgotten updates --- .../circuit_builder/goblin_ultra_circuit_builder.cpp | 2 ++ .../circuit_builder/goblin_ultra_circuit_builder.hpp | 2 ++ .../src/barretenberg/sumcheck/instance/prover_instance.cpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index 610aefccf09..be29dc3a3cb 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -60,6 +60,8 @@ template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_ this->q_lookup_type.emplace_back(0); this->q_elliptic.emplace_back(0); this->q_aux.emplace_back(0); + this->q_poseidon2_external.emplace_back(0); + this->q_poseidon2_internal.emplace_back(0); ++this->num_gates; } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index f4532a31895..88d4cd7a95a 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -43,6 +43,8 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui WireVector& ecc_op_wire_4 = std::get<3>(ecc_op_wires); SelectorVector& q_busread = this->selectors.q_busread(); + SelectorVector& q_poseidon2_external = this->selectors.q_poseidon2_external(); + SelectorVector& q_poseidon2_internal = this->selectors.q_poseidon2_internal(); // DataBus call/return data arrays std::vector public_calldata; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 34f2842eede..dee8b4fe4b5 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -338,6 +338,8 @@ template void ProverInstance_::initialize_prover_polynomi prover_polynomials.lookup_inverses = proving_key->lookup_inverses; prover_polynomials.q_busread = proving_key->q_busread; prover_polynomials.databus_id = proving_key->databus_id; + prover_polynomials.q_poseidon2_external = proving_key->q_poseidon2_external; + prover_polynomials.q_poseidon2_internal = proving_key->q_poseidon2_internal; } // These polynomials have not yet been computed; initialize them so prover_polynomials is "full" and we can use @@ -530,6 +532,8 @@ std::shared_ptr ProverInstance_::compu verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); verification_key->q_busread = commitment_key->commit(proving_key->q_busread); verification_key->databus_id = commitment_key->commit(proving_key->databus_id); + verification_key->q_poseidon2_external = commitment_key->commit(proving_key->q_poseidon2_external); + verification_key->q_poseidon2_internal = commitment_key->commit(proving_key->q_poseidon2_internal); } return verification_key; From f09ed9183685e7fcacfd747a76461c23e3f74868 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 17:50:11 +0000 Subject: [PATCH 18/34] external poseidon2 round relation --- .../relations/poseidon2_relation.hpp | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp new file mode 100644 index 00000000000..5aec4ddaf60 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp @@ -0,0 +1,95 @@ +#pragma once +#include "relation_parameters.hpp" +#include "relation_types.hpp" + +namespace proof_system { + +template class Poseidon2ExternalRelationImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_LENGTHS{ + 7, // external poseidon2 round sub-relation for first value + 7, // external poseidon2 round sub-relation for second value + 7, // external poseidon2 round sub-relation for third value + 7, // external poseidon2 round sub-relation for fourth value + }; + + /** + * @brief Expression for the poseidon2 external gate. + * @details This relation is defined as: + * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - + * w_4_shift) ) = 0 + * where: + * t0 := w_1 + w_2 (1, 1, 0, 0) + * t1 := w_3 + w_4 (0, 0, 1, 1) + * t2 := w_2 + w_2 + t1 = 2 * w_2 + w_3 + w_4 (0, 2, 1, 1) + * t3 := w_4 + w_4 + t0 = w_1 + w_2 + 2 * w_4 (1, 1, 0, 2) + * t4 := 2 * (t1 + t1) + t3 = w_1 + w_2 + 4 * w_3 + 6 * w_4 (1, 1, 4, 6) + * t5 := 2 * (t0 + t0) + t2 = 4 * w_1 + 6 * w_2 + w_3 + w_4 (4, 6, 1, 1) + * t6 := t3 + t5 = 5 * w_1 + 7 * w_2 + 1 * w_3 + 3 * w_4 (5, 7, 1, 3) + * t7 := t2 + t4 (1, 3, 5, 7) + * + * @param evals transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& in, + const RelationParameters&, + const FF& scaling_factor) + { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + auto w_l = View(in.w_l); + auto w_r = View(in.w_r); + auto w_o = View(in.w_o); + auto w_4 = View(in.w_4); + auto w_l_shift = View(in.w_l_shift); + auto w_r_shift = View(in.w_r_shift); + auto w_o_shift = View(in.w_o_shift); + auto w_4_shift = View(in.w_4_shift); + auto q_pos2_ext = View(in.q_pos2_ext); + + auto t0 = w_l + w_r; // A + B + auto t1 = w_o + w_4; // C + D + auto t2 = w_r + w_r; // 2B + t2 += t1; // 2B + C + D + auto t3 = w_4 + w_4; // 2D + t3 += t0; // 2D + A + B + auto t4 = t1 + t1; + t4 += t4; + t4 += t3; // A + B + 4C + 6D + auto t5 = t0 + t0; + t5 += t5; + t5 += t2; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 3C + D + auto t7 = t2 + t4; // A + 3B + 5D + 7C + + { + auto tmp = q_pos2_ext * (t6 - w_l_shift); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t5 - w_r_shift); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t7 - w_o_shift); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + { + auto tmp = q_pos2_ext * (t4 - w_4_shift); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + }; +}; + +template using Poseidon2ExternalRelation = Relation>; +} // namespace proof_system From d67958112e66c6fe2357134489a2d8b3a1c4c6a0 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 19:41:00 +0000 Subject: [PATCH 19/34] added ARC and SBox rounds to external --- .../relations/poseidon2_relation.hpp | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp index 5aec4ddaf60..075b6dfa64e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp @@ -18,16 +18,19 @@ template class Poseidon2ExternalRelationImpl { /** * @brief Expression for the poseidon2 external gate. * @details This relation is defined as: - * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - - * w_4_shift) ) = 0 - * where: - * t0 := w_1 + w_2 (1, 1, 0, 0) - * t1 := w_3 + w_4 (0, 0, 1, 1) - * t2 := w_2 + w_2 + t1 = 2 * w_2 + w_3 + w_4 (0, 2, 1, 1) - * t3 := w_4 + w_4 + t0 = w_1 + w_2 + 2 * w_4 (1, 1, 0, 2) - * t4 := 2 * (t1 + t1) + t3 = w_1 + w_2 + 4 * w_3 + 6 * w_4 (1, 1, 4, 6) - * t5 := 2 * (t0 + t0) + t2 = 4 * w_1 + 6 * w_2 + w_3 + w_4 (4, 6, 1, 1) - * t6 := t3 + t5 = 5 * w_1 + 7 * w_2 + 1 * w_3 + 3 * w_4 (5, 7, 1, 3) + * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + + * \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - w_4_shift) ) = 0 where: + * v1 := (w_1 + q_1)^5 + * v2 := (w_2 + q_2)^5 + * v3 := (w_3 + q_3)^5 + * v4 := (w_4 + q_4)^5 + * t0 := v1 + v2 (1, 1, 0, 0) + * t1 := v3 + v4 (0, 0, 1, 1) + * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) + * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) + * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) + * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) + * t6 := t3 + t5 = 5 * v1 + 7 * v2 + 1 * v3 + 3 * v4 (5, 7, 1, 3) * t7 := t2 + t4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` @@ -52,13 +55,38 @@ template class Poseidon2ExternalRelationImpl { auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); auto q_pos2_ext = View(in.q_pos2_ext); + auto q_l = View(in.q_l); + auto q_r = View(in.q_r); + auto q_o = View(in.q_o); + auto q_4 = View(in.q_4); - auto t0 = w_l + w_r; // A + B - auto t1 = w_o + w_4; // C + D - auto t2 = w_r + w_r; // 2B - t2 += t1; // 2B + C + D - auto t3 = w_4 + w_4; // 2D - t3 += t0; // 2D + A + B + // add round constants + w_l += q_l; + w_r += q_r; + w_o += q_o; + w_4 += q_4; + + // apply s-box round + auto v1 = w_l * w_l; + v1 *= v1; + v1 *= w_l; + auto v2 = w_r * w_r; + v2 *= v2; + v2 *= w_r; + auto v3 = w_o * w_o; + v3 *= v3; + v3 *= w_o; + auto v4 = w_4 * w_4; + v4 *= v4; + v4 *= w_4; + + // matrix mul with 14 additions + auto t0 = v1 + v2; // A + B + auto t1 = v3 + v4; // C + D + auto t2 = v2 + v2; // 2B + t2 += t1; // 2B + C + D + auto t3 = v4 + v4; // 2D + t3 += t0; // 2D + A + B auto t4 = t1 + t1; t4 += t4; t4 += t3; // A + B + 4C + 6D From 35ab7d903212f3c36a1e28ec58f0037d930b4538 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 20 Nov 2023 20:11:33 +0000 Subject: [PATCH 20/34] created internal round relation --- ...on.hpp => poseidon2_external_relation.hpp} | 16 +-- .../relations/poseidon2_internal_relation.hpp | 106 ++++++++++++++++++ 2 files changed, 114 insertions(+), 8 deletions(-) rename barretenberg/cpp/src/barretenberg/relations/{poseidon2_relation.hpp => poseidon2_external_relation.hpp} (93%) create mode 100644 barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp similarity index 93% rename from barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp rename to barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 075b6dfa64e..1548812c03e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -24,14 +24,14 @@ template class Poseidon2ExternalRelationImpl { * v2 := (w_2 + q_2)^5 * v3 := (w_3 + q_3)^5 * v4 := (w_4 + q_4)^5 - * t0 := v1 + v2 (1, 1, 0, 0) - * t1 := v3 + v4 (0, 0, 1, 1) - * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) - * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) - * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) - * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) + * t0 := v1 + v2 (1, 1, 0, 0) + * t1 := v3 + v4 (0, 0, 1, 1) + * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) + * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) + * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) + * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) * t6 := t3 + t5 = 5 * v1 + 7 * v2 + 1 * v3 + 3 * v4 (5, 7, 1, 3) - * t7 := t2 + t4 (1, 3, 5, 7) + * t7 := t2 + t4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -60,7 +60,7 @@ template class Poseidon2ExternalRelationImpl { auto q_o = View(in.q_o); auto q_4 = View(in.q_4); - // add round constants + // add round constants which are loaded in selectors w_l += q_l; w_r += q_r; w_o += q_o; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp new file mode 100644 index 00000000000..c6b57349012 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -0,0 +1,106 @@ +#pragma once +#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" +#include "relation_parameters.hpp" +#include "relation_types.hpp" + +namespace proof_system { + +template class Poseidon2InternalRelationImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_LENGTHS{ + 7, // internal poseidon2 round sub-relation for first value + 7, // internal poseidon2 round sub-relation for second value + 7, // internal poseidon2 round sub-relation for third value + 7, // internal poseidon2 round sub-relation for fourth value + }; + + /** + * @brief Expression for the poseidon2 internal gate. + * @details This relation is defined as: + * q_pos2 * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) + + * \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where: + * v1 := (w_1 + q_1)^5 + * v2 := w_2 + * v3 := w_3 + * v4 := w_4 + * sum := v1 + v2 + v3 + v4 + * v1 := v1 * D1 + sum + * v2 := v2 * D2 + sum + * v3 := v3 * D3 + sum + * v4 := v4 * D4 + sum + * + * @param evals transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& in, + const RelationParameters&, + const FF& scaling_factor) + { + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + auto w_l = View(in.w_l); + auto w_r = View(in.w_r); + auto w_o = View(in.w_o); + auto w_4 = View(in.w_4); + auto w_l_shift = View(in.w_l_shift); + auto w_r_shift = View(in.w_r_shift); + auto w_o_shift = View(in.w_o_shift); + auto w_4_shift = View(in.w_4_shift); + auto q_pos2_ext = View(in.q_pos2_ext); + auto q_l = View(in.q_l); + auto q_r = View(in.q_r); + auto q_o = View(in.q_o); + auto q_4 = View(in.q_4); + + // add round constants + w_l += q_l; + + // apply s-box round + auto v1 = w_l * w_l; + v1 *= v1; + v1 *= w_l; + auto v2 = w_r; + auto v3 = w_o; + auto v4 = w_4; + + // matrix mul with 4 muls and 7 additions + auto sum = v1 + v2 + v3 + v4; + { + v1 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + v1 += sum; + auto tmp = q_pos2_ext * (v1 - w_l_shift); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + { + v2 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + v2 += sum; + auto tmp = q_pos2_ext * (v2 - w_r_shift); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + { + v3 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + v3 += sum; + auto tmp = q_pos2_ext * (v3 - w_o_shift); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + { + v4 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + v4 += sum; + auto tmp = q_pos2_ext * (v4 - w_4_shift); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + }; +}; // namespace proof_system + +template using Poseidon2InternalRelation = Relation>; +} // namespace proof_system From 5e9469830b810e35ab457d406279163f8a5ad42a Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 22 Nov 2023 20:52:46 +0000 Subject: [PATCH 21/34] naming update --- .../relations/poseidon2_external_relation.hpp | 46 +++++++++---------- .../relations/poseidon2_internal_relation.hpp | 41 ++++++++--------- 2 files changed, 41 insertions(+), 46 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 1548812c03e..8f06a364f53 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -1,14 +1,12 @@ #pragma once -#include "relation_parameters.hpp" -#include "relation_types.hpp" - +#include "barretenberg/relations/relation_types.hpp" namespace proof_system { template class Poseidon2ExternalRelationImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 7, // external poseidon2 round sub-relation for first value 7, // external poseidon2 round sub-relation for second value 7, // external poseidon2 round sub-relation for third value @@ -38,10 +36,10 @@ template class Poseidon2ExternalRelationImpl { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - template + template void static accumulate(ContainerOverSubrelations& evals, const AllEntities& in, - const RelationParameters&, + const Parameters&, const FF& scaling_factor) { using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; @@ -54,31 +52,31 @@ template class Poseidon2ExternalRelationImpl { auto w_r_shift = View(in.w_r_shift); auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); - auto q_pos2_ext = View(in.q_pos2_ext); auto q_l = View(in.q_l); auto q_r = View(in.q_r); auto q_o = View(in.q_o); auto q_4 = View(in.q_4); + auto q_poseidon2_external = View(in.q_poseidon2_external); // add round constants which are loaded in selectors - w_l += q_l; - w_r += q_r; - w_o += q_o; - w_4 += q_4; + auto tmp1 = w_l + q_l; + auto tmp2 = w_r + q_r; + auto tmp3 = w_o + q_o; + auto tmp4 = w_4 + q_4; // apply s-box round - auto v1 = w_l * w_l; + auto v1 = tmp1 * tmp1; v1 *= v1; - v1 *= w_l; - auto v2 = w_r * w_r; + v1 *= tmp1; + auto v2 = tmp2 * tmp2; v2 *= v2; - v2 *= w_r; - auto v3 = w_o * w_o; + v2 *= tmp2; + auto v3 = tmp3 * tmp3; v3 *= v3; - v3 *= w_o; - auto v4 = w_4 * w_4; + v3 *= tmp3; + auto v4 = tmp4 * tmp4; v4 *= v4; - v4 *= w_4; + v4 *= tmp4; // matrix mul with 14 additions auto t0 = v1 + v2; // A + B @@ -97,22 +95,22 @@ template class Poseidon2ExternalRelationImpl { auto t7 = t2 + t4; // A + 3B + 5D + 7C { - auto tmp = q_pos2_ext * (t6 - w_l_shift); + auto tmp = q_poseidon2_external * (t6 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t5 - w_r_shift); + auto tmp = q_poseidon2_external * (t5 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t7 - w_o_shift); + auto tmp = q_poseidon2_external * (t7 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - auto tmp = q_pos2_ext * (t4 - w_4_shift); + auto tmp = q_poseidon2_external * (t4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -120,4 +118,4 @@ template class Poseidon2ExternalRelationImpl { }; template using Poseidon2ExternalRelation = Relation>; -} // namespace proof_system +} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index c6b57349012..c4f24bd904e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -1,6 +1,5 @@ #pragma once #include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" -#include "relation_parameters.hpp" #include "relation_types.hpp" namespace proof_system { @@ -9,7 +8,7 @@ template class Poseidon2InternalRelationImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 7, // internal poseidon2 round sub-relation for first value 7, // internal poseidon2 round sub-relation for second value 7, // internal poseidon2 round sub-relation for third value @@ -30,16 +29,17 @@ template class Poseidon2InternalRelationImpl { * v2 := v2 * D2 + sum * v3 := v3 * D3 + sum * v4 := v4 * D4 + sum + * Di is the ith internal diagonal value - 1 of the internal matrix * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - template + template void static accumulate(ContainerOverSubrelations& evals, const AllEntities& in, - const RelationParameters&, + const Parameters&, const FF& scaling_factor) { using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; @@ -52,19 +52,16 @@ template class Poseidon2InternalRelationImpl { auto w_r_shift = View(in.w_r_shift); auto w_o_shift = View(in.w_o_shift); auto w_4_shift = View(in.w_4_shift); - auto q_pos2_ext = View(in.q_pos2_ext); auto q_l = View(in.q_l); - auto q_r = View(in.q_r); - auto q_o = View(in.q_o); - auto q_4 = View(in.q_4); + auto q_poseidon2_internal = View(in.q_poseidon2_internal); // add round constants - w_l += q_l; + auto tmp1 = w_l + q_l; // apply s-box round - auto v1 = w_l * w_l; + auto v1 = tmp1 * tmp1; v1 *= v1; - v1 *= w_l; + v1 *= tmp1; auto v2 = w_r; auto v3 = w_o; auto v4 = w_4; @@ -74,28 +71,28 @@ template class Poseidon2InternalRelationImpl { { v1 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; v1 += sum; - auto tmp = q_pos2_ext * (v1 - w_l_shift); + auto tmp = q_poseidon2_internal * (v1 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - v2 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; - v2 += sum; - auto tmp = q_pos2_ext * (v2 - w_r_shift); + auto tmp2 = v2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + tmp2 += sum; + auto tmp = q_poseidon2_internal * (tmp2 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - v3 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; - v3 += sum; - auto tmp = q_pos2_ext * (v3 - w_o_shift); + auto tmp3 = v3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + tmp3 += sum; + auto tmp = q_poseidon2_internal * (tmp3 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - v4 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; - v4 += sum; - auto tmp = q_pos2_ext * (v4 - w_4_shift); + auto tmp4 = v4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + tmp4 += sum; + auto tmp = q_poseidon2_internal * (tmp4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -103,4 +100,4 @@ template class Poseidon2InternalRelationImpl { }; // namespace proof_system template using Poseidon2InternalRelation = Relation>; -} // namespace proof_system +} // namespace proof_system \ No newline at end of file From 14157c101e25f5fcdbbf06e149bf19eda50f696f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 22 Nov 2023 21:19:42 +0000 Subject: [PATCH 22/34] external relation consistency test --- .../ultra_relation_consistency.test.cpp | 141 ++++++++++++++---- 1 file changed, 108 insertions(+), 33 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 9320053a485..189f5e40086 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -18,6 +18,7 @@ #include "barretenberg/relations/gen_perm_sort_relation.hpp" #include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" +#include "barretenberg/relations/poseidon2_external_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include @@ -28,7 +29,7 @@ namespace proof_system::ultra_relation_consistency_tests { using FF = barretenberg::fr; struct InputElements { - static constexpr size_t NUM_ELEMENTS = 43; + static constexpr size_t NUM_ELEMENTS = 45; std::array _data; static InputElements get_random() @@ -60,38 +61,40 @@ struct InputElements { FF& q_elliptic = std::get<8>(_data); FF& q_aux = std::get<9>(_data); FF& q_lookup = std::get<10>(_data); - FF& sigma_1 = std::get<11>(_data); - FF& sigma_2 = std::get<12>(_data); - FF& sigma_3 = std::get<13>(_data); - FF& sigma_4 = std::get<14>(_data); - FF& id_1 = std::get<15>(_data); - FF& id_2 = std::get<16>(_data); - FF& id_3 = std::get<17>(_data); - FF& id_4 = std::get<18>(_data); - FF& table_1 = std::get<19>(_data); - FF& table_2 = std::get<20>(_data); - FF& table_3 = std::get<21>(_data); - FF& table_4 = std::get<22>(_data); - FF& lagrange_first = std::get<23>(_data); - FF& lagrange_last = std::get<24>(_data); - FF& w_l = std::get<25>(_data); - FF& w_r = std::get<26>(_data); - FF& w_o = std::get<27>(_data); - FF& w_4 = std::get<28>(_data); - FF& sorted_accum = std::get<29>(_data); - FF& z_perm = std::get<30>(_data); - FF& z_lookup = std::get<31>(_data); - FF& table_1_shift = std::get<32>(_data); - FF& table_2_shift = std::get<33>(_data); - FF& table_3_shift = std::get<34>(_data); - FF& table_4_shift = std::get<35>(_data); - FF& w_l_shift = std::get<36>(_data); - FF& w_r_shift = std::get<37>(_data); - FF& w_o_shift = std::get<38>(_data); - FF& w_4_shift = std::get<39>(_data); - FF& sorted_accum_shift = std::get<40>(_data); - FF& z_perm_shift = std::get<41>(_data); - FF& z_lookup_shift = std::get<42>(_data); + FF& q_poseidon2_external = std::get<11>(_data); + FF& q_poseidon2_internal = std::get<12>(_data); + FF& sigma_1 = std::get<13>(_data); + FF& sigma_2 = std::get<14>(_data); + FF& sigma_3 = std::get<15>(_data); + FF& sigma_4 = std::get<16>(_data); + FF& id_1 = std::get<17>(_data); + FF& id_2 = std::get<18>(_data); + FF& id_3 = std::get<19>(_data); + FF& id_4 = std::get<20>(_data); + FF& table_1 = std::get<21>(_data); + FF& table_2 = std::get<22>(_data); + FF& table_3 = std::get<23>(_data); + FF& table_4 = std::get<24>(_data); + FF& lagrange_first = std::get<25>(_data); + FF& lagrange_last = std::get<26>(_data); + FF& w_l = std::get<27>(_data); + FF& w_r = std::get<28>(_data); + FF& w_o = std::get<29>(_data); + FF& w_4 = std::get<30>(_data); + FF& sorted_accum = std::get<31>(_data); + FF& z_perm = std::get<32>(_data); + FF& z_lookup = std::get<33>(_data); + FF& table_1_shift = std::get<34>(_data); + FF& table_2_shift = std::get<35>(_data); + FF& table_3_shift = std::get<36>(_data); + FF& table_4_shift = std::get<37>(_data); + FF& w_l_shift = std::get<38>(_data); + FF& w_r_shift = std::get<39>(_data); + FF& w_o_shift = std::get<40>(_data); + FF& w_4_shift = std::get<41>(_data); + FF& sorted_accum_shift = std::get<42>(_data); + FF& z_perm_shift = std::get<43>(_data); + FF& z_lookup_shift = std::get<44>(_data); }; class UltraRelationConsistency : public testing::Test { @@ -551,4 +554,76 @@ TEST_F(UltraRelationConsistency, AuxiliaryRelation) run_test(/*random_inputs=*/true); }; +TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) +{ + const auto run_test = []([[maybe_unused]] bool random_inputs) { + using Relation = Poseidon2ExternalRelation; + using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; + const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); + + const auto& w_1 = input_elements.w_l; + const auto& w_2 = input_elements.w_r; + const auto& w_3 = input_elements.w_o; + const auto& w_4 = input_elements.w_4; + const auto& w_1_shift = input_elements.w_l_shift; + const auto& w_2_shift = input_elements.w_r_shift; + const auto& w_3_shift = input_elements.w_o_shift; + const auto& w_4_shift = input_elements.w_4_shift; + const auto& q_1 = input_elements.q_l; + const auto& q_2 = input_elements.q_r; + const auto& q_3 = input_elements.q_o; + const auto& q_4 = input_elements.q_4; + const auto& q_poseidon2_external = input_elements.q_poseidon2_external; + SumcheckArrayOfValuesOverSubrelations expected_values; + + // add round constants + auto v1 = w_1 + q_1; + auto v2 = w_2 + q_2; + auto v3 = w_3 + q_3; + auto v4 = w_4 + q_4; + + // apply s-box + auto u1 = v1 * v1; + u1 *= u1; + u1 *= v1; + auto u2 = v2 * v2; + u2 *= u2; + u2 *= v2; + auto u3 = v3 * v3; + u3 *= u3; + u3 *= v3; + auto u4 = v4 * v4; + u4 *= u4; + u4 *= v4; + + auto t0 = u1 + u2; // A + B + auto t1 = u3 + u4; // C + D + auto t2 = u2 + u2; // 2B + t2 += t1; // 2B + C + D + auto t3 = u4 + u4; // 2D + t3 += t0; // 2D + A + B + auto t4 = t1 + t1; + t4 += t4; + t4 += t3; // A + B + 4C + 6D + auto t5 = t0 + t0; + t5 += t5; + t5 += t2; // 4A + 6B + C + D + auto t6 = t3 + t5; // 5A + 7B + 3C + D + auto t7 = t2 + t4; // A + 3B + 5D + 7C + // output is { t6, t5, t7, t4 } + + expected_values[0] = q_poseidon2_external * (t6 - w_1_shift); + expected_values[1] = q_poseidon2_external * (t5 - w_2_shift); + expected_values[2] = q_poseidon2_external * (t7 - w_3_shift); + expected_values[3] = q_poseidon2_external * (t4 - w_4_shift); + + const auto parameters = RelationParameters::get_random(); + validate_relation_execution(expected_values, input_elements, parameters); + + // validate_relation_execution(expected_values, input_elements, parameters); + }; + run_test(/*random_inputs=*/false); + run_test(/*random_inputs=*/true); +}; + } // namespace proof_system::ultra_relation_consistency_tests From e04037e0c06ca9adc860d666f302afd959f7816f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 22 Nov 2023 21:31:58 +0000 Subject: [PATCH 23/34] internal round consistency test --- .../ultra_relation_consistency.test.cpp | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 189f5e40086..b7d026b07b9 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -19,6 +19,7 @@ #include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/poseidon2_external_relation.hpp" +#include "barretenberg/relations/poseidon2_internal_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include @@ -596,6 +597,7 @@ TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) u4 *= u4; u4 *= v4; + // multiply with external matrix auto t0 = u1 + u2; // A + B auto t1 = u3 + u4; // C + D auto t2 = u2 + u2; // 2B @@ -626,4 +628,56 @@ TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) run_test(/*random_inputs=*/true); }; +TEST_F(UltraRelationConsistency, Poseidon2InternalRelation) +{ + const auto run_test = []([[maybe_unused]] bool random_inputs) { + using Relation = Poseidon2InternalRelation; + using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; + const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); + + const auto& w_1 = input_elements.w_l; + const auto& w_2 = input_elements.w_r; + const auto& w_3 = input_elements.w_o; + const auto& w_4 = input_elements.w_4; + const auto& w_1_shift = input_elements.w_l_shift; + const auto& w_2_shift = input_elements.w_r_shift; + const auto& w_3_shift = input_elements.w_o_shift; + const auto& w_4_shift = input_elements.w_4_shift; + const auto& q_1 = input_elements.q_l; + const auto& q_poseidon2_internal = input_elements.q_poseidon2_internal; + SumcheckArrayOfValuesOverSubrelations expected_values; + + // add round constants on only first element + auto v1 = w_1 + q_1; + + // apply s-box to only first element + auto u1 = v1 * v1; + u1 *= u1; + u1 *= v1; + + // multiply with internal matrix + auto sum = u1 + w_2 + w_3 + w_4; + auto t0 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + t0 += sum; + auto t1 = w_2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + t1 += sum; + auto t2 = w_3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + t2 += sum; + auto t3 = w_4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + t3 += sum; + + expected_values[0] = q_poseidon2_internal * (t0 - w_1_shift); + expected_values[1] = q_poseidon2_internal * (t1 - w_2_shift); + expected_values[2] = q_poseidon2_internal * (t2 - w_3_shift); + expected_values[3] = q_poseidon2_internal * (t3 - w_4_shift); + + const auto parameters = RelationParameters::get_random(); + validate_relation_execution(expected_values, input_elements, parameters); + + // validate_relation_execution(expected_values, input_elements, parameters); + }; + run_test(/*random_inputs=*/false); + run_test(/*random_inputs=*/true); +}; + } // namespace proof_system::ultra_relation_consistency_tests From 6da3335c46b4c7db34f91e60b2f92b8e8af9ac9f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 22 Nov 2023 22:10:15 +0000 Subject: [PATCH 24/34] initial manual relation tests --- .../relations/relation_manual.test.cpp | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp b/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp new file mode 100644 index 00000000000..c57d73c2e0b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp @@ -0,0 +1,89 @@ +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/relations/poseidon2_external_relation.hpp" +#include "barretenberg/relations/poseidon2_internal_relation.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include + +namespace proof_system::relation_manual_tests { + +using FF = barretenberg::fr; + +class RelationManual : public testing::Test {}; + +TEST_F(RelationManual, Poseidon2ExternalRelationZeros) +{ + using Accumulator = std::array; + using Relation = Poseidon2ExternalRelation; + + Accumulator acc{ 0, 0, 0, 0 }; + struct AllPoseidonValues { + FF w_l; + FF w_r; + FF w_o; + FF w_4; + FF w_l_shift; + FF w_r_shift; + FF w_o_shift; + FF w_4_shift; + FF q_l; + FF q_r; + FF q_o; + FF q_4; + FF q_poseidon2_external; + }; + AllPoseidonValues all_poseidon_values{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + const auto parameters = RelationParameters::get_random(); + Relation::accumulate(acc, all_poseidon_values, parameters, 1); + EXPECT_EQ(acc[0], 0); + EXPECT_EQ(acc[1], 0); + EXPECT_EQ(acc[2], 0); + EXPECT_EQ(acc[3], 0); +} + +TEST_F(RelationManual, Poseidon2ExternalRelationRandom) +{ + using Accumulator = std::array; + using Relation = Poseidon2ExternalRelation; + + Accumulator acc{ 0, 0, 0, 0 }; + struct AllPoseidonValues { + FF q_poseidon2_external; + FF w_l; + FF w_r; + FF w_o; + FF w_4; + FF q_l; + FF q_r; + FF q_o; + FF q_4; + FF w_l_shift; + FF w_r_shift; + FF w_o_shift; + FF w_4_shift; + }; + /* + * v1 = w_1 + q_1 = 5 + 6 = 11 + * v2 = w_2 + q_2 = 4 + 9 = 13 + * v3 = w_3 + q_3 = 1 + 8 = 9 + * v4 = w_4 + q_4 = 7 + 3 = 10 + * u1 = v1^5 = 11^5 = 161051 + * u2 = v2^5 = 13^5 = 371293 + * u3 = v3^5 = 9^5 = 59049 + * u4 = v4^5 = 10^5 = 100000 + * matrix mul with calculator: + * 1 3763355 + * 2 3031011 + * 3 2270175 + * 4 1368540 + */ + AllPoseidonValues all_poseidon_values{ 1, 5, 4, 1, 7, 6, 9, 8, 3, 3763355, 3031011, 2270175, 1368540 }; + + const auto parameters = RelationParameters::get_random(); + Relation::accumulate(acc, all_poseidon_values, parameters, 1); + EXPECT_EQ(acc[0], 0); + EXPECT_EQ(acc[1], 0); + EXPECT_EQ(acc[2], 0); + EXPECT_EQ(acc[3], 0); +} +}; // namespace proof_system::relation_manual_tests \ No newline at end of file From 0c961b156f9fe597035d3c1782cf922ef473174f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 24 Nov 2023 19:09:25 +0000 Subject: [PATCH 25/34] variable renaming --- .../relations/poseidon2_external_relation.hpp | 62 +++++++++---------- .../relations/poseidon2_internal_relation.hpp | 35 +++++------ 2 files changed, 47 insertions(+), 50 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 8f06a364f53..8b8670e3a48 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -18,17 +18,17 @@ template class Poseidon2ExternalRelationImpl { * @details This relation is defined as: * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + * \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - w_4_shift) ) = 0 where: - * v1 := (w_1 + q_1)^5 - * v2 := (w_2 + q_2)^5 - * v3 := (w_3 + q_3)^5 - * v4 := (w_4 + q_4)^5 - * t0 := v1 + v2 (1, 1, 0, 0) - * t1 := v3 + v4 (0, 0, 1, 1) - * t2 := v2 + v2 + t1 = 2 * v2 + v3 + v4 (0, 2, 1, 1) - * t3 := v4 + v4 + t0 = v1 + v2 + 2 * v4 (1, 1, 0, 2) - * t4 := 4 * t1 + t3 = v1 + v2 + 4 * v3 + 6 * v4 (1, 1, 4, 6) - * t5 := 4 * t0 + t2 = 4 * v1 + 6 * v2 + v3 + v4 (4, 6, 1, 1) - * t6 := t3 + t5 = 5 * v1 + 7 * v2 + 1 * v3 + 3 * v4 (5, 7, 1, 3) + * u1 := (w_1 + q_1)^5 + * u2 := (w_2 + q_2)^5 + * u3 := (w_3 + q_3)^5 + * u4 := (w_4 + q_4)^5 + * t0 := u1 + u2 (1, 1, 0, 0) + * t1 := u3 + u4 (0, 0, 1, 1) + * t2 := u2 + u2 + t1 = 2 * u2 + u3 + u4 (0, 2, 1, 1) + * t3 := u4 + u4 + t0 = u1 + u2 + 2 * u4 (1, 1, 0, 2) + * t4 := 4 * t1 + t3 = u1 + u2 + 4 * u3 + 6 * u4 (1, 1, 4, 6) + * t5 := 4 * t0 + t2 = 4 * u1 + 6 * u2 + u3 + u4 (4, 6, 1, 1) + * t6 := t3 + t5 = 5 * u1 + 7 * u2 + 1 * u3 + 3 * u4 (5, 7, 1, 3) * t7 := t2 + t4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` @@ -59,31 +59,31 @@ template class Poseidon2ExternalRelationImpl { auto q_poseidon2_external = View(in.q_poseidon2_external); // add round constants which are loaded in selectors - auto tmp1 = w_l + q_l; - auto tmp2 = w_r + q_r; - auto tmp3 = w_o + q_o; - auto tmp4 = w_4 + q_4; + auto v1 = w_l + q_l; + auto v2 = w_r + q_r; + auto v3 = w_o + q_o; + auto v4 = w_4 + q_4; // apply s-box round - auto v1 = tmp1 * tmp1; - v1 *= v1; - v1 *= tmp1; - auto v2 = tmp2 * tmp2; - v2 *= v2; - v2 *= tmp2; - auto v3 = tmp3 * tmp3; - v3 *= v3; - v3 *= tmp3; - auto v4 = tmp4 * tmp4; - v4 *= v4; - v4 *= tmp4; + auto u1 = v1 * v1; + u1 *= u1; + u1 *= v1; + auto u2 = v2 * v2; + u2 *= u2; + u2 *= v2; + auto u3 = v3 * v3; + u3 *= u3; + u3 *= v3; + auto u4 = v4 * v4; + u4 *= u4; + u4 *= v4; // matrix mul with 14 additions - auto t0 = v1 + v2; // A + B - auto t1 = v3 + v4; // C + D - auto t2 = v2 + v2; // 2B + auto t0 = u1 + u2; // A + B + auto t1 = u3 + u4; // C + D + auto t2 = u2 + u2; // 2B t2 += t1; // 2B + C + D - auto t3 = v4 + v4; // 2D + auto t3 = u4 + u4; // 2D t3 += t0; // 2D + A + B auto t4 = t1 + t1; t4 += t4; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index c4f24bd904e..54720ef7ff1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -56,43 +56,40 @@ template class Poseidon2InternalRelationImpl { auto q_poseidon2_internal = View(in.q_poseidon2_internal); // add round constants - auto tmp1 = w_l + q_l; + auto v1 = w_l + q_l; // apply s-box round - auto v1 = tmp1 * tmp1; - v1 *= v1; - v1 *= tmp1; - auto v2 = w_r; - auto v3 = w_o; - auto v4 = w_4; + auto u1 = v1 * v1; + u1 *= u1; + u1 *= v1; // matrix mul with 4 muls and 7 additions - auto sum = v1 + v2 + v3 + v4; + auto sum = v1 + w_r + w_o + w_4; { - v1 *= crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; - v1 += sum; + auto t0 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + t0 += sum; auto tmp = q_poseidon2_internal * (v1 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - auto tmp2 = v2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; - tmp2 += sum; - auto tmp = q_poseidon2_internal * (tmp2 - w_r_shift); + auto t1 = w_r * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + t1 += sum; + auto tmp = q_poseidon2_internal * (t1 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - auto tmp3 = v3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; - tmp3 += sum; - auto tmp = q_poseidon2_internal * (tmp3 - w_o_shift); + auto t2 = w_o * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + t2 += sum; + auto tmp = q_poseidon2_internal * (t2 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - auto tmp4 = v4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; - tmp4 += sum; - auto tmp = q_poseidon2_internal * (tmp4 - w_4_shift); + auto t3 = w_4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + t3 += sum; + auto tmp = q_poseidon2_internal * (t3 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } From 8ef04dba52de65d709d48a65f068ae69cbafc23f Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 24 Nov 2023 19:25:05 +0000 Subject: [PATCH 26/34] added manual tests for internal --- .../relations/poseidon2_internal_relation.hpp | 4 +- .../relations/relation_manual.test.cpp | 81 ++++++++++++++++++- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index 54720ef7ff1..a2dd00ced24 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -64,11 +64,11 @@ template class Poseidon2InternalRelationImpl { u1 *= v1; // matrix mul with 4 muls and 7 additions - auto sum = v1 + w_r + w_o + w_4; + auto sum = u1 + w_r + w_o + w_4; { auto t0 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; t0 += sum; - auto tmp = q_poseidon2_internal * (v1 - w_l_shift); + auto tmp = q_poseidon2_internal * (t0 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp b/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp index c57d73c2e0b..752852167a1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/relation_manual.test.cpp @@ -17,6 +17,7 @@ TEST_F(RelationManual, Poseidon2ExternalRelationZeros) Accumulator acc{ 0, 0, 0, 0 }; struct AllPoseidonValues { + FF q_poseidon2_external; FF w_l; FF w_r; FF w_o; @@ -29,7 +30,6 @@ TEST_F(RelationManual, Poseidon2ExternalRelationZeros) FF q_r; FF q_o; FF q_4; - FF q_poseidon2_external; }; AllPoseidonValues all_poseidon_values{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -86,4 +86,83 @@ TEST_F(RelationManual, Poseidon2ExternalRelationRandom) EXPECT_EQ(acc[2], 0); EXPECT_EQ(acc[3], 0); } + +TEST_F(RelationManual, Poseidon2InternalRelationZeros) +{ + using Accumulator = std::array; + using Relation = Poseidon2InternalRelation; + + Accumulator acc{ 0, 0, 0, 0 }; + struct AllPoseidonValues { + FF q_poseidon2_internal; + FF w_l; + FF w_r; + FF w_o; + FF w_4; + FF w_l_shift; + FF w_r_shift; + FF w_o_shift; + FF w_4_shift; + FF q_l; + FF q_r; + FF q_o; + FF q_4; + }; + AllPoseidonValues all_poseidon_values{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + const auto parameters = RelationParameters::get_random(); + Relation::accumulate(acc, all_poseidon_values, parameters, 1); + EXPECT_EQ(acc[0], 0); + EXPECT_EQ(acc[1], 0); + EXPECT_EQ(acc[2], 0); + EXPECT_EQ(acc[3], 0); +} + +TEST_F(RelationManual, Poseidon2InternalRelationRandom) +{ + using Accumulator = std::array; + using Relation = Poseidon2InternalRelation; + + Accumulator acc{ 0, 0, 0, 0 }; + struct AllPoseidonValues { + FF q_poseidon2_internal; + FF w_l; + FF w_r; + FF w_o; + FF w_4; + FF q_l; + + FF w_l_shift; + FF w_r_shift; + FF w_o_shift; + FF w_4_shift; + }; + /* + * u1 = (w_1 + q_1)^5 = (1 + 5)^5 = 7776 + * sum = u1 + w_2 + w_3 + w_4 = 7776 + 2 + 3 + 4 = 7785 + * matrix mul with calculator: + * 1 0x122d9ce41e83c533318954d77a4ebc40eb729f6543ebd5f2e4ecb175ced3bc74 + * 2 0x185028b6d489be7c029367a14616776b33bf2eada9bb370950d6719f68b5067f + * 3 0x00fce289a96b3f4a18562d0ef0ab76ca165e613222aa0c24501377003c5622a8 + * 4 0x27e7677799fda1694819803f459b76d2fb1c45fdf0773375c72d61e8efb92893 + */ + AllPoseidonValues all_poseidon_values{ + 1, + 1, + 2, + 3, + 4, + 5, + FF(std::string("0x122d9ce41e83c533318954d77a4ebc40eb729f6543ebd5f2e4ecb175ced3bc74")), + FF(std::string("0x185028b6d489be7c029367a14616776b33bf2eada9bb370950d6719f68b5067f")), + FF(std::string("0x00fce289a96b3f4a18562d0ef0ab76ca165e613222aa0c24501377003c5622a8")), + FF(std::string("0x27e7677799fda1694819803f459b76d2fb1c45fdf0773375c72d61e8efb92893")) + }; + const auto parameters = RelationParameters::get_random(); + Relation::accumulate(acc, all_poseidon_values, parameters, 1); + EXPECT_EQ(acc[0], 0); + EXPECT_EQ(acc[1], 0); + EXPECT_EQ(acc[2], 0); + EXPECT_EQ(acc[3], 0); +} }; // namespace proof_system::relation_manual_tests \ No newline at end of file From b2a7a7b408c8a0019d6d3bb99669c457a6d732aa Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 27 Nov 2023 15:43:26 +0000 Subject: [PATCH 27/34] added mock gates to prevent zero selector polys --- .../goblin_ultra_circuit_builder.cpp | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index be29dc3a3cb..2a8775b1b86 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -25,8 +25,8 @@ template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_ // Most polynomials are handled via the conventional Ultra method UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_zero(); - // All that remains is to handle databus related polynomials. In what follows we populate the calldata with some - // mock data then constuct a single calldata read gate + // All that remains is to handle databus related and poseidon2 related polynomials. In what follows we populate the + // calldata with some mock data then constuct a single calldata read gate // Populate the calldata with some data public_calldata.emplace_back(this->add_variable(FF(5))); @@ -64,6 +64,50 @@ template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_ this->q_poseidon2_internal.emplace_back(0); ++this->num_gates; + + // mock gates that use poseidon selectors, with all zeros as input + this->w_l.emplace_back(this->zero_idx); + this->w_r.emplace_back(this->zero_idx); + this->w_o.emplace_back(this->zero_idx); + this->w_4.emplace_back(this->zero_idx); + this->q_m.emplace_back(0); + this->q_1.emplace_back(0); + this->q_2.emplace_back(0); + this->q_3.emplace_back(0); + this->q_c.emplace_back(0); + this->q_arith.emplace_back(0); + this->q_4.emplace_back(0); + this->q_sort.emplace_back(0); + this->q_lookup_type.emplace_back(0); + this->q_elliptic.emplace_back(0); + this->q_aux.emplace_back(0); + this->q_busread.emplace_back(0); + this->q_poseidon2_external.emplace_back(1); + this->q_poseidon2_internal.emplace_back(1); + + ++this->num_gates; + + // second gate that stores the output of all zeros of the poseidon gates + this->w_l.emplace_back(this->zero_idx); + this->w_r.emplace_back(this->zero_idx); + this->w_o.emplace_back(this->zero_idx); + this->w_4.emplace_back(this->zero_idx); + this->q_m.emplace_back(0); + this->q_1.emplace_back(0); + this->q_2.emplace_back(0); + this->q_3.emplace_back(0); + this->q_c.emplace_back(0); + this->q_arith.emplace_back(0); + this->q_4.emplace_back(0); + this->q_sort.emplace_back(0); + this->q_lookup_type.emplace_back(0); + this->q_elliptic.emplace_back(0); + this->q_aux.emplace_back(0); + this->q_busread.emplace_back(0); + this->q_poseidon2_external.emplace_back(0); + this->q_poseidon2_internal.emplace_back(0); + + ++this->num_gates; } /** From be9d63c24d488c3ee6c48790d320b7a7b01b5260 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 28 Nov 2023 20:46:17 +0000 Subject: [PATCH 28/34] added new gates to goblin ultra builder --- .../arithmetization/gate_data.hpp | 16 +++++++ .../goblin_ultra_circuit_builder.cpp | 48 +++++++++++++++++++ .../goblin_ultra_circuit_builder.hpp | 2 + 3 files changed, 66 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp index 4f8f799c42b..91540d90d72 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp @@ -132,4 +132,20 @@ template struct ecc_dbl_gate_ { uint32_t x3; uint32_t y3; }; + +template struct poseidon2_external_gate_ { + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t round_idx; +}; + +template struct poseidon2_internal_gate_ { + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t round_idx; +}; } // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index 2a8775b1b86..f625f4a0d9f 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -1,9 +1,11 @@ #include "goblin_ultra_circuit_builder.hpp" +#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" #include #include #include using namespace barretenberg; +using namespace crypto; namespace proof_system { @@ -243,5 +245,51 @@ template void GoblinUltraCircuitBuilder_::populate_ecc_op_wire num_ecc_op_gates += 2; }; +template +void GoblinUltraCircuitBuilder_::create_poseidon2_external_gate(const poseidon2_external_gate_& in) +{ + this->w_l.emplace_back(in.a); + this->w_r.emplace_back(in.b); + this->w_o.emplace_back(in.c); + this->w_4.emplace_back(in.d); + this->q_m.emplace_back(0); + this->q_1.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->q_2.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][1]); + this->q_3.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][2]); + this->q_c.emplace_back(0); + this->q_arith.emplace_back(0); + this->q_4.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][3]); + this->q_sort.emplace_back(0); + this->q_lookup_type.emplace_back(0); + this->q_elliptic.emplace_back(0); + this->q_aux.emplace_back(0); + this->q_busread.emplace_back(0); + this->q_poseidon2_external.emplace_back(1); + this->q_poseidon2_internal.emplace_back(0); +} + +template +void GoblinUltraCircuitBuilder_::create_poseidon2_internal_gate(const poseidon2_internal_gate_& in) +{ + this->w_l.emplace_back(in.a); + this->w_r.emplace_back(in.b); + this->w_o.emplace_back(in.c); + this->w_4.emplace_back(in.d); + this->q_m.emplace_back(0); + this->q_1.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->q_2.emplace_back(0); + this->q_3.emplace_back(0); + this->q_c.emplace_back(0); + this->q_arith.emplace_back(0); + this->q_4.emplace_back(0); + this->q_sort.emplace_back(0); + this->q_lookup_type.emplace_back(0); + this->q_elliptic.emplace_back(0); + this->q_aux.emplace_back(0); + this->q_busread.emplace_back(0); + this->q_poseidon2_external.emplace_back(0); + this->q_poseidon2_internal.emplace_back(1); +} + template class GoblinUltraCircuitBuilder_; } // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index 88d4cd7a95a..74738c83374 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -134,6 +134,8 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui } public_calldata.emplace_back(witness_index); } + void create_poseidon2_external_gate(const poseidon2_external_gate_& in); + void create_poseidon2_internal_gate(const poseidon2_internal_gate_& in); }; extern template class GoblinUltraCircuitBuilder_; using GoblinUltraCircuitBuilder = GoblinUltraCircuitBuilder_; From 80958c56c6e371f707141eacb698f6fc97885d57 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 30 Nov 2023 20:44:08 +0000 Subject: [PATCH 29/34] updated based on review --- .../crypto/poseidon2/CMakeLists.txt | 2 +- .../poseidon2/poseidon2_permutation.hpp | 4 +- .../relations/poseidon2_external_relation.hpp | 47 ++++++++------- .../relations/poseidon2_internal_relation.hpp | 59 ++++++++++--------- .../ultra_relation_consistency.test.cpp | 45 +++++++------- 5 files changed, 84 insertions(+), 73 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt index 0d82013d16c..e8d8f8e2013 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(crypto_poseidon2 ecc numeric) +barretenberg_module(crypto_poseidon2 ecc) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp index 40606b4887b..9e3931cdac3 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2_permutation.hpp @@ -70,8 +70,8 @@ template class Poseidon2Permutation { auto t5 = t0 + t0; t5 += t5; t5 += t2; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + 3C + D - auto t7 = t2 + t4; // A + 3B + 5D + 7C + auto t6 = t3 + t5; // 5A + 7B + C + 3D + auto t7 = t2 + t4; // A + 3B + 5C + 7D input[0] = t6; input[1] = t5; input[2] = t7; diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 8b8670e3a48..ae7bef9e1b1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -14,9 +14,10 @@ template class Poseidon2ExternalRelationImpl { }; /** - * @brief Expression for the poseidon2 external gate. + * @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of + * https://eprint.iacr.org/2023/323.pdf. * @details This relation is defined as: - * q_pos2 * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + + * q_poseidon2_external * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + * \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - w_4_shift) ) = 0 where: * u1 := (w_1 + q_1)^5 * u2 := (w_2 + q_2)^5 @@ -59,26 +60,26 @@ template class Poseidon2ExternalRelationImpl { auto q_poseidon2_external = View(in.q_poseidon2_external); // add round constants which are loaded in selectors - auto v1 = w_l + q_l; - auto v2 = w_r + q_r; - auto v3 = w_o + q_o; - auto v4 = w_4 + q_4; + auto s1 = w_l + q_l; + auto s2 = w_r + q_r; + auto s3 = w_o + q_o; + auto s4 = w_4 + q_4; // apply s-box round - auto u1 = v1 * v1; + auto u1 = s1 * s1; u1 *= u1; - u1 *= v1; - auto u2 = v2 * v2; + u1 *= s1; + auto u2 = s2 * s2; u2 *= u2; - u2 *= v2; - auto u3 = v3 * v3; + u2 *= s2; + auto u3 = s3 * s3; u3 *= u3; - u3 *= v3; - auto u4 = v4 * v4; + u3 *= s3; + auto u4 = s4 * s4; u4 *= u4; - u4 *= v4; + u4 *= s4; - // matrix mul with 14 additions + // matrix mul v = M_E * u with 14 additions auto t0 = u1 + u2; // A + B auto t1 = u3 + u4; // C + D auto t2 = u2 + u2; // 2B @@ -91,26 +92,30 @@ template class Poseidon2ExternalRelationImpl { auto t5 = t0 + t0; t5 += t5; t5 += t2; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + 3C + D - auto t7 = t2 + t4; // A + 3B + 5D + 7C + auto t6 = t3 + t5; // 5A + 7B + C + 3D + auto t7 = t2 + t4; // A + 3B + 5C + 7D + auto v1 = t6; + auto v2 = t5; + auto v3 = t7; + auto v4 = t4; { - auto tmp = q_poseidon2_external * (t6 - w_l_shift); + auto tmp = q_poseidon2_external * (v1 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - auto tmp = q_poseidon2_external * (t5 - w_r_shift); + auto tmp = q_poseidon2_external * (v2 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - auto tmp = q_poseidon2_external * (t7 - w_o_shift); + auto tmp = q_poseidon2_external * (v3 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - auto tmp = q_poseidon2_external * (t4 - w_4_shift); + auto tmp = q_poseidon2_external * (v4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index a2dd00ced24..6500663fb94 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -16,20 +16,18 @@ template class Poseidon2InternalRelationImpl { }; /** - * @brief Expression for the poseidon2 internal gate. + * @brief Expression for the poseidon2 internal round relation, based on I_i in Section 6 of + * https://eprint.iacr.org/2023/323.pdf. * @details This relation is defined as: - * q_pos2 * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) + + * q_poseidon2_internal * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) + * \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where: - * v1 := (w_1 + q_1)^5 - * v2 := w_2 - * v3 := w_3 - * v4 := w_4 - * sum := v1 + v2 + v3 + v4 - * v1 := v1 * D1 + sum - * v2 := v2 * D2 + sum - * v3 := v3 * D3 + sum - * v4 := v4 * D4 + sum - * Di is the ith internal diagonal value - 1 of the internal matrix + * u1 := (w_1 + q_1)^5 + * sum := u1 + w_2 + w_3 + w_4 + * v1 := u1 * D1 + sum + * v2 := w_2 * D2 + sum + * v3 := w_3 * D3 + sum + * v4 := w_4 * D4 + sum + * Di is the ith internal diagonal value - 1 of the internal matrix M_I * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -56,40 +54,43 @@ template class Poseidon2InternalRelationImpl { auto q_poseidon2_internal = View(in.q_poseidon2_internal); // add round constants - auto v1 = w_l + q_l; + auto s1 = w_l + q_l; // apply s-box round - auto u1 = v1 * v1; + auto u1 = s1 * s1; u1 *= u1; - u1 *= v1; + u1 *= s1; + auto u2 = w_r; + auto u3 = w_o; + auto u4 = w_4; - // matrix mul with 4 muls and 7 additions - auto sum = u1 + w_r + w_o + w_4; + // matrix mul with v = M_I * u 4 muls and 7 additions + auto sum = u1 + u2 + u3 + u4; { - auto t0 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; - t0 += sum; - auto tmp = q_poseidon2_internal * (t0 - w_l_shift); + auto v1 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + v1 += sum; + auto tmp = q_poseidon2_internal * (v1 - w_l_shift); tmp *= scaling_factor; std::get<0>(evals) += tmp; } { - auto t1 = w_r * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; - t1 += sum; - auto tmp = q_poseidon2_internal * (t1 - w_r_shift); + auto v2 = u2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + v2 += sum; + auto tmp = q_poseidon2_internal * (v2 - w_r_shift); tmp *= scaling_factor; std::get<1>(evals) += tmp; } { - auto t2 = w_o * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; - t2 += sum; - auto tmp = q_poseidon2_internal * (t2 - w_o_shift); + auto v3 = u3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + v3 += sum; + auto tmp = q_poseidon2_internal * (v3 - w_o_shift); tmp *= scaling_factor; std::get<2>(evals) += tmp; } { - auto t3 = w_4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; - t3 += sum; - auto tmp = q_poseidon2_internal * (t3 - w_4_shift); + auto v4 = u4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + v4 += sum; + auto tmp = q_poseidon2_internal * (v4 - w_4_shift); tmp *= scaling_factor; std::get<3>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index b7d026b07b9..452fc20b2a2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -578,24 +578,24 @@ TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) SumcheckArrayOfValuesOverSubrelations expected_values; // add round constants - auto v1 = w_1 + q_1; - auto v2 = w_2 + q_2; - auto v3 = w_3 + q_3; - auto v4 = w_4 + q_4; + auto s1 = w_1 + q_1; + auto s2 = w_2 + q_2; + auto s3 = w_3 + q_3; + auto s4 = w_4 + q_4; - // apply s-box - auto u1 = v1 * v1; + // apply s-box round + auto u1 = s1 * s1; u1 *= u1; - u1 *= v1; - auto u2 = v2 * v2; + u1 *= s1; + auto u2 = s2 * s2; u2 *= u2; - u2 *= v2; - auto u3 = v3 * v3; + u2 *= s2; + auto u3 = s3 * s3; u3 *= u3; - u3 *= v3; - auto u4 = v4 * v4; + u3 *= s3; + auto u4 = s4 * s4; u4 *= u4; - u4 *= v4; + u4 *= s4; // multiply with external matrix auto t0 = u1 + u2; // A + B @@ -610,14 +610,19 @@ TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) auto t5 = t0 + t0; t5 += t5; t5 += t2; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + 3C + D - auto t7 = t2 + t4; // A + 3B + 5D + 7C - // output is { t6, t5, t7, t4 } + auto t6 = t3 + t5; // 5A + 7B + C + 3D + auto t7 = t2 + t4; // A + 3B + 5C + 7D - expected_values[0] = q_poseidon2_external * (t6 - w_1_shift); - expected_values[1] = q_poseidon2_external * (t5 - w_2_shift); - expected_values[2] = q_poseidon2_external * (t7 - w_3_shift); - expected_values[3] = q_poseidon2_external * (t4 - w_4_shift); + // output is { t6, t5, t7, t4 } + auto v1 = t6; + auto v2 = t5; + auto v3 = t7; + auto v4 = t4; + + expected_values[0] = q_poseidon2_external * (v1 - w_1_shift); + expected_values[1] = q_poseidon2_external * (v2 - w_2_shift); + expected_values[2] = q_poseidon2_external * (v3 - w_3_shift); + expected_values[3] = q_poseidon2_external * (v4 - w_4_shift); const auto parameters = RelationParameters::get_random(); validate_relation_execution(expected_values, input_elements, parameters); From a3c8eede519d6865fa028b55b600d7e773f38b47 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 30 Nov 2023 21:33:54 +0000 Subject: [PATCH 30/34] naming update --- .../relations/poseidon2_external_relation.hpp | 36 +++++++++---------- .../ultra_relation_consistency.test.cpp | 24 ++++++------- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index ae7bef9e1b1..f55a2d42a63 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -17,20 +17,20 @@ template class Poseidon2ExternalRelationImpl { * @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of * https://eprint.iacr.org/2023/323.pdf. * @details This relation is defined as: - * q_poseidon2_external * ( (t6 - w_1_shift) + \alpha * (t5 - w_2_shift) + - * \alpha^2 * (t7 - w_3_shift) + \alpha^3 * (t4 - w_4_shift) ) = 0 where: + * q_poseidon2_external * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) + + * \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where: * u1 := (w_1 + q_1)^5 * u2 := (w_2 + q_2)^5 * u3 := (w_3 + q_3)^5 * u4 := (w_4 + q_4)^5 * t0 := u1 + u2 (1, 1, 0, 0) * t1 := u3 + u4 (0, 0, 1, 1) - * t2 := u2 + u2 + t1 = 2 * u2 + u3 + u4 (0, 2, 1, 1) - * t3 := u4 + u4 + t0 = u1 + u2 + 2 * u4 (1, 1, 0, 2) - * t4 := 4 * t1 + t3 = u1 + u2 + 4 * u3 + 6 * u4 (1, 1, 4, 6) - * t5 := 4 * t0 + t2 = 4 * u1 + 6 * u2 + u3 + u4 (4, 6, 1, 1) - * t6 := t3 + t5 = 5 * u1 + 7 * u2 + 1 * u3 + 3 * u4 (5, 7, 1, 3) - * t7 := t2 + t4 (1, 3, 5, 7) + * t2 := 2 * u2 + t1 = 2 * u2 + u3 + u4 (0, 2, 1, 1) + * t3 := 2 * u4 + t0 = u1 + u2 + 2 * u4 (1, 1, 0, 2) + * v4 := 4 * t1 + t3 = u1 + u2 + 4 * u3 + 6 * u4 (1, 1, 4, 6) + * v2 := 4 * t0 + t2 = 4 * u1 + 6 * u2 + u3 + u4 (4, 6, 1, 1) + * v1 := t3 + v2 = 5 * u1 + 7 * u2 + 1 * u3 + 3 * u4 (5, 7, 1, 3) + * v3 := t2 + v4 (1, 3, 5, 7) * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -86,19 +86,15 @@ template class Poseidon2ExternalRelationImpl { t2 += t1; // 2B + C + D auto t3 = u4 + u4; // 2D t3 += t0; // 2D + A + B - auto t4 = t1 + t1; - t4 += t4; - t4 += t3; // A + B + 4C + 6D - auto t5 = t0 + t0; - t5 += t5; - t5 += t2; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + C + 3D - auto t7 = t2 + t4; // A + 3B + 5C + 7D + auto v4 = t1 + t1; + v4 += v4; + v4 += t3; // A + B + 4C + 6D + auto v2 = t0 + t0; + v2 += v2; + v2 += t2; // 4A + 6B + C + D + auto v1 = t3 + v2; // 5A + 7B + C + 3D + auto v3 = t2 + v4; // A + 3B + 5C + 7D - auto v1 = t6; - auto v2 = t5; - auto v3 = t7; - auto v4 = t4; { auto tmp = q_poseidon2_external * (v1 - w_l_shift); tmp *= scaling_factor; diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 452fc20b2a2..f692148f9f4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -604,20 +604,16 @@ TEST_F(UltraRelationConsistency, Poseidon2ExternalRelation) t2 += t1; // 2B + C + D auto t3 = u4 + u4; // 2D t3 += t0; // 2D + A + B - auto t4 = t1 + t1; - t4 += t4; - t4 += t3; // A + B + 4C + 6D - auto t5 = t0 + t0; - t5 += t5; - t5 += t2; // 4A + 6B + C + D - auto t6 = t3 + t5; // 5A + 7B + C + 3D - auto t7 = t2 + t4; // A + 3B + 5C + 7D - - // output is { t6, t5, t7, t4 } - auto v1 = t6; - auto v2 = t5; - auto v3 = t7; - auto v4 = t4; + auto v4 = t1 + t1; + v4 += v4; + v4 += t3; // A + B + 4C + 6D + auto v2 = t0 + t0; + v2 += v2; + v2 += t2; // 4A + 6B + C + D + auto v1 = t3 + v2; // 5A + 7B + C + 3D + auto v3 = t2 + v4; // A + 3B + 5C + 7D + + // output is { v1, v2, v3, v4 } expected_values[0] = q_poseidon2_external * (v1 - w_1_shift); expected_values[1] = q_poseidon2_external * (v2 - w_2_shift); From aa818dfa581931889718198e3f90e40c8a315e08 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 30 Nov 2023 22:05:40 +0000 Subject: [PATCH 31/34] add poseidon checks to goblin check_circuit --- .../goblin_ultra_circuit_builder.cpp | 199 ++++++++++++++++++ .../goblin_ultra_circuit_builder.hpp | 31 +++ 2 files changed, 230 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index f625f4a0d9f..108e16471e0 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -1,5 +1,6 @@ #include "goblin_ultra_circuit_builder.hpp" #include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" +#include "barretenberg/flavor/goblin_ultra.hpp" #include #include #include @@ -266,6 +267,7 @@ void GoblinUltraCircuitBuilder_::create_poseidon2_external_gate(const poseid this->q_busread.emplace_back(0); this->q_poseidon2_external.emplace_back(1); this->q_poseidon2_internal.emplace_back(0); + ++this->num_gates; } template @@ -289,6 +291,203 @@ void GoblinUltraCircuitBuilder_::create_poseidon2_internal_gate(const poseid this->q_busread.emplace_back(0); this->q_poseidon2_external.emplace_back(0); this->q_poseidon2_internal.emplace_back(1); + ++this->num_gates; +} + +template +inline FF GoblinUltraCircuitBuilder_::compute_poseidon2_external_identity(FF q_poseidon2_external_value, + FF q_1_value, + FF q_2_value, + FF q_3_value, + FF q_4_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const +{ + // Power of alpha to separate individual sub-relations + // TODO(kesha): This is a repeated computation which can be efficiently optimized + const FF alpha_a = alpha_base; + const FF alpha_b = alpha_a * alpha; + const FF alpha_c = alpha_b * alpha; + const FF alpha_d = alpha_c * alpha; + + FF s1 = w_1_value + q_1_value; + FF s2 = w_2_value + q_2_value; + FF s3 = w_3_value + q_3_value; + FF s4 = w_4_value + q_4_value; + + FF u1 = s1 * s1; + u1 *= u1; + u1 *= s1; + FF u2 = s2 * s2; + u2 *= u2; + u2 *= s2; + FF u3 = s3 * s3; + u3 *= u3; + u3 *= s3; + FF u4 = s4 * s4; + u4 *= u4; + u4 *= s4; + + auto t0 = u1 + u2; + auto t1 = u3 + u4; + auto t2 = u2 + u2; + t2 += t1; + auto t3 = u4 + u4; + t3 += t0; + auto v4 = t1 + t1; + v4 += v4; + v4 += t3; + auto v2 = t0 + t0; + v2 += v2; + v2 += t2; + auto v1 = t3 + v2; + auto v3 = t2 + v4; + + return q_poseidon2_external_value * (alpha_a * (v1 - w_1_shifted_value) + alpha_b * (v2 - w_2_shifted_value) + + alpha_c * (v3 - w_3_shifted_value) + alpha_d * (v4 - w_4_shifted_value)); +} + +template +inline FF GoblinUltraCircuitBuilder_::compute_poseidon2_internal_identity(FF q_poseidon2_internal_value, + FF q_1_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const +{ + // Power of alpha to separate individual sub-relations + // TODO(kesha): This is a repeated computation which can be efficiently optimized + const FF alpha_a = alpha_base; + const FF alpha_b = alpha_a * alpha; + const FF alpha_c = alpha_b * alpha; + const FF alpha_d = alpha_c * alpha; + + auto s1 = w_1_value + q_1_value; + + auto u1 = s1 * s1; + u1 *= u1; + u1 *= s1; + + auto sum = u1 + w_2_value + w_3_value + w_4_value; + auto v1 = u1 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[0]; + v1 += sum; + auto v2 = w_2_value * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; + v2 += sum; + auto v3 = w_3_value * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; + v3 += sum; + auto v4 = w_4_value * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; + v4 += sum; + + return q_poseidon2_internal_value * (alpha_a * (v1 - w_1_shifted_value) + alpha_b * (v2 - w_2_shifted_value) + + alpha_c * (v3 - w_3_shifted_value) + alpha_d * (v4 - w_4_shifted_value)); +} + +template bool GoblinUltraCircuitBuilder_::check_circuit() +{ + bool result = true; + if (!UltraCircuitBuilder_>::check_circuit()) { + return false; + } + + const FF poseidon2_external_base = FF::random_element(); + const FF poseidon2_internal_base = FF::random_element(); + const FF alpha = FF::random_element(); + + // For each gate + for (size_t i = 0; i < this->num_gates; i++) { + FF q_poseidon2_external_value; + FF q_poseidon2_internal_value; + FF q_1_value; + FF q_2_value; + FF q_3_value; + FF q_4_value; + FF w_1_value; + FF w_2_value; + FF w_3_value; + FF w_4_value; + // Get the values of selectors and wires and update tag products along the way + q_poseidon2_external_value = this->q_poseidon2_external[i]; + q_poseidon2_internal_value = this->q_poseidon2_internal[i]; + q_1_value = this->q_1[i]; + q_2_value = this->q_2[i]; + q_3_value = this->q_3[i]; + q_4_value = this->q_4[i]; + w_1_value = this->get_variable(this->w_l[i]); + w_2_value = this->get_variable(this->w_r[i]); + w_3_value = this->get_variable(this->w_o[i]); + w_4_value = this->get_variable(this->w_4[i]); + FF w_1_shifted_value; + FF w_2_shifted_value; + FF w_3_shifted_value; + FF w_4_shifted_value; + if (i < (this->num_gates - 1)) { + w_1_shifted_value = this->get_variable(this->w_l[i + 1]); + w_2_shifted_value = this->get_variable(this->w_r[i + 1]); + w_3_shifted_value = this->get_variable(this->w_o[i + 1]); + w_4_shifted_value = this->get_variable(this->w_4[i + 1]); + } else { + w_1_shifted_value = FF::zero(); + w_2_shifted_value = FF::zero(); + w_3_shifted_value = FF::zero(); + w_4_shifted_value = FF::zero(); + } + if (!compute_poseidon2_external_identity(q_poseidon2_external_value, + q_1_value, + q_2_value, + q_3_value, + q_4_value, + w_1_value, + w_2_value, + w_3_value, + w_4_value, + w_1_shifted_value, + w_2_shifted_value, + w_3_shifted_value, + w_4_shifted_value, + poseidon2_external_base, + alpha) + .is_zero()) { +#ifndef FUZZING + info("Poseidon2External identity fails at gate ", i); +#endif + result = false; + break; + } + if (!compute_poseidon2_internal_identity(q_poseidon2_internal_value, + q_1_value, + w_1_value, + w_2_value, + w_3_value, + w_4_value, + w_1_shifted_value, + w_2_shifted_value, + w_3_shifted_value, + w_4_shifted_value, + poseidon2_internal_base, + alpha) + .is_zero()) { +#ifndef FUZZING + info("Poseidon2Internal identity fails at gate ", i); +#endif + result = false; + break; + } + } + return result; } template class GoblinUltraCircuitBuilder_; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index 74738c83374..af7ba39c8a5 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -136,6 +136,37 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui } void create_poseidon2_external_gate(const poseidon2_external_gate_& in); void create_poseidon2_internal_gate(const poseidon2_internal_gate_& in); + + FF compute_poseidon2_external_identity(FF q_poseidon2_external_value, + FF q_1_value, + FF q_2_value, + FF q_3_value, + FF q_4_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const; + + FF compute_poseidon2_internal_identity(FF q_poseidon2_internal_value, + FF q_1_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const; + + bool check_circuit(); }; extern template class GoblinUltraCircuitBuilder_; using GoblinUltraCircuitBuilder = GoblinUltraCircuitBuilder_; From 53abcc604657310192f3ffb8fb63a5adacec59a9 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 30 Nov 2023 22:24:56 +0000 Subject: [PATCH 32/34] base case test for goblin ultra check circuit --- .../goblin_ultra_circuit_builder.test.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp index 5d95b57e39a..7a3424626ae 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp @@ -8,6 +8,15 @@ auto& engine = numeric::random::get_debug_engine(); } namespace proof_system { +TEST(GoblinUltraCircuitBuilder, BaseCase) +{ + GoblinUltraCircuitBuilder circuit_constructor = GoblinUltraCircuitBuilder(); + fr a = fr::one(); + circuit_constructor.add_public_variable(a); + bool result = circuit_constructor.check_circuit(); + EXPECT_EQ(result, true); +} + /** * @brief Test the queueing of simple ecc ops via the Goblin builder * @details There are two things to check here: 1) When ecc ops are queued by the builder, the corresponding native @@ -15,7 +24,7 @@ namespace proof_system { * encoded in the op_wires, i.e. the operands can be reconstructed as expected. * */ -TEST(UltraCircuitBuilder, GoblinSimple) +TEST(GoblinUltraCircuitBuilder, GoblinSimple) { const size_t CHUNK_SIZE = plonk::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 2; @@ -81,7 +90,7 @@ TEST(UltraCircuitBuilder, GoblinSimple) * @brief Check that the ultra ops are recorded correctly in the EccOpQueue * */ -TEST(UltraCircuitBuilder, GoblinEccOpQueueUltraOps) +TEST(GoblinUltraCircuitBuilder, GoblinEccOpQueueUltraOps) { // Construct a simple circuit with op gates auto builder = GoblinUltraCircuitBuilder(); From b24c737b1b1746e550c9705fdd2e2e421d246253 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Thu, 30 Nov 2023 22:25:04 +0000 Subject: [PATCH 33/34] typo fix --- .../proof_system/circuit_builder/ultra_circuit_builder.cpp | 2 +- .../proof_system/circuit_builder/ultra_circuit_builder.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp index 047e3e8489e..1501a2e8a38 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp @@ -3363,7 +3363,7 @@ template bool UltraCircuitBuilder_:: alpha) .is_zero()) { #ifndef FUZZING - info("Arithemtic identity fails at gate ", i); + info("Arithmetic identity fails at gate ", i); #endif result = false; break; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index a8186c477dc..8f332551832 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -708,7 +708,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase size imbalance between sorted and non-sorted sets. Checking for this + * gates. No arithmetic gate => size imbalance between sorted and non-sorted sets. Checking for this * and throwing an error would require a refactor of the Composer to catelog all 'orphan' variables not * assigned to gates. * From a6d59c553b5b5ee3df08b8a0ed823bc56fabcb82 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 4 Dec 2023 16:34:54 +0000 Subject: [PATCH 34/34] compile error fix --- barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index ed2addfa82f..80d1ca652e9 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -62,7 +62,6 @@ class GoblinUltra { proof_system::DatabusLookupRelation, proof_system::Poseidon2ExternalRelation, proof_system::Poseidon2InternalRelation>; - > ; using Relations = Relations_; using LogDerivLookupRelation = proof_system::DatabusLookupRelation;