15#include <unordered_map>
22using simulation::TxContextEvent;
25template <
class... Ts>
struct overloaded : Ts... {
26 using Ts::operator()...;
29template <
class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
31constexpr size_t NUM_PHASES = 12;
52 return is_note_hash_insert_phase(phase) || is_nullifier_insert_phase(phase);
83 return is_collect_fee_phase(phase) || is_tree_padding_phase(phase) || is_cleanup_phase(phase);
97 { Column::tx_prev_note_hash_tree_root, prev_state.tree_states.noteHashTree.tree.root },
98 { Column::tx_prev_note_hash_tree_size, prev_state.tree_states.noteHashTree.tree.nextAvailableLeafIndex },
99 { Column::tx_prev_num_note_hashes_emitted, prev_state.tree_states.noteHashTree.counter },
101 { Column::tx_prev_nullifier_tree_root, prev_state.tree_states.nullifierTree.tree.root },
102 { Column::tx_prev_nullifier_tree_size, prev_state.tree_states.nullifierTree.tree.nextAvailableLeafIndex },
103 { Column::tx_prev_num_nullifiers_emitted, prev_state.tree_states.nullifierTree.counter },
105 { Column::tx_prev_public_data_tree_root, prev_state.tree_states.publicDataTree.tree.root },
106 { Column::tx_prev_public_data_tree_size, prev_state.tree_states.publicDataTree.tree.nextAvailableLeafIndex },
108 { Column::tx_prev_written_public_data_slots_tree_root,
109 prev_state.written_public_data_slots_tree_snapshot.root },
110 { Column::tx_prev_written_public_data_slots_tree_size,
111 prev_state.written_public_data_slots_tree_snapshot.nextAvailableLeafIndex },
113 { Column::tx_l1_l2_tree_root, prev_state.tree_states.l1ToL2MessageTree.tree.root },
116 { Column::tx_next_note_hash_tree_root, next_state.tree_states.noteHashTree.tree.root },
117 { Column::tx_next_note_hash_tree_size, next_state.tree_states.noteHashTree.tree.nextAvailableLeafIndex },
118 { Column::tx_next_num_note_hashes_emitted, next_state.tree_states.noteHashTree.counter },
120 { Column::tx_next_nullifier_tree_root, next_state.tree_states.nullifierTree.tree.root },
121 { Column::tx_next_nullifier_tree_size, next_state.tree_states.nullifierTree.tree.nextAvailableLeafIndex },
122 { Column::tx_next_num_nullifiers_emitted, next_state.tree_states.nullifierTree.counter },
124 { Column::tx_next_public_data_tree_root, next_state.tree_states.publicDataTree.tree.root },
125 { Column::tx_next_public_data_tree_size, next_state.tree_states.publicDataTree.tree.nextAvailableLeafIndex },
127 { Column::tx_next_written_public_data_slots_tree_root,
128 next_state.written_public_data_slots_tree_snapshot.root },
129 { Column::tx_next_written_public_data_slots_tree_size,
130 next_state.written_public_data_slots_tree_snapshot.nextAvailableLeafIndex },
133 { Column::tx_prev_num_unencrypted_logs, prev_state.side_effect_states.numUnencryptedLogs },
134 { Column::tx_prev_num_l2_to_l1_messages, prev_state.side_effect_states.numL2ToL1Messages },
137 { Column::tx_next_num_unencrypted_logs, next_state.side_effect_states.numUnencryptedLogs },
138 { Column::tx_next_num_l2_to_l1_messages, next_state.side_effect_states.numL2ToL1Messages },
141 { Column::tx_next_context_id, prev_state.next_context_id },
146 const SideEffectStates& next_side_effect_states)
150 Column::tx_prev_num_unencrypted_logs,
151 prev_side_effect_states.numUnencryptedLogs,
154 Column::tx_prev_num_l2_to_l1_messages,
155 prev_side_effect_states.numL2ToL1Messages,
158 Column::tx_next_num_unencrypted_logs,
159 next_side_effect_states.numUnencryptedLogs,
162 Column::tx_next_num_l2_to_l1_messages,
163 next_side_effect_states.numL2ToL1Messages,
174 auto remaining_length = phase_length - read_counter;
175 auto remaining_length_inv = remaining_length == 0 ? 0 :
FF(remaining_length).invert();
176 auto remaining_length_minus_one_inv = remaining_length - 1 == 0 ? 0 :
FF(remaining_length - 1).invert();
179 { Column::tx_read_pi_offset, read_offset + read_counter },
180 { Column::tx_read_pi_length_offset, length_offset - read_counter },
182 { Column::tx_remaining_phase_counter, remaining_length },
183 { Column::tx_remaining_phase_inv, remaining_length_inv },
184 { Column::tx_remaining_phase_minus_one_inv, remaining_length_minus_one_inv },
191 { Column::tx_prev_da_gas_used, prev_gas_used.daGas },
192 { Column::tx_prev_l2_gas_used, prev_gas_used.l2Gas },
199 { Column::tx_next_da_gas_used, next_gas_used.daGas },
200 { Column::tx_next_l2_gas_used, next_gas_used.l2Gas },
207 { Column::tx_da_gas_limit, gas_limit.daGas },
208 { Column::tx_l2_gas_limit, gas_limit.l2Gas },
213 const simulation::EnqueuedCallEvent&
event)
215 return { { Column::tx_is_public_call_request, 1 },
216 { Column::tx_should_process_call_request, 1 },
217 { Column::tx_is_teardown_phase, is_teardown_phase(phase) },
218 { Column::tx_msg_sender,
event.msg_sender },
219 { Column::tx_contract_addr,
event.contract_address },
220 { Column::tx_fee,
event.transaction_fee },
221 { Column::tx_is_static,
event.is_static },
222 { Column::tx_calldata_hash,
event.calldata_hash },
223 { Column::tx_reverted, !
event.success },
224 { Column::tx_prev_da_gas_used_sent_to_enqueued_call,
event.start_gas.daGas },
225 { Column::tx_prev_l2_gas_used_sent_to_enqueued_call,
event.start_gas.l2Gas },
226 { Column::tx_next_da_gas_used_sent_to_enqueued_call,
event.end_gas.daGas },
227 { Column::tx_next_l2_gas_used_sent_to_enqueued_call,
event.end_gas.l2Gas },
228 { Column::tx_gas_limit_pi_offset,
230 { Column::tx_should_read_gas_limit, is_teardown_phase(phase) } };
235 const TxContextEvent& state_before,
241 { Column::tx_is_tree_insert_phase, 1 },
242 { Column::tx_leaf_value,
event.leaf_value },
243 { Column::tx_remaining_side_effects_inv, remaining_note_hashes == 0 ? 0 :
FF(remaining_note_hashes).invert() },
246 { Column::tx_should_try_note_hash_append, 1 },
247 { Column::tx_should_note_hash_append, remaining_note_hashes > 0 },
248 { Column::tx_reverted, reverted ? 1 : 0 },
254 const TxContextEvent& state_before,
257 uint32_t remaining_nullifiers =
MAX_NULLIFIERS_PER_TX - state_before.tree_states.nullifierTree.counter;
260 { Column::tx_is_tree_insert_phase, 1 },
261 { Column::tx_leaf_value,
event.leaf_value },
262 { Column::tx_remaining_side_effects_inv, remaining_nullifiers == 0 ? 0 :
FF(remaining_nullifiers).invert() },
265 { Column::tx_should_try_nullifier_append, 1 },
266 { Column::tx_should_nullifier_append, remaining_nullifiers > 0 },
267 { Column::tx_reverted, reverted ? 1 : 0 },
273 const TxContextEvent& state_before,
276 if (is_note_hash_insert_phase(phase)) {
277 return handle_note_hash_append(
event, phase, state_before, reverted);
279 if (is_nullifier_insert_phase(phase)) {
280 return handle_nullifier_append(
event, phase, state_before, reverted);
282 throw std::runtime_error(
"Invalid phase for append tree event");
287 const TxContextEvent& state_before,
294 { Column::tx_should_try_l2_l1_msg_append, 1 },
295 { Column::tx_remaining_side_effects_inv,
296 remaining_l2_to_l1_msgs == 0 ? 0 :
FF(remaining_l2_to_l1_msgs).invert() },
297 { Column::tx_should_l2_l1_msg_append, remaining_l2_to_l1_msgs > 0 },
298 { Column::tx_l2_l1_msg_contract_address,
event.scoped_msg.contractAddress },
299 { Column::tx_l2_l1_msg_recipient,
event.scoped_msg.message.recipient },
300 { Column::tx_l2_l1_msg_content,
event.scoped_msg.message.content },
301 { Column::tx_write_pi_offset,
303 state_before.side_effect_states.numL2ToL1Messages },
305 { Column::tx_reverted, reverted ? 1 : 0 },
312 { Column::tx_is_collect_fee, 1 },
313 { Column::tx_effective_fee_per_da_gas,
FF(
event.effective_fee_per_da_gas) },
314 { Column::tx_effective_fee_per_l2_gas,
FF(
event.effective_fee_per_l2_gas) },
315 { Column::tx_fee_payer,
event.fee_payer },
322 Column::tx_fee_juice_contract_address,
326 Column::tx_fee_juice_balances_slot,
330 Column::tx_fee_juice_balance_slot,
331 event.fee_juice_balance_slot,
334 Column::tx_fee_payer_balance,
335 event.fee_payer_balance,
338 Column::tx_fee_payer_new_balance,
339 event.fee_payer_balance -
event.fee,
341 { Column::tx_uint32_max, 0xffffffff },
349 { Column::tx_is_tree_padding, 1 },
356 { Column::tx_is_cleanup, 1 },
359 { Column::tx_should_read_note_hash_tree, 1 },
361 { Column::tx_should_read_nullifier_tree, 1 },
363 { Column::tx_should_read_public_data_tree, 1 },
365 { Column::tx_should_read_l1_l2_tree, 1 },
367 { Column::tx_should_read_gas_used, 1 },
368 { Column::tx_array_length_note_hashes_pi_offset,
370 { Column::tx_array_length_nullifiers_pi_offset,
373 { Column::tx_array_length_l2_to_l1_messages_pi_offset,
375 { Column::tx_array_length_unencrypted_logs_pi_offset,
383 { Column::tx_start_tx, 1 },
385 { Column::tx_should_read_note_hash_tree, 1 },
387 { Column::tx_should_read_nullifier_tree, 1 },
389 { Column::tx_should_read_public_data_tree, 1 },
391 { Column::tx_should_read_l1_l2_tree, 1 },
393 { Column::tx_should_read_gas_used, 1 },
395 { Column::tx_should_read_gas_limit, 1 },
409 { Column::tx_sel, 1 },
410 { Column::tx_discard,
discard ? 1 : 0 },
411 { Column::tx_phase_value,
static_cast<uint8_t
>(phase) },
413 { Column::tx_is_padded, 1 },
414 { Column::tx_start_phase, 1 },
415 { Column::tx_sel_read_phase_length, !is_one_shot_phase(phase) },
418 { Column::tx_is_collect_fee, is_collect_fee_phase(phase) ? 1 : 0 },
419 { Column::tx_end_phase, 1 },
421 { Column::tx_is_tree_insert_phase, is_tree_insert_phase(phase) ? 1 : 0 },
422 { Column::tx_is_public_call_request, is_public_call_request_phase(phase) ? 1 : 0 },
423 { Column::tx_is_collect_fee, is_collect_fee_phase(phase) ? 1 : 0 },
432 { Column::tx_is_collect_fee, is_collect_fee_phase(phase) ? 1 : 0 },
434 { Column::tx_is_revertible, is_revertible(phase) ? 1 : 0 },
436 { Column::tx_is_teardown_phase, is_teardown_phase(phase) },
437 { Column::tx_gas_limit_pi_offset,
439 { Column::tx_should_read_gas_limit, is_teardown_phase(phase) },
441 { Column::tx_prev_da_gas_used_sent_to_enqueued_call,
443 { Column::tx_prev_l2_gas_used_sent_to_enqueued_call,
445 { Column::tx_next_da_gas_used_sent_to_enqueued_call,
447 { Column::tx_next_l2_gas_used_sent_to_enqueued_call,
457 { Column::tx_sel_can_emit_note_hash,
458 is_note_hash_insert_phase(phase) || is_public_call_request_phase(phase) || is_tree_padding_phase(phase) },
459 { Column::tx_sel_can_emit_nullifier,
460 is_nullifier_insert_phase(phase) || is_public_call_request_phase(phase) || is_tree_padding_phase(phase) },
461 { Column::tx_sel_can_write_public_data, is_collect_fee_phase(phase) || is_public_call_request_phase(phase) },
462 { Column::tx_sel_can_emit_unencrypted_log, is_public_call_request_phase(phase) },
463 { Column::tx_sel_can_emit_l2_l1_msg, is_l2_l1_msg_phase(phase) || is_public_call_request_phase(phase) },
498 bool r_insertion_or_app_logic_failure =
false;
500 for (
const auto& tx_event : events) {
506 phase_buckets[
static_cast<uint8_t
>(tx_phase_event.
phase) - 1].push_back(&tx_phase_event);
510 if (!is_revertible(tx_phase_event.
phase)) {
511 throw std::runtime_error(
"Reverted in non-revertible phase: " +
518 r_insertion_or_app_logic_failure =
true;
524 if (!startup_event.has_value()) {
525 throw std::runtime_error(
"Transaction startup event is missing");
528 const auto& startup_event_data = startup_event.value();
534 Gas current_gas_limit = startup_event_data.gas_limit;
535 Gas teardown_gas_limit = startup_event_data.teardown_gas_limit;
536 Gas gas_used = startup_event_data.state.gas_used;
539 for (uint32_t i = 0; i < NUM_PHASES; i++) {
540 const auto& phase_events = phase_buckets[i];
545 if (is_revertible(phase)) {
554 if (is_teardown_phase(phase)) {
555 current_gas_limit = teardown_gas_limit;
558 if (phase_events.empty()) {
559 trace.set(row, insert_state(propagated_state, propagated_state));
560 trace.set(row, handle_padded_row(phase, gas_used,
discard));
561 trace.set(row, handle_pi_read(phase, 0, 0));
562 trace.set(row, handle_prev_gas_used(gas_used));
563 trace.set(row, handle_next_gas_used(gas_used));
564 trace.set(row, handle_gas_limit(current_gas_limit));
565 trace.set(row, handle_state_change_selectors(phase));
567 trace.set(row, handle_first_row());
571 end_setup_snapshot = propagated_state;
577 uint32_t phase_counter = 0;
578 uint32_t phase_length =
static_cast<uint32_t
>(phase_events.size());
581 for (
const auto& tx_phase_event : phase_events) {
583 trace.set(row, insert_state(tx_phase_event->state_before, tx_phase_event->state_after));
585 insert_side_effect_states(tx_phase_event->state_before.side_effect_states,
586 tx_phase_event->state_after.side_effect_states));
591 { C::tx_discard,
discard ? 1 : 0 },
592 { C::tx_phase_value,
static_cast<uint8_t
>(tx_phase_event->phase) },
594 { C::tx_is_padded, 0 },
595 { C::tx_start_phase, phase_counter == 0 ? 1 : 0 },
596 { C::tx_sel_read_phase_length, phase_counter == 0 && !is_one_shot_phase(tx_phase_event->phase) },
597 { C::tx_is_revertible, is_revertible(tx_phase_event->phase) ? 1 : 0 },
598 { C::tx_end_phase, phase_counter == phase_events.size() - 1 ? 1 : 0 },
600 trace.set(row, handle_prev_gas_used(gas_used));
601 trace.set(row, handle_state_change_selectors(tx_phase_event->phase));
603 trace.set(row, handle_first_row());
609 trace.set(row, handle_enqueued_call_event(tx_phase_event->phase,
event));
611 trace.set(row, handle_pi_read(tx_phase_event->phase, phase_length, phase_counter));
613 gas_used = tx_phase_event->state_after.gas_used;
617 handle_append_tree_event(
event,
618 tx_phase_event->phase,
619 tx_phase_event->state_before,
620 tx_phase_event->reverted));
622 trace.set(row, handle_pi_read(tx_phase_event->phase, phase_length, phase_counter));
626 handle_l2_l1_msg_event(
event,
627 tx_phase_event->phase,
628 tx_phase_event->state_before,
629 tx_phase_event->reverted));
630 trace.set(row, handle_pi_read(tx_phase_event->phase, phase_length, phase_counter));
633 trace.set(row, handle_pi_read(tx_phase_event->phase, 1, 0));
634 trace.set(row, handle_collect_gas_fee_event(
event));
637 trace.set(row, handle_pi_read(tx_phase_event->phase, 1, 0));
638 trace.set(row, handle_tree_padding());
641 trace.set(row, handle_pi_read(tx_phase_event->phase, 1, 0));
642 trace.set(row, handle_cleanup());
644 tx_phase_event->event);
645 trace.set(row, handle_next_gas_used(gas_used));
646 trace.set(row, handle_gas_limit(current_gas_limit));
660 propagated_state = phase_events.back()->state_after;
664 end_setup_snapshot = phase_events.back()->state_after;
666 if (phase_events.back()->reverted) {
684 .add<lookup_tx_phase_jump_on_revert_settings, InteractionType::LookupGeneric>()
686 .add<lookup_tx_read_public_call_request_phase_settings, InteractionType::LookupGeneric>()
688 .add<lookup_tx_dispatch_exec_end_settings, InteractionType::LookupGeneric>()
690 .add<lookup_tx_read_l2_l1_msg_settings, InteractionType::LookupGeneric>()
692 .add<lookup_tx_read_effective_fee_public_inputs_settings, InteractionType::LookupGeneric>()
694 .add<lookup_tx_balance_validation_settings, InteractionType::LookupGeneric>()
696 .add<lookup_tx_nullifier_append_settings, InteractionType::LookupGeneric>()
698 .add<lookup_tx_balance_update_settings, InteractionType::LookupGeneric>()
700 .add<lookup_tx_balance_slot_poseidon2_settings, InteractionType::LookupGeneric>()
702 .add<lookup_tx_context_public_inputs_nullifier_tree_settings, InteractionType::LookupIntoIndexedByClk>()
704 .add<lookup_tx_context_public_inputs_l1_l2_tree_settings, InteractionType::LookupIntoIndexedByClk>()
706 .add<lookup_tx_context_public_inputs_read_gas_limit_settings, InteractionType::LookupIntoIndexedByClk>()
708 .add<lookup_tx_context_public_inputs_write_nullifier_count_settings, InteractionType::LookupIntoIndexedByClk>()
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_ARRAY_LENGTHS_NOTE_HASHES_ROW_IDX
#define AVM_PUBLIC_INPUTS_END_TREE_SNAPSHOTS_L1_TO_L2_MESSAGE_TREE_ROW_IDX
#define AVM_PUBLIC_INPUTS_FEE_PAYER_ROW_IDX
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX
#define AVM_PUBLIC_INPUTS_GAS_SETTINGS_TEARDOWN_GAS_LIMITS_ROW_IDX
#define AVM_PUBLIC_INPUTS_TRANSACTION_FEE_ROW_IDX
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_ARRAY_LENGTHS_L2_TO_L1_MSGS_ROW_IDX
#define AVM_PUBLIC_INPUTS_END_GAS_USED_ROW_IDX
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_ARRAY_LENGTHS_NULLIFIERS_ROW_IDX
#define AVM_PUBLIC_INPUTS_START_TREE_SNAPSHOTS_L1_TO_L2_MESSAGE_TREE_ROW_IDX
#define AVM_PUBLIC_INPUTS_END_TREE_SNAPSHOTS_NULLIFIER_TREE_ROW_IDX
#define FEE_JUICE_ADDRESS
#define AVM_PUBLIC_INPUTS_START_TREE_SNAPSHOTS_NOTE_HASH_TREE_ROW_IDX
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_ARRAY_LENGTHS_PUBLIC_LOGS_ROW_IDX
#define AVM_PUBLIC_INPUTS_END_TREE_SNAPSHOTS_NOTE_HASH_TREE_ROW_IDX
#define MAX_L2_TO_L1_MSGS_PER_TX
#define MAX_NOTE_HASHES_PER_TX
#define AVM_PUBLIC_INPUTS_START_TREE_SNAPSHOTS_PUBLIC_DATA_TREE_ROW_IDX
#define FEE_JUICE_BALANCES_SLOT
#define AVM_PUBLIC_INPUTS_START_TREE_SNAPSHOTS_NULLIFIER_TREE_ROW_IDX
#define MAX_NULLIFIERS_PER_TX
#define AVM_PUBLIC_INPUTS_START_GAS_USED_ROW_IDX
#define AVM_PUBLIC_INPUTS_GAS_SETTINGS_GAS_LIMITS_ROW_IDX
#define AVM_PUBLIC_INPUTS_END_TREE_SNAPSHOTS_PUBLIC_DATA_TREE_ROW_IDX
std::vector< Event > Container
InteractionDefinition & add(auto &&... args)
static const Offsets & get_offsets(TransactionPhase phase)
void process(const simulation::EventEmitterInterface< simulation::TxEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
lookup_settings< lookup_tx_context_public_inputs_write_l2_to_l1_message_count_settings_ > lookup_tx_context_public_inputs_write_l2_to_l1_message_count_settings
lookup_settings< lookup_tx_read_fee_payer_public_inputs_settings_ > lookup_tx_read_fee_payer_public_inputs_settings
lookup_settings< lookup_tx_balance_read_settings_ > lookup_tx_balance_read_settings
lookup_settings< lookup_tx_context_public_inputs_note_hash_tree_settings_ > lookup_tx_context_public_inputs_note_hash_tree_settings
lookup_settings< lookup_tx_read_tree_insert_value_settings_ > lookup_tx_read_tree_insert_value_settings
lookup_settings< lookup_tx_read_phase_table_settings_ > lookup_tx_read_phase_table_settings
lookup_settings< lookup_tx_write_fee_public_inputs_settings_ > lookup_tx_write_fee_public_inputs_settings
lookup_settings< lookup_tx_context_public_inputs_public_data_tree_settings_ > lookup_tx_context_public_inputs_public_data_tree_settings
lookup_settings< lookup_tx_context_public_inputs_gas_used_settings_ > lookup_tx_context_public_inputs_gas_used_settings
lookup_settings< lookup_tx_write_l2_l1_msg_settings_ > lookup_tx_write_l2_l1_msg_settings
lookup_settings< lookup_tx_context_restore_state_on_revert_settings_ > lookup_tx_context_restore_state_on_revert_settings
lookup_settings< lookup_tx_context_public_inputs_write_note_hash_count_settings_ > lookup_tx_context_public_inputs_write_note_hash_count_settings
lookup_settings< lookup_tx_note_hash_append_settings_ > lookup_tx_note_hash_append_settings
lookup_settings< lookup_tx_dispatch_exec_start_settings_ > lookup_tx_dispatch_exec_start_settings
lookup_settings< lookup_tx_read_phase_length_settings_ > lookup_tx_read_phase_length_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
simulation::PublicDataTreeReadWriteEvent event
AppendOnlyTreeSnapshot written_public_data_slots_tree_snapshot
SideEffectStates side_effect_states