Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
registers.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
11
12namespace bb::avm2::constraining {
13namespace {
14
15using tracegen::TestTraceContainer;
17using C = Column;
18using registers = bb::avm2::registers<FF>;
19
20TEST(RegistersConstrainingTest, EmptyRow)
21{
22 check_relation<registers>(testing::empty_trace());
23}
24
25TEST(RegistersConstrainingTest, EffectiveRegOpSelectorNoReadNoWrite)
26{
27 // This represents the case where we are not reading nor writing.
28 TestTraceContainer trace({ {
29 { C::execution_sel_should_read_registers, 0 },
30 { C::execution_sel_should_write_registers, 0 },
31 // Register 0: read, active.
32 { C::execution_sel_mem_op_reg_0_, 1 },
33 { C::execution_rw_reg_0_, 0 },
34 { C::execution_sel_op_reg_effective_0_, 0 },
35 // Register 1: write, active.
36 { C::execution_sel_mem_op_reg_1_, 1 },
37 { C::execution_rw_reg_1_, 1 },
38 { C::execution_sel_op_reg_effective_1_, 0 },
39 // Register 2: read, inactive.
40 { C::execution_sel_mem_op_reg_2_, 0 },
41 { C::execution_rw_reg_2_, 0 },
42 { C::execution_sel_op_reg_effective_2_, 0 },
43 // Register 3: write, inactive.
44 { C::execution_sel_mem_op_reg_3_, 0 },
45 { C::execution_rw_reg_3_, 1 },
46 { C::execution_sel_op_reg_effective_3_, 0 },
47 } });
48 check_relation<registers>(trace,
56
57 // Mismatch in effective selector should fail.
58 trace.set(0,
59 { {
60 { C::execution_sel_op_reg_effective_0_, 1 },
61 { C::execution_sel_op_reg_effective_1_, 1 },
62 { C::execution_sel_op_reg_effective_2_, 1 },
63 { C::execution_sel_op_reg_effective_3_, 1 },
64 } });
66 "SEL_OP_REG_EFFECTIVE_0");
68 "SEL_OP_REG_EFFECTIVE_1");
70 "SEL_OP_REG_EFFECTIVE_2");
72 "SEL_OP_REG_EFFECTIVE_3");
73}
74
75TEST(RegistersConstrainingTest, EffectiveRegOpSelectorOnlyRead)
76{
77 // This represents the case where we are only reading and failed before the write phase.
78 TestTraceContainer trace({ {
79 { C::execution_sel_should_read_registers, 1 },
80 { C::execution_sel_should_write_registers, 0 },
81 // Register 0: read, active.
82 { C::execution_sel_mem_op_reg_0_, 1 },
83 { C::execution_rw_reg_0_, 0 },
84 { C::execution_sel_op_reg_effective_0_, 1 },
85 // Register 1: write, active.
86 { C::execution_sel_mem_op_reg_1_, 1 },
87 { C::execution_rw_reg_1_, 1 },
88 { C::execution_sel_op_reg_effective_1_, 0 }, // 0 since we are not writing.
89 // Register 2: read, inactive.
90 { C::execution_sel_mem_op_reg_2_, 0 },
91 { C::execution_rw_reg_2_, 0 },
92 { C::execution_sel_op_reg_effective_2_, 0 }, // Correct.
93 // Register 3: write, inactive.
94 { C::execution_sel_mem_op_reg_3_, 0 },
95 { C::execution_rw_reg_3_, 1 },
96 { C::execution_sel_op_reg_effective_3_, 0 }, // Correct.
97 } });
98 check_relation<registers>(trace,
106
107 // Mismatch in effective selector should fail.
108 trace.set(0,
109 { {
110 { C::execution_sel_op_reg_effective_0_, 0 },
111 { C::execution_sel_op_reg_effective_1_, 1 },
112 { C::execution_sel_op_reg_effective_2_, 1 },
113 { C::execution_sel_op_reg_effective_3_, 1 },
114 } });
116 "SEL_OP_REG_EFFECTIVE_0");
118 "SEL_OP_REG_EFFECTIVE_1");
120 "SEL_OP_REG_EFFECTIVE_2");
122 "SEL_OP_REG_EFFECTIVE_3");
123}
124
125TEST(RegistersConstrainingTest, EffectiveRegOpSelectorReadThenWrite)
126{
127 // This represents the case where we are both reading and writing.
128 TestTraceContainer trace({ {
129 { C::execution_sel_should_read_registers, 1 },
130 { C::execution_sel_should_write_registers, 1 },
131 // Register 0: read, active.
132 { C::execution_sel_mem_op_reg_0_, 1 },
133 { C::execution_rw_reg_0_, 0 },
134 { C::execution_sel_op_reg_effective_0_, 1 }, // Correct.
135 // Register 1: write, active.
136 { C::execution_sel_mem_op_reg_1_, 1 },
137 { C::execution_rw_reg_1_, 1 },
138 { C::execution_sel_op_reg_effective_1_, 1 }, // Correct.
139 // Register 2: read, inactive.
140 { C::execution_sel_mem_op_reg_2_, 0 },
141 { C::execution_rw_reg_2_, 0 },
142 { C::execution_sel_op_reg_effective_2_, 0 }, // Correct.
143 // Register 3: write, inactive.
144 { C::execution_sel_mem_op_reg_3_, 0 },
145 { C::execution_rw_reg_3_, 1 },
146 { C::execution_sel_op_reg_effective_3_, 0 }, // Correct.
147 } });
148 check_relation<registers>(trace,
156
157 // Mismatch in effective selector should fail.
158 trace.set(0,
159 { {
160 { C::execution_sel_op_reg_effective_0_, 0 },
161 { C::execution_sel_op_reg_effective_1_, 0 },
162 { C::execution_sel_op_reg_effective_2_, 1 },
163 { C::execution_sel_op_reg_effective_3_, 1 },
164 } });
166 "SEL_OP_REG_EFFECTIVE_0");
168 "SEL_OP_REG_EFFECTIVE_1");
170 "SEL_OP_REG_EFFECTIVE_2");
172 "SEL_OP_REG_EFFECTIVE_3");
173}
174
175TEST(RegistersConstrainingTest, TagCheckNoFailure)
176{
177 TestTraceContainer trace({
178 {
179 { C::execution_sel_should_read_registers, 1 },
180 // Reg 0: check U8, is U8.
181 { C::execution_sel_tag_check_reg_0_, 1 },
182 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
183 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
184 // Reg 1: check U16, is U16.
185 { C::execution_sel_tag_check_reg_1_, 1 },
186 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
187 { C::execution_expected_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
188 // Reg 2: not checked.
189 { C::execution_sel_tag_check_reg_2_, 0 },
190 { C::execution_mem_tag_reg_2_, static_cast<uint8_t>(MemoryTag::FF) },
191 { C::execution_expected_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
192 // Inverse
193 { C::execution_batched_tags_diff_inv_reg, 0 }, // diff is 0.
194 // No error
195 { C::execution_sel_register_read_error, 0 },
196 },
197 });
198 // This passes. Observe that `sel_mem_op_reg` doesn't matter for tag checking!
199 check_relation<registers>(trace);
200
201 // Should fail if I try to trick the selector.
202 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/1);
204 "REGISTER_READ_TAG_CHECK");
205}
206
207TEST(RegistersConstrainingTest, TagCheckSingleFailure)
208{
209 FF batched_tags_diff =
210 FF(1 << 0) * (FF(static_cast<uint8_t>(MemoryTag::FF)) - FF(static_cast<uint8_t>(MemoryTag::U8)));
211
212 TestTraceContainer trace({
213 {
214 { C::execution_sel_should_read_registers, 1 },
215 // Reg 0: check U8, is FF -> FAILURE
216 { C::execution_sel_tag_check_reg_0_, 1 },
217 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
218 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
219 // Mismatched tag error
220 { C::execution_sel_register_read_error, 1 },
221 { C::execution_batched_tags_diff_inv_reg, batched_tags_diff.invert() },
222 },
223 });
224
225 check_relation<registers>(trace);
226
227 // Should fail if I try to trick the selector.
228 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/0);
230 "REGISTER_READ_TAG_CHECK");
231
232 // Should fail if inverse is wrong.
233 trace.set(C::execution_batched_tags_diff_inv_reg, /*row=*/0, /*value=*/0);
235 "REGISTER_READ_TAG_CHECK");
236}
237
238TEST(RegistersConstrainingTest, TagCheckIgnoresFailureWhenNotReading)
239{
240 TestTraceContainer trace({
241 {
242 { C::execution_sel_should_read_registers, 0 },
243 // Reg 0: check U8, is FF -> FAILURE
244 { C::execution_sel_tag_check_reg_0_, 1 },
245 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
246 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
247 // No error
248 { C::execution_sel_register_read_error, 0 },
249 { C::execution_batched_tags_diff_inv_reg, 0 },
250 },
251 });
252 check_relation<registers>(trace);
253
254 // Should fail if I try to trick the selector.
255 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/1);
257 "REGISTER_READ_TAG_CHECK");
258}
259
260TEST(RegistersConstrainingTest, TagCheckMultipleFailures)
261{
262 FF batched_tags_diff =
263 FF(1 << 0) * (FF(static_cast<uint8_t>(MemoryTag::FF)) - FF(static_cast<uint8_t>(MemoryTag::U8))) +
264 FF(1 << 3) * (FF(static_cast<uint8_t>(MemoryTag::U16)) - FF(static_cast<uint8_t>(MemoryTag::U32)));
265
266 TestTraceContainer trace({
267 {
268 { C::execution_sel_should_read_registers, 1 },
269 // Reg 0: check U8, is FF -> FAILURE
270 { C::execution_sel_tag_check_reg_0_, 1 },
271 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
272 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
273 // Reg 1: check U32, is U16 -> FAILURE
274 { C::execution_sel_tag_check_reg_1_, 1 },
275 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
276 { C::execution_expected_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U32) },
277 // Reg 2: check U8, is U8 -> SUCCESS
278 { C::execution_sel_tag_check_reg_2_, 1 },
279 { C::execution_mem_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
280 { C::execution_expected_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
281 // Mismatched tag error
282 { C::execution_sel_register_read_error, 1 },
283 { C::execution_batched_tags_diff_inv_reg, batched_tags_diff.invert() },
284 },
285 });
286 check_relation<registers>(trace);
287
288 // Should fail if I try to trick the selector.
289 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/0);
291 "REGISTER_READ_TAG_CHECK");
292
293 // Should fail if inverse is wrong.
294 trace.set(C::execution_batched_tags_diff_inv_reg, /*row=*/0, /*value=*/0);
296 "REGISTER_READ_TAG_CHECK");
297}
298
299} // namespace
300} // namespace bb::avm2::constraining
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_1
Definition registers.hpp:63
static constexpr size_t SR_REGISTER_READ_TAG_CHECK
Definition registers.hpp:69
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_3
Definition registers.hpp:65
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_0
Definition registers.hpp:62
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_6
Definition registers.hpp:68
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_5
Definition registers.hpp:67
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_2
Definition registers.hpp:64
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_4
Definition registers.hpp:66
void set(Column col, uint32_t row, const FF &value)
TestTraceContainer trace
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
AvmFlavorSettings::FF FF
TEST(TxExecutionConstrainingTest, WriteTreeValue)
Definition tx.test.cpp:508
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
typename Flavor::FF FF