Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
poseidon2_permutation.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
8
10
11namespace bb::stdlib {
12
13template <typename Builder>
16{
17 State current_state(input);
18 NativeState current_native_state;
19 for (size_t i = 0; i < t; ++i) {
20 current_native_state[i] = current_state[i].get_value();
21 }
22
23 // Apply 1st linear layer both natively and in-circuit.
24 NativePermutation::matrix_multiplication_external(current_native_state);
25 matrix_multiplication_external(current_state);
26
27 // First set of external rounds
28 constexpr size_t rounds_f_beginning = rounds_f / 2;
29 for (size_t i = 0; i < rounds_f_beginning; ++i) {
30 poseidon2_external_gate_<FF> in{ current_state[0].get_witness_index(),
31 current_state[1].get_witness_index(),
32 current_state[2].get_witness_index(),
33 current_state[3].get_witness_index(),
34 i };
35 builder->create_poseidon2_external_gate(in);
36 // calculate the new witnesses
37 NativePermutation::add_round_constants(current_native_state, round_constants[i]);
38 NativePermutation::apply_sbox(current_native_state);
39 NativePermutation::matrix_multiplication_external(current_native_state);
40 for (size_t j = 0; j < t; ++j) {
41 current_state[j] = witness_t<Builder>(builder, current_native_state[j]);
42 }
43 }
44
45 propagate_current_state_to_next_row(builder, current_state, builder->blocks.poseidon2_external);
46
47 // Internal rounds
48 const size_t p_end = rounds_f_beginning + rounds_p;
49 for (size_t i = rounds_f_beginning; i < p_end; ++i) {
50 poseidon2_internal_gate_<FF> in{ current_state[0].get_witness_index(),
51 current_state[1].get_witness_index(),
52 current_state[2].get_witness_index(),
53 current_state[3].get_witness_index(),
54 i };
55 builder->create_poseidon2_internal_gate(in);
56 current_native_state[0] += round_constants[i][0];
57 NativePermutation::apply_single_sbox(current_native_state[0]);
58 NativePermutation::matrix_multiplication_internal(current_native_state);
59 for (size_t j = 0; j < t; ++j) {
60 current_state[j] = witness_t<Builder>(builder, current_native_state[j]);
61 }
62 }
63
64 propagate_current_state_to_next_row(builder, current_state, builder->blocks.poseidon2_internal);
65
66 // Remaining external rounds
67 for (size_t i = p_end; i < NUM_ROUNDS; ++i) {
68 poseidon2_external_gate_<FF> in{ current_state[0].get_witness_index(),
69 current_state[1].get_witness_index(),
70 current_state[2].get_witness_index(),
71 current_state[3].get_witness_index(),
72 i };
73 builder->create_poseidon2_external_gate(in);
74 // calculate the new witnesses
75 NativePermutation::add_round_constants(current_native_state, round_constants[i]);
76 NativePermutation::apply_sbox(current_native_state);
77 NativePermutation::matrix_multiplication_external(current_native_state);
78 for (size_t j = 0; j < t; ++j) {
79 current_state[j] = witness_t<Builder>(builder, current_native_state[j]);
80 }
81 }
82
83 propagate_current_state_to_next_row(builder, current_state, builder->blocks.poseidon2_external);
84
85 return current_state;
86}
87
93template <typename Builder>
95{
96 const bb::fr two(2);
97 const bb::fr four(4);
98 // create the 6 gates for the initial matrix multiplication
99 // gate 1: Compute tmp1 = state[0] + state[1] + 2 * state[3]
100 field_t<Builder> tmp1 = state[0].add_two(state[1], state[3] * two);
101
102 // gate 2: Compute tmp2 = 2 * state[1] + state[2] + state[3]
103 field_t<Builder> tmp2 = state[2].add_two(state[1] * two, state[3]);
104
105 // gate 3: Compute v2 = 4 * state[0] + 4 * state[1] + tmp2
106 state[1] = tmp2.add_two(state[0] * four, state[1] * four);
107
108 // gate 4: Compute v1 = v2 + tmp1
109 state[0] = state[1] + tmp1;
110
111 // gate 5: Compute v4 = tmp1 + 4 * state[2] + 4 * state[3]
112 state[3] = tmp1.add_two(state[2] * four, state[3] * four);
113
114 // gate 6: Compute v3 = v4 + tmp2
115 state[2] = state[3] + tmp2;
116
117 // This can only happen if the input contained constant `field_t` elements.
118 ASSERT(state[0].is_normalized() && state[1].is_normalized() && state[2].is_normalized() &&
119 state[3].is_normalized());
120}
121
122template class Poseidon2Permutation<MegaCircuitBuilder>;
123template class Poseidon2Permutation<UltraCircuitBuilder>;
124
125} // namespace bb::stdlib
#define ASSERT(expression,...)
Definition assert.hpp:77
static void matrix_multiplication_external(State &state)
In-circuit method to efficiently multiply the inital state by the external matrix ....
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.
field_t add_two(const field_t &add_b, const field_t &add_c) const
Efficiently compute (this + a + b) using big_mul gate.
Definition field.cpp:574
AluTraceBuilder builder
Definition alu.test.cpp:123
constexpr uint32_t round_constants[64]