Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
calldata_trace.test.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <cmath>
3#include <cstddef>
4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
6
7#include <cstdint>
8#include <memory>
9#include <sys/types.h>
10#include <vector>
11
21
23using testing::SizeIs;
24
25namespace bb::avm2::tracegen {
26namespace {
27
28using C = Column;
30
31TEST(CalldataTraceGenTest, BasicHashing)
32{
33 TestTraceContainer trace;
34 CalldataTraceBuilder builder;
35
36 builder.process_hashing(
37 {
38 simulation::CalldataEvent{
39 .context_id = 1,
40 .calldata = { 10, 20, 30 },
41 },
42 },
43 trace);
44 const auto rows = trace.as_rows();
45
46 // One extra empty row is prepended.
47 EXPECT_THAT(rows.at(1),
48 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
49 ROW_FIELD_EQ(calldata_hashing_start, 1),
50 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
51 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
52 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 1),
53 ROW_FIELD_EQ(calldata_hashing_latch, 0),
54 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
55 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
56 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
57 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
58 ROW_FIELD_EQ(calldata_hashing_input_0_, GENERATOR_INDEX__PUBLIC_CALLDATA),
59 ROW_FIELD_EQ(calldata_hashing_input_1_, 10),
60 ROW_FIELD_EQ(calldata_hashing_input_2_, 20),
61 ROW_FIELD_EQ(calldata_hashing_calldata_size, 3),
62 ROW_FIELD_EQ(calldata_hashing_input_len, 4),
63 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 2),
64 ROW_FIELD_EQ(calldata_hashing_output_hash,
66
67 // Latched row
68 EXPECT_THAT(rows.at(2),
69 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
70 ROW_FIELD_EQ(calldata_hashing_start, 0),
71 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 1),
72 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 0),
73 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 0),
74 ROW_FIELD_EQ(calldata_hashing_latch, 1),
75 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
76 ROW_FIELD_EQ(calldata_hashing_index_0_, 3),
77 ROW_FIELD_EQ(calldata_hashing_index_1_, 4),
78 ROW_FIELD_EQ(calldata_hashing_index_2_, 5),
79 ROW_FIELD_EQ(calldata_hashing_input_0_, 30),
80 ROW_FIELD_EQ(calldata_hashing_input_1_, 0),
81 ROW_FIELD_EQ(calldata_hashing_input_2_, 0),
82 ROW_FIELD_EQ(calldata_hashing_calldata_size, 3),
83 ROW_FIELD_EQ(calldata_hashing_input_len, 4),
84 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
85 ROW_FIELD_EQ(calldata_hashing_output_hash,
87}
88
89TEST(CalldataTraceGenTest, BasicRetrievalAndHashing)
90{
91 TestTraceContainer trace;
92 CalldataTraceBuilder builder;
93
94 // Must be sorted by context_id in ascending order.
95 const auto events = { simulation::CalldataEvent{
96 .context_id = 1,
97 .calldata = { 1, 2 },
98 },
99 simulation::CalldataEvent{
100 .context_id = 3,
101 .calldata = { 3 },
102 } };
103
104 builder.process_retrieval(events, trace);
105 builder.process_hashing(events, trace);
106 const auto rows = trace.as_rows();
107
108 // One extra empty row is prepended.
109 EXPECT_THAT(rows.at(1),
110 AllOf(ROW_FIELD_EQ(calldata_sel, 1),
111 ROW_FIELD_EQ(calldata_latch, 0),
112 ROW_FIELD_EQ(calldata_context_id, 1),
113 ROW_FIELD_EQ(calldata_index, 1),
114 ROW_FIELD_EQ(calldata_value, 1),
115 ROW_FIELD_EQ(calldata_diff_context_id, 0)));
116 EXPECT_THAT(rows.at(2),
117 AllOf(ROW_FIELD_EQ(calldata_sel, 1),
118 ROW_FIELD_EQ(calldata_latch, 1),
119 ROW_FIELD_EQ(calldata_context_id, 1),
120 ROW_FIELD_EQ(calldata_index, 2),
121 ROW_FIELD_EQ(calldata_value, 2),
122 // Note that the diff is shifted by 1 to ensure the context_ids are increasing:
123 ROW_FIELD_EQ(calldata_diff_context_id, 1)));
124 EXPECT_THAT(rows.at(3),
125 AllOf(ROW_FIELD_EQ(calldata_sel, 1),
126 ROW_FIELD_EQ(calldata_latch, 1),
127 ROW_FIELD_EQ(calldata_context_id, 3),
128 ROW_FIELD_EQ(calldata_index, 1),
129 ROW_FIELD_EQ(calldata_value, 3),
130 // Last one and therefore no diff:
131 ROW_FIELD_EQ(calldata_diff_context_id, 0)));
132 // Hashing tracegen:
133 EXPECT_THAT(rows.at(1),
134 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
135 ROW_FIELD_EQ(calldata_hashing_start, 1),
136 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
137 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
138 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 1),
139 ROW_FIELD_EQ(calldata_hashing_latch, 1),
140 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
141 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
142 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
143 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
144 ROW_FIELD_EQ(calldata_hashing_input_0_, GENERATOR_INDEX__PUBLIC_CALLDATA),
145 ROW_FIELD_EQ(calldata_hashing_input_1_, 1),
146 ROW_FIELD_EQ(calldata_hashing_input_2_, 2),
147 ROW_FIELD_EQ(calldata_hashing_calldata_size, 2),
148 ROW_FIELD_EQ(calldata_hashing_input_len, 3),
149 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
150 ROW_FIELD_EQ(calldata_hashing_output_hash,
152
153 EXPECT_THAT(
154 rows.at(2),
155 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
156 ROW_FIELD_EQ(calldata_hashing_start, 1),
157 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
158 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
159 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 0),
160 ROW_FIELD_EQ(calldata_hashing_latch, 1),
161 ROW_FIELD_EQ(calldata_hashing_context_id, 3),
162 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
163 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
164 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
165 ROW_FIELD_EQ(calldata_hashing_input_0_, GENERATOR_INDEX__PUBLIC_CALLDATA),
166 ROW_FIELD_EQ(calldata_hashing_input_1_, 3),
167 ROW_FIELD_EQ(calldata_hashing_input_2_, 0),
168 ROW_FIELD_EQ(calldata_hashing_calldata_size, 1),
169 ROW_FIELD_EQ(calldata_hashing_input_len, 2),
170 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
171 ROW_FIELD_EQ(calldata_hashing_output_hash, RawPoseidon2::hash({ GENERATOR_INDEX__PUBLIC_CALLDATA, 3 }))));
172}
173
174TEST(CalldataTraceGenTest, BasicRetrievalAndHashingEmpty)
175{
176 TestTraceContainer trace;
177 CalldataTraceBuilder builder;
178
179 const auto events = { simulation::CalldataEvent{
180 .context_id = 12,
181 .calldata = {},
182 } };
183
184 builder.process_retrieval(events, trace);
185 builder.process_hashing(events, trace);
186 const auto rows = trace.as_rows();
187
188 // One extra empty row is prepended.
189
190 // Retrieval tracegen should have created the special empty case row:
191 EXPECT_THAT(rows.at(1),
192 AllOf(ROW_FIELD_EQ(calldata_sel, 1),
193 ROW_FIELD_EQ(calldata_latch, 1),
194 ROW_FIELD_EQ(calldata_context_id, 12),
195 // This is the only case where the index is 0 and sel is on:
196 ROW_FIELD_EQ(calldata_index, 0)));
197 // Hashing tracegen should set the output hash as H(sep):
198 EXPECT_THAT(
199 rows.at(1),
200 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
201 ROW_FIELD_EQ(calldata_hashing_start, 1),
202 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
203 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 0),
204 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 0),
205 ROW_FIELD_EQ(calldata_hashing_latch, 1),
206 ROW_FIELD_EQ(calldata_hashing_context_id, 12),
207 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
208 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
209 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
210 ROW_FIELD_EQ(calldata_hashing_input_0_, GENERATOR_INDEX__PUBLIC_CALLDATA),
211 ROW_FIELD_EQ(calldata_hashing_input_1_, 0),
212 ROW_FIELD_EQ(calldata_hashing_input_2_, 0),
213 ROW_FIELD_EQ(calldata_hashing_calldata_size, 0),
214 ROW_FIELD_EQ(calldata_hashing_input_len, 1),
215 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
216 ROW_FIELD_EQ(calldata_hashing_output_hash, RawPoseidon2::hash({ GENERATOR_INDEX__PUBLIC_CALLDATA }))));
217}
218
219TEST(CalldataTraceGenTest, LongerHash)
220{
221 TestTraceContainer trace;
222 CalldataTraceBuilder builder;
223
224 std::vector<FF> calldata = random_fields(100);
225 std::vector<FF> preimage = { GENERATOR_INDEX__PUBLIC_CALLDATA };
226 preimage.insert(preimage.end(), calldata.begin(), calldata.end());
227 FF output_hash = RawPoseidon2::hash(preimage);
228
229 builder.process_hashing(
230 {
231 simulation::CalldataEvent{
232 .context_id = 1,
233 .calldata = calldata,
234 },
235 },
236 trace);
237 const auto rows = trace.as_rows();
238 // Omit the prepended first row:
239 const auto calldata_rows = std::span(rows.begin() + 1, rows.end());
240
241 // 100 field calldata => hash 101 fields => 34 poseidon chunks
242 EXPECT_THAT(calldata_rows, SizeIs(34));
243
244 uint32_t expected_index = 0;
245 for (auto row : calldata_rows) {
246 // Elts which should match each row:
247 EXPECT_THAT(row,
248 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
249 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
250 ROW_FIELD_EQ(calldata_hashing_calldata_size, 100),
251 ROW_FIELD_EQ(calldata_hashing_input_len, 101),
252 ROW_FIELD_EQ(calldata_hashing_output_hash, output_hash)));
253
254 // Elts which change each row:
255 EXPECT_THAT(
256 row,
257 AllOf(ROW_FIELD_EQ(calldata_hashing_index_0_, expected_index),
258 ROW_FIELD_EQ(calldata_hashing_index_1_, expected_index + 1),
259 ROW_FIELD_EQ(calldata_hashing_index_2_, expected_index + 2),
260 ROW_FIELD_EQ(calldata_hashing_input_0_, preimage.at(expected_index)),
261 ROW_FIELD_EQ(calldata_hashing_input_1_, preimage.at(expected_index + 1)),
262 // The final value is padded:
263 ROW_FIELD_EQ(calldata_hashing_input_2_, expected_index == 99 ? 0 : preimage.at(expected_index + 2)),
264 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 34 - (expected_index / 3))));
265
266 // Elts for start/end rows:
267 EXPECT_THAT(row,
268 AllOf(ROW_FIELD_EQ(calldata_hashing_start, expected_index == 0 ? 1 : 0),
269 ROW_FIELD_EQ(calldata_hashing_sel_not_start, expected_index == 0 ? 0 : 1),
270 ROW_FIELD_EQ(calldata_hashing_latch, expected_index == 99 ? 1 : 0),
271 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
272 // The final value is padded:
273 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, expected_index == 99 ? 0 : 1)));
274
275 expected_index += 3;
276 }
277}
278
279} // namespace
280} // namespace bb::avm2::tracegen
#define GENERATOR_INDEX__PUBLIC_CALLDATA
std::vector< AvmFullRowConstRef > as_rows() const
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AluTraceBuilder builder
Definition alu.test.cpp:124
TestTraceContainer trace
#define ROW_FIELD_EQ(field_name, expression)
Definition macros.hpp:15
std::vector< FF > random_fields(size_t n)
Definition fixtures.cpp:23
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
std::vector< MemoryValue > calldata