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_, DOM_SEP__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(
134 rows.at(1),
135 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
136 ROW_FIELD_EQ(calldata_hashing_start, 1),
137 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
138 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
139 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 1),
140 ROW_FIELD_EQ(calldata_hashing_latch, 1),
141 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
142 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
143 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
144 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
145 ROW_FIELD_EQ(calldata_hashing_input_0_, DOM_SEP__PUBLIC_CALLDATA),
146 ROW_FIELD_EQ(calldata_hashing_input_1_, 1),
147 ROW_FIELD_EQ(calldata_hashing_input_2_, 2),
148 ROW_FIELD_EQ(calldata_hashing_calldata_size, 2),
149 ROW_FIELD_EQ(calldata_hashing_input_len, 3),
150 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
151 ROW_FIELD_EQ(calldata_hashing_output_hash, RawPoseidon2::hash({ DOM_SEP__PUBLIC_CALLDATA, 1, 2 }))));
152
153 EXPECT_THAT(rows.at(2),
154 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
155 ROW_FIELD_EQ(calldata_hashing_start, 1),
156 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
157 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
158 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 0),
159 ROW_FIELD_EQ(calldata_hashing_latch, 1),
160 ROW_FIELD_EQ(calldata_hashing_context_id, 3),
161 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
162 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
163 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
164 ROW_FIELD_EQ(calldata_hashing_input_0_, DOM_SEP__PUBLIC_CALLDATA),
165 ROW_FIELD_EQ(calldata_hashing_input_1_, 3),
166 ROW_FIELD_EQ(calldata_hashing_input_2_, 0),
167 ROW_FIELD_EQ(calldata_hashing_calldata_size, 1),
168 ROW_FIELD_EQ(calldata_hashing_input_len, 2),
169 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
170 ROW_FIELD_EQ(calldata_hashing_output_hash, RawPoseidon2::hash({ DOM_SEP__PUBLIC_CALLDATA, 3 }))));
171}
172
173TEST(CalldataTraceGenTest, BasicRetrievalAndHashingEmpty)
174{
175 TestTraceContainer trace;
176 CalldataTraceBuilder builder;
177
178 const auto events = { simulation::CalldataEvent{
179 .context_id = 12,
180 .calldata = {},
181 } };
182
183 builder.process_retrieval(events, trace);
184 builder.process_hashing(events, trace);
185 const auto rows = trace.as_rows();
186
187 // One extra empty row is prepended.
188
189 // Retrieval tracegen should have created the special empty case row:
190 EXPECT_THAT(rows.at(1),
191 AllOf(ROW_FIELD_EQ(calldata_sel, 1),
192 ROW_FIELD_EQ(calldata_latch, 1),
193 ROW_FIELD_EQ(calldata_context_id, 12),
194 // This is the only case where the index is 0 and sel is on:
195 ROW_FIELD_EQ(calldata_index, 0)));
196 // Hashing tracegen should set the output hash as H(sep):
197 EXPECT_THAT(rows.at(1),
198 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
199 ROW_FIELD_EQ(calldata_hashing_start, 1),
200 ROW_FIELD_EQ(calldata_hashing_sel_not_start, 0),
201 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 0),
202 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, 0),
203 ROW_FIELD_EQ(calldata_hashing_latch, 1),
204 ROW_FIELD_EQ(calldata_hashing_context_id, 12),
205 ROW_FIELD_EQ(calldata_hashing_index_0_, 0),
206 ROW_FIELD_EQ(calldata_hashing_index_1_, 1),
207 ROW_FIELD_EQ(calldata_hashing_index_2_, 2),
208 ROW_FIELD_EQ(calldata_hashing_input_0_, DOM_SEP__PUBLIC_CALLDATA),
209 ROW_FIELD_EQ(calldata_hashing_input_1_, 0),
210 ROW_FIELD_EQ(calldata_hashing_input_2_, 0),
211 ROW_FIELD_EQ(calldata_hashing_calldata_size, 0),
212 ROW_FIELD_EQ(calldata_hashing_input_len, 1),
213 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 1),
214 ROW_FIELD_EQ(calldata_hashing_output_hash, RawPoseidon2::hash({ DOM_SEP__PUBLIC_CALLDATA }))));
215}
216
217TEST(CalldataTraceGenTest, LongerHash)
218{
219 TestTraceContainer trace;
220 CalldataTraceBuilder builder;
221
222 std::vector<FF> calldata = random_fields(100);
223 std::vector<FF> preimage = { DOM_SEP__PUBLIC_CALLDATA };
224 preimage.insert(preimage.end(), calldata.begin(), calldata.end());
225 FF output_hash = RawPoseidon2::hash(preimage);
226
227 builder.process_hashing(
228 {
229 simulation::CalldataEvent{
230 .context_id = 1,
231 .calldata = calldata,
232 },
233 },
234 trace);
235 const auto rows = trace.as_rows();
236 // Omit the prepended first row:
237 const auto calldata_rows = std::span(rows.begin() + 1, rows.end());
238
239 // 100 field calldata => hash 101 fields => 34 poseidon chunks
240 EXPECT_THAT(calldata_rows, SizeIs(34));
241
242 uint32_t expected_index = 0;
243 for (auto row : calldata_rows) {
244 // Elts which should match each row:
245 EXPECT_THAT(row,
246 AllOf(ROW_FIELD_EQ(calldata_hashing_sel, 1),
247 ROW_FIELD_EQ(calldata_hashing_context_id, 1),
248 ROW_FIELD_EQ(calldata_hashing_calldata_size, 100),
249 ROW_FIELD_EQ(calldata_hashing_input_len, 101),
250 ROW_FIELD_EQ(calldata_hashing_output_hash, output_hash)));
251
252 // Elts which change each row:
253 EXPECT_THAT(
254 row,
255 AllOf(ROW_FIELD_EQ(calldata_hashing_index_0_, expected_index),
256 ROW_FIELD_EQ(calldata_hashing_index_1_, expected_index + 1),
257 ROW_FIELD_EQ(calldata_hashing_index_2_, expected_index + 2),
258 ROW_FIELD_EQ(calldata_hashing_input_0_, preimage.at(expected_index)),
259 ROW_FIELD_EQ(calldata_hashing_input_1_, preimage.at(expected_index + 1)),
260 // The final value is padded:
261 ROW_FIELD_EQ(calldata_hashing_input_2_, expected_index == 99 ? 0 : preimage.at(expected_index + 2)),
262 ROW_FIELD_EQ(calldata_hashing_rounds_rem, 34 - (expected_index / 3))));
263
264 // Elts for start/end rows:
265 EXPECT_THAT(row,
266 AllOf(ROW_FIELD_EQ(calldata_hashing_start, expected_index == 0 ? 1 : 0),
267 ROW_FIELD_EQ(calldata_hashing_sel_not_start, expected_index == 0 ? 0 : 1),
268 ROW_FIELD_EQ(calldata_hashing_latch, expected_index == 99 ? 1 : 0),
269 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_1, 1),
270 // The final value is padded:
271 ROW_FIELD_EQ(calldata_hashing_sel_not_padding_2, expected_index == 99 ? 0 : 1)));
272
273 expected_index += 3;
274 }
275}
276
277} // namespace
278} // namespace bb::avm2::tracegen
#define DOM_SEP__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:7
std::vector< FF > random_fields(size_t n)
Definition fixtures.cpp:23
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
std::vector< MemoryValue > calldata