Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
call_stack_metadata_collector.cpp
Go to the documentation of this file.
2
7
8namespace bb::avm2::simulation {
9
14
16{
17 // Check call stack depth limit (size - 1 because we have a dummy root).
19 return true;
20 }
21 // Check total call stack items limit.
23 return true;
24 }
25 return false;
26}
27
29 uint32_t caller_pc,
30 const CalldataProvider& calldata_provider,
31 bool is_static_call,
32 const Gas& gas_limit)
33{
34 BB_ASSERT(!call_stack_metadata.empty(), "Call stack metadata is empty");
35
36 // Check if we should stop collecting due to limits.
38 return;
39 }
40
41 call_stack_metadata.top().num_nested_calls++;
43
44 // Use configured limit or default.
45 uint32_t max_calldata_size = limits.max_calldata_size_in_fields > 0 ? limits.max_calldata_size_in_fields : 1024;
46 std::vector<FF> calldata = calldata_provider(max_calldata_size);
47
49 .timestamp = timestamp++,
50 .phase = current_phase,
51 .contract_address = contract_address,
52 .caller_pc = caller_pc,
53 .calldata = calldata,
54 .is_static_call = is_static_call,
55 .gas_limit = gas_limit,
56 // To be filled in by the exit call or further nested calls.
57 .reverted = false,
58 .nested = {},
59 .internal_call_stack_at_exit = {},
60 .num_nested_calls = 0,
61 });
62}
63
65 uint32_t pc,
66 const std::optional<std::string>& halting_message,
67 const ReturnDataProvider& return_data_provider,
68 const InternalCallStackProvider& internal_call_stack_provider)
69{
70 // If we only have the dummy root, we skipped collection for this call.
71 if (call_stack_metadata.size() <= 1) {
72 return;
73 }
74
75 // Use configured limit or default.
76 uint32_t max_return_data_size =
78 std::vector<FF> return_data = return_data_provider(max_return_data_size);
79 std::vector<PC> internal_call_stack = internal_call_stack_provider();
80 internal_call_stack.push_back(pc);
81
82 CallStackMetadata top_call_stack_metadata = call_stack_metadata.top();
83 top_call_stack_metadata.reverted = !success;
84 top_call_stack_metadata.halting_message = std::move(halting_message);
85 top_call_stack_metadata.output = std::move(return_data);
87
88 // While exiting, we will move the top call of the stack to the nested vector of the parent call.
89 BB_ASSERT_GT(call_stack_metadata.size(), static_cast<size_t>(1), "Call stack metadata size is not greater than 1");
91 call_stack_metadata.top().nested.push_back(std::move(top_call_stack_metadata));
92}
93
94void CallStackMetadataCollector::notify_tx_revert(const std::string& revert_message)
95{
96 // Create a synthetic CallStackMetadata entry to capture the revert reason.
97 // This is used when a tx-level revert happens outside of an enqueued call
98 // (e.g., during revertible insertions from private).
99 BB_ASSERT_EQ(call_stack_metadata.size(), static_cast<size_t>(1), "Call stack metadata size is not equal to 1");
100 call_stack_metadata.top().nested.push_back({
101 .timestamp = timestamp++,
102 .phase = current_phase,
103 .contract_address = 0, // No specific contract
104 .caller_pc = 0,
105 .calldata = {},
106 .is_static_call = false,
107 .gas_limit = {},
108 .output = {},
109 .reverted = true,
110 .nested = {},
111 .internal_call_stack_at_exit = {},
112 .halting_message = revert_message,
113 .num_nested_calls = 0,
114 });
115}
116
118{
119 BB_ASSERT_EQ(call_stack_metadata.size(), static_cast<size_t>(1), "Call stack metadata size is not equal to 1");
120 return std::move(call_stack_metadata.top().nested);
121}
122
124{
125 auto cd_size = context.get_parent_cd_size();
126 return [&context, cd_size](uint32_t max_size) -> std::vector<FF> {
127 // NOTE: get_calldata will handle offsetting into parent memory for nested contexts
128 // TODO(AVM-186): check if this will pad to size. We don't want that.
129 auto data = context.get_calldata(0, std::min(max_size, cd_size));
130 return std::vector<FF>(data.begin(), data.end());
131 };
132}
133
134ReturnDataProvider make_return_data_provider(const ContextInterface& context, uint32_t rd_offset, uint32_t rd_size)
135{
136 return [&context, rd_offset, rd_size](uint32_t max_size) -> std::vector<FF> {
137 // TODO(AVM-187): Consider using get_returndata instead.
138 const auto& memory = context.get_memory();
139 std::vector<FF> data;
140 data.reserve(std::min(max_size, rd_size));
141 for (uint32_t i = 0; i < std::min(max_size, rd_size); i++) {
142 data.push_back(memory.get(rd_offset + i).as_ff());
143 }
144 return data;
145 };
146}
147
149 const InternalCallStackManagerInterface& internal_call_stack_manager)
150{
151 return [&internal_call_stack_manager]() -> std::vector<PC> {
152 return internal_call_stack_manager.get_current_call_stack();
153 };
154}
155
156} // namespace bb::avm2::simulation
#define BB_ASSERT(expression,...)
Definition assert.hpp:80
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:123
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:93
void notify_exit_call(bool success, uint32_t pc, const std::optional< std::string > &halting_message, const ReturnDataProvider &return_data_provider, const InternalCallStackProvider &internal_call_stack_provider) override
void set_phase(CoarseTransactionPhase phase) override
std::vector< CallStackMetadata > dump_call_stack_metadata() override
void notify_enter_call(const AztecAddress &contract_address, uint32_t caller_pc, const CalldataProvider &calldata_provider, bool is_static_call, const Gas &gas_limit) override
void notify_tx_revert(const std::string &revert_message) override
virtual std::vector< PC > get_current_call_stack() const =0
const std::vector< MemoryValue > data
std::function< std::vector< PC >()> InternalCallStackProvider
InternalCallStackProvider make_internal_call_stack_provider(const InternalCallStackManagerInterface &internal_call_stack_manager)
ReturnDataProvider make_return_data_provider(const ContextInterface &context, uint32_t rd_offset, uint32_t rd_size)
std::function< std::vector< FF >(uint32_t max_size)> CalldataProvider
std::function< std::vector< FF >(uint32_t max_size)> ReturnDataProvider
CalldataProvider make_calldata_provider(const ContextInterface &context)
CoarseTransactionPhase
Definition avm_io.hpp:482
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< PC > internal_call_stack_at_exit
Definition avm_io.hpp:515
std::optional< std::string > halting_message
Definition avm_io.hpp:516
std::vector< FF > output
Definition avm_io.hpp:511