Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
hybrid_execution.cpp
Go to the documentation of this file.
2
13
14namespace bb::avm2::simulation {
15
16// This context interface is a top-level enqueued one.
17// NOTE: For the moment this trace is not returning the context back.
19{
20 BB_BENCH_NAME("HybridExecution::execute");
21 call_stack_metadata_collector.notify_enter_call(enqueued_call_context->get_address(),
22 0,
23 make_calldata_provider(*enqueued_call_context),
24 enqueued_call_context->get_is_static(),
25 enqueued_call_context->get_gas_limit());
26 external_call_stack.push(std::move(enqueued_call_context));
27
28 while (!external_call_stack.empty()) {
29 // Throws CancelledException if cancelled. No-op when cancellation_token_ is nullptr (non-NAPI paths).
31 cancellation_token_->check_and_throw();
32 }
33
34 // We fix the context at this point. Even if the opcode changes the stack
35 // we'll always use this in the loop.
36 auto& context = *external_call_stack.top();
37
38 try {
39 auto pc = context.get_pc();
40
42
43 // We try to get the bytecode id. This can throw if the contract is not deployed or if we have retrieved too
44 // many unique class ids. Note: bytecode_id is tracked in context events, not in the top-level execution
45 // event. It is already included in the before_context_event (defaulting to 0 on error/not-found).
46 context.get_bytecode_manager().get_bytecode_id();
47
49
50 // We try to fetch an instruction.
51 Instruction instruction = context.get_bytecode_manager().read_instruction(pc);
52
53 debug("@", pc, " ", instruction.to_string());
54 context.set_next_pc(pc + static_cast<uint32_t>(instruction.size_in_bytes()));
55
57
58 // Resolve the operands.
59 AddressingEvent addressing_event; // FIXME(fcarreiro): shouldn't need this.
60 auto addressing = execution_components.make_addressing(addressing_event);
61 std::vector<Operand> resolved_operands = addressing->resolve(instruction, context.get_memory());
62
64 GasEvent gas_event; // FIXME(fcarreiro): shouldn't need this.
66 dispatch_opcode(instruction.get_exec_opcode(), context, resolved_operands);
67 }
68 // TODO(fcarreiro): handle this in a better way.
69 catch (const BytecodeRetrievalError& e) {
70 vinfo("Bytecode retrieval error:: ", e.what());
72 } catch (const InstructionFetchingError& e) {
73 vinfo("Instruction fetching error: ", e.what());
75 } catch (const AddressingException& e) {
76 vinfo("Addressing exception: ", e.what());
78 } catch (const RegisterValidationException& e) {
79 vinfo("Register validation exception: ", e.what());
81 } catch (const OutOfGasException& e) {
82 vinfo("Out of gas exception: ", e.what());
84 } catch (const OpcodeExecutionException& e) {
85 vinfo("Opcode execution exception: ", e.what());
87 } catch (const std::exception& e) {
88 // This is a coding error, we should not get here.
89 // All exceptions should fall in the above catch blocks.
90 important("An unhandled exception occurred: ", e.what());
91 throw;
92 }
93
94 // We always do what follows. "Finally".
95 // Move on to the next pc.
96 context.set_pc(context.get_next_pc());
98
99 // If the context has halted, we need to exit the external call.
100 // The external call stack is expected to be popped.
101 if (context.halted()) {
103 }
104 }
105
107 return {
108 .success = result.success,
109 .gas_used = result.gas_used,
110 };
111}
112
113} // namespace bb::avm2::simulation
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:219
virtual void notify_enter_call(const AztecAddress &contract_address, uint32_t caller_pc, const CalldataProvider &calldata_provider, bool is_static_call, const Gas &gas_limit)=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
std::unique_ptr< GasTrackerInterface > gas_tracker
void dispatch_opcode(ExecutionOpCode opcode, ContextInterface &context, const std::vector< Operand > &resolved_operands)
Dispatch an opcode. This is the main function that dispatches the opcode to the appropriate handler.
ExecutionComponentsProviderInterface & execution_components
CallStackMetadataCollectorInterface & call_stack_metadata_collector
const ExecutionResult & get_execution_result() const
CancellationTokenPtr cancellation_token_
void handle_exceptional_halt(ContextInterface &context, const std::string &halting_message)
Handle the exceptional halt of a context. This is called when an exception is thrown during the execu...
std::stack< std::unique_ptr< ContextInterface > > external_call_stack
void handle_exit_call()
Handle the exiting of a call. This is called when a call returns or reverts.
ExecutionIdManagerInterface & execution_id_manager
EnqueuedCallResult execute(std::unique_ptr< ContextInterface > enqueued_call_context) override
Execute a top-level enqueued call.
#define vinfo(...)
Definition log.hpp:94
#define debug(...)
Definition log.hpp:76
void important(Args... args)
Definition log.hpp:104
GasEvent gas_event
Instruction instruction
CalldataProvider make_calldata_provider(const ContextInterface &context)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13