Skip to content

Commit

Permalink
feat: new Poseidon2 relations (#3406)
Browse files Browse the repository at this point in the history
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
lucasxia01 authored Dec 1, 2023
1 parent 50d7327 commit 14b9736
Show file tree
Hide file tree
Showing 6 changed files with 548 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(crypto_poseidon2 ecc numeric)
barretenberg_module(crypto_poseidon2 ecc)
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ template <typename Params> 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;
Expand Down
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
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
Loading

0 comments on commit 14b9736

Please sign in to comment.