Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
emit_public_log.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
14
15namespace bb::avm2::simulation {
16namespace {
17
18using ::testing::_;
19using ::testing::ElementsAre;
20using ::testing::Return;
21using ::testing::ReturnRef;
22using ::testing::StrictMock;
23
24std::vector<MemoryValue> to_memory_values(const std::vector<FF>& fields)
25{
26 std::vector<MemoryValue> memory_values;
27 memory_values.reserve(fields.size());
28 for (const FF& field : fields) {
29 memory_values.push_back(MemoryValue::from<FF>(field));
30 }
31 return memory_values;
32}
33
34TEST(EmitPublicLogTest, Basic)
35{
36 StrictMock<MockMemory> memory;
37 StrictMock<MockContext> context;
38 StrictMock<MockGreaterThan> greater_than;
39 StrictMock<MockExecutionIdManager> execution_id_manager;
40 StrictMock<MockSideEffectTracker> side_effect_tracker;
41 EventEmitter<EmitPublicLogEvent> event_emitter;
42
43 AztecAddress address = 0xdeadbeef;
44 MemoryAddress log_offset = 27;
45 const std::vector<FF> log_fields = { log_offset, log_offset + 1 };
46 uint32_t log_size = static_cast<uint32_t>(log_fields.size());
47 uint64_t end_log_address = 28;
48 TrackedSideEffects side_effect_states = { .public_logs = {} };
49 TrackedSideEffects side_effect_states_after = { .public_logs = PublicLogs{ { { log_fields, address } } } };
50
51 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
52
53 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(1));
54 EXPECT_CALL(greater_than, gt(side_effect_states_after.get_num_public_log_fields(), FLAT_PUBLIC_LOGS_PAYLOAD_LENGTH))
55 .WillOnce(Return(false));
56 EXPECT_CALL(greater_than, gt(end_log_address + 1, AVM_MEMORY_SIZE)).WillOnce(Return(false));
57
58 EXPECT_CALL(context, get_side_effect_tracker()).WillRepeatedly(ReturnRef(side_effect_tracker));
59 EXPECT_CALL(side_effect_tracker, get_side_effects())
60 .WillOnce(ReturnRef(side_effect_states))
61 .WillOnce(ReturnRef(side_effect_states_after));
62 EXPECT_CALL(side_effect_tracker, add_public_log(address, std::vector<FF>{ log_offset, log_offset + 1 }));
63
64 EXPECT_CALL(memory, get(_)).WillRepeatedly([](MemoryAddress address) -> const MemoryValue& {
65 static thread_local MemoryValue value;
66 value = MemoryValue::from<FF>(FF(address));
67 return value;
68 });
69
70 EXPECT_CALL(memory, get_space_id()).WillOnce(Return(57));
71 EXPECT_CALL(context, get_is_static()).WillOnce(Return(false));
72
73 emit_public_log.emit_public_log(memory, context, address, log_offset, log_size);
74
75 EmitPublicLogWriteEvent expect_event = {
76 .execution_clk = 1,
77 .contract_address = address,
78 .space_id = 57,
79 .log_address = log_offset,
80 .log_size = log_size,
81 .prev_num_public_log_fields = side_effect_states.get_num_public_log_fields(),
82 .next_num_public_log_fields = side_effect_states_after.get_num_public_log_fields(),
83 .is_static = false,
84 .values = to_memory_values(log_fields),
85 .error_memory_out_of_bounds = false,
86 .error_too_many_log_fields = false,
87 .error_tag_mismatch = false,
88 };
89
90 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
91}
92
93TEST(EmitPublicLogTest, NegativeMemoryOutOfBounds)
94{
95 StrictMock<MockMemory> memory;
96 StrictMock<MockContext> context;
97 StrictMock<MockGreaterThan> greater_than;
98 StrictMock<MockExecutionIdManager> execution_id_manager;
99 StrictMock<MockSideEffectTracker> side_effect_tracker;
100 EventEmitter<EmitPublicLogEvent> event_emitter;
101
102 AztecAddress address = 0xdeadbeef;
104 const std::vector<FF> log_fields = { log_offset, log_offset + 1 };
105 uint32_t log_size = static_cast<uint32_t>(log_fields.size());
106 uint64_t end_log_address = static_cast<uint64_t>(log_offset) + log_size - 1;
107 TrackedSideEffects side_effect_states = { .public_logs = {} };
108 // No change to side effect states due to failure.
109 const TrackedSideEffects& side_effect_states_after = side_effect_states;
110
111 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
112
113 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(1));
114 EXPECT_CALL(greater_than,
115 gt(side_effect_states.get_num_public_log_fields() + PUBLIC_LOG_HEADER_LENGTH + log_size,
117 .WillOnce(Return(false));
118 EXPECT_CALL(greater_than, gt(end_log_address + 1, AVM_MEMORY_SIZE)).WillOnce(Return(true));
119
120 EXPECT_CALL(context, get_side_effect_tracker()).WillRepeatedly(ReturnRef(side_effect_tracker));
121 EXPECT_CALL(side_effect_tracker, get_side_effects())
122 .WillOnce(ReturnRef(side_effect_states))
123 .WillOnce(ReturnRef(side_effect_states_after));
124
125 EXPECT_CALL(memory, get_space_id()).WillOnce(Return(57));
126 EXPECT_CALL(context, get_is_static()).WillOnce(Return(false));
127
128 EXPECT_THROW(emit_public_log.emit_public_log(memory, context, address, log_offset, log_size),
129 EmitPublicLogException);
130
131 EmitPublicLogWriteEvent expect_event = {
132 .execution_clk = 1,
133 .contract_address = address,
134 .space_id = 57,
135 .log_address = log_offset,
136 .log_size = log_size,
137 .prev_num_public_log_fields = side_effect_states.get_num_public_log_fields(),
138 .next_num_public_log_fields = side_effect_states_after.get_num_public_log_fields(),
139 .is_static = false,
140 .values = {},
141 .error_memory_out_of_bounds = true,
142 .error_too_many_log_fields = false,
143 .error_tag_mismatch = false,
144 };
145
146 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
147}
148
149TEST(EmitPublicLogTest, NegativeTooManyLogs)
150{
151 StrictMock<MockMemory> memory;
152 StrictMock<MockContext> context;
153 StrictMock<MockGreaterThan> greater_than;
154 StrictMock<MockExecutionIdManager> execution_id_manager;
155 StrictMock<MockSideEffectTracker> side_effect_tracker;
156 EventEmitter<EmitPublicLogEvent> event_emitter;
157
158 AztecAddress address = 0xdeadbeef;
159 MemoryAddress log_offset = 27;
160 const std::vector<FF> log_fields = { log_offset, log_offset + 1 };
161 uint32_t log_size = static_cast<uint32_t>(log_fields.size());
162 uint64_t end_log_address = 28;
163 // Minus three so header = 2 + log_size = 2 doesn't fit
164 TrackedSideEffects side_effect_states = {
165 .public_logs = PublicLogs{ { { .fields = testing::random_fields(FLAT_PUBLIC_LOGS_PAYLOAD_LENGTH -
167 .contract_address = 0xdeadbeef } } }
168 };
169 // No change to side effect states due to failure.
170 const TrackedSideEffects& side_effect_states_after = side_effect_states;
171
172 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
173
174 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(1));
175 EXPECT_CALL(greater_than,
176 gt(side_effect_states.get_num_public_log_fields() + PUBLIC_LOG_HEADER_LENGTH + log_size,
178 .WillOnce(Return(true));
179 EXPECT_CALL(greater_than, gt(end_log_address + 1, AVM_MEMORY_SIZE)).WillOnce(Return(false));
180
181 EXPECT_CALL(context, get_side_effect_tracker()).WillOnce(ReturnRef(side_effect_tracker));
182 EXPECT_CALL(side_effect_tracker, get_side_effects())
183 .WillOnce(ReturnRef(side_effect_states))
184 .WillOnce(ReturnRef(side_effect_states_after));
185
186 EXPECT_CALL(memory, get(_)).WillRepeatedly([](MemoryAddress address) -> const MemoryValue& {
187 static thread_local MemoryValue value;
188 value = MemoryValue::from<FF>(FF(address));
189 return value;
190 });
191
192 EXPECT_CALL(memory, get_space_id()).WillOnce(Return(57));
193 EXPECT_CALL(context, get_is_static()).WillOnce(Return(false));
194
195 EXPECT_THROW(emit_public_log.emit_public_log(memory, context, address, log_offset, log_size),
196 EmitPublicLogException);
197
198 EmitPublicLogWriteEvent expect_event = {
199 .execution_clk = 1,
200 .contract_address = address,
201 .space_id = 57,
202 .log_address = log_offset,
203 .log_size = log_size,
204 .prev_num_public_log_fields = side_effect_states.get_num_public_log_fields(),
205 .next_num_public_log_fields = side_effect_states_after.get_num_public_log_fields(),
206 .is_static = false,
207 .values = to_memory_values(log_fields),
208 .error_memory_out_of_bounds = false,
209 .error_too_many_log_fields = true,
210 .error_tag_mismatch = false,
211 };
212
213 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
214}
215
216TEST(EmitPublicLogTest, NegativeTagMismatch)
217{
218 StrictMock<MockMemory> memory;
219 StrictMock<MockContext> context;
220 StrictMock<MockGreaterThan> greater_than;
221 StrictMock<MockExecutionIdManager> execution_id_manager;
222 StrictMock<MockSideEffectTracker> side_effect_tracker;
223 EventEmitter<EmitPublicLogEvent> event_emitter;
224
225 AztecAddress address = 0xdeadbeef;
226 MemoryAddress log_offset = 27;
227 uint32_t log_size = 2;
228 uint64_t end_log_address = 28;
229 TrackedSideEffects side_effect_states = { .public_logs = {} };
230 // No change to side effect states due to failure.
231 const TrackedSideEffects& side_effect_states_after = side_effect_states;
232
233 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
234
235 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(1));
236 EXPECT_CALL(greater_than,
237 gt(side_effect_states.get_num_public_log_fields() + PUBLIC_LOG_HEADER_LENGTH + log_size,
239 .WillOnce(Return(false));
240 EXPECT_CALL(greater_than, gt(end_log_address + 1, AVM_MEMORY_SIZE)).WillOnce(Return(false));
241
242 EXPECT_CALL(context, get_side_effect_tracker()).WillOnce(ReturnRef(side_effect_tracker));
243 EXPECT_CALL(side_effect_tracker, get_side_effects())
244 .WillOnce(ReturnRef(side_effect_states))
245 .WillOnce(ReturnRef(side_effect_states_after));
246
247 EXPECT_CALL(memory, get(_)).WillRepeatedly([](MemoryAddress address) -> const MemoryValue& {
248 static thread_local MemoryValue value;
249 value = MemoryValue::from<uint32_t>(address);
250 return value;
251 });
252
253 EXPECT_CALL(memory, get_space_id()).WillOnce(Return(57));
254 EXPECT_CALL(context, get_is_static()).WillOnce(Return(false));
255
256 EXPECT_THROW(emit_public_log.emit_public_log(memory, context, address, log_offset, log_size),
257 EmitPublicLogException);
258
259 EmitPublicLogWriteEvent expect_event = {
260 .execution_clk = 1,
261 .contract_address = address,
262 .space_id = 57,
263 .log_address = log_offset,
264 .log_size = log_size,
265 .prev_num_public_log_fields = side_effect_states.get_num_public_log_fields(),
266 .next_num_public_log_fields = side_effect_states_after.get_num_public_log_fields(),
267 .is_static = false,
268 .values = { MemoryValue::from<uint32_t>(log_offset), MemoryValue::from<uint32_t>(log_offset + 1) },
269 .error_memory_out_of_bounds = false,
270 .error_too_many_log_fields = false,
271 .error_tag_mismatch = true,
272 };
273
274 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
275}
276
277TEST(EmitPublicLogTest, NegativeStatic)
278{
279 StrictMock<MockMemory> memory;
280 StrictMock<MockContext> context;
281 StrictMock<MockGreaterThan> greater_than;
282 StrictMock<MockExecutionIdManager> execution_id_manager;
283 StrictMock<MockSideEffectTracker> side_effect_tracker;
284 EventEmitter<EmitPublicLogEvent> event_emitter;
285
286 AztecAddress address = 0xdeadbeef;
287 MemoryAddress log_offset = 27;
288 const std::vector<FF> log_fields = { log_offset, log_offset + 1 };
289 uint32_t log_size = static_cast<uint32_t>(log_fields.size());
290 uint64_t end_log_address = 28;
291 TrackedSideEffects side_effect_states = { .public_logs = {} };
292 // No change to side effect states due to failure.
293 const TrackedSideEffects& side_effect_states_after = side_effect_states;
294
295 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
296
297 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(1));
298 EXPECT_CALL(greater_than,
299 gt(side_effect_states.get_num_public_log_fields() + PUBLIC_LOG_HEADER_LENGTH + log_size,
301 .WillOnce(Return(false));
302 EXPECT_CALL(greater_than, gt(end_log_address + 1, AVM_MEMORY_SIZE)).WillOnce(Return(false));
303
304 EXPECT_CALL(context, get_side_effect_tracker()).WillOnce(ReturnRef(side_effect_tracker));
305 EXPECT_CALL(side_effect_tracker, get_side_effects())
306 .WillOnce(ReturnRef(side_effect_states))
307 .WillOnce(ReturnRef(side_effect_states_after));
308
309 EXPECT_CALL(memory, get(_)).WillRepeatedly([](MemoryAddress address) -> const MemoryValue& {
310 static thread_local MemoryValue value;
311 value = MemoryValue::from<FF>(FF(address));
312 return value;
313 });
314
315 EXPECT_CALL(memory, get_space_id()).WillOnce(Return(57));
316 EXPECT_CALL(context, get_is_static()).WillOnce(Return(true));
317
318 EXPECT_THROW(emit_public_log.emit_public_log(memory, context, address, log_offset, log_size),
319 EmitPublicLogException);
320
321 EmitPublicLogWriteEvent expect_event = {
322 .execution_clk = 1,
323 .contract_address = address,
324 .space_id = 57,
325 .log_address = log_offset,
326 .log_size = log_size,
327 .prev_num_public_log_fields = side_effect_states.get_num_public_log_fields(),
328 .next_num_public_log_fields = side_effect_states_after.get_num_public_log_fields(),
329 .is_static = true,
330 .values = to_memory_values(log_fields),
331 .error_memory_out_of_bounds = false,
332 .error_too_many_log_fields = false,
333 .error_tag_mismatch = false,
334 };
335
336 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
337}
338
339TEST(EmitPublicLogTest, CheckpointListener)
340{
341 StrictMock<MockMemory> memory;
342 StrictMock<MockContext> context;
343 StrictMock<MockGreaterThan> greater_than;
344 StrictMock<MockExecutionIdManager> execution_id_manager;
345 EventEmitter<EmitPublicLogEvent> event_emitter;
346 EmitPublicLog emit_public_log(execution_id_manager, greater_than, event_emitter);
347
348 emit_public_log.on_checkpoint_created();
349 emit_public_log.on_checkpoint_committed();
350 emit_public_log.on_checkpoint_reverted();
351 EXPECT_THAT(event_emitter.get_events().size(), 3);
352 EXPECT_THAT(event_emitter.dump_events(),
356}
357
358} // namespace
359} // namespace bb::avm2::simulation
GreaterThan greater_than
#define FLAT_PUBLIC_LOGS_PAYLOAD_LENGTH
#define FLAT_PUBLIC_LOGS_HEADER_LENGTH
#define PUBLIC_LOG_HEADER_LENGTH
#define AVM_MEMORY_SIZE
#define AVM_HIGHEST_MEM_ADDRESS
ExecutionIdManager execution_id_manager
EventEmitter< DataCopyEvent > event_emitter
GreaterThan gt
StrictMock< MockContext > context
AVM range check gadget for witness generation.
std::vector< FF > random_fields(size_t n)
Definition fixtures.cpp:23
TaggedValue MemoryValue
AvmFlavorSettings::FF FF
Definition field.hpp:10
uint32_t MemoryAddress
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory
SideEffectTracker side_effect_tracker