28using simulation::CollectGasFeeEvent;
29using simulation::EnqueuedCallEvent;
30using simulation::PhaseLengths;
31using simulation::PrivateAppendTreeEvent;
32using simulation::PrivateEmitL2L1MessageEvent;
33using simulation::TxContextEvent;
36template <
class... Ts>
struct overloaded : Ts... {
37 using Ts::operator()...;
43uint32_t get_phase_length(
const PhaseLengths& phase_lengths,
TransactionPhase phase)
47 return phase_lengths.nr_nullifier_insertion;
49 return phase_lengths.nr_note_insertion;
51 return phase_lengths.nr_l2_to_l1_message;
53 return phase_lengths.setup;
55 return phase_lengths.r_nullifier_insertion;
57 return phase_lengths.r_note_insertion;
59 return phase_lengths.r_l2_to_l1_message;
61 return phase_lengths.app_logic;
63 return phase_lengths.teardown;
142 { C::tx_prev_note_hash_tree_root, prev_state.tree_states.note_hash_tree.tree.root },
143 { C::tx_prev_note_hash_tree_size, prev_state.tree_states.note_hash_tree.tree.next_available_leaf_index },
144 { C::tx_prev_num_note_hashes_emitted, prev_state.tree_states.note_hash_tree.counter },
146 { C::tx_prev_nullifier_tree_root, prev_state.tree_states.nullifier_tree.tree.root },
147 { C::tx_prev_nullifier_tree_size, prev_state.tree_states.nullifier_tree.tree.next_available_leaf_index },
148 { C::tx_prev_num_nullifiers_emitted, prev_state.tree_states.nullifier_tree.counter },
150 { C::tx_prev_public_data_tree_root, prev_state.tree_states.public_data_tree.tree.root },
151 { C::tx_prev_public_data_tree_size, prev_state.tree_states.public_data_tree.tree.next_available_leaf_index },
153 { C::tx_prev_written_public_data_slots_tree_root, prev_state.written_public_data_slots_tree_snapshot.root },
154 { C::tx_prev_written_public_data_slots_tree_size,
155 prev_state.written_public_data_slots_tree_snapshot.next_available_leaf_index },
157 { C::tx_l1_l2_tree_root, prev_state.tree_states.l1_to_l2_message_tree.tree.root },
158 { C::tx_l1_l2_tree_size, prev_state.tree_states.l1_to_l2_message_tree.tree.next_available_leaf_index },
160 { C::tx_prev_retrieved_bytecodes_tree_root, prev_state.retrieved_bytecodes_tree_snapshot.root },
161 { C::tx_prev_retrieved_bytecodes_tree_size,
162 prev_state.retrieved_bytecodes_tree_snapshot.next_available_leaf_index },
165 { C::tx_next_note_hash_tree_root, next_state.tree_states.note_hash_tree.tree.root },
166 { C::tx_next_note_hash_tree_size, next_state.tree_states.note_hash_tree.tree.next_available_leaf_index },
167 { C::tx_next_num_note_hashes_emitted, next_state.tree_states.note_hash_tree.counter },
169 { C::tx_next_nullifier_tree_root, next_state.tree_states.nullifier_tree.tree.root },
170 { C::tx_next_nullifier_tree_size, next_state.tree_states.nullifier_tree.tree.next_available_leaf_index },
171 { C::tx_next_num_nullifiers_emitted, next_state.tree_states.nullifier_tree.counter },
173 { C::tx_next_public_data_tree_root, next_state.tree_states.public_data_tree.tree.root },
174 { C::tx_next_public_data_tree_size, next_state.tree_states.public_data_tree.tree.next_available_leaf_index },
176 { C::tx_next_written_public_data_slots_tree_root, next_state.written_public_data_slots_tree_snapshot.root },
177 { C::tx_next_written_public_data_slots_tree_size,
178 next_state.written_public_data_slots_tree_snapshot.next_available_leaf_index },
180 { C::tx_next_retrieved_bytecodes_tree_root, next_state.retrieved_bytecodes_tree_snapshot.root },
181 { C::tx_next_retrieved_bytecodes_tree_size,
182 next_state.retrieved_bytecodes_tree_snapshot.next_available_leaf_index },
185 { C::tx_next_context_id, prev_state.next_context_id },
198 const TxContextEvent& next_state)
201 { C::tx_prev_num_public_log_fields, prev_state.numPublicLogFields },
202 { C::tx_prev_num_l2_to_l1_messages, prev_state.numL2ToL1Messages },
203 { C::tx_next_num_public_log_fields, next_state.numPublicLogFields },
204 { C::tx_next_num_l2_to_l1_messages, next_state.numL2ToL1Messages },
221 const auto remaining_length = phase_length - read_counter;
224 { C::tx_read_pi_offset, phase_spec.read_pi_start_offset + read_counter },
225 { C::tx_remaining_phase_counter, remaining_length },
226 { C::tx_remaining_phase_inv, remaining_length },
227 { C::tx_remaining_phase_minus_one_inv, remaining_length - 1 },
243 { C::tx_phase_value,
static_cast<uint8_t
>(phase) },
244 { C::tx_is_public_call_request, phase_spec.is_public_call_request ? 1 : 0 },
245 { C::tx_is_teardown, phase_spec.is_teardown ? 1 : 0 },
246 { C::tx_is_collect_fee, phase_spec.is_collect_fee ? 1 : 0 },
247 { C::tx_is_tree_padding, phase_spec.is_tree_padding ? 1 : 0 },
248 { C::tx_is_cleanup, phase_spec.is_cleanup ? 1 : 0 },
249 { C::tx_is_revertible, phase_spec.is_revertible ? 1 : 0 },
250 { C::tx_read_pi_start_offset, phase_spec.read_pi_start_offset },
251 { C::tx_read_pi_length_offset, phase_spec.read_pi_length_offset },
252 { C::tx_sel_non_revertible_append_note_hash, phase_spec.non_revertible_append_note_hash ? 1 : 0 },
253 { C::tx_sel_non_revertible_append_nullifier, phase_spec.non_revertible_append_nullifier ? 1 : 0 },
254 { C::tx_sel_non_revertible_append_l2_l1_msg, phase_spec.non_revertible_append_l2_l1_msg ? 1 : 0 },
255 { C::tx_sel_revertible_append_note_hash, phase_spec.revertible_append_note_hash ? 1 : 0 },
256 { C::tx_sel_revertible_append_nullifier, phase_spec.revertible_append_nullifier ? 1 : 0 },
257 { C::tx_sel_revertible_append_l2_l1_msg, phase_spec.revertible_append_l2_l1_msg ? 1 : 0 },
258 { C::tx_next_phase_on_revert, phase_spec.next_phase_on_revert },
261 { C::tx_is_tree_insert_phase, (is_note_hash_insert_phase(phase) || is_nullifier_insert_phase(phase)) ? 1 : 0 },
274 { C::tx_prev_da_gas_used, prev_gas_used.da_gas },
275 { C::tx_prev_l2_gas_used, prev_gas_used.l2_gas },
288 { C::tx_next_da_gas_used, next_gas_used.da_gas },
289 { C::tx_next_l2_gas_used, next_gas_used.l2_gas },
301 const bool is_phase_teardown = is_teardown(phase);
303 uint32_t gas_limit_pi_offset = 0;
304 if (is_phase_teardown) {
306 }
else if (is_first_active_row) {
311 { C::tx_gas_limit_pi_offset, gas_limit_pi_offset },
312 { C::tx_should_read_gas_limit, (is_phase_teardown || is_first_active_row) ? 1 : 0 },
313 { C::tx_da_gas_limit, gas_limit.da_gas },
314 { C::tx_l2_gas_limit, gas_limit.l2_gas },
327 return { { C::tx_should_process_call_request, 1 },
328 { C::tx_msg_sender,
event.msg_sender },
329 { C::tx_contract_addr,
event.contract_address },
330 { C::tx_fee,
event.transaction_fee },
331 { C::tx_is_static,
event.is_static ? 1 : 0 },
332 { C::tx_calldata_size,
event.calldata_size },
333 { C::tx_calldata_hash,
event.calldata_hash },
334 { C::tx_prev_da_gas_used_sent_to_enqueued_call,
event.start_gas.da_gas },
335 { C::tx_prev_l2_gas_used_sent_to_enqueued_call,
event.start_gas.l2_gas },
336 { C::tx_next_da_gas_used_sent_to_enqueued_call,
event.end_gas.da_gas },
337 { C::tx_next_l2_gas_used_sent_to_enqueued_call,
event.end_gas.l2_gas } };
349 const TxContextEvent& state_before)
351 uint32_t remaining_note_hashes =
MAX_NOTE_HASHES_PER_TX - state_before.tree_states.note_hash_tree.counter;
354 { C::tx_leaf_value,
event.leaf_value },
355 { C::tx_remaining_side_effects_inv, remaining_note_hashes },
356 { C::tx_should_try_note_hash_append, 1 },
357 { C::tx_should_note_hash_append, remaining_note_hashes > 0 ? 1 : 0 },
370 const TxContextEvent& state_before)
372 uint32_t remaining_nullifiers =
MAX_NULLIFIERS_PER_TX - state_before.tree_states.nullifier_tree.counter;
374 return { { C::tx_leaf_value,
event.leaf_value },
375 { C::tx_nullifier_limit_error, remaining_nullifiers > 0 ? 0 : 1 },
376 { C::tx_remaining_side_effects_inv, remaining_nullifiers },
377 { C::tx_should_try_nullifier_append, 1 },
378 { C::tx_should_nullifier_append, remaining_nullifiers > 0 ? 1 : 0 },
379 { C::tx_write_nullifier_pi_offset,
381 state_before.tree_states.nullifier_tree.counter },
394 TransactionPhase phase,
395 const TxContextEvent& state_before)
397 if (is_note_hash_insert_phase(phase)) {
398 return handle_note_hash_append(
event, state_before);
400 if (is_nullifier_insert_phase(phase)) {
401 return handle_nullifier_append(
event, state_before);
404 BB_ASSERT(
false,
format(
"Invalid phase for append tree event: ",
static_cast<uint8_t
>(phase)));
417 const TxContextEvent& state_before,
422 { C::tx_should_try_l2_l1_msg_append, 1 },
423 { C::tx_remaining_side_effects_inv, remaining_l2_to_l1_msgs },
424 { C::tx_should_l2_l1_msg_append, (remaining_l2_to_l1_msgs > 0 && !
discard) ? 1 : 0 },
425 { C::tx_l2_l1_msg_contract_address,
event.scoped_msg.contract_address },
426 { C::tx_l2_l1_msg_recipient,
event.scoped_msg.message.recipient },
427 { C::tx_l2_l1_msg_content,
event.scoped_msg.message.content },
428 { C::tx_write_pi_offset,
442 { C::tx_effective_fee_per_da_gas,
FF(
event.effective_fee_per_da_gas) },
443 { C::tx_effective_fee_per_l2_gas,
FF(
event.effective_fee_per_l2_gas) },
444 { C::tx_fee_payer,
event.fee_payer },
446 { C::tx_fee,
event.fee },
450 { C::tx_fee_juice_balance_slot,
event.fee_juice_balance_slot },
451 { C::tx_const_three, 3 },
452 { C::tx_fee_payer_balance,
event.fee_payer_balance },
453 { C::tx_fee_payer_new_balance,
event.fee_payer_balance -
event.fee },
454 { C::tx_uint32_max, UINT32_MAX },
468 { C::tx_sel_read_trees_and_gas_used, 1 },
475 { C::tx_array_length_note_hashes_pi_offset,
477 { C::tx_array_length_nullifiers_pi_offset,
480 { C::tx_array_length_l2_to_l1_messages_pi_offset,
494 { C::tx_start_tx, 1 },
495 { C::tx_sel_read_trees_and_gas_used, 1 },
571 bool r_insertion_or_app_logic_failure =
false;
578 for (
const auto& tx_event : events) {
581 phase_lengths = startup_event.value().phase_lengths;
584 phase_buckets[
static_cast<uint8_t
>(tx_phase_event.
phase)].push_back(&tx_phase_event);
590 format(
"Reverted in non-revertible phase: ",
static_cast<uint8_t
>(tx_phase_event.
phase)));
592 if (is_teardown(tx_phase_event.
phase)) {
595 r_insertion_or_app_logic_failure =
true;
602 BB_ASSERT(startup_event.has_value(),
"Transaction startup event is missing");
604 const auto& startup_event_data = startup_event.value();
606 Gas current_gas_limit = startup_event_data.gas_limit;
607 const Gas& teardown_gas_limit = startup_event_data.teardown_gas_limit;
609 Gas gas_used = startup_event_data.gas_used;
611 bool tx_reverted =
false;
615 trace.set(row, handle_first_active_row());
618 for (uint32_t i = 0; i < NUM_PHASES; i++) {
619 const auto& phase_events = phase_buckets[i];
620 if (phase_events.empty()) {
630 if (is_revertible(phase)) {
631 if (is_teardown(phase)) {
639 if (is_teardown(phase)) {
640 current_gas_limit = teardown_gas_limit;
644 uint32_t phase_counter = 0;
648 const uint32_t phase_length = get_phase_length(phase_lengths, phase);
651 for (
const auto* tx_phase_event : phase_events) {
653 tx_reverted = tx_reverted || tx_phase_event->reverted;
659 { C::tx_discard,
discard ? 1 : 0 },
660 { C::tx_reverted, tx_phase_event->reverted ? 1 : 0 },
661 { C::tx_tx_reverted, tx_reverted ? 1 : 0 },
662 { C::tx_setup_phase_value,
static_cast<uint8_t
>(TransactionPhase::SETUP) },
663 { C::tx_start_phase, phase_counter == 0 ? 1 : 0 },
664 { C::tx_sel_read_phase_length, (phase_counter == 0 && !is_one_shot_phase(phase)) ? 1 : 0 },
665 { C::tx_end_phase, phase_counter == phase_events.size() - 1 ? 1 : 0 },
669 trace.set(row, handle_phase_spec(phase));
672 trace.set(row, handle_pi_read(phase, phase_length, phase_counter));
675 trace.set(row, insert_tree_state(tx_phase_event->state_before, tx_phase_event->state_after));
676 trace.set(row, insert_side_effect_states(tx_phase_event->state_before, tx_phase_event->state_after));
677 trace.set(row, handle_prev_gas_used(gas_used));
683 trace.set(row, handle_enqueued_call_event(
event));
684 gas_used = tx_phase_event->state_after.gas_used;
687 trace.set(row, handle_append_tree_event(
event, phase, tx_phase_event->state_before));
690 trace.set(row, handle_l2_l1_msg_event(
event, tx_phase_event->state_before,
discard));
699 trace.set(C::tx_is_padded, row, 1);
701 tx_phase_event->event);
703 trace.set(row, handle_next_gas_used(gas_used));
704 trace.set(row, handle_gas_limit(phase, current_gas_limit, row == 1));
712 trace.invert_columns(
713 { { C::tx_remaining_phase_inv, C::tx_remaining_phase_minus_one_inv, C::tx_remaining_side_effects_inv } });
719 .add<lookup_tx_read_phase_length_settings, InteractionType::LookupIntoIndexedByRow>()
721 .add<lookup_tx_read_public_call_request_phase_settings, InteractionType::LookupIntoIndexedByRow>()
723 .add<perm_tx_dispatch_exec_end_settings, InteractionType::Permutation>()
725 .add<lookup_tx_read_l2_l1_msg_settings, InteractionType::LookupIntoIndexedByRow>()
727 .add<lookup_tx_read_effective_fee_public_inputs_settings, InteractionType::LookupIntoIndexedByRow>()
729 .add<lookup_tx_balance_validation_settings, InteractionType::LookupGeneric>()
731 .add<lookup_tx_nullifier_append_settings, InteractionType::LookupSequential>()
734 .add<lookup_tx_write_fee_public_inputs_settings, InteractionType::LookupIntoIndexedByRow>()
737 .add<lookup_tx_context_public_inputs_note_hash_tree_settings, InteractionType::LookupIntoIndexedByRow>()
739 .add<lookup_tx_context_public_inputs_public_data_tree_settings, InteractionType::LookupIntoIndexedByRow>()
741 .add<lookup_tx_context_public_inputs_gas_used_settings, InteractionType::LookupIntoIndexedByRow>()
743 .add<lookup_tx_context_public_inputs_read_reverted_settings, InteractionType::LookupIntoIndexedByRow>()
745 .add<lookup_tx_context_public_inputs_write_nullifier_count_settings, InteractionType::LookupIntoIndexedByRow>()
747 InteractionType::LookupIntoIndexedByRow>()
748 .add<lookup_tx_context_public_inputs_write_public_log_count_settings, InteractionType::LookupIntoIndexedByRow>()
#define BB_ASSERT(expression,...)
#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_NULLIFIERS_ROW_IDX
#define DOM_SEP__PUBLIC_STORAGE_MAP_SLOT
#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_END_TREE_SNAPSHOTS_NOTE_HASH_TREE_ROW_IDX
#define NULLIFIER_TREE_HEIGHT
#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 AVM_PUBLIC_INPUTS_REVERTED_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_AVM_ACCUMULATED_DATA_PUBLIC_LOGS_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)
std::string format(Args... args)
const std::unordered_map< TransactionPhase, TxPhaseSpec > & get_tx_phase_spec_map()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
simulation::PublicDataTreeReadWriteEvent event
Settings to be passed ot GenericLookupRelationImpl.