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_read_registers, 0 },
30 { C::execution_sel_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
49 check_relation<registers>(trace,
54
55 // Mismatch in effective selector should fail.
56 trace.set(0,
57 { {
58 { C::execution_sel_op_reg_effective_0_, 1 },
59 { C::execution_sel_op_reg_effective_1_, 1 },
60 { C::execution_sel_op_reg_effective_2_, 1 },
61 { C::execution_sel_op_reg_effective_3_, 1 },
62 } });
71}
72
73TEST(RegistersConstrainingTest, EffectiveRegOpSelectorOnlyRead)
74{
75 // This represents the case where we are only reading and failed before the write phase.
76 TestTraceContainer trace({ {
77 { C::execution_sel_read_registers, 1 },
78 { C::execution_sel_write_registers, 0 },
79 // Register 0: read, active.
80 { C::execution_sel_mem_op_reg_0_, 1 },
81 { C::execution_rw_reg_0_, 0 },
82 { C::execution_sel_op_reg_effective_0_, 1 },
83 // Register 1: write, active.
84 { C::execution_sel_mem_op_reg_1_, 1 },
85 { C::execution_rw_reg_1_, 1 },
86 { C::execution_sel_op_reg_effective_1_, 0 }, // 0 since we are not writing.
87 // Register 2: read, inactive.
88 { C::execution_sel_mem_op_reg_2_, 0 },
89 { C::execution_rw_reg_2_, 0 },
90 { C::execution_sel_op_reg_effective_2_, 0 }, // Correct.
91 // Register 3: write, inactive.
92 { C::execution_sel_mem_op_reg_3_, 0 },
93 { C::execution_rw_reg_3_, 1 },
94 { C::execution_sel_op_reg_effective_3_, 0 }, // Correct.
95 } });
96
97 check_relation<registers>(trace,
102
103 // Mismatch in effective selector should fail.
104 trace.set(0,
105 { {
106 { C::execution_sel_op_reg_effective_0_, 0 },
107 { C::execution_sel_op_reg_effective_1_, 1 },
108 { C::execution_sel_op_reg_effective_2_, 1 },
109 { C::execution_sel_op_reg_effective_3_, 1 },
110 } });
111 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_0),
113 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_1),
115 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_2),
117 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_3),
119}
120
121TEST(RegistersConstrainingTest, EffectiveRegOpSelectorReadThenWrite)
122{
123 // This represents the case where we are both reading and writing.
124 TestTraceContainer trace({ {
125 { C::execution_sel_read_registers, 1 },
126 { C::execution_sel_write_registers, 1 },
127 // Register 0: read, active.
128 { C::execution_sel_mem_op_reg_0_, 1 },
129 { C::execution_rw_reg_0_, 0 },
130 { C::execution_sel_op_reg_effective_0_, 1 }, // Correct.
131 // Register 1: write, active.
132 { C::execution_sel_mem_op_reg_1_, 1 },
133 { C::execution_rw_reg_1_, 1 },
134 { C::execution_sel_op_reg_effective_1_, 1 }, // Correct.
135 // Register 2: read, inactive.
136 { C::execution_sel_mem_op_reg_2_, 0 },
137 { C::execution_rw_reg_2_, 0 },
138 { C::execution_sel_op_reg_effective_2_, 0 }, // Correct.
139 // Register 3: write, inactive.
140 { C::execution_sel_mem_op_reg_3_, 0 },
141 { C::execution_rw_reg_3_, 1 },
142 { C::execution_sel_op_reg_effective_3_, 0 }, // Correct.
143 } });
144
145 check_relation<registers>(trace,
150
151 // Mismatch in effective selector should fail.
152 trace.set(0,
153 { {
154 { C::execution_sel_op_reg_effective_0_, 0 },
155 { C::execution_sel_op_reg_effective_1_, 0 },
156 { C::execution_sel_op_reg_effective_2_, 1 },
157 { C::execution_sel_op_reg_effective_3_, 1 },
158 } });
159 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_0),
161 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_1),
163 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_2),
165 EXPECT_THROW_WITH_MESSAGE(check_relation<registers>(trace, registers::SR_SEL_OP_REG_EFFECTIVE_3),
167}
168
169TEST(RegistersConstrainingTest, TagCheckNoFailure)
170{
171 TestTraceContainer trace({
172 {
173 { C::execution_sel_read_registers, 1 },
174 // Reg 0: check U8, is U8.
175 { C::execution_sel_tag_check_reg_0_, 1 },
176 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
177 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
178 // Reg 1: check U16, is U16.
179 { C::execution_sel_tag_check_reg_1_, 1 },
180 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
181 { C::execution_expected_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
182 // Reg 2: not checked.
183 { C::execution_sel_tag_check_reg_2_, 0 },
184 { C::execution_mem_tag_reg_2_, static_cast<uint8_t>(MemoryTag::FF) },
185 { C::execution_expected_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
186 // Inverse
187 { C::execution_batched_tags_diff_inv_reg, 0 }, // diff is 0.
188 // No error
189 { C::execution_sel_register_read_error, 0 },
190 },
191 });
192 // This passes. Observe that `sel_mem_op_reg` doesn't matter for tag checking!
193 check_relation<registers>(trace);
194
195 // Should fail if I try to trick the selector.
196 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/1);
199}
200
201TEST(RegistersConstrainingTest, TagCheckSingleFailure)
202{
203 FF batched_tags_diff =
204 FF(1 << 0) * (FF(static_cast<uint8_t>(MemoryTag::FF)) - FF(static_cast<uint8_t>(MemoryTag::U8)));
205
206 TestTraceContainer trace({
207 {
208 { C::execution_sel_read_registers, 1 },
209 // Reg 0: check U8, is FF -> FAILURE
210 { C::execution_sel_tag_check_reg_0_, 1 },
211 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
212 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
213 // Mismatched tag error
214 { C::execution_sel_register_read_error, 1 },
215 { C::execution_batched_tags_diff_inv_reg, batched_tags_diff.invert() },
216 },
217 });
218
219 check_relation<registers>(trace);
220
221 // Should fail if I try to trick the selector.
222 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/0);
225
226 // Should fail if inverse is wrong.
227 trace.set(C::execution_batched_tags_diff_inv_reg, /*row=*/0, /*value=*/0);
230}
231
232TEST(RegistersConstrainingTest, TagCheckIgnoresFailureWhenNotReading)
233{
234 TestTraceContainer trace({
235 {
236 { C::execution_sel_read_registers, 0 },
237 // Reg 0: check U8, is FF -> FAILURE
238 { C::execution_sel_tag_check_reg_0_, 1 },
239 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
240 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
241 // No error
242 { C::execution_sel_register_read_error, 0 },
243 { C::execution_batched_tags_diff_inv_reg, 0 },
244 },
245 });
246 check_relation<registers>(trace);
247
248 // Should fail if I try to trick the selector.
249 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/1);
252}
253
254TEST(RegistersConstrainingTest, TagCheckMultipleFailures)
255{
256 FF batched_tags_diff =
257 FF(1 << 0) * (FF(static_cast<uint8_t>(MemoryTag::FF)) - FF(static_cast<uint8_t>(MemoryTag::U8))) +
258 FF(1 << 3) * (FF(static_cast<uint8_t>(MemoryTag::U16)) - FF(static_cast<uint8_t>(MemoryTag::U32)));
259
260 TestTraceContainer trace({
261 {
262 { C::execution_sel_read_registers, 1 },
263 // Reg 0: check U8, is FF -> FAILURE
264 { C::execution_sel_tag_check_reg_0_, 1 },
265 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
266 { C::execution_expected_tag_reg_0_, static_cast<uint8_t>(MemoryTag::U8) },
267 // Reg 1: check U32, is U16 -> FAILURE
268 { C::execution_sel_tag_check_reg_1_, 1 },
269 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U16) },
270 { C::execution_expected_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U32) },
271 // Reg 2: check U8, is U8 -> SUCCESS
272 { C::execution_sel_tag_check_reg_2_, 1 },
273 { C::execution_mem_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
274 { C::execution_expected_tag_reg_2_, static_cast<uint8_t>(MemoryTag::U8) },
275 // Mismatched tag error
276 { C::execution_sel_register_read_error, 1 },
277 { C::execution_batched_tags_diff_inv_reg, batched_tags_diff.invert() },
278 },
279 });
280 check_relation<registers>(trace);
281
282 // Should fail if I try to trick the selector.
283 trace.set(C::execution_sel_register_read_error, /*row=*/0, /*value=*/0);
286
287 // Should fail if inverse is wrong.
288 trace.set(C::execution_batched_tags_diff_inv_reg, /*row=*/0, /*value=*/0);
291}
292
293} // namespace
294} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:224
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_1
Definition registers.hpp:38
static constexpr size_t SR_REGISTER_READ_TAG_CHECK
Definition registers.hpp:41
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_3
Definition registers.hpp:40
static std::string get_subrelation_label(size_t index)
Definition registers.hpp:43
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_0
Definition registers.hpp:37
static constexpr size_t SR_SEL_OP_REG_EFFECTIVE_2
Definition registers.hpp:39
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
TestTraceContainer trace
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TestTraceContainer empty_trace()
Definition fixtures.cpp:156
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr field invert() const noexcept