28 { C::poseidon2_perm_T_0_6, C::poseidon2_perm_T_0_5, C::poseidon2_perm_T_0_7, C::poseidon2_perm_T_0_4 },
29 { C::poseidon2_perm_T_1_6, C::poseidon2_perm_T_1_5, C::poseidon2_perm_T_1_7, C::poseidon2_perm_T_1_4 },
30 { C::poseidon2_perm_T_2_6, C::poseidon2_perm_T_2_5, C::poseidon2_perm_T_2_7, C::poseidon2_perm_T_2_4 },
31 { C::poseidon2_perm_T_3_6, C::poseidon2_perm_T_3_5, C::poseidon2_perm_T_3_7, C::poseidon2_perm_T_3_4 },
33 { C::poseidon2_perm_B_4_0, C::poseidon2_perm_B_4_1, C::poseidon2_perm_B_4_2, C::poseidon2_perm_B_4_3 },
34 { C::poseidon2_perm_B_5_0, C::poseidon2_perm_B_5_1, C::poseidon2_perm_B_5_2, C::poseidon2_perm_B_5_3 },
35 { C::poseidon2_perm_B_6_0, C::poseidon2_perm_B_6_1, C::poseidon2_perm_B_6_2, C::poseidon2_perm_B_6_3 },
36 { C::poseidon2_perm_B_7_0, C::poseidon2_perm_B_7_1, C::poseidon2_perm_B_7_2, C::poseidon2_perm_B_7_3 },
37 { C::poseidon2_perm_B_8_0, C::poseidon2_perm_B_8_1, C::poseidon2_perm_B_8_2, C::poseidon2_perm_B_8_3 },
38 { C::poseidon2_perm_B_9_0, C::poseidon2_perm_B_9_1, C::poseidon2_perm_B_9_2, C::poseidon2_perm_B_9_3 },
39 { C::poseidon2_perm_B_10_0, C::poseidon2_perm_B_10_1, C::poseidon2_perm_B_10_2, C::poseidon2_perm_B_10_3 },
40 { C::poseidon2_perm_B_11_0, C::poseidon2_perm_B_11_1, C::poseidon2_perm_B_11_2, C::poseidon2_perm_B_11_3 },
41 { C::poseidon2_perm_B_12_0, C::poseidon2_perm_B_12_1, C::poseidon2_perm_B_12_2, C::poseidon2_perm_B_12_3 },
42 { C::poseidon2_perm_B_13_0, C::poseidon2_perm_B_13_1, C::poseidon2_perm_B_13_2, C::poseidon2_perm_B_13_3 },
43 { C::poseidon2_perm_B_14_0, C::poseidon2_perm_B_14_1, C::poseidon2_perm_B_14_2, C::poseidon2_perm_B_14_3 },
44 { C::poseidon2_perm_B_15_0, C::poseidon2_perm_B_15_1, C::poseidon2_perm_B_15_2, C::poseidon2_perm_B_15_3 },
45 { C::poseidon2_perm_B_16_0, C::poseidon2_perm_B_16_1, C::poseidon2_perm_B_16_2, C::poseidon2_perm_B_16_3 },
46 { C::poseidon2_perm_B_17_0, C::poseidon2_perm_B_17_1, C::poseidon2_perm_B_17_2, C::poseidon2_perm_B_17_3 },
47 { C::poseidon2_perm_B_18_0, C::poseidon2_perm_B_18_1, C::poseidon2_perm_B_18_2, C::poseidon2_perm_B_18_3 },
48 { C::poseidon2_perm_B_19_0, C::poseidon2_perm_B_19_1, C::poseidon2_perm_B_19_2, C::poseidon2_perm_B_19_3 },
49 { C::poseidon2_perm_B_20_0, C::poseidon2_perm_B_20_1, C::poseidon2_perm_B_20_2, C::poseidon2_perm_B_20_3 },
50 { C::poseidon2_perm_B_21_0, C::poseidon2_perm_B_21_1, C::poseidon2_perm_B_21_2, C::poseidon2_perm_B_21_3 },
51 { C::poseidon2_perm_B_22_0, C::poseidon2_perm_B_22_1, C::poseidon2_perm_B_22_2, C::poseidon2_perm_B_22_3 },
52 { C::poseidon2_perm_B_23_0, C::poseidon2_perm_B_23_1, C::poseidon2_perm_B_23_2, C::poseidon2_perm_B_23_3 },
53 { C::poseidon2_perm_B_24_0, C::poseidon2_perm_B_24_1, C::poseidon2_perm_B_24_2, C::poseidon2_perm_B_24_3 },
54 { C::poseidon2_perm_B_25_0, C::poseidon2_perm_B_25_1, C::poseidon2_perm_B_25_2, C::poseidon2_perm_B_25_3 },
55 { C::poseidon2_perm_B_26_0, C::poseidon2_perm_B_26_1, C::poseidon2_perm_B_26_2, C::poseidon2_perm_B_26_3 },
56 { C::poseidon2_perm_B_27_0, C::poseidon2_perm_B_27_1, C::poseidon2_perm_B_27_2, C::poseidon2_perm_B_27_3 },
57 { C::poseidon2_perm_B_28_0, C::poseidon2_perm_B_28_1, C::poseidon2_perm_B_28_2, C::poseidon2_perm_B_28_3 },
58 { C::poseidon2_perm_B_29_0, C::poseidon2_perm_B_29_1, C::poseidon2_perm_B_29_2, C::poseidon2_perm_B_29_3 },
59 { C::poseidon2_perm_B_30_0, C::poseidon2_perm_B_30_1, C::poseidon2_perm_B_30_2, C::poseidon2_perm_B_30_3 },
60 { C::poseidon2_perm_B_31_0, C::poseidon2_perm_B_31_1, C::poseidon2_perm_B_31_2, C::poseidon2_perm_B_31_3 },
61 { C::poseidon2_perm_B_32_0, C::poseidon2_perm_B_32_1, C::poseidon2_perm_B_32_2, C::poseidon2_perm_B_32_3 },
62 { C::poseidon2_perm_B_33_0, C::poseidon2_perm_B_33_1, C::poseidon2_perm_B_33_2, C::poseidon2_perm_B_33_3 },
63 { C::poseidon2_perm_B_34_0, C::poseidon2_perm_B_34_1, C::poseidon2_perm_B_34_2, C::poseidon2_perm_B_34_3 },
64 { C::poseidon2_perm_B_35_0, C::poseidon2_perm_B_35_1, C::poseidon2_perm_B_35_2, C::poseidon2_perm_B_35_3 },
65 { C::poseidon2_perm_B_36_0, C::poseidon2_perm_B_36_1, C::poseidon2_perm_B_36_2, C::poseidon2_perm_B_36_3 },
66 { C::poseidon2_perm_B_37_0, C::poseidon2_perm_B_37_1, C::poseidon2_perm_B_37_2, C::poseidon2_perm_B_37_3 },
67 { C::poseidon2_perm_B_38_0, C::poseidon2_perm_B_38_1, C::poseidon2_perm_B_38_2, C::poseidon2_perm_B_38_3 },
68 { C::poseidon2_perm_B_39_0, C::poseidon2_perm_B_39_1, C::poseidon2_perm_B_39_2, C::poseidon2_perm_B_39_3 },
69 { C::poseidon2_perm_B_40_0, C::poseidon2_perm_B_40_1, C::poseidon2_perm_B_40_2, C::poseidon2_perm_B_40_3 },
70 { C::poseidon2_perm_B_41_0, C::poseidon2_perm_B_41_1, C::poseidon2_perm_B_41_2, C::poseidon2_perm_B_41_3 },
71 { C::poseidon2_perm_B_42_0, C::poseidon2_perm_B_42_1, C::poseidon2_perm_B_42_2, C::poseidon2_perm_B_42_3 },
72 { C::poseidon2_perm_B_43_0, C::poseidon2_perm_B_43_1, C::poseidon2_perm_B_43_2, C::poseidon2_perm_B_43_3 },
73 { C::poseidon2_perm_B_44_0, C::poseidon2_perm_B_44_1, C::poseidon2_perm_B_44_2, C::poseidon2_perm_B_44_3 },
74 { C::poseidon2_perm_B_45_0, C::poseidon2_perm_B_45_1, C::poseidon2_perm_B_45_2, C::poseidon2_perm_B_45_3 },
75 { C::poseidon2_perm_B_46_0, C::poseidon2_perm_B_46_1, C::poseidon2_perm_B_46_2, C::poseidon2_perm_B_46_3 },
76 { C::poseidon2_perm_B_47_0, C::poseidon2_perm_B_47_1, C::poseidon2_perm_B_47_2, C::poseidon2_perm_B_47_3 },
77 { C::poseidon2_perm_B_48_0, C::poseidon2_perm_B_48_1, C::poseidon2_perm_B_48_2, C::poseidon2_perm_B_48_3 },
78 { C::poseidon2_perm_B_49_0, C::poseidon2_perm_B_49_1, C::poseidon2_perm_B_49_2, C::poseidon2_perm_B_49_3 },
79 { C::poseidon2_perm_B_50_0, C::poseidon2_perm_B_50_1, C::poseidon2_perm_B_50_2, C::poseidon2_perm_B_50_3 },
80 { C::poseidon2_perm_B_51_0, C::poseidon2_perm_B_51_1, C::poseidon2_perm_B_51_2, C::poseidon2_perm_B_51_3 },
81 { C::poseidon2_perm_B_52_0, C::poseidon2_perm_B_52_1, C::poseidon2_perm_B_52_2, C::poseidon2_perm_B_52_3 },
82 { C::poseidon2_perm_B_53_0, C::poseidon2_perm_B_53_1, C::poseidon2_perm_B_53_2, C::poseidon2_perm_B_53_3 },
83 { C::poseidon2_perm_B_54_0, C::poseidon2_perm_B_54_1, C::poseidon2_perm_B_54_2, C::poseidon2_perm_B_54_3 },
84 { C::poseidon2_perm_B_55_0, C::poseidon2_perm_B_55_1, C::poseidon2_perm_B_55_2, C::poseidon2_perm_B_55_3 },
85 { C::poseidon2_perm_B_56_0, C::poseidon2_perm_B_56_1, C::poseidon2_perm_B_56_2, C::poseidon2_perm_B_56_3 },
86 { C::poseidon2_perm_B_57_0, C::poseidon2_perm_B_57_1, C::poseidon2_perm_B_57_2, C::poseidon2_perm_B_57_3 },
87 { C::poseidon2_perm_B_58_0, C::poseidon2_perm_B_58_1, C::poseidon2_perm_B_58_2, C::poseidon2_perm_B_58_3 },
88 { C::poseidon2_perm_B_59_0, C::poseidon2_perm_B_59_1, C::poseidon2_perm_B_59_2, C::poseidon2_perm_B_59_3 },
90 { C::poseidon2_perm_T_60_6, C::poseidon2_perm_T_60_5, C::poseidon2_perm_T_60_7, C::poseidon2_perm_T_60_4 },
91 { C::poseidon2_perm_T_61_6, C::poseidon2_perm_T_61_5, C::poseidon2_perm_T_61_7, C::poseidon2_perm_T_61_4 },
92 { C::poseidon2_perm_T_62_6, C::poseidon2_perm_T_62_5, C::poseidon2_perm_T_62_7, C::poseidon2_perm_T_62_4 },
93 { C::poseidon2_perm_T_63_6, C::poseidon2_perm_T_63_5, C::poseidon2_perm_T_63_7, C::poseidon2_perm_T_63_4 },
110 for (
const auto&
event : hash_events) {
111 auto input_size =
event.inputs.size();
113 const auto num_perm_events =
event.intermediate_states.size() - 1;
117 const auto padding_size = (2 * input_size) % 3;
119 for (
size_t i = 0; i < num_perm_events; i++) {
120 std::array<FF, 3> perm_input = { 0, 0, 0 };
121 auto perm_state =
event.intermediate_states[i];
122 const auto& perm_output =
event.intermediate_states[i + 1];
123 size_t chunk_size = std::min(input_size,
static_cast<size_t>(3));
125 for (
size_t j = 0; j < chunk_size; j++) {
127 perm_input[j] =
event.inputs[(i * 3) + j];
129 perm_state[j] += perm_input[j];
133 { C::poseidon2_hash_sel, 1 },
134 { C::poseidon2_hash_start, i == 0 ? 1 : 0 },
135 { C::poseidon2_hash_end, i == (num_perm_events - 1) ? 1 : 0 },
136 { C::poseidon2_hash_input_len,
event.inputs.size() },
137 { C::poseidon2_hash_padding, padding_size },
138 { C::poseidon2_hash_input_0, perm_input[0] },
139 { C::poseidon2_hash_input_1, perm_input[1] },
140 { C::poseidon2_hash_input_2, perm_input[2] },
142 { C::poseidon2_hash_num_perm_rounds_rem, num_perm_events - i },
143 { C::poseidon2_hash_num_perm_rounds_rem_min_one_inv,
144 num_perm_events - i - 1 },
146 { C::poseidon2_hash_a_0, perm_state[0] },
147 { C::poseidon2_hash_a_1, perm_state[1] },
148 { C::poseidon2_hash_a_2, perm_state[2] },
149 { C::poseidon2_hash_a_3, perm_state[3] },
151 { C::poseidon2_hash_b_0, perm_output[0] },
152 { C::poseidon2_hash_b_1, perm_output[1] },
153 { C::poseidon2_hash_b_2, perm_output[2] },
154 { C::poseidon2_hash_b_3, perm_output[3] },
155 { C::poseidon2_hash_output,
event.output },
157 input_size -= chunk_size;
162 trace.invert_columns({ { C::poseidon2_hash_num_perm_rounds_rem_min_one_inv } });
178 std::array<FF, 4> current_state;
184 for (
const auto&
event : perm_events) {
187 current_state =
event.input;
193 { C::poseidon2_perm_sel, 1 },
194 { C::poseidon2_perm_a_0,
event.input[0] },
195 { C::poseidon2_perm_a_1,
event.input[1] },
196 { C::poseidon2_perm_a_2,
event.input[2] },
197 { C::poseidon2_perm_a_3,
event.input[3] },
199 { C::poseidon2_perm_EXT_LAYER_6, current_state[0] },
200 { C::poseidon2_perm_EXT_LAYER_5, current_state[1] },
201 { C::poseidon2_perm_EXT_LAYER_7, current_state[2] },
202 { C::poseidon2_perm_EXT_LAYER_4, current_state[3] },
209 for (
size_t i = 0; i < rounds_f_beginning; ++i) {
214 round_state_cols = intermediate_round_cols[i];
216 { { { round_state_cols[0], current_state[0] },
217 { round_state_cols[1], current_state[1] },
218 { round_state_cols[2], current_state[2] },
219 { round_state_cols[3], current_state[3] } } });
224 for (
size_t i = rounds_f_beginning; i < p_end; ++i) {
229 round_state_cols = intermediate_round_cols[i];
231 { { { round_state_cols[0], current_state[0] },
232 { round_state_cols[1], current_state[1] },
233 { round_state_cols[2], current_state[2] },
234 { round_state_cols[3], current_state[3] } } });
242 round_state_cols = intermediate_round_cols[i];
244 { { { round_state_cols[0], current_state[0] },
245 { round_state_cols[1], current_state[1] },
246 { round_state_cols[2], current_state[2] },
247 { round_state_cols[3], current_state[3] } } });
252 { C::poseidon2_perm_b_0, current_state[0] },
253 { C::poseidon2_perm_b_1, current_state[1] },
254 { C::poseidon2_perm_b_2, current_state[2] },
255 { C::poseidon2_perm_b_3, current_state[3] },
282 for (
const auto&
event : perm_mem_events) {
284 const uint64_t src_addr =
static_cast<uint64_t
>(
event.src_address);
285 const uint64_t
dst_addr =
static_cast<uint64_t
>(
event.dst_address);
291 const bool should_read_mem = !(src_out_of_range_err || dst_out_of_range_err);
295 std::ranges::any_of(
event.input, [](
const auto& input) { return input.get_tag() != MemoryTag::FF; });
297 FF batch_tag_inv = 0;
302 FF batched_tag_check = 0;
306 for (uint32_t i = 0; i <
event.input.size(); i++) {
307 uint32_t exponent = 3 * i;
308 uint32_t current_tag =
static_cast<uint32_t
>(
event.input[i].get_tag());
309 batched_tag_check += (
FF(current_tag) -
FF(target_tag)) *
FF((1 << exponent));
311 batch_tag_inv = batched_tag_check.invert();
314 const bool err = src_out_of_range_err || dst_out_of_range_err || invalid_tag;
318 { C::poseidon2_perm_mem_sel, 1 },
319 { C::poseidon2_perm_mem_execution_clk,
event.execution_clk },
320 { C::poseidon2_perm_mem_space_id,
event.space_id },
323 { C::poseidon2_perm_mem_sel_src_out_of_range_err, src_out_of_range_err ? 1 : 0 },
324 { C::poseidon2_perm_mem_sel_dst_out_of_range_err, dst_out_of_range_err ? 1 : 0 },
325 { C::poseidon2_perm_mem_sel_invalid_tag_err, invalid_tag ? 1 : 0 },
326 { C::poseidon2_perm_mem_batch_tag_inv, batch_tag_inv },
327 { C::poseidon2_perm_mem_err, err ? 1 : 0 },
329 { C::poseidon2_perm_mem_sel_should_read_mem, should_read_mem ? 1 : 0 },
331 { C::poseidon2_perm_mem_read_address_0_, src_addr },
332 { C::poseidon2_perm_mem_read_address_1_, src_addr + 1 },
333 { C::poseidon2_perm_mem_read_address_2_, src_addr + 2 },
334 { C::poseidon2_perm_mem_read_address_3_, src_addr + 3 },
336 { C::poseidon2_perm_mem_write_address_0_,
dst_addr },
337 { C::poseidon2_perm_mem_write_address_1_,
dst_addr + 1 },
338 { C::poseidon2_perm_mem_write_address_2_,
dst_addr + 2 },
339 { C::poseidon2_perm_mem_write_address_3_,
dst_addr + 3 },
341 { C::poseidon2_perm_mem_input_0_,
event.input[0].as_ff() },
342 { C::poseidon2_perm_mem_input_1_,
event.input[1].as_ff() },
343 { C::poseidon2_perm_mem_input_2_,
event.input[2].as_ff() },
344 { C::poseidon2_perm_mem_input_3_,
event.input[3].as_ff() },
346 { C::poseidon2_perm_mem_input_tag_0_,
static_cast<uint8_t
>(
event.input[0].get_tag()) },
347 { C::poseidon2_perm_mem_input_tag_1_,
static_cast<uint8_t
>(
event.input[1].get_tag()) },
348 { C::poseidon2_perm_mem_input_tag_2_,
static_cast<uint8_t
>(
event.input[2].get_tag()) },
349 { C::poseidon2_perm_mem_input_tag_3_,
static_cast<uint8_t
>(
event.input[3].get_tag()) },
351 { C::poseidon2_perm_mem_sel_should_exec, !err ? 1 : 0 },
352 { C::poseidon2_perm_mem_output_0_,
event.output[0] },
353 { C::poseidon2_perm_mem_output_1_,
event.output[1] },
354 { C::poseidon2_perm_mem_output_2_,
event.output[2] },
355 { C::poseidon2_perm_mem_output_3_,
event.output[3] },
365 .add<lookup_poseidon2_mem_input_output_poseidon2_perm_settings, InteractionType::LookupSequential>()
368 .add<lookup_poseidon2_mem_check_dst_addr_in_range_settings, InteractionType::LookupGeneric>(C::gt_sel);
#define AVM_HIGHEST_MEM_ADDRESS
std::vector< Event > Container
InteractionDefinition & add(auto &&... args)
static const InteractionDefinition interactions
void process_permutation(const simulation::EventEmitterInterface< simulation::Poseidon2PermutationEvent >::Container &perm_events, TraceContainer &trace)
Processes the permutation events for the Poseidon2 permutation function. It populates the columns for...
void process_permutation_with_memory(const simulation::EventEmitterInterface< simulation::Poseidon2PermutationMemoryEvent >::Container &perm_mem_events, TraceContainer &trace)
Processes the events for the Poseidon2 memory-aware permutation function. It populates the columns fo...
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
Processes the hash events for the Poseidon2 hash function. It populates the columns for the poseidon2...
Applies the Poseidon2 permutation function from https://eprint.iacr.org/2023/323.
static constexpr size_t NUM_ROUNDS
static constexpr size_t rounds_f
static constexpr size_t rounds_p
static constexpr void apply_single_sbox(FF &input)
S-box: x -> x^5.
static constexpr void matrix_multiplication_internal(State &input)
static constexpr void matrix_multiplication_external(State &input)
static constexpr void add_round_constants(State &input, const RoundConstants &rc)
static constexpr void apply_sbox(State &input)
static constexpr RoundConstantsContainer round_constants
lookup_settings< lookup_poseidon2_hash_poseidon2_perm_settings_ > lookup_poseidon2_hash_poseidon2_perm_settings
lookup_settings< lookup_poseidon2_mem_check_src_addr_in_range_settings_ > lookup_poseidon2_mem_check_src_addr_in_range_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
simulation::PublicDataTreeReadWriteEvent event