14template <
typename Builder>
20 for (
auto& state_limb : state) {
21 if (state_limb.is_constant()) {
28template <
typename Builder>
32 for (
size_t i = 0; i < Poseidon2Permutation<Builder>::t; ++i) {
33 native_state[i] = state[i].get_value();
37template <
typename Builder>
48 for (
size_t i = begin; i < end; ++i) {
49 poseidon2_external_gate_<FF> in{ current_state[0].get_witness_index(),
50 current_state[1].get_witness_index(),
51 current_state[2].get_witness_index(),
52 current_state[3].get_witness_index(),
54 builder->create_poseidon2_external_gate(in);
56 Permutation::NativePermutation::apply_sbox(current_native_state);
59 current_state[j] = Witness(
builder, current_native_state[j]);
64template <
typename Builder>
68 const size_t rounds_f_beginning,
74 for (
size_t i = rounds_f_beginning; i < p_end; ++i) {
75 poseidon2_internal_gate_<typename Permutation::FF> in{ current_state[0].get_witness_index(),
76 current_state[1].get_witness_index(),
77 current_state[2].get_witness_index(),
78 current_state[3].get_witness_index(),
80 builder->create_poseidon2_internal_gate(in);
82 Permutation::NativePermutation::apply_single_sbox(current_native_state[0]);
83 Permutation::NativePermutation::matrix_multiplication_internal(current_native_state);
85 current_state[j] = Witness(
builder, current_native_state[j]);
94 const size_t rounds_f_beginning)
96 using Permutation = Poseidon2Permutation<MegaCircuitBuilder>;
110 poseidon2_transition_entry_gate_<FF> in{
111 current_state[0].get_witness_index(),
112 current_state[1].get_witness_index(),
113 current_state[2].get_witness_index(),
114 current_state[3].get_witness_index(),
117 builder->create_poseidon2_transition_entry_gate(in);
120 auto advance_internal_round = [](NativeState& state,
const FF& round_constant) {
121 state[0] += round_constant;
122 Permutation::NativePermutation::apply_single_sbox(state[0]);
123 Permutation::NativePermutation::matrix_multiplication_internal(state);
128 auto emit_quad_row = [&](
size_t quad_idx,
bool is_terminal) {
129 const size_t start = rounds_f_beginning + (4 * quad_idx);
130 const size_t next_start = start + 4;
132 NativeState state_after_1 = current_native_state;
134 auto s0_at_1 = Witness(
builder, state_after_1[0]);
136 NativeState state_after_2 = state_after_1;
138 auto s0_at_2 = Witness(
builder, state_after_2[0]);
140 NativeState state_after_3 = state_after_2;
142 auto s0_at_3 = Witness(
builder, state_after_3[0]);
144 poseidon2_quad_internal_gate_<FF> in{
145 current_state[0].get_witness_index(),
146 s0_at_1.witness_index,
147 s0_at_2.witness_index,
148 s0_at_3.witness_index,
153 builder->create_poseidon2_quad_internal_gate(in);
156 current_native_state = state_after_3;
162 current_state[0] = Witness(
builder, current_native_state[0]);
165 current_state[j] = Witness(
builder, current_native_state[j]);
171 for (
size_t q = 0; q < num_quad_rows - 1; ++q) {
172 emit_quad_row(q,
false);
175 emit_quad_row(num_quad_rows - 1,
true);
179 builder->create_unconstrained_gate(
builder->blocks.poseidon2_quad_internal,
180 current_state[0].get_witness_index(),
181 current_state[1].get_witness_index(),
182 current_state[2].get_witness_index(),
183 current_state[3].get_witness_index());
188template <
typename Builder>
192 State current_state(input);
193 NativeState current_native_state;
195 matrix_multiplication_external(current_state);
196 sync_native_state_from_state<Builder>(current_native_state, current_state);
199 constexpr size_t rounds_f_beginning = rounds_f / 2;
200 apply_external_rounds(
builder, current_state, current_native_state, 0, rounds_f_beginning);
202 propagate_current_state_to_next_row(
builder, current_state,
builder->blocks.poseidon2_external);
205 const size_t p_end = rounds_f_beginning + rounds_p;
207 apply_mega_internal_rounds(
builder, current_state, current_native_state, rounds_f_beginning);
209 apply_standard_internal_rounds(
builder, current_state, current_native_state, rounds_f_beginning, p_end);
213 apply_external_rounds(
builder, current_state, current_native_state, p_end, NUM_ROUNDS);
215 propagate_current_state_to_next_row(
builder, current_state,
builder->blocks.poseidon2_external);
217 return current_state;
225template <
typename Builder>
239 state[1] = tmp2.
add_two(state[0] * four, state[1] * four);
242 state[0] = state[1] + tmp1;
245 state[3] = tmp1.
add_two(state[2] * four, state[3] * four);
248 state[2] = state[3] + tmp2;
251template <
typename Builder>
256 BB_ASSERT(
builder !=
nullptr,
"Poseidon2 Mega initial external layer needs a builder context");
258 NativeState native_state;
259 for (
size_t i = 0; i < t; ++i) {
260 native_state[i] = state[i].get_value();
262 NativePermutation::matrix_multiplication_external(native_state);
264 materialize_constants_for_initial_layer(
builder, state);
267 state[1].get_witness_index(),
268 state[2].get_witness_index(),
269 state[3].get_witness_index() };
270 builder->create_poseidon2_initial_external_gate(in);
271 for (
size_t j = 0; j < t; ++j) {
276template class Poseidon2Permutation<MegaCircuitBuilder>;
277template class Poseidon2Permutation<UltraCircuitBuilder>;
#define BB_ASSERT(expression,...)
Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323.
static void propagate_current_state_to_next_row(Builder *builder, const State &state, auto &block)
The result of applying a round of Poseidon2 is stored in the next row and is accessed by Poseidon2 In...
static void matrix_multiplication_external(State &state)
In-circuit method to efficiently multiply the initial state by the external matrix .
static constexpr size_t rounds_p
static constexpr RoundConstantsContainer round_constants
std::array< field_t< Builder >, t > State
static State permutation(Builder *builder, const State &input)
Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323.
std::array< FF, t > NativeState
static constexpr size_t t
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
field_t add_two(const field_t &add_b, const field_t &add_c) const
Efficiently compute (this + a + b) using big_mul gate.
MegaCircuitBuilder_< field< Bn254FrParams > > MegaCircuitBuilder