308 FailingContexts failures = preprocess_for_discard(ex_events);
310 uint32_t last_seen_parent_id = 0;
311 FF cached_parent_id_inv = 0;
316 uint32_t dying_context_id = 0;
317 FF dying_context_id_inv = 0;
318 bool is_first_event_in_enqueued_call =
true;
319 bool prev_row_was_enter_call =
false;
321 for (
const auto& ex_event : ex_events) {
324 if (
discard == 0 && is_first_event_in_enqueued_call &&
325 is_phase_discarded(ex_event.after_context_event.phase, failures)) {
327 dying_context_id = dying_context_for_phase(ex_event.after_context_event.phase, failures);
328 dying_context_id_inv =
FF(dying_context_id).invert();
332 bool has_parent = ex_event.after_context_event.parent_id != 0;
333 if (last_seen_parent_id != ex_event.after_context_event.parent_id) {
334 last_seen_parent_id = ex_event.after_context_event.parent_id;
335 cached_parent_id_inv = has_parent ?
FF(ex_event.after_context_event.parent_id).invert() : 0;
345 { C::execution_sel, 1 },
348 { C::execution_enqueued_call_start, is_first_event_in_enqueued_call ? 1 : 0 },
350 { C::execution_context_id, ex_event.after_context_event.id },
351 { C::execution_parent_id, ex_event.after_context_event.parent_id },
352 { C::execution_pc, ex_event.before_context_event.pc },
353 { C::execution_msg_sender, ex_event.after_context_event.msg_sender },
354 { C::execution_contract_address, ex_event.after_context_event.contract_addr },
355 { C::execution_transaction_fee, ex_event.after_context_event.transaction_fee },
356 { C::execution_is_static, ex_event.after_context_event.is_static },
357 { C::execution_parent_calldata_addr, ex_event.after_context_event.parent_cd_addr },
358 { C::execution_parent_calldata_size, ex_event.after_context_event.parent_cd_size },
359 { C::execution_last_child_returndata_addr, ex_event.after_context_event.last_child_rd_addr },
360 { C::execution_last_child_returndata_size, ex_event.after_context_event.last_child_rd_size },
361 { C::execution_last_child_success, ex_event.after_context_event.last_child_success },
362 { C::execution_last_child_id, ex_event.after_context_event.last_child_id },
363 { C::execution_l2_gas_limit, ex_event.after_context_event.gas_limit.l2Gas },
364 { C::execution_da_gas_limit, ex_event.after_context_event.gas_limit.daGas },
365 { C::execution_l2_gas_used, ex_event.after_context_event.gas_used.l2Gas },
366 { C::execution_da_gas_used, ex_event.after_context_event.gas_used.daGas },
367 { C::execution_parent_l2_gas_limit, ex_event.after_context_event.parent_gas_limit.l2Gas },
368 { C::execution_parent_da_gas_limit, ex_event.after_context_event.parent_gas_limit.daGas },
369 { C::execution_parent_l2_gas_used, ex_event.after_context_event.parent_gas_used.l2Gas },
370 { C::execution_parent_da_gas_used, ex_event.after_context_event.parent_gas_used.daGas },
371 { C::execution_next_context_id, ex_event.next_context_id },
373 { C::execution_prev_l2_gas_used, ex_event.before_context_event.gas_used.l2Gas },
374 { C::execution_prev_da_gas_used, ex_event.before_context_event.gas_used.daGas },
377 { C::execution_prev_written_public_data_slots_tree_root,
378 ex_event.before_context_event.written_public_data_slots_tree_snapshot.root },
379 { C::execution_prev_written_public_data_slots_tree_size,
380 ex_event.before_context_event.written_public_data_slots_tree_snapshot.nextAvailableLeafIndex },
381 { C::execution_written_public_data_slots_tree_root,
382 ex_event.after_context_event.written_public_data_slots_tree_snapshot.root },
383 { C::execution_written_public_data_slots_tree_size,
384 ex_event.after_context_event.written_public_data_slots_tree_snapshot.nextAvailableLeafIndex },
385 { C::execution_prev_public_data_tree_root,
386 ex_event.before_context_event.tree_states.publicDataTree.tree.root },
387 { C::execution_prev_public_data_tree_size,
388 ex_event.before_context_event.tree_states.publicDataTree.tree.nextAvailableLeafIndex },
390 { C::execution_prev_nullifier_tree_root,
391 ex_event.before_context_event.tree_states.nullifierTree.tree.root },
392 { C::execution_prev_nullifier_tree_size,
393 ex_event.before_context_event.tree_states.nullifierTree.tree.nextAvailableLeafIndex },
394 { C::execution_prev_num_nullifiers_emitted,
395 ex_event.before_context_event.tree_states.nullifierTree.counter },
396 { C::execution_nullifier_tree_root, ex_event.after_context_event.tree_states.nullifierTree.tree.root },
397 { C::execution_nullifier_tree_size,
398 ex_event.after_context_event.tree_states.nullifierTree.tree.nextAvailableLeafIndex },
399 { C::execution_num_nullifiers_emitted, ex_event.after_context_event.tree_states.nullifierTree.counter },
401 { C::execution_public_data_tree_root,
402 ex_event.after_context_event.tree_states.publicDataTree.tree.root },
403 { C::execution_public_data_tree_size,
404 ex_event.after_context_event.tree_states.publicDataTree.tree.nextAvailableLeafIndex },
406 { C::execution_prev_note_hash_tree_root,
407 ex_event.before_context_event.tree_states.noteHashTree.tree.root },
408 { C::execution_prev_note_hash_tree_size,
409 ex_event.before_context_event.tree_states.noteHashTree.tree.nextAvailableLeafIndex },
410 { C::execution_prev_num_note_hashes_emitted,
411 ex_event.before_context_event.tree_states.noteHashTree.counter },
412 { C::execution_note_hash_tree_root, ex_event.after_context_event.tree_states.noteHashTree.tree.root },
413 { C::execution_note_hash_tree_size,
414 ex_event.after_context_event.tree_states.noteHashTree.tree.nextAvailableLeafIndex },
415 { C::execution_num_note_hashes_emitted, ex_event.after_context_event.tree_states.noteHashTree.counter },
417 { C::execution_l1_l2_tree_root, ex_event.after_context_event.tree_states.l1ToL2MessageTree.tree.root },
419 { C::execution_prev_num_unencrypted_logs,
420 ex_event.before_context_event.side_effect_states.numUnencryptedLogs },
421 { C::execution_num_unencrypted_logs,
422 ex_event.after_context_event.side_effect_states.numUnencryptedLogs },
423 { C::execution_prev_num_l2_to_l1_messages,
424 ex_event.before_context_event.side_effect_states.numL2ToL1Messages },
425 { C::execution_num_l2_to_l1_messages,
426 ex_event.after_context_event.side_effect_states.numL2ToL1Messages },
428 { C::execution_bytecode_id, ex_event.before_context_event.bytecode_id },
430 { C::execution_has_parent_ctx, has_parent ? 1 : 0 },
431 { C::execution_is_parent_id_inv, cached_parent_id_inv },
437 { C::execution_internal_call_id, ex_event.before_context_event.internal_call_id },
438 { C::execution_internal_call_return_id, ex_event.before_context_event.internal_call_return_id },
439 { C::execution_next_internal_call_id, ex_event.before_context_event.next_internal_call_id },
446 bool bytecode_retrieval_failed = ex_event.error == ExecutionError::BYTECODE_NOT_FOUND;
449 { C::execution_sel_bytecode_retrieval_failure, bytecode_retrieval_failed ? 1 : 0 },
450 { C::execution_sel_bytecode_retrieval_success, !bytecode_retrieval_failed ? 1 : 0 },
451 { C::execution_bytecode_id, ex_event.before_context_event.bytecode_id },
460 bool process_instruction_fetching = !bytecode_retrieval_failed;
461 bool instruction_fetching_failed = ex_event.error == ExecutionError::INSTRUCTION_FETCHING;
462 trace.set(C::execution_sel_instruction_fetching_failure, row, instruction_fetching_failed ? 1 : 0);
463 if (process_instruction_fetching && !instruction_fetching_failed) {
464 exec_opcode = ex_event.wire_instruction.get_exec_opcode();
469 { C::execution_next_pc,
470 ex_event.before_context_event.pc + ex_event.wire_instruction.size_in_bytes() },
479 bool should_read_exec_spec = process_instruction_fetching && !instruction_fetching_failed;
480 if (should_read_exec_spec) {
484 bool should_resolve_address = should_read_exec_spec;
486 if (should_resolve_address) {
489 bool addressing_failed = ex_event.error == ExecutionError::ADDRESSING;
498 bool should_process_registers = should_resolve_address && !addressing_failed;
499 bool register_processing_failed = ex_event.error == ExecutionError::REGISTER_READ;
500 if (should_process_registers) {
508 bool should_check_gas = should_process_registers && !register_processing_failed;
509 bool oog = ex_event.error == ExecutionError::GAS;
510 trace.set(C::execution_sel_should_check_gas, row, should_check_gas ? 1 : 0);
511 if (should_check_gas) {
516 uint32_t radix = ex_event.inputs[1].as<uint32_t>();
517 uint32_t num_limbs = ex_event.inputs[2].as<uint32_t>();
518 uint32_t num_p_limbs = radix > 256 ? 32 :
static_cast<uint32_t
>(
get_p_limbs_per_radix()[radix].size());
522 { C::execution_two_five_six, 256 },
523 { C::execution_sel_radix_gt_256, radix > 256 ? 1 : 0 },
524 { C::execution_sel_lookup_num_p_limbs, radix <= 256 ? 1 : 0 },
525 { C::execution_num_p_limbs, num_p_limbs },
526 { C::execution_sel_use_num_limbs, num_limbs > num_p_limbs ? 1 : 0 },
530 trace.set(C::execution_dynamic_da_gas_factor, row,
registers[1].as<uint32_t>());
544 bool should_execute_opcode = should_check_gas && !oog;
545 bool should_execute_call =
547 bool should_execute_static_call =
549 bool should_execute_return =
551 bool should_execute_revert =
554 bool is_err = ex_event.error != ExecutionError::NONE;
555 bool is_failure = should_execute_revert || is_err;
556 bool sel_enter_call = should_execute_call || should_execute_static_call;
558 bool sel_exit_call = should_execute_return || should_execute_revert || is_err;
565 { C::execution_sel_execute_return, should_execute_return ? 1 : 0 },
566 { C::execution_sel_execute_revert, should_execute_revert ? 1 : 0 },
567 { C::execution_sel_exit_call, sel_exit_call ? 1 : 0 },
568 { C::execution_nested_return, should_execute_return && has_parent ? 1 : 0 },
570 { C::execution_enqueued_call_end, !has_parent ? 1 : 0 },
571 { C::execution_nested_exit_call, has_parent ? 1 : 0 },
575 bool opcode_execution_failed = ex_event.error == ExecutionError::OPCODE_EXECUTION;
576 if (should_execute_opcode) {
581 { C::execution_sel_should_execute_opcode, 1 },
582 { C::execution_sel_opcode_error, opcode_execution_failed ? 1 : 0 },
588 trace.set(get_execution_opcode_selector(*exec_opcode), row, 1);
592 if (sel_enter_call) {
593 Gas gas_left = ex_event.after_context_event.gas_limit - ex_event.after_context_event.gas_used;
595 uint32_t allocated_l2_gas =
registers[0].as<uint32_t>();
596 bool is_l2_gas_allocated_lt_left = allocated_l2_gas < gas_left.
l2Gas;
597 uint32_t allocated_left_l2_cmp_diff = is_l2_gas_allocated_lt_left
598 ? gas_left.
l2Gas - allocated_l2_gas - 1
599 : allocated_l2_gas - gas_left.
l2Gas;
601 uint32_t allocated_da_gas =
registers[1].as<uint32_t>();
602 bool is_da_gas_allocated_lt_left = allocated_da_gas < gas_left.
daGas;
603 uint32_t allocated_left_da_cmp_diff = is_da_gas_allocated_lt_left
604 ? gas_left.
daGas - allocated_da_gas - 1
605 : allocated_da_gas - gas_left.
daGas;
609 { C::execution_sel_enter_call, sel_enter_call ? 1 : 0 },
610 { C::execution_sel_execute_call, should_execute_call ? 1 : 0 },
611 { C::execution_sel_execute_static_call, should_execute_static_call ? 1 : 0 },
612 { C::execution_constant_32, 32 },
613 { C::execution_call_is_l2_gas_allocated_lt_left, is_l2_gas_allocated_lt_left },
614 { C::execution_call_allocated_left_l2_cmp_diff, allocated_left_l2_cmp_diff },
615 { C::execution_call_is_da_gas_allocated_lt_left, is_da_gas_allocated_lt_left },
616 { C::execution_call_allocated_left_da_cmp_diff, allocated_left_da_cmp_diff },
624 assert(ex_event.addressing_event.resolution_info.size() == 2 &&
625 "GETENVVAR should have exactly two resolved operands (envvar enum and output)");
627 TaggedValue envvar_enum = ex_event.addressing_event.resolution_info[1].resolved_operand;
630 trace.set(C::execution_internal_call_return_id_inv,
632 ex_event.before_context_event.internal_call_return_id != 0
633 ?
FF(ex_event.before_context_event.internal_call_return_id).invert()
637 ex_event.before_context_event.tree_states.publicDataTree.counter;
641 { C::execution_max_data_writes_reached, remaining_data_writes == 0 },
642 { C::execution_remaining_data_writes_inv,
643 remaining_data_writes == 0 ? 0 :
FF(remaining_data_writes).invert() },
644 { C::execution_sel_write_public_data, !opcode_execution_failed },
647 uint64_t leaf_index =
registers[1].as<uint64_t>();
649 bool note_hash_leaf_in_range = leaf_index < note_hash_tree_leaf_count;
653 { C::execution_note_hash_leaf_in_range, note_hash_leaf_in_range },
654 { C::execution_note_hash_tree_leaf_count,
FF(note_hash_tree_leaf_count) },
657 uint32_t remaining_note_hashes =
662 { C::execution_sel_reached_max_note_hashes, remaining_note_hashes == 0 },
663 { C::execution_remaining_note_hashes_inv,
664 remaining_note_hashes == 0 ? 0 :
FF(remaining_note_hashes).invert() },
665 { C::execution_sel_write_note_hash, !opcode_execution_failed },
668 uint64_t leaf_index =
registers[1].as<uint64_t>();
670 bool l1_to_l2_msg_leaf_in_range = leaf_index < l1_to_l2_msg_tree_leaf_count;
674 { C::execution_l1_to_l2_msg_leaf_in_range, l1_to_l2_msg_leaf_in_range },
675 { C::execution_l1_to_l2_msg_tree_leaf_count,
FF(l1_to_l2_msg_tree_leaf_count) },
680 uint32_t remaining_nullifiers =
685 { C::execution_sel_reached_max_nullifiers, remaining_nullifiers == 0 },
686 { C::execution_remaining_nullifiers_inv,
687 remaining_nullifiers == 0 ? 0 :
FF(remaining_nullifiers).invert() },
688 { C::execution_sel_write_nullifier,
689 remaining_nullifiers != 0 && !ex_event.before_context_event.is_static },
692 uint32_t remaining_l2_to_l1_msgs =
696 { { { C::execution_sel_l2_to_l1_msg_limit_error, remaining_l2_to_l1_msgs == 0 },
697 { C::execution_remaining_l2_to_l1_msgs_inv,
698 remaining_l2_to_l1_msgs == 0 ? 0 :
FF(remaining_l2_to_l1_msgs).invert() },
699 { C::execution_sel_write_l2_to_l1_msg, !opcode_execution_failed && !
discard },
701 C::execution_public_inputs_index,
703 ex_event.before_context_event.side_effect_states.numL2ToL1Messages,
712 bool should_process_register_write = should_execute_opcode && !opcode_execution_failed;
713 if (should_process_register_write) {
721 bool is_dying_context =
discard == 1 && (ex_event.after_context_event.id == dying_context_id);
724 FF dying_context_diff_inv = 0;
725 if (!is_dying_context) {
727 FF diff =
FF(ex_event.after_context_event.id) -
FF(dying_context_id);
728 if (!diff.is_zero()) {
729 dying_context_diff_inv = diff.invert();
734 bool sel_first_row_in_context = prev_row_was_enter_call || is_first_event_in_enqueued_call;
736 bool enqueued_call_end = sel_exit_call && !has_parent;
737 bool resolves_dying_context = is_failure && is_dying_context;
738 bool nested_call_rom_undiscarded_context = sel_enter_call &&
discard == 0;
739 bool propagate_discard = !enqueued_call_end && !resolves_dying_context && !nested_call_rom_undiscarded_context;
743 bool rollback_context = (should_execute_revert || is_err) && has_parent;
750 { C::execution_sel_exit_call, sel_exit_call ? 1 : 0 },
751 { C::execution_rollback_context, rollback_context ? 1 : 0 },
752 { C::execution_sel_error, is_err ? 1 : 0 },
753 { C::execution_sel_failure, is_failure ? 1 : 0 },
754 { C::execution_discard,
discard },
755 { C::execution_dying_context_id, dying_context_id },
756 { C::execution_dying_context_id_inv, dying_context_id_inv },
757 { C::execution_is_dying_context, is_dying_context ? 1 : 0 },
758 { C::execution_dying_context_diff_inv, dying_context_diff_inv },
759 { C::execution_enqueued_call_end, enqueued_call_end ? 1 : 0 },
760 { C::execution_sel_first_row_in_context, sel_first_row_in_context ? 1 : 0 },
761 { C::execution_resolves_dying_context, resolves_dying_context ? 1 : 0 },
762 { C::execution_nested_call_from_undiscarded_context, nested_call_rom_undiscarded_context ? 1 : 0 },
763 { C::execution_propagate_discard, propagate_discard ? 1 : 0 },
768 bool event_kills_dying_context =
769 discard == 1 && is_failure && ex_event.after_context_event.id == dying_context_id;
771 if (event_kills_dying_context) {
773 dying_context_id = 0;
774 dying_context_id_inv = 0;
776 }
else if (sel_enter_call &&
discard == 0 && !is_err &&
777 failures.does_context_fail.contains(ex_event.next_context_id)) {
782 dying_context_id = ex_event.next_context_id;
783 dying_context_id_inv =
FF(dying_context_id).invert();
792 is_first_event_in_enqueued_call = ex_event.after_context_event.parent_id == 0 && sel_exit_call;
795 prev_row_was_enter_call = sel_enter_call;
800 if (!ex_events.empty()) {
801 trace.set(C::execution_last, row - 1, 1);