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 // We fix the context at this point. Even if the opcode changes the stack
30 // we'll always use this in the loop.
31 auto& context = *external_call_stack.top();
32
33 try {
34 auto pc = context.get_pc();
35
37
38 // We try to get the bytecode id. This can throw if the contract is not deployed or if we have retrieved too
39 // many unique class ids. Note: bytecode_id is tracked in context events, not in the top-level execution
40 // event. It is already included in the before_context_event (defaulting to 0 on error/not-found).
41 context.get_bytecode_manager().get_bytecode_id();
42
44
45 // We try to fetch an instruction.
46 Instruction instruction = context.get_bytecode_manager().read_instruction(pc);
47
48 debug("@", pc, " ", instruction.to_string());
49 context.set_next_pc(pc + static_cast<uint32_t>(instruction.size_in_bytes()));
50
52
53 // Resolve the operands.
54 AddressingEvent addressing_event; // FIXME(fcarreiro): shouldn't need this.
55 auto addressing = execution_components.make_addressing(addressing_event);
56 std::vector<Operand> resolved_operands = addressing->resolve(instruction, context.get_memory());
57
59 GasEvent gas_event; // FIXME(fcarreiro): shouldn't need this.
61 dispatch_opcode(instruction.get_exec_opcode(), context, resolved_operands);
62 }
63 // TODO(fcarreiro): handle this in a better way.
64 catch (const BytecodeRetrievalError& e) {
65 vinfo("Bytecode retrieval error:: ", e.what());
67 } catch (const InstructionFetchingError& e) {
68 vinfo("Instruction fetching error: ", e.what());
70 } catch (const AddressingException& e) {
71 vinfo("Addressing exception: ", e.what());
73 } catch (const RegisterValidationException& e) {
74 vinfo("Register validation exception: ", e.what());
76 } catch (const OutOfGasException& e) {
77 vinfo("Out of gas exception: ", e.what());
79 } catch (const OpcodeExecutionException& e) {
80 vinfo("Opcode execution exception: ", e.what());
82 } catch (const std::exception& e) {
83 // This is a coding error, we should not get here.
84 // All exceptions should fall in the above catch blocks.
85 info("An unhandled exception occurred: ", e.what());
86 throw e;
87 }
88
89 // We always do what follows. "Finally".
90 // Move on to the next pc.
91 context.set_pc(context.get_next_pc());
93
94 // If the context has halted, we need to exit the external call.
95 // The external call stack is expected to be popped.
96 if (context.halted()) {
98 }
99 }
100
102 return {
103 .success = result.success,
104 .gas_used = result.gas_used,
105 };
106}
107
108} // 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
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:80
#define debug(...)
Definition log.hpp:62
void info(Args... args)
Definition log.hpp:75
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