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
9
11
12namespace bb::avm2::tracegen {
13
16{
17 using C = Column;
18
19 // The calldata events must be sorted by context_id according to simulation.
20 // This is a prerequisite to satisfy the constraint #[RANGE_CHECK_CONTEXT_ID_DIFF].
21
22 uint32_t row = 1; // Has shifted columns
23
24 for (uint32_t j = 0; j < events.size(); j++) {
25 const auto& event = events[j];
26 const auto& calldata = event.calldata;
27 const auto context_id = event.context_id;
28 bool is_last = j == events.size() - 1;
29
30 for (size_t i = 0; i < calldata.size(); i++) {
31 bool is_latch = i == calldata.size() - 1;
32 trace.set(row,
33 { {
34 { C::calldata_sel, 1 },
35 { C::calldata_context_id, context_id },
36 { C::calldata_value, calldata[i] },
37 { C::calldata_index, i + 1 },
38 { C::calldata_latch, is_latch ? 1 : 0 },
39 // Note that the diff is shifted by 1 to ensure the context_ids are increasing:
40 { C::calldata_diff_context_id,
41 (is_latch && !is_last) ? events[j + 1].context_id - context_id - 1 : 0 },
42 } });
43 row++;
44 }
45
46 // Handle empty calldata:
47 if (calldata.size() == 0) {
48 // To ensure that we indicate a certain context_id has been processed, we include a special row
49 // in the calldata trace. This is the only case where sel = 1 and index = 0. Lookups into this trace
50 // to access values always shift by 1, so should never attempt to access a non-existent value:
51 trace.set(row,
52 { {
53 { C::calldata_sel, 1 },
54 { C::calldata_context_id, context_id },
55 { C::calldata_value, 0 },
56 { C::calldata_index, 0 },
57 { C::calldata_latch, 1 },
58 // Note that the diff is shifted by 1 to ensure the context_ids are increasing:
59 { C::calldata_diff_context_id, !is_last ? events[j + 1].context_id - context_id - 1 : 0 },
60 } });
61 row++;
62 }
63 }
64}
65
68{
69 using C = Column;
70 uint32_t row = 1;
71
72 for (const auto& event : events) {
73 std::vector<FF> calldata_with_sep = { GENERATOR_INDEX__PUBLIC_CALLDATA };
74 size_t input_size = event.calldata.size() + 1; // +1 for the separator
75 calldata_with_sep.reserve(input_size);
76 calldata_with_sep.insert(calldata_with_sep.end(), event.calldata.begin(), event.calldata.end());
77 auto calldata_field_at = [&calldata_with_sep](size_t i) -> FF {
78 return i < calldata_with_sep.size() ? calldata_with_sep[i] : 0;
79 };
80
81 FF output_hash = Poseidon2::hash(calldata_with_sep);
82 // We must pad up to the next multiple of 3:
83 // n % 3 == 0 => padding_amount = 0 = 2n % 3
84 // n % 3 == 1 => padding_amount = 2 = 2n % 3
85 // n % 3 == 2 => padding_amount = 1 = 2n % 3
86 auto padding_amount = (2 * calldata_with_sep.size()) % 3;
87 auto num_rounds_rem = (calldata_with_sep.size() + padding_amount) / 3;
88 uint32_t index = 0;
89 while (num_rounds_rem > 0) {
90 trace.set(
91 row,
92 { {
93 { C::calldata_hashing_sel, 1 },
94 { C::calldata_hashing_start, index == 0 ? 1 : 0 },
95 { C::calldata_hashing_sel_not_start, index == 0 ? 0 : 1 },
96 { C::calldata_hashing_context_id, event.context_id },
97 { C::calldata_hashing_calldata_size, event.calldata.size() },
98 { C::calldata_hashing_input_len, calldata_with_sep.size() },
99 { C::calldata_hashing_rounds_rem, num_rounds_rem },
100 { C::calldata_hashing_index_0_, index },
101 { C::calldata_hashing_index_1_, index + 1 },
102 { C::calldata_hashing_index_2_, index + 2 },
103 { C::calldata_hashing_input_0_, calldata_field_at(index) },
104 { C::calldata_hashing_input_1_, calldata_field_at(index + 1) },
105 { C::calldata_hashing_input_2_, calldata_field_at(index + 2) },
106 { C::calldata_hashing_output_hash, output_hash },
107 { C::calldata_hashing_sel_not_padding_1, (num_rounds_rem == 1) && (padding_amount == 2) ? 0 : 1 },
108 { C::calldata_hashing_sel_not_padding_2, (num_rounds_rem == 1) && (padding_amount > 0) ? 0 : 1 },
109 { C::calldata_hashing_latch, num_rounds_rem == 1 ? 1 : 0 },
110 } });
111 index += 3;
112 row++;
113 num_rounds_rem--;
114 }
115 }
116}
117
121 .add<lookup_calldata_hashing_get_calldata_field_0_settings, InteractionType::LookupSequential>()
123 .add<lookup_calldata_hashing_get_calldata_field_2_settings, InteractionType::LookupSequential>()
126 InteractionType::LookupGeneric>(); // Note: using lookup generic to avoid dedup issues
127
128} // 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
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
simulation::PublicDataTreeReadWriteEvent event
uint32_t context_id