-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new Poseidon2 relations (#3406)
New Poseidon2 relations for efficient stdlib implementation of Poseidon2. We create new relations for the external and internal rounds of Poseidon2, in order to be able to execute a permutation with t=4 in just 64 rounds. Added new tests, including consistency checks and manual hardcoded tests. Resolves AztecProtocol/barretenberg#775.
- Loading branch information
1 parent
50d7327
commit 14b9736
Showing
6 changed files
with
548 additions
and
36 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
barretenberg/cpp/src/barretenberg/crypto/poseidon2/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
barretenberg_module(crypto_poseidon2 ecc numeric) | ||
barretenberg_module(crypto_poseidon2 ecc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#pragma once | ||
#include "barretenberg/relations/relation_types.hpp" | ||
namespace proof_system { | ||
|
||
template <typename FF_> class Poseidon2ExternalRelationImpl { | ||
public: | ||
using FF = FF_; | ||
|
||
static constexpr std::array<size_t, 4> 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 | ||
7, // external poseidon2 round sub-relation for fourth value | ||
}; | ||
|
||
/** | ||
* @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 C(in(X)...) := | ||
* 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 := 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. | ||
* @param parameters contains beta, gamma, and public_input_delta, .... | ||
* @param scaling_factor optional term to scale the evaluation before adding to evals. | ||
*/ | ||
template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters> | ||
void static accumulate(ContainerOverSubrelations& evals, | ||
const AllEntities& in, | ||
const Parameters&, | ||
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_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 | ||
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 = s1 * s1; | ||
u1 *= u1; | ||
u1 *= s1; | ||
auto u2 = s2 * s2; | ||
u2 *= u2; | ||
u2 *= s2; | ||
auto u3 = s3 * s3; | ||
u3 *= u3; | ||
u3 *= s3; | ||
auto u4 = s4 * s4; | ||
u4 *= u4; | ||
u4 *= s4; | ||
|
||
// matrix mul v = M_E * u with 14 additions | ||
auto t0 = u1 + u2; // u_1 + u_2 | ||
auto t1 = u3 + u4; // u_3 + u_4 | ||
auto t2 = u2 + u2; // 2u_2 | ||
t2 += t1; // 2u_2 + u_3 + u_4 | ||
auto t3 = u4 + u4; // 2u_4 | ||
t3 += t0; // u_1 + u_2 + 2u_4 | ||
auto v4 = t1 + t1; | ||
v4 += v4; | ||
v4 += t3; // u_1 + u_2 + 4u_3 + 6u_4 | ||
auto v2 = t0 + t0; | ||
v2 += v2; | ||
v2 += t2; // 4u_1 + 6u_2 + u_3 + u_4 | ||
auto v1 = t3 + v2; // 5u_1 + 7u_2 + u_3 + 3u_4 | ||
auto v3 = t2 + v4; // u_1 + 3u_2 + 5u_3 + 7u_4 | ||
|
||
auto tmp = q_poseidon2_external * (v1 - w_l_shift); | ||
tmp *= scaling_factor; | ||
std::get<0>(evals) += tmp; | ||
|
||
tmp = q_poseidon2_external * (v2 - w_r_shift); | ||
tmp *= scaling_factor; | ||
std::get<1>(evals) += tmp; | ||
|
||
tmp = q_poseidon2_external * (v3 - w_o_shift); | ||
tmp *= scaling_factor; | ||
std::get<2>(evals) += tmp; | ||
|
||
tmp = q_poseidon2_external * (v4 - w_4_shift); | ||
tmp *= scaling_factor; | ||
std::get<3>(evals) += tmp; | ||
}; | ||
}; | ||
|
||
template <typename FF> using Poseidon2ExternalRelation = Relation<Poseidon2ExternalRelationImpl<FF>>; | ||
} // namespace proof_system |
97 changes: 97 additions & 0 deletions
97
barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#pragma once | ||
#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" | ||
#include "relation_types.hpp" | ||
|
||
namespace proof_system { | ||
|
||
template <typename FF_> class Poseidon2InternalRelationImpl { | ||
public: | ||
using FF = FF_; | ||
|
||
static constexpr std::array<size_t, 4> 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 | ||
7, // internal poseidon2 round sub-relation for fourth value | ||
}; | ||
|
||
/** | ||
* @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 C(in(X)...) := | ||
* 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: | ||
* 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. | ||
* @param parameters contains beta, gamma, and public_input_delta, .... | ||
* @param scaling_factor optional term to scale the evaluation before adding to evals. | ||
*/ | ||
template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters> | ||
void static accumulate(ContainerOverSubrelations& evals, | ||
const AllEntities& in, | ||
const Parameters&, | ||
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_l = View(in.q_l); | ||
auto q_poseidon2_internal = View(in.q_poseidon2_internal); | ||
|
||
// add round constants | ||
auto s1 = w_l + q_l; | ||
|
||
// apply s-box round | ||
auto u1 = s1 * s1; | ||
u1 *= u1; | ||
u1 *= s1; | ||
auto u2 = w_r; | ||
auto u3 = w_o; | ||
auto u4 = w_4; | ||
|
||
// matrix mul with v = M_I * u 4 muls and 7 additions | ||
auto sum = u1 + u2 + u3 + u4; | ||
|
||
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 v2 = u2 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[1]; | ||
v2 += sum; | ||
tmp = q_poseidon2_internal * (v2 - w_r_shift); | ||
tmp *= scaling_factor; | ||
std::get<1>(evals) += tmp; | ||
|
||
auto v3 = u3 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[2]; | ||
v3 += sum; | ||
tmp = q_poseidon2_internal * (v3 - w_o_shift); | ||
tmp *= scaling_factor; | ||
std::get<2>(evals) += tmp; | ||
|
||
auto v4 = u4 * crypto::Poseidon2Bn254ScalarFieldParams::internal_matrix_diagonal[3]; | ||
v4 += sum; | ||
tmp = q_poseidon2_internal * (v4 - w_4_shift); | ||
tmp *= scaling_factor; | ||
std::get<3>(evals) += tmp; | ||
}; | ||
}; // namespace proof_system | ||
|
||
template <typename FF> using Poseidon2InternalRelation = Relation<Poseidon2InternalRelationImpl<FF>>; | ||
} // namespace proof_system |
Oops, something went wrong.