Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
calldata_trace.cpp
Go to the documentation of this file.
2
8
10
11namespace bb::avm2::tracegen {
12
15{
16 using C = Column;
17 // Sort events by context_id:
18 auto cmp = [](const simulation::CalldataEvent* a, const simulation::CalldataEvent* b) {
19 return a->context_id < b->context_id;
20 };
22 sorted_events.reserve(events.size());
23 for (const auto& event : events) {
24 sorted_events.push_back(&event);
25 }
26 std::ranges::sort(sorted_events.begin(), sorted_events.end(), cmp);
27
28 uint32_t row = 1; // Has skip relations
29
30 for (uint32_t j = 0; j < events.size(); j++) {
31 const auto& event = sorted_events[j];
32 const auto& calldata = event->calldata;
33 const auto context_id = event->context_id;
34 bool is_last = j == events.size() - 1;
35
36 for (size_t i = 0; i < calldata.size(); i++) {
37 bool is_latch = i == calldata.size() - 1;
38 trace.set(row,
39 { {
40 { C::calldata_sel, 1 },
41 { C::calldata_context_id, context_id },
42 { C::calldata_value, calldata[i] },
43 { C::calldata_index, i + 1 },
44 { C::calldata_latch, is_latch ? 1 : 0 },
45 // Note that the diff is shifted by 1 to ensure the context_ids are increasing:
46 { C::calldata_diff_context_id,
47 (is_latch && !is_last) ? sorted_events[j + 1]->context_id - context_id - 1 : 0 },
48 } });
49 row++;
50 }
51
52 // Handle empty calldata:
53 if (calldata.size() == 0) {
54 // To ensure that we indicate a certain context_id has been processed, we include a special row
55 // in the calldata trace. This is the only case where sel = 1 and index = 0. Lookups into this trace
56 // to access values always shift by 1, so should never attempt to access a non-existent value:
57 trace.set(
58 row,
59 { {
60 { C::calldata_sel, 1 },
61 { C::calldata_context_id, context_id },
62 { C::calldata_value, 0 },
63 { C::calldata_index, 0 },
64 { C::calldata_latch, 1 },
65 // Note that the diff is shifted by 1 to ensure the context_ids are increasing:
66 { C::calldata_diff_context_id, !is_last ? sorted_events[j + 1]->context_id - context_id - 1 : 0 },
67 } });
68 row++;
69 }
70 }
71}
72
75{
76 using C = Column;
77 uint32_t row = 1;
78
79 for (const auto& event : events) {
80 std::vector<FF> calldata_with_sep = { GENERATOR_INDEX__PUBLIC_CALLDATA };
81 size_t input_size = event.calldata.size() + 1; // +1 for the separator
82 calldata_with_sep.reserve(input_size);
83 calldata_with_sep.insert(calldata_with_sep.end(), event.calldata.begin(), event.calldata.end());
84 auto calldata_field_at = [&calldata_with_sep](size_t i) -> FF {
85 return i < calldata_with_sep.size() ? calldata_with_sep[i] : 0;
86 };
87
88 FF output_hash = Poseidon2::hash(calldata_with_sep);
89 // We must pad up to the next multiple of 3:
90 // n % 3 == 0 => padding_amount = 0 = 2n % 3
91 // n % 3 == 1 => padding_amount = 2 = 2n % 3
92 // n % 3 == 2 => padding_amount = 1 = 2n % 3
93 auto padding_amount = (2 * calldata_with_sep.size()) % 3;
94 auto num_rounds_rem = (calldata_with_sep.size() + padding_amount) / 3;
95 uint32_t index = 0;
96 while (num_rounds_rem > 0) {
97 trace.set(
98 row,
99 { {
100 { C::calldata_hashing_sel, 1 },
101 { C::calldata_hashing_start, index == 0 ? 1 : 0 },
102 { C::calldata_hashing_sel_not_start, index == 0 ? 0 : 1 },
103 { C::calldata_hashing_context_id, event.context_id },
104 { C::calldata_hashing_calldata_size, event.calldata.size() },
105 { C::calldata_hashing_input_len, calldata_with_sep.size() },
106 { C::calldata_hashing_rounds_rem, num_rounds_rem },
107 { C::calldata_hashing_index_0_, index },
108 { C::calldata_hashing_index_1_, index + 1 },
109 { C::calldata_hashing_index_2_, index + 2 },
110 { C::calldata_hashing_input_0_, calldata_field_at(index) },
111 { C::calldata_hashing_input_1_, calldata_field_at(index + 1) },
112 { C::calldata_hashing_input_2_, calldata_field_at(index + 2) },
113 { C::calldata_hashing_output_hash, output_hash },
114 { C::calldata_hashing_sel_not_padding_1, (num_rounds_rem == 1) && (padding_amount == 2) ? 0 : 1 },
115 { C::calldata_hashing_sel_not_padding_2, (num_rounds_rem == 1) && (padding_amount > 0) ? 0 : 1 },
116 { C::calldata_hashing_latch, num_rounds_rem == 1 ? 1 : 0 },
117 } });
118 index += 3;
119 row++;
120 num_rounds_rem--;
121 }
122 }
123}
124
128 .add<lookup_calldata_hashing_get_calldata_field_0_settings, InteractionType::LookupSequential>()
130 .add<lookup_calldata_hashing_get_calldata_field_2_settings, InteractionType::LookupSequential>()
133 InteractionType::LookupGeneric>(); // Note: using lookup generic to avoid dedup issues
134
135} // namespace bb::avm2::tracegen
#define GENERATOR_INDEX__PUBLIC_CALLDATA
void process_hashing(const simulation::EventEmitterInterface< simulation::CalldataEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_retrieval(const simulation::EventEmitterInterface< simulation::CalldataEvent >::Container &events, TraceContainer &trace)
InteractionDefinition & add(auto &&... args)
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
TestTraceContainer trace
FF a
FF b
lookup_settings< lookup_calldata_hashing_get_calldata_field_1_settings_ > lookup_calldata_hashing_get_calldata_field_1_settings
lookup_settings< lookup_calldata_hashing_check_final_size_settings_ > lookup_calldata_hashing_check_final_size_settings
lookup_settings< lookup_calldata_range_check_context_id_diff_settings_ > lookup_calldata_range_check_context_id_diff_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event
uint32_t context_id