29class RegisterValidationException :
public std::runtime_error {
31 RegisterValidationException(
const std::string& message)
32 :
std::runtime_error(message)
36class OpcodeExecutionException :
public std::runtime_error {
38 OpcodeExecutionException(
const std::string& message)
39 :
std::runtime_error(message)
60 throw OpcodeExecutionException(
"Alu add operation failed");
79 throw OpcodeExecutionException(
"Alu sub operation failed");
98 throw OpcodeExecutionException(
"Alu mul operation failed");
117 throw OpcodeExecutionException(
"Alu div operation failed");
136 throw OpcodeExecutionException(
"Alu fdiv operation failed");
155 throw OpcodeExecutionException(
"Alu eq operation failed");
174 throw OpcodeExecutionException(
"Alu lt operation failed");
193 throw OpcodeExecutionException(
"Alu lte operation failed");
211 throw OpcodeExecutionException(
"Alu not operation failed");
230 throw OpcodeExecutionException(
"SHL Exception: " + std::string(e.what()));
249 throw OpcodeExecutionException(
"SHR Exception: " + std::string(e.what()));
257 auto val =
memory.get(src_addr);
278 result = TaggedValue::from<FF>(
context.get_address());
281 result = TaggedValue::from<FF>(
context.get_msg_sender());
284 result = TaggedValue::from<FF>(
context.get_transaction_fee());
287 result = TaggedValue::from<FF>(
context.get_globals().chainId);
290 result = TaggedValue::from<FF>(
context.get_globals().version);
293 result = TaggedValue::from<uint32_t>(
context.get_globals().blockNumber);
296 result = TaggedValue::from<uint64_t>(
context.get_globals().timestamp);
299 result = TaggedValue::from<uint128_t>(
context.get_globals().gasFees.feePerL2Gas);
302 result = TaggedValue::from<uint128_t>(
context.get_globals().gasFees.feePerDaGas);
305 result = TaggedValue::from<uint1_t>(
context.get_is_static() ? 1 : 0);
308 result = TaggedValue::from<uint32_t>(
context.gas_left().l2Gas);
311 result = TaggedValue::from<uint32_t>(
context.gas_left().daGas);
314 throw OpcodeExecutionException(
"Invalid environment variable enum value");
336 auto v =
memory.get(src_addr);
356 const auto& allocated_l2_gas_read =
memory.get(l2_gas_offset);
357 const auto& allocated_da_gas_read =
memory.get(da_gas_offset);
360 const auto& cd_size =
memory.get(cd_size_offset);
366 Gas{ allocated_l2_gas_read.as<uint32_t>(), allocated_da_gas_read.as<uint32_t>() });
374 cd_size.as<uint32_t>(),
377 context.get_side_effect_states(),
395 const auto& allocated_l2_gas_read =
memory.get(l2_gas_offset);
396 const auto& allocated_da_gas_read =
memory.get(da_gas_offset);
399 const auto& cd_size =
memory.get(cd_size_offset);
405 Gas{ allocated_l2_gas_read.as<uint32_t>(), allocated_da_gas_read.as<uint32_t>() });
413 cd_size.as<uint32_t>(),
416 context.get_side_effect_states(),
430 auto cd_copy_size =
memory.get(cd_size_offset);
438 }
catch (
const std::exception& e) {
439 throw OpcodeExecutionException(
"cd copy failed: " + std::string(e.what()));
450 auto rd_copy_size =
memory.get(rd_size_offset);
451 auto rd_offset_read =
memory.get(rd_offset);
458 }
catch (
const std::exception& e) {
459 throw OpcodeExecutionException(
"rd copy failed: " + std::string(e.what()));
486 .rd_size =
rd_size.as<uint32_t>(),
487 .gas_used =
context.get_gas_used(),
488 .side_effect_states =
context.get_side_effect_states(),
498 auto rev_size =
memory.get(rev_size_offset);
504 .rd_size = rev_size.as<uint32_t>(),
505 .gas_used =
context.get_gas_used(),
506 .side_effect_states =
context.get_side_effect_states(),
524 auto resolved_cond =
memory.get(cond_addr);
538 auto& internal_call_stack_manager =
context.get_internal_call_stack_manager();
540 internal_call_stack_manager.push(
context.get_next_pc());
548 auto& internal_call_stack_manager =
context.get_internal_call_stack_manager();
550 auto next_pc = internal_call_stack_manager.pop();
552 }
catch (
const std::exception& e) {
554 throw OpcodeExecutionException(
"Internal return failed: " + std::string(e.what()));
565 throw OpcodeExecutionException(
"Keccak permutation failed: " + std::string(e.what()));
573 uint16_t message_size,
574 bool is_debug_logging_enabled)
582 if (is_debug_logging_enabled) {
587 const auto fields_size_value =
memory.get(fields_size_offset);
588 const uint32_t fields_size = fields_size_value.as<uint32_t>();
591 std::string message_as_str;
593 for (uint32_t i = 0; i < truncated_message_size; ++i) {
594 const auto message_field =
memory.get(message_offset + i);
595 message_as_str +=
static_cast<char>(
static_cast<uint8_t
>(message_field.as_ff()));
597 message_as_str +=
": [";
600 for (uint32_t i = 0; i < fields_size; ++i) {
603 if (i < fields_size - 1) {
604 message_as_str +=
", ";
607 message_as_str +=
"]";
609 debug(
"DEBUGLOG: ", message_as_str);
610 }
catch (
const std::exception& e) {
611 debug(
"DEBUGLOG: Error: ", e.what());
645 throw OpcodeExecutionException(
"Bitwise AND Exeception");
666 throw OpcodeExecutionException(
"Bitwise OR Exception");
687 throw OpcodeExecutionException(
"Bitwise XOR Exception");
719 uint32_t da_gas_factor =
static_cast<uint32_t
>(!was_slot_written_before);
723 throw OpcodeExecutionException(
"SSTORE: Cannot write to storage in static context");
726 if (!was_slot_written_before &&
728 throw OpcodeExecutionException(
"SSTORE: Maximum number of data writes reached");
742 auto unique_note_hash =
memory.get(unique_note_hash_addr);
743 auto leaf_index =
memory.get(leaf_index_addr);
748 uint64_t leaf_index_value = leaf_index.as<uint64_t>();
754 if (index_in_range) {
757 value = MemoryValue::from<uint1_t>(0);
773 auto address =
memory.get(address_offset);
785 memory.set(exists_offset, result);
800 throw OpcodeExecutionException(
"EMITNULLIFIER: Cannot emit nullifier in static context");
804 throw OpcodeExecutionException(
"EMITNULLIFIER: Maximum number of nullifiers reached");
811 throw OpcodeExecutionException(
"EMITNULLIFIER: Nullifier collision");
824 auto address_value =
memory.get(address_offset);
835 throw OpcodeExecutionException(
"GetContractInstance Exception");
846 auto note_hash =
memory.get(note_hash_addr);
852 throw OpcodeExecutionException(
"EMITNOTEHASH: Cannot emit note hash in static context");
856 throw OpcodeExecutionException(
"EMITNOTEHASH: Maximum number of note hashes reached");
870 auto msg_hash =
memory.get(msg_hash_addr);
871 auto leaf_index =
memory.get(leaf_index_addr);
876 uint64_t leaf_index_value = leaf_index.as<uint64_t>();
882 if (index_in_range) {
885 value = MemoryValue::from<uint1_t>(0);
898 throw OpcodeExecutionException(
"Poseidon2 permutation failed: " + std::string(e.what()));
934 throw OpcodeExecutionException(
"Embedded curve add failed: " + std::string(e.what()));
968 uint32_t radix_value = radix.
as<uint32_t>();
986 num_limbs.
as<uint32_t>(),
990 throw OpcodeExecutionException(
"ToRadixBe gadget failed: " + std::string(e.what()));
999 auto first_field =
memory.get(log_offset);
1000 auto log_size =
memory.get(log_size_offset);
1002 uint32_t log_size_int = log_size.as<uint32_t>();
1011 throw OpcodeExecutionException(
"EmitUnencryptedLog Exception");
1020 auto recipient =
memory.get(recipient_addr);
1021 auto content =
memory.get(content_addr);
1026 auto side_effects_states_before =
context.get_side_effect_states();
1028 if (
context.get_is_static()) {
1029 throw OpcodeExecutionException(
"SENDL2TOL1MSG: Cannot send L2 to L1 message in static context");
1033 throw OpcodeExecutionException(
"SENDL2TOL1MSG: Maximum number of L2 to L1 messages reached");
1039 side_effects_states_before.numL2ToL1Messages++;
1040 context.set_side_effect_states(side_effects_states_before);
1051 sha256.compression(
context.get_memory(), state_addr, input_addr, output_addr);
1053 throw OpcodeExecutionException(
"Sha256 Compression failed: " + std::string(e.what()));
1082 context.get_bytecode_manager().get_bytecode_id();
1106 vinfo(
"Bytecode not found: ", e.what());
1110 vinfo(
"Instruction fetching error: ", e.what());
1114 vinfo(
"Addressing exception: ", e.what());
1117 }
catch (
const RegisterValidationException& e) {
1118 vinfo(
"Register validation exception: ", e.what());
1122 vinfo(
"Out of gas exception: ", e.what());
1125 }
catch (
const OpcodeExecutionException& e) {
1126 vinfo(
"Opcode execution exception: ", e.what());
1129 }
catch (
const std::exception& e) {
1132 info(
"An unhandled exception occurred: ", e.what());
1164 .entered_context_id = child_context->get_context_id(),
1201 parent_context.set_last_rd_addr(result.
rd_offset);
1202 parent_context.set_last_rd_size(result.
rd_size);
1203 parent_context.set_last_success(result.
success);
1205 parent_context.set_gas_used(result.
gas_used + parent_context.get_gas_used());
1209 parent_context.set_child_context(
std::move(child_context));
1213 throw std::runtime_error(
format(
"Checkpoint id mismatch: ",
1214 parent_context.get_checkpoint_id_at_creation(),
1217 " (gone back to the wrong db/context)"));
1230 .gas_used =
context.get_gas_used(),
1231 .side_effect_states =
context.get_side_effect_states(),
1242 output = TaggedValue::from<FF>(0);
1244 debug(
"Dispatching opcode: ", opcode,
" (",
static_cast<uint32_t
>(opcode),
")");
1335 resolved_operands.at(3).as<uint16_t>(),
1391 throw std::runtime_error(
"Tried to dispatch unknown execution opcode: " +
1398template <
typename... Ts>
1401 const
std::vector<
Operand>& resolved_operands)
1403 assert(resolved_operands.size() ==
sizeof...(Ts));
1407 (this->*f)(
context,
static_cast<Ts
>(resolved_operands.at(Is).as_ff())...);
1416 assert(
inputs.size() == register_info.num_inputs());
1418 for (
size_t i = 0; i < register_info.num_inputs(); i++) {
1419 if (register_info.expected_tag(i) && register_info.expected_tag(i) != this->inputs.at(i).get_tag()) {
1420 throw RegisterValidationException(
format(
"Input ",
1424 " does not match expected tag ",
1433 (void)register_info;
1434 assert(register_info.num_outputs() == 1);
#define NOTE_HASH_TREE_LEAF_COUNT
#define L1_TO_L2_MSG_TREE_LEAF_COUNT
#define MAX_L2_TO_L1_MSGS_PER_TX
#define MAX_NOTE_HASHES_PER_TX
#define MAX_NULLIFIERS_PER_TX
#define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
virtual std::optional< BytecodeId > try_get_bytecode_id()=0
virtual const AztecAddress & get_msg_sender() const =0
virtual Gas get_parent_gas_limit() const =0
virtual uint32_t get_next_pc() const =0
virtual uint32_t get_parent_cd_size() const =0
virtual MemoryAddress get_parent_cd_addr() const =0
virtual AppendOnlyTreeSnapshot get_written_public_data_slots_tree_snapshot()=0
virtual SideEffectStates & get_side_effect_states()=0
virtual uint32_t get_parent_id() const =0
virtual bool get_is_static() const =0
virtual BytecodeManagerInterface & get_bytecode_manager()=0
virtual const AztecAddress & get_address() const =0
virtual uint32_t get_context_id() const =0
virtual Gas get_parent_gas_used() const =0
virtual uint32_t get_next_context_id() const =0
virtual std::unique_ptr< ContextInterface > make_nested_context(AztecAddress address, AztecAddress msg_sender, FF transaction_fee, ContextInterface &parent_context, MemoryAddress cd_offset_address, uint32_t cd_size, bool is_static, Gas gas_limit, SideEffectStates side_effect_states, TransactionPhase phase)=0
virtual EmbeddedCurvePoint add(const EmbeddedCurvePoint &p, const EmbeddedCurvePoint &q)=0
virtual void emit_unencrypted_log(MemoryInterface &memory, ContextInterface &context, AztecAddress contract_address, MemoryAddress log_offset, uint32_t log_size)=0
virtual std::unique_ptr< GasTrackerInterface > make_gas_tracker(GasEvent &gas_event, const Instruction &instruction, ContextInterface &context)=0
virtual std::unique_ptr< AddressingInterface > make_addressing(AddressingEvent &event)=0
void lt(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void emit_note_hash(ContextInterface &context, MemoryAddress note_hash_addr)
void mov(ContextInterface &context, MemoryAddress src_addr, MemoryAddress dst_addr)
const TaggedValue & get_output() const
void static_call(ContextInterface &context, MemoryAddress l2_gas_offset, MemoryAddress da_gas_offset, MemoryAddress addr, MemoryAddress cd_size_offset, MemoryAddress cd_offset)
EventEmitterInterface< ExecutionEvent > & events
void cd_copy(ContextInterface &context, MemoryAddress cd_size_offset, MemoryAddress cd_offset, MemoryAddress dst_addr)
std::unique_ptr< GasTrackerInterface > gas_tracker
void send_l2_to_l1_msg(ContextInterface &context, MemoryAddress recipient_addr, MemoryAddress content_addr)
void dispatch_opcode(ExecutionOpCode opcode, ContextInterface &context, const std::vector< Operand > &resolved_operands)
ExecutionComponentsProviderInterface & execution_components
void sstore(ContextInterface &context, MemoryAddress src_addr, MemoryAddress slot_addr)
void set(ContextInterface &context, MemoryAddress dst_addr, uint8_t tag, const FF &value)
void internal_return(ContextInterface &context)
void set_output(ExecutionOpCode opcode, TaggedValue output)
virtual GasTrackerInterface & get_gas_tracker()
void poseidon2_permutation(ContextInterface &context, MemoryAddress src_addr, MemoryAddress dst_addr)
void success_copy(ContextInterface &context, MemoryAddress dst_addr)
void fdiv(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void jumpi(ContextInterface &context, MemoryAddress cond_addr, uint32_t loc)
void emit_unencrypted_log(ContextInterface &context, MemoryAddress log_offset, MemoryAddress log_size_offset)
void sub(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void rd_copy(ContextInterface &context, MemoryAddress rd_size_offset, MemoryAddress rd_offset, MemoryAddress dst_addr)
void l1_to_l2_message_exists(ContextInterface &context, MemoryAddress msg_hash_addr, MemoryAddress leaf_index_addr, MemoryAddress dst_addr)
void div(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void emit_nullifier(ContextInterface &context, MemoryAddress nullifier_addr)
EventEmitterInterface< ContextStackEvent > & ctx_stack_events
void set_execution_result(ExecutionResult exec_result)
void ecc_add(ContextInterface &context, MemoryAddress p_x_addr, MemoryAddress p_y_addr, MemoryAddress p_inf_addr, MemoryAddress q_x_addr, MemoryAddress q_y_addr, MemoryAddress q_inf_addr, MemoryAddress dst_addr)
void keccak_permutation(ContextInterface &context, MemoryAddress dst_addr, MemoryAddress src_addr)
void jump(ContextInterface &context, uint32_t loc)
void sha256_compression(ContextInterface &context, MemoryAddress output_addr, MemoryAddress state_addr, MemoryAddress input_addr)
void sload(ContextInterface &context, MemoryAddress slot_addr, MemoryAddress dst_addr)
void ret(ContextInterface &context, MemoryAddress ret_size_offset, MemoryAddress ret_offset)
std::vector< TaggedValue > inputs
void internal_call(ContextInterface &context, uint32_t loc)
EccInterface & embedded_curve
void op_not(ContextInterface &context, MemoryAddress src_addr, MemoryAddress dst_addr)
void handle_exceptional_halt(ContextInterface &context)
void handle_enter_call(ContextInterface &parent_context, std::unique_ptr< ContextInterface > child_context)
void nullifier_exists(ContextInterface &context, MemoryAddress nullifier_offset, MemoryAddress address_offset, MemoryAddress exists_offset)
void note_hash_exists(ContextInterface &context, MemoryAddress unique_note_hash_addr, MemoryAddress leaf_index_addr, MemoryAddress dst_addr)
void debug_log(ContextInterface &context, MemoryAddress message_offset, MemoryAddress fields_offset, MemoryAddress fields_size_offset, uint16_t message_size, bool is_debug_logging_enabled)
ContextProviderInterface & context_provider
ExecutionResult execute(std::unique_ptr< ContextInterface > enqueued_call_context) override
void shl(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress c_addr)
void cast(ContextInterface &context, MemoryAddress src_addr, MemoryAddress dst_addr, uint8_t dst_tag)
void to_radix_be(ContextInterface &context, MemoryAddress value_addr, MemoryAddress radix_addr, MemoryAddress num_limbs_addr, MemoryAddress is_output_bits_addr, MemoryAddress dst_addr)
EmitUnencryptedLogInterface & emit_unencrypted_log_component
void eq(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void call(ContextInterface &context, MemoryAddress l2_gas_offset, MemoryAddress da_gas_offset, MemoryAddress addr, MemoryAddress cd_size_offset, MemoryAddress cd_offset)
std::stack< std::unique_ptr< ContextInterface > > external_call_stack
GreaterThanInterface & greater_than
void set_and_validate_inputs(ExecutionOpCode opcode, std::vector< TaggedValue > inputs)
void revert(ContextInterface &context, MemoryAddress rev_size_offset, MemoryAddress rev_offset)
void rd_size(ContextInterface &context, MemoryAddress dst_addr)
void mul(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void or_op(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
const std::vector< TaggedValue > & get_inputs() const
void xor_op(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void get_contract_instance(ContextInterface &context, MemoryAddress address_offset, MemoryAddress dst_offset, uint8_t member_enum)
ExecutionResult get_execution_result() const
GetContractInstanceInterface & get_contract_instance_component
void get_env_var(ContextInterface &context, MemoryAddress dst_addr, uint8_t var_enum)
void lte(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
const InstructionInfoDBInterface & instruction_info_db
HighLevelMerkleDBInterface & merkle_db
void and_op(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void shr(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress c_addr)
ExecutionIdManagerInterface & execution_id_manager
void add(ContextInterface &context, MemoryAddress a_addr, MemoryAddress b_addr, MemoryAddress dst_addr)
void call_with_operands(void(Execution::*f)(ContextInterface &, Ts...), ContextInterface &context, const std::vector< Operand > &resolved_operands)
virtual void increment_execution_id()=0
virtual void consume_gas(const Gas &dynamic_gas_factor={ 0, 0 })=0
virtual Gas compute_gas_limit_for_call(const Gas &allocated_gas)=0
virtual void get_contract_instance(MemoryInterface &memory, AztecAddress contract_address, MemoryAddress dst_offset, uint8_t member_enum)=0
virtual bool gt(const FF &a, const FF &b)=0
virtual void revert_checkpoint()=0
virtual bool note_hash_exists(uint64_t leaf_index, const FF &unique_note_hash) const =0
virtual FF storage_read(const AztecAddress &contract_address, const FF &slot) const =0
virtual uint32_t get_checkpoint_id() const =0
virtual void commit_checkpoint()=0
virtual bool was_storage_written(const AztecAddress &contract_address, const FF &slot) const =0
virtual void note_hash_write(const AztecAddress &contract_address, const FF ¬e_hash)=0
virtual bool nullifier_exists(const AztecAddress &contract_address, const FF &nullifier) const =0
virtual void storage_write(const AztecAddress &contract_address, const FF &slot, const FF &value, bool is_protocol_write)=0
virtual bool l1_to_l2_msg_exists(uint64_t leaf_index, const FF &msg_hash) const =0
virtual bool nullifier_write(const AztecAddress &contract_address, const FF &nullifier)=0
virtual TreeStates get_tree_state() const =0
virtual const ExecInstructionSpec & get(ExecutionOpCode opcode) const =0
A 1-bit unsigned integer type.
constexpr uint8_t value() const noexcept
std::string format(Args... args)
AztecAddress contract_address
const std::array< std::vector< uint8_t >, 257 > & get_p_limbs_per_radix()
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
std::string field_to_string(const FF &ff)
uint8_t get_tag_bytes(ValueTag tag)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
RegisterInfo register_info
ContextEvent after_context_event
std::vector< TaggedValue > inputs
AddressingEvent addressing_event
ContextEvent before_context_event
Instruction wire_instruction
SideEffectStates side_effect_states
General class for prime fields see Prime field documentation["field documentation"] for general imple...