Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
execution.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
6#include <memory>
7
42
43namespace bb::avm2::simulation {
44namespace {
45
46using ::testing::_;
47using ::testing::NiceMock;
48using ::testing::Return;
49using ::testing::ReturnRef;
50using ::testing::StrictMock;
51using ::testing::Throw;
52
53// TODO(fcarreiro): This is a hack to get the gas tracker for testing.
54class TestingExecution : public Execution {
55 public:
56 using Execution::Execution;
57
58 void set_gas_tracker(GasTrackerInterface& gas_tracker) { this->testing_gas_tracker = &gas_tracker; }
59
60 GasTrackerInterface& get_gas_tracker() override { return *testing_gas_tracker; }
61
62 private:
63 GasTrackerInterface* testing_gas_tracker;
64};
65
66class ExecutionSimulationTest : public ::testing::Test {
67 protected:
68 ExecutionSimulationTest()
69 {
70 ON_CALL(context, get_memory).WillByDefault(ReturnRef(memory));
71 ON_CALL(context, get_bytecode_manager).WillByDefault(ReturnRef(bytecode_manager));
72 execution.set_gas_tracker(gas_tracker);
73 }
74
75 StrictMock<MockAlu> alu;
76 StrictMock<MockBitwise> bitwise;
77 StrictMock<MockMemory> memory;
78 StrictMock<MockExecutionComponentsProvider> execution_components;
79 StrictMock<MockContext> context;
80 StrictMock<MockDataCopy> data_copy;
81 StrictMock<MockInternalCallStackManager> internal_call_stack_manager;
82 StrictMock<MockKeccakF1600> keccakf1600;
83 StrictMock<MockGetContractInstance> get_contract_instance;
84 EventEmitter<ExecutionEvent> execution_event_emitter;
85 EventEmitter<ContextStackEvent> context_stack_event_emitter;
86 InstructionInfoDB instruction_info_db; // Using the real thing.
87 StrictMock<MockContextProvider> context_provider;
88 StrictMock<MockExecutionIdManager> execution_id_manager;
89 StrictMock<MockGasTracker> gas_tracker;
90 StrictMock<MockHighLevelMerkleDB> merkle_db;
91 StrictMock<MockGreaterThan> greater_than;
92 StrictMock<MockPoseidon2> poseidon2;
93 StrictMock<MockEcc> ecc;
94 StrictMock<MockToRadix> to_radix;
95 StrictMock<MockEmitUnencryptedLog> emit_unencrypted_log;
96 StrictMock<MockBytecodeManager> bytecode_manager;
97 StrictMock<MockSha256> sha256;
98 StrictMock<MockDebugLog> debug_log;
99 TestingExecution execution = TestingExecution(alu,
100 bitwise,
101 data_copy,
102 poseidon2,
103 ecc,
104 to_radix,
105 sha256,
106 execution_components,
110 execution_event_emitter,
111 context_stack_event_emitter,
112 keccakf1600,
114 get_contract_instance,
115 emit_unencrypted_log,
116 debug_log,
117 merkle_db);
118};
119
120// NOTE: MemoryAddresses x, y used in the below tests like: execution.fn(context, x, y, ..) are just unchecked arbitrary
121// addresses. We test the MemoryValues and destination addresses.
122
123TEST_F(ExecutionSimulationTest, Add)
124{
125 MemoryValue a = MemoryValue::from<uint32_t>(4);
126 MemoryValue b = MemoryValue::from<uint32_t>(5);
127
128 EXPECT_CALL(context, get_memory);
129 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
130 EXPECT_CALL(alu, add(a, b)).WillOnce(Return(MemoryValue::from<uint32_t>(9)));
131 EXPECT_CALL(memory, set(6, MemoryValue::from<uint32_t>(9)));
132 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
133
134 execution.add(context, 4, 5, 6);
135}
136
137TEST_F(ExecutionSimulationTest, Sub)
138{
139 MemoryValue a = MemoryValue::from<uint64_t>(5);
140 MemoryValue b = MemoryValue::from<uint64_t>(3);
141
142 EXPECT_CALL(context, get_memory);
143 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
144 EXPECT_CALL(alu, sub(a, b)).WillOnce(Return(MemoryValue::from<uint64_t>(2)));
145 EXPECT_CALL(memory, set(3, MemoryValue::from<uint64_t>(2)));
146 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
147
148 execution.sub(context, 1, 2, 3);
149}
150
151TEST_F(ExecutionSimulationTest, Mul)
152{
154 auto a = MemoryValue::from<uint128_t>(max);
155 auto b = MemoryValue::from<uint128_t>(max - 3);
156
157 EXPECT_CALL(context, get_memory);
158 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
159 EXPECT_CALL(alu, mul(a, b)).WillOnce(Return(MemoryValue::from<uint128_t>(4)));
160 EXPECT_CALL(memory, set(3, MemoryValue::from<uint128_t>(4)));
161 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
162
163 execution.mul(context, 1, 2, 3);
164}
165
166TEST_F(ExecutionSimulationTest, Div)
167{
168 auto a = MemoryValue::from<uint128_t>(6);
169 auto b = MemoryValue::from<uint128_t>(3);
170
171 EXPECT_CALL(context, get_memory);
172 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
173 EXPECT_CALL(alu, div(a, b)).WillOnce(Return(MemoryValue::from<uint128_t>(2)));
174 EXPECT_CALL(memory, set(3, MemoryValue::from<uint128_t>(2)));
175 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
176
177 execution.div(context, 1, 2, 3);
178}
179
180TEST_F(ExecutionSimulationTest, FDiv)
181{
182 auto a = MemoryValue::from<FF>(FF::modulus - 4);
183 auto b = MemoryValue::from<FF>(2);
184
185 EXPECT_CALL(context, get_memory);
186 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
187 EXPECT_CALL(alu, fdiv(a, b)).WillOnce(Return(MemoryValue::from<FF>(FF::modulus - 2)));
188 EXPECT_CALL(memory, set(3, MemoryValue::from<FF>(FF::modulus - 2)));
189 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
190
191 execution.fdiv(context, 1, 2, 3);
192}
193
194TEST_F(ExecutionSimulationTest, Shl)
195{
196 auto a = MemoryValue::from<uint32_t>(64);
197 auto b = MemoryValue::from<uint32_t>(2);
198
199 EXPECT_CALL(context, get_memory);
200 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
201 EXPECT_CALL(alu, shl(a, b)).WillOnce(Return(MemoryValue::from<uint32_t>(256)));
202 EXPECT_CALL(memory, set(3, MemoryValue::from<uint32_t>(256)));
203 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
204
205 execution.shl(context, 1, 2, 3);
206}
207
208TEST_F(ExecutionSimulationTest, Shr)
209{
210 auto a = MemoryValue::from<uint64_t>(64);
211 auto b = MemoryValue::from<uint64_t>(2);
212
213 EXPECT_CALL(context, get_memory);
214 EXPECT_CALL(memory, get).Times(2).WillOnce(ReturnRef(a)).WillOnce(ReturnRef(b));
215 EXPECT_CALL(alu, shr(a, b)).WillOnce(Return(MemoryValue::from<uint64_t>(16)));
216 EXPECT_CALL(memory, set(3, MemoryValue::from<uint64_t>(16)));
217 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
218
219 execution.shr(context, 1, 2, 3);
220}
221
222// TODO(MW): Add alu tests here for other ops
223
224TEST_F(ExecutionSimulationTest, Call)
225{
226 FF zero = 0;
227 AztecAddress parent_address = 0xdeadbeef;
228 AztecAddress nested_address = 0xc0ffee;
229 MemoryValue nested_address_value = MemoryValue::from<FF>(nested_address);
230 MemoryValue l2_gas_allocated = MemoryValue::from<uint32_t>(6);
231 MemoryValue da_gas_allocated = MemoryValue::from<uint32_t>(7);
232 MemoryValue cd_size = MemoryValue::from<uint32_t>(8);
233 AppendOnlyTreeSnapshot written_public_data_slots_tree_snapshot = AppendOnlyTreeSnapshot{
234 .root = 0x12345678,
235 .nextAvailableLeafIndex = 10,
236 };
237 TreeStates tree_states = TreeStates {
238 .noteHashTree = {
239 .tree = {
240 .root = 10,
241 .nextAvailableLeafIndex = 9,
242 },
243 .counter = 8,
244 },
245 .nullifierTree = {
246 .tree = {
247 .root = 7,
248 .nextAvailableLeafIndex = 6,
249 },
250 .counter = 5,
251 },
252 .l1ToL2MessageTree = {
253 .tree = {
254 .root = 4,
255 .nextAvailableLeafIndex = 3,
256 },
257 .counter = 0,
258 },
259 .publicDataTree = {
260 .tree = {
261 .root = 2,
262 .nextAvailableLeafIndex = 1,
263 },
264 .counter = 1,
265 }
266 };
267
268 SideEffectStates side_effect_states = SideEffectStates{ .numUnencryptedLogFields = 1, .numL2ToL1Messages = 2 };
269
270 EXPECT_CALL(gas_tracker, compute_gas_limit_for_call(Gas{ 6, 7 })).WillOnce(Return(Gas{ 2, 3 }));
271 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
272
273 // Context snapshotting
274 EXPECT_CALL(context, get_context_id);
275 EXPECT_CALL(context, get_parent_id);
276 EXPECT_CALL(context, get_bytecode_manager).WillOnce(ReturnRef(bytecode_manager));
277 EXPECT_CALL(bytecode_manager, get_retrieved_bytecode_id).WillOnce(Return(FF(1)));
278 EXPECT_CALL(context, get_next_pc);
279 EXPECT_CALL(context, get_is_static).WillRepeatedly(Return(false));
280 EXPECT_CALL(context, get_msg_sender).WillOnce(ReturnRef(parent_address));
281 EXPECT_CALL(context, get_transaction_fee).WillOnce(ReturnRef(zero));
282 EXPECT_CALL(context, get_parent_cd_addr);
283 EXPECT_CALL(context, get_parent_cd_size);
284 EXPECT_CALL(context, get_parent_gas_used);
285 EXPECT_CALL(context, get_parent_gas_limit);
286 EXPECT_CALL(context, get_written_public_data_slots_tree_snapshot)
287 .WillOnce(Return(written_public_data_slots_tree_snapshot));
288 EXPECT_CALL(context, get_side_effect_states).WillRepeatedly(ReturnRef(side_effect_states));
289
290 EXPECT_CALL(context, get_phase).WillOnce(Return(TransactionPhase::APP_LOGIC));
291
292 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_states));
293
294 EXPECT_CALL(context, get_memory);
295 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(parent_address));
296 EXPECT_CALL(memory, get(1)).WillOnce(ReturnRef(l2_gas_allocated)); // l2_gas_offset
297 EXPECT_CALL(memory, get(2)).WillOnce(ReturnRef(da_gas_allocated)); // da_gas_offset
298 EXPECT_CALL(memory, get(3)).WillOnce(ReturnRef(nested_address_value)); // contract_address
299 EXPECT_CALL(memory, get(4)).WillOnce(ReturnRef(cd_size)); // cd_size
300
301 auto nested_context = std::make_unique<NiceMock<MockContext>>();
302 ON_CALL(*nested_context, halted())
303 .WillByDefault(Return(true)); // We just want the recursive call to return immediately.
304
305 EXPECT_CALL(context_provider,
306 make_nested_context(nested_address,
307 parent_address,
308 _,
309 _,
310 _,
311 _,
312 _,
313 Gas{ 2, 3 },
314 side_effect_states,
316 .WillOnce(Return(std::move(nested_context)));
317
318 execution.call(context,
319 /*l2_gas_offset=*/1,
320 /*da_gas_offset=*/2,
321 /*addr=*/3,
322 /*cd_size_offset=*/4,
323 /*cd_offset=*/5);
324}
325
326// Test staticness propagation for external calls (CALL vs STATICCALL)
327TEST_F(ExecutionSimulationTest, ExternalCallStaticnessPropagation)
328{
329 // Common test data setup
330 FF zero = 0;
331 AztecAddress parent_address = 0xdeadbeef;
332 AztecAddress nested_address = 0xc0ffee;
333 MemoryValue nested_address_value = MemoryValue::from<FF>(nested_address);
334 MemoryValue l2_gas_allocated = MemoryValue::from<uint32_t>(6);
335 MemoryValue da_gas_allocated = MemoryValue::from<uint32_t>(7);
336 MemoryValue cd_size = MemoryValue::from<uint32_t>(8);
337 AppendOnlyTreeSnapshot written_public_data_slots_tree_snapshot = AppendOnlyTreeSnapshot{
338 .root = 0x12345678,
339 .nextAvailableLeafIndex = 10,
340 };
341 TreeStates tree_states =
342 TreeStates{ .noteHashTree = { .tree = { .root = 10, .nextAvailableLeafIndex = 9 }, .counter = 8 },
343 .nullifierTree = { .tree = { .root = 7, .nextAvailableLeafIndex = 6 }, .counter = 5 },
344 .l1ToL2MessageTree = { .tree = { .root = 4, .nextAvailableLeafIndex = 3 }, .counter = 0 },
345 .publicDataTree = { .tree = { .root = 2, .nextAvailableLeafIndex = 1 }, .counter = 1 } };
346 SideEffectStates side_effect_states = SideEffectStates{ .numUnencryptedLogFields = 1, .numL2ToL1Messages = 2 };
347
348 auto setup_context_expectations = [&](bool parent_is_static) {
349 EXPECT_CALL(gas_tracker, compute_gas_limit_for_call(Gas{ 6, 7 })).WillOnce(Return(Gas{ 2, 3 }));
350 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
351 EXPECT_CALL(context, get_context_id);
352 EXPECT_CALL(context, get_parent_id);
353 EXPECT_CALL(context, get_bytecode_manager).WillOnce(ReturnRef(bytecode_manager));
354 EXPECT_CALL(bytecode_manager, get_retrieved_bytecode_id).WillOnce(Return(FF(1)));
355 EXPECT_CALL(context, get_next_pc);
356 EXPECT_CALL(context, get_is_static).WillRepeatedly(Return(parent_is_static));
357 EXPECT_CALL(context, get_msg_sender).WillOnce(ReturnRef(parent_address));
358 EXPECT_CALL(context, get_transaction_fee).WillOnce(ReturnRef(zero));
359 EXPECT_CALL(context, get_parent_cd_addr);
360 EXPECT_CALL(context, get_parent_cd_size);
361 EXPECT_CALL(context, get_parent_gas_used);
362 EXPECT_CALL(context, get_parent_gas_limit);
363 EXPECT_CALL(context, get_written_public_data_slots_tree_snapshot)
364 .WillOnce(Return(written_public_data_slots_tree_snapshot));
365 EXPECT_CALL(context, get_side_effect_states).WillRepeatedly(ReturnRef(side_effect_states));
366 EXPECT_CALL(context, get_phase).WillOnce(Return(TransactionPhase::APP_LOGIC));
367 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_states));
368 EXPECT_CALL(context, get_memory);
369 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(parent_address));
370 EXPECT_CALL(memory, get(1)).WillOnce(ReturnRef(l2_gas_allocated));
371 EXPECT_CALL(memory, get(2)).WillOnce(ReturnRef(da_gas_allocated));
372 EXPECT_CALL(memory, get(3)).WillOnce(ReturnRef(nested_address_value));
373 EXPECT_CALL(memory, get(4)).WillOnce(ReturnRef(cd_size));
374 };
375
376 auto create_nested_context = []() {
378 ON_CALL(*nested, halted()).WillByDefault(Return(true));
379 return nested;
380 };
381
382 // Test Case 1: Non-static context + CALL -> nested context is non-static
383 setup_context_expectations(false);
384 EXPECT_CALL(context_provider,
385 make_nested_context(nested_address,
386 parent_address,
387 _,
388 _,
389 _,
390 _,
391 /*is_static=*/false,
392 Gas{ 2, 3 },
393 side_effect_states,
395 .WillOnce(Return(create_nested_context()));
396 execution.call(context, 1, 2, 3, 4, 5);
397
398 // Test Case 2: Non-static context + STATICCALL -> nested context is static
399 setup_context_expectations(false);
400 EXPECT_CALL(context_provider,
401 make_nested_context(nested_address,
402 parent_address,
403 _,
404 _,
405 _,
406 _,
407 /*is_static=*/true,
408 Gas{ 2, 3 },
409 side_effect_states,
411 .WillOnce(Return(create_nested_context()));
412 execution.static_call(context, 1, 2, 3, 4, 5);
413
414 // Test Case 3: Static context + CALL -> nested context remains static
415 setup_context_expectations(true);
416 EXPECT_CALL(context_provider,
417 make_nested_context(nested_address,
418 parent_address,
419 _,
420 _,
421 _,
422 _,
423 /*is_static=*/true,
424 Gas{ 2, 3 },
425 side_effect_states,
427 .WillOnce(Return(create_nested_context()));
428 execution.call(context, 1, 2, 3, 4, 5);
429
430 // Test Case 4: Static context + STATICCALL -> nested context remains static
431 setup_context_expectations(true);
432 EXPECT_CALL(context_provider,
433 make_nested_context(nested_address,
434 parent_address,
435 _,
436 _,
437 _,
438 _,
439 /*is_static=*/true,
440 Gas{ 2, 3 },
441 side_effect_states,
443 .WillOnce(Return(create_nested_context()));
444 execution.static_call(context, 1, 2, 3, 4, 5);
445}
446
447TEST_F(ExecutionSimulationTest, InternalCall)
448{
449 uint32_t return_pc = 500; // This is next pc that we should return to after the internal call.
450 uint32_t pc_loc = 11; // This is the pc of the internal call
451
452 NiceMock<MockInternalCallStackManager> internal_call_stack_manager;
453 ON_CALL(context, get_internal_call_stack_manager).WillByDefault(ReturnRef(internal_call_stack_manager));
454
455 // ==== Internal Call
456 // Get manager
457 EXPECT_CALL(context, get_internal_call_stack_manager());
458 // Store the return pc (i.e. context.get_next_pc())
459 EXPECT_CALL(context, get_next_pc()).WillOnce(Return(return_pc));
460 EXPECT_CALL(internal_call_stack_manager, push(return_pc));
461 // Set next pc to the parameter pc_loc
462 EXPECT_CALL(context, set_next_pc(pc_loc));
463 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
464
465 execution.internal_call(context, pc_loc);
466
467 // ==== Internal Return
468 // Get manager
469 EXPECT_CALL(context, get_internal_call_stack_manager());
470 // Pop the return pc from the stack
471 EXPECT_CALL(internal_call_stack_manager, pop()).WillOnce(Return(return_pc));
472 // Set the next pc to the return pc
473 EXPECT_CALL(context, set_next_pc(return_pc));
474 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
475
476 execution.internal_return(context);
477}
478
479TEST_F(ExecutionSimulationTest, GetEnvVarAddress)
480{
481 AztecAddress addr = 0xdeadbeef;
482 EXPECT_CALL(context, get_address).WillOnce(ReturnRef(addr));
483 EXPECT_CALL(context, get_memory);
484 EXPECT_CALL(memory, set(1, MemoryValue::from<FF>(addr)));
485 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
486
487 execution.get_env_var(context, 1, static_cast<uint8_t>(EnvironmentVariable::ADDRESS));
488}
489
490TEST_F(ExecutionSimulationTest, GetEnvVarChainId)
491{
492 GlobalVariables globals;
493 globals.chainId = 1;
494 EXPECT_CALL(context, get_globals).WillOnce(ReturnRef(globals));
495 EXPECT_CALL(context, get_memory);
496 EXPECT_CALL(memory, set(1, MemoryValue::from<FF>(1)));
497 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
498
499 execution.get_env_var(context, 1, static_cast<uint8_t>(EnvironmentVariable::CHAINID));
500}
501
502TEST_F(ExecutionSimulationTest, GetEnvVarIsStaticCall)
503{
504 EXPECT_CALL(context, get_is_static).WillOnce(Return(true));
505 EXPECT_CALL(context, get_memory);
506 EXPECT_CALL(memory, set(1, MemoryValue::from<uint1_t>(1)));
507 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
508
509 execution.get_env_var(context, 1, static_cast<uint8_t>(EnvironmentVariable::ISSTATICCALL));
510}
511
512TEST_F(ExecutionSimulationTest, GetEnvVarInvalidEnum)
513{
514 EXPECT_CALL(context, get_memory);
515 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
516
517 EXPECT_THROW(execution.get_env_var(context, 1, 255), std::runtime_error);
518}
519
520// Trivial test at the moment.
521// TODO: Attempt to have infra to call execution.execute() with a JUMP and a second instruction
522// and check the pc value for the second instruction is correct.
523TEST_F(ExecutionSimulationTest, Jump)
524{
525 EXPECT_CALL(context, set_next_pc(120));
526 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
527
528 execution.jump(context, 120);
529}
530
531TEST_F(ExecutionSimulationTest, SuccessCopyTrue)
532{
533 EXPECT_CALL(context, get_memory);
534 EXPECT_CALL(context, get_last_success).WillOnce(Return(true));
535 EXPECT_CALL(memory, set(10, MemoryValue::from<uint1_t>(1)));
536 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
537
538 execution.success_copy(context, 10);
539}
540
541TEST_F(ExecutionSimulationTest, SuccessCopyFalse)
542{
543 EXPECT_CALL(context, get_memory);
544 EXPECT_CALL(context, get_last_success).WillOnce(Return(false));
545 EXPECT_CALL(memory, set(10, MemoryValue::from<uint1_t>(0)));
546 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
547
548 execution.success_copy(context, 10);
549}
550
551TEST_F(ExecutionSimulationTest, RdSize)
552{
553 EXPECT_CALL(context, get_memory);
554 EXPECT_CALL(context, get_last_rd_size).WillOnce(Return(42));
555 EXPECT_CALL(memory, set(10, MemoryValue::from<uint32_t>(42)));
556 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
557
558 execution.rd_size(context, /*dst_addr=*/10);
559}
560
561TEST_F(ExecutionSimulationTest, DebugLog)
562{
563 // Setup test data
564 MemoryAddress level_offset = 50;
565 MemoryAddress message_offset = 100;
566 MemoryAddress fields_offset = 200;
567 MemoryAddress fields_size_offset = 300;
568 uint16_t message_size = 5;
569 AztecAddress address = 0xdeadbeef;
570
571 EXPECT_CALL(context, get_memory);
572 EXPECT_CALL(context, get_address).WillOnce(ReturnRef(address));
573 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
574 EXPECT_CALL(debug_log,
575 debug_log(_, address, level_offset, message_offset, message_size, fields_offset, fields_size_offset));
576
577 execution.debug_log(context, level_offset, message_offset, fields_offset, fields_size_offset, message_size);
578}
579
580TEST_F(ExecutionSimulationTest, Sload)
581{
582 MemoryAddress slot_addr = 27;
584 AztecAddress address = 0xdeadbeef;
585 auto slot = MemoryValue::from<FF>(42);
586
587 EXPECT_CALL(context, get_memory);
588
589 EXPECT_CALL(memory, get(slot_addr)).WillOnce(ReturnRef(slot));
590 EXPECT_CALL(context, get_address).WillOnce(ReturnRef(address));
591 EXPECT_CALL(merkle_db, storage_read(address, slot.as<FF>())).WillOnce(Return(7));
592
593 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<FF>(7)));
594 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
595
596 execution.sload(context, slot_addr, dst_addr);
597}
598
599TEST_F(ExecutionSimulationTest, SStore)
600{
601 MemoryAddress slot_addr = 27;
602 MemoryAddress value_addr = 10;
603 AztecAddress address = 0xdeadbeef;
604 auto slot = MemoryValue::from<FF>(42);
605 auto value = MemoryValue::from<FF>(7);
606 TreeStates tree_state = {};
607 EXPECT_CALL(context, get_memory);
608
609 EXPECT_CALL(memory, get(slot_addr)).WillOnce(ReturnRef(slot));
610 EXPECT_CALL(memory, get(value_addr)).WillOnce(ReturnRef(value));
611 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
612 EXPECT_CALL(merkle_db, was_storage_written(address, slot.as<FF>())).WillOnce(Return(false));
613 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
614 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 1 }));
615
616 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
617
618 EXPECT_CALL(merkle_db, storage_write(address, slot.as<FF>(), value.as<FF>(), false));
619
620 execution.sstore(context, value_addr, slot_addr);
621}
622
623TEST_F(ExecutionSimulationTest, SStoreDuringStaticCall)
624{
625 MemoryAddress slot_addr = 27;
626 MemoryAddress value_addr = 10;
627 AztecAddress address = 0xdeadbeef;
628 auto slot = MemoryValue::from<FF>(42);
629 auto value = MemoryValue::from<FF>(7);
630 EXPECT_CALL(context, get_memory);
631
632 EXPECT_CALL(memory, get(slot_addr)).WillOnce(ReturnRef(slot));
633 EXPECT_CALL(memory, get(value_addr)).WillOnce(ReturnRef(value));
634 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
635 EXPECT_CALL(merkle_db, was_storage_written(address, slot.as<FF>())).WillOnce(Return(false));
636 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 1 }));
637
638 EXPECT_CALL(context, get_is_static).WillOnce(Return(true));
639 EXPECT_THROW_WITH_MESSAGE(execution.sstore(context, value_addr, slot_addr),
640 "SSTORE: Cannot write to storage in static context");
641}
642
643TEST_F(ExecutionSimulationTest, SStoreLimitReached)
644{
645 MemoryAddress slot_addr = 27;
646 MemoryAddress value_addr = 10;
647 AztecAddress address = 0xdeadbeef;
648 auto slot = MemoryValue::from<FF>(42);
649 auto value = MemoryValue::from<FF>(7);
650 TreeStates tree_state = {};
651 tree_state.publicDataTree.counter = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX;
652 EXPECT_CALL(context, get_memory);
653
654 EXPECT_CALL(memory, get(slot_addr)).WillOnce(ReturnRef(slot));
655 EXPECT_CALL(memory, get(value_addr)).WillOnce(ReturnRef(value));
656 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
657 EXPECT_CALL(merkle_db, was_storage_written(address, slot.as<FF>())).WillOnce(Return(false));
658 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
659 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 1 }));
660
661 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
662
663 EXPECT_THROW_WITH_MESSAGE(execution.sstore(context, value_addr, slot_addr),
664 "SSTORE: Maximum number of data writes reached");
665}
666
667TEST_F(ExecutionSimulationTest, SStoreLimitReachedSquashed)
668{
669 MemoryAddress slot_addr = 27;
670 MemoryAddress value_addr = 10;
671 AztecAddress address = 0xdeadbeef;
672 auto slot = MemoryValue::from<FF>(42);
673 auto value = MemoryValue::from<FF>(7);
674 TreeStates tree_state = {};
675 tree_state.publicDataTree.counter = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX;
676 EXPECT_CALL(context, get_memory);
677
678 EXPECT_CALL(memory, get(slot_addr)).WillOnce(ReturnRef(slot));
679 EXPECT_CALL(memory, get(value_addr)).WillOnce(ReturnRef(value));
680 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
681 // has been written before, so it does not count against the limit.
682 EXPECT_CALL(merkle_db, was_storage_written(address, slot.as<FF>())).WillOnce(Return(true));
683 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
684
685 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
686
687 EXPECT_CALL(merkle_db, storage_write(address, slot.as<FF>(), value.as<FF>(), false));
688
689 execution.sstore(context, value_addr, slot_addr);
690}
691
692TEST_F(ExecutionSimulationTest, NoteHashExists)
693{
694 MemoryAddress unique_note_hash_addr = 10;
695 MemoryAddress leaf_index_addr = 11;
697
698 auto unique_note_hash = MemoryValue::from<FF>(42);
699 auto leaf_index = MemoryValue::from<uint64_t>(7);
700
701 EXPECT_CALL(context, get_memory);
702 EXPECT_CALL(memory, get(unique_note_hash_addr)).WillOnce(ReturnRef(unique_note_hash));
703 EXPECT_CALL(memory, get(leaf_index_addr)).WillOnce(ReturnRef(leaf_index));
704
705 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
706
707 EXPECT_CALL(greater_than, gt(NOTE_HASH_TREE_LEAF_COUNT, leaf_index.as<uint64_t>())).WillOnce(Return(true));
708
709 EXPECT_CALL(merkle_db, note_hash_exists(leaf_index.as<uint64_t>(), unique_note_hash.as<FF>()))
710 .WillOnce(Return(true));
711
712 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint1_t>(1)));
713
714 execution.note_hash_exists(context, unique_note_hash_addr, leaf_index_addr, dst_addr);
715}
716
717TEST_F(ExecutionSimulationTest, NoteHashExistsOutOfRange)
718{
719 MemoryAddress unique_note_hash_addr = 10;
720 MemoryAddress leaf_index_addr = 11;
722
723 auto unique_note_hash = MemoryValue::from<FF>(42);
724 auto leaf_index = MemoryValue::from<uint64_t>(NOTE_HASH_TREE_LEAF_COUNT + 1);
725
726 EXPECT_CALL(context, get_memory);
727 EXPECT_CALL(memory, get(unique_note_hash_addr)).WillOnce(ReturnRef(unique_note_hash));
728 EXPECT_CALL(memory, get(leaf_index_addr)).WillOnce(ReturnRef(leaf_index));
729
730 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
731
732 EXPECT_CALL(greater_than, gt(NOTE_HASH_TREE_LEAF_COUNT, leaf_index.as<uint64_t>())).WillOnce(Return(false));
733
734 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint1_t>(0)));
735
736 execution.note_hash_exists(context, unique_note_hash_addr, leaf_index_addr, dst_addr);
737}
738
739TEST_F(ExecutionSimulationTest, EmitNoteHash)
740{
741 MemoryAddress note_hash_addr = 10;
742
743 auto note_hash = MemoryValue::from<FF>(42);
744 AztecAddress address = 0xdeadbeef;
745 TreeStates tree_state = {};
746
747 EXPECT_CALL(context, get_memory);
748 EXPECT_CALL(memory, get(note_hash_addr)).WillOnce(ReturnRef(note_hash));
749 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
750
751 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
752
753 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
754 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
755 EXPECT_CALL(merkle_db, note_hash_write(address, note_hash.as<FF>()));
756
757 execution.emit_note_hash(context, note_hash_addr);
758}
759
760TEST_F(ExecutionSimulationTest, EmitNoteHashDuringStaticCall)
761{
762 MemoryAddress note_hash_addr = 10;
763
764 auto note_hash = MemoryValue::from<FF>(42);
765 AztecAddress address = 0xdeadbeef;
766
767 EXPECT_CALL(context, get_memory);
768 EXPECT_CALL(memory, get(note_hash_addr)).WillOnce(ReturnRef(note_hash));
769 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
770
771 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
772
773 EXPECT_CALL(context, get_is_static).WillOnce(Return(true));
774 EXPECT_THROW_WITH_MESSAGE(execution.emit_note_hash(context, note_hash_addr),
775 "EMITNOTEHASH: Cannot emit note hash in static context");
776}
777
778TEST_F(ExecutionSimulationTest, EmitNoteHashLimitReached)
779{
780 MemoryAddress note_hash_addr = 10;
781
782 auto note_hash = MemoryValue::from<FF>(42);
783 AztecAddress address = 0xdeadbeef;
784 TreeStates tree_state = {};
785 tree_state.noteHashTree.counter = MAX_NOTE_HASHES_PER_TX;
786
787 EXPECT_CALL(context, get_memory);
788 EXPECT_CALL(memory, get(note_hash_addr)).WillOnce(ReturnRef(note_hash));
789 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
790
791 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
792
793 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
794 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
795
796 EXPECT_THROW_WITH_MESSAGE(execution.emit_note_hash(context, note_hash_addr),
797 "EMITNOTEHASH: Maximum number of note hashes reached");
798}
799
800TEST_F(ExecutionSimulationTest, L1ToL2MessageExists)
801{
802 MemoryAddress msg_hash_addr = 10;
803 MemoryAddress leaf_index_addr = 11;
805
806 auto msg_hash = MemoryValue::from<FF>(42);
807 auto leaf_index = MemoryValue::from<uint64_t>(7);
808
809 EXPECT_CALL(context, get_memory);
810 EXPECT_CALL(memory, get(msg_hash_addr)).WillOnce(ReturnRef(msg_hash));
811 EXPECT_CALL(memory, get(leaf_index_addr)).WillOnce(ReturnRef(leaf_index));
812
813 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
814
815 EXPECT_CALL(greater_than, gt(L1_TO_L2_MSG_TREE_LEAF_COUNT, leaf_index.as<uint64_t>())).WillOnce(Return(true));
816
817 EXPECT_CALL(merkle_db, l1_to_l2_msg_exists(leaf_index.as<uint64_t>(), msg_hash.as<FF>())).WillOnce(Return(true));
818
819 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint1_t>(1)));
820
821 execution.l1_to_l2_message_exists(context, msg_hash_addr, leaf_index_addr, dst_addr);
822}
823
824TEST_F(ExecutionSimulationTest, L1ToL2MessageExistsOutOfRange)
825{
826 MemoryAddress msg_hash_addr = 10;
827 MemoryAddress leaf_index_addr = 11;
829
830 auto msg_hash = MemoryValue::from<FF>(42);
831 auto leaf_index = MemoryValue::from<uint64_t>(L1_TO_L2_MSG_TREE_LEAF_COUNT + 1);
832
833 EXPECT_CALL(context, get_memory);
834 EXPECT_CALL(memory, get(msg_hash_addr)).WillOnce(ReturnRef(msg_hash));
835 EXPECT_CALL(memory, get(leaf_index_addr)).WillOnce(ReturnRef(leaf_index));
836
837 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
838
839 EXPECT_CALL(greater_than, gt(L1_TO_L2_MSG_TREE_LEAF_COUNT, leaf_index.as<uint64_t>())).WillOnce(Return(false));
840
841 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint1_t>(0)));
842
843 execution.l1_to_l2_message_exists(context, msg_hash_addr, leaf_index_addr, dst_addr);
844}
845
846TEST_F(ExecutionSimulationTest, NullifierExists)
847{
848 MemoryAddress nullifier_offset = 10;
849 MemoryAddress address_offset = 11;
850 MemoryAddress exists_offset = 12;
851
852 auto nullifier = MemoryValue::from<FF>(42);
853 auto address = MemoryValue::from<FF>(7);
854
855 EXPECT_CALL(context, get_memory);
856 EXPECT_CALL(memory, get(nullifier_offset)).WillOnce(ReturnRef(nullifier));
857 EXPECT_CALL(memory, get(address_offset)).WillOnce(ReturnRef(address));
858
859 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
860
861 EXPECT_CALL(merkle_db, nullifier_exists(address.as_ff(), nullifier.as_ff())).WillOnce(Return(true));
862
863 EXPECT_CALL(memory, set(exists_offset, MemoryValue::from<uint1_t>(1)));
864
865 execution.nullifier_exists(context, nullifier_offset, address_offset, exists_offset);
866}
867
868TEST_F(ExecutionSimulationTest, EmitNullifier)
869{
870 MemoryAddress nullifier_addr = 10;
871
872 auto nullifier = MemoryValue::from<FF>(42);
873 AztecAddress address = 0xdeadbeef;
874 TreeStates tree_state = {};
875
876 EXPECT_CALL(context, get_memory);
877 EXPECT_CALL(memory, get(nullifier_addr)).WillOnce(ReturnRef(nullifier));
878 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
879
880 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
881
882 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
883 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
884 EXPECT_CALL(merkle_db, nullifier_write(address, nullifier.as_ff())).WillOnce(Return()); // success
885
886 execution.emit_nullifier(context, nullifier_addr);
887}
888
889TEST_F(ExecutionSimulationTest, EmitNullifierDuringStaticCall)
890{
891 MemoryAddress nullifier_addr = 10;
892
893 auto nullifier = MemoryValue::from<FF>(42);
894 AztecAddress address = 0xdeadbeef;
895
896 EXPECT_CALL(context, get_memory);
897 EXPECT_CALL(memory, get(nullifier_addr)).WillOnce(ReturnRef(nullifier));
898 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
899
900 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
901
902 EXPECT_CALL(context, get_is_static).WillOnce(Return(true));
903 EXPECT_THROW_WITH_MESSAGE(execution.emit_nullifier(context, nullifier_addr),
904 "EMITNULLIFIER: Cannot emit nullifier in static context");
905}
906
907TEST_F(ExecutionSimulationTest, EmitNullifierLimitReached)
908{
909 MemoryAddress nullifier_addr = 10;
910
911 auto nullifier = MemoryValue::from<FF>(42);
912 AztecAddress address = 0xdeadbeef;
913 TreeStates tree_state = {};
914 tree_state.nullifierTree.counter = MAX_NULLIFIERS_PER_TX;
915
916 EXPECT_CALL(context, get_memory);
917 EXPECT_CALL(memory, get(nullifier_addr)).WillOnce(ReturnRef(nullifier));
918 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
919
920 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
921
922 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
923 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
924
925 EXPECT_THROW_WITH_MESSAGE(execution.emit_nullifier(context, nullifier_addr),
926 "EMITNULLIFIER: Maximum number of nullifiers reached");
927}
928
929TEST_F(ExecutionSimulationTest, EmitNullifierCollision)
930{
931 MemoryAddress nullifier_addr = 10;
932
933 auto nullifier = MemoryValue::from<FF>(42);
934 AztecAddress address = 0xdeadbeef;
935 TreeStates tree_state = {};
936
937 EXPECT_CALL(context, get_memory);
938 EXPECT_CALL(memory, get(nullifier_addr)).WillOnce(ReturnRef(nullifier));
939 EXPECT_CALL(context, get_address).WillRepeatedly(ReturnRef(address));
940
941 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
942
943 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
944 EXPECT_CALL(merkle_db, get_tree_state).WillOnce(Return(tree_state));
945 EXPECT_CALL(merkle_db, nullifier_write(address, nullifier.as<FF>()))
946 .WillOnce(Throw(NullifierCollisionException("Nullifier collision"))); // collision
947
948 EXPECT_THROW_WITH_MESSAGE(execution.emit_nullifier(context, nullifier_addr), "EMITNULLIFIER: Nullifier collision");
949}
950
951TEST_F(ExecutionSimulationTest, Set)
952{
954 uint8_t dst_tag = static_cast<uint8_t>(MemoryTag::U8);
955 FF value = 7;
956
957 EXPECT_CALL(context, get_memory);
958 EXPECT_CALL(alu, truncate(value, static_cast<MemoryTag>(dst_tag))).WillOnce(Return(MemoryValue::from<uint8_t>(7)));
959 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint8_t>(7)));
960 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
961
962 execution.set(context, dst_addr, dst_tag, value);
963}
964
965TEST_F(ExecutionSimulationTest, Cast)
966{
967 MemoryAddress src_addr = 9;
969 uint8_t dst_tag = static_cast<uint8_t>(MemoryTag::U1);
970 MemoryValue value = MemoryValue::from<uint64_t>(7);
971
972 EXPECT_CALL(context, get_memory).WillOnce(ReturnRef(memory));
973 EXPECT_CALL(memory, get(src_addr)).WillOnce(ReturnRef(value));
974
975 EXPECT_CALL(alu, truncate(value.as_ff(), static_cast<MemoryTag>(dst_tag)))
976 .WillOnce(Return(MemoryValue::from<uint1_t>(1)));
977 EXPECT_CALL(memory, set(dst_addr, MemoryValue::from<uint1_t>(1)));
978 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
979
980 execution.cast(context, src_addr, dst_addr, dst_tag);
981}
982
983TEST_F(ExecutionSimulationTest, Poseidon2Perm)
984{
985 MemoryAddress src_address = 10;
986 MemoryAddress dst_address = 20;
987
988 EXPECT_CALL(context, get_memory);
989 EXPECT_CALL(gas_tracker, consume_gas);
990 EXPECT_CALL(poseidon2, permutation(_, src_address, dst_address));
991
992 execution.poseidon2_permutation(context, src_address, dst_address);
993}
994
995TEST_F(ExecutionSimulationTest, EccAdd)
996{
997 MemoryAddress p_x_addr = 10;
998 MemoryAddress p_y_addr = 15;
999 MemoryAddress p_is_inf_addr = 25;
1000 MemoryAddress q_x_addr = 20;
1001 MemoryAddress q_y_addr = 30;
1002 MemoryAddress q_is_inf_addr = 35;
1004
1005 MemoryValue p_x = MemoryValue::from<FF>(FF("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a"));
1006 MemoryValue p_y = MemoryValue::from<FF>(FF("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60"));
1007 EmbeddedCurvePoint p(p_x.as_ff(), p_y, false);
1008
1009 MemoryValue q_x = MemoryValue::from<FF>(FF("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7"));
1010 MemoryValue q_y = MemoryValue::from<FF>(FF("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3"));
1011 EmbeddedCurvePoint q(q_x.as_ff(), q_y.as_ff(), false);
1012
1013 // Mock the context and memory interactions
1014 MemoryValue zero = MemoryValue::from<uint1_t>(0);
1015 EXPECT_CALL(context, get_memory).WillRepeatedly(ReturnRef(memory));
1016 EXPECT_CALL(Const(memory), get(p_x_addr)).WillOnce(ReturnRef(p_x));
1017 EXPECT_CALL(memory, get(p_y_addr)).WillOnce(ReturnRef(p_y));
1018 EXPECT_CALL(memory, get(p_is_inf_addr)).WillOnce(ReturnRef(zero)); // p is not infinity
1019 EXPECT_CALL(memory, get(q_x_addr)).WillOnce(ReturnRef(q_x));
1020 EXPECT_CALL(memory, get(q_y_addr)).WillOnce(ReturnRef(q_y));
1021 EXPECT_CALL(memory, get(q_is_inf_addr)).WillOnce(ReturnRef(zero)); // q is not infinity
1022
1023 EXPECT_CALL(gas_tracker, consume_gas);
1024
1025 // Mock the ECC add operation
1026 EXPECT_CALL(ecc, add(_, _, _, dst_addr));
1027
1028 // Execute the ECC add operation
1029 execution.ecc_add(context, p_x_addr, p_y_addr, p_is_inf_addr, q_x_addr, q_y_addr, q_is_inf_addr, dst_addr);
1030}
1031
1032TEST_F(ExecutionSimulationTest, ToRadixBE)
1033{
1034 MemoryAddress value_addr = 5;
1035 MemoryAddress radix_addr = 6;
1036 MemoryAddress num_limbs_addr = 7;
1037 MemoryAddress is_output_bits_addr = 8;
1038
1040 MemoryValue value = MemoryValue::from<FF>(42069);
1041 MemoryValue radix = MemoryValue::from<uint32_t>(16);
1042 std::vector<MemoryValue> be_limbs = { MemoryValue::from<uint8_t>(0xa4),
1043 MemoryValue::from<uint8_t>(0x55),
1044 MemoryValue::from<uint8_t>(0x00) };
1045 MemoryValue num_limbs = MemoryValue::from<uint32_t>(3);
1046 MemoryValue is_output_bits = MemoryValue::from<uint1_t>(false);
1047 uint32_t num_p_limbs = 64;
1048
1049 EXPECT_CALL(context, get_memory).WillOnce(ReturnRef(memory));
1050 EXPECT_CALL(memory, get(value_addr)).WillOnce(ReturnRef(value));
1051 EXPECT_CALL(memory, get(radix_addr)).WillOnce(ReturnRef(radix));
1052 EXPECT_CALL(memory, get(num_limbs_addr)).WillOnce(ReturnRef(num_limbs));
1053 EXPECT_CALL(memory, get(is_output_bits_addr)).WillOnce(ReturnRef(is_output_bits));
1054
1055 EXPECT_CALL(greater_than, gt(radix.as<uint32_t>(), /*max_radix/*/ 256)).WillOnce(Return(false));
1056 EXPECT_CALL(greater_than, gt(num_limbs.as<uint32_t>(), num_p_limbs)).WillOnce(Return(false));
1057
1058 EXPECT_CALL(gas_tracker, consume_gas);
1059 EXPECT_CALL(to_radix, to_be_radix);
1060
1061 execution.to_radix_be(context, value_addr, radix_addr, num_limbs_addr, is_output_bits_addr, dst_addr);
1062}
1063
1064TEST_F(ExecutionSimulationTest, EmitUnencryptedLog)
1065{
1066 MemoryAddress log_offset = 10;
1067 MemoryAddress log_size_offset = 20;
1068 MemoryValue log_size = MemoryValue::from<uint32_t>(10);
1069 AztecAddress address = 0xdeadbeef;
1070
1071 EXPECT_CALL(context, get_memory);
1072 EXPECT_CALL(memory, get(log_size_offset)).WillOnce(ReturnRef(log_size));
1073
1074 EXPECT_CALL(context, get_address).WillOnce(ReturnRef(address));
1075
1076 EXPECT_CALL(emit_unencrypted_log, emit_unencrypted_log(_, _, address, log_offset, log_size.as<uint32_t>()));
1077
1078 EXPECT_CALL(gas_tracker, consume_gas(Gas{ log_size.as<uint32_t>(), log_size.as<uint32_t>() }));
1079
1080 execution.emit_unencrypted_log(context, log_size_offset, log_offset);
1081}
1082
1083TEST_F(ExecutionSimulationTest, SendL2ToL1Msg)
1084{
1085 MemoryAddress recipient_addr = 10;
1086 MemoryAddress content_addr = 11;
1087
1088 auto recipient = MemoryValue::from<FF>(42);
1089 auto content = MemoryValue::from<FF>(27);
1090
1091 SideEffectStates side_effects_states = {};
1092 side_effects_states.numL2ToL1Messages = MAX_L2_TO_L1_MSGS_PER_TX - 1;
1093 SideEffectStates side_effects_states_after = side_effects_states;
1094 side_effects_states_after.numL2ToL1Messages++;
1095
1096 EXPECT_CALL(context, get_memory);
1097
1098 EXPECT_CALL(memory, get(recipient_addr)).WillOnce(ReturnRef(recipient));
1099 EXPECT_CALL(memory, get(content_addr)).WillOnce(ReturnRef(content));
1100
1101 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
1102
1103 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
1104
1105 EXPECT_CALL(context, get_side_effect_states).WillOnce(ReturnRef(side_effects_states));
1106 EXPECT_CALL(context, set_side_effect_states(side_effects_states_after));
1107
1108 execution.send_l2_to_l1_msg(context, recipient_addr, content_addr);
1109}
1110
1111TEST_F(ExecutionSimulationTest, SendL2ToL1MsgStaticCall)
1112{
1113 MemoryAddress recipient_addr = 10;
1114 MemoryAddress content_addr = 11;
1115
1116 auto recipient = MemoryValue::from<FF>(42);
1117 auto content = MemoryValue::from<FF>(27);
1118
1119 SideEffectStates side_effects_states = {};
1120 side_effects_states.numL2ToL1Messages = MAX_L2_TO_L1_MSGS_PER_TX - 1;
1121
1122 EXPECT_CALL(context, get_memory);
1123
1124 EXPECT_CALL(memory, get(recipient_addr)).WillOnce(ReturnRef(recipient));
1125 EXPECT_CALL(memory, get(content_addr)).WillOnce(ReturnRef(content));
1126
1127 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
1128
1129 EXPECT_CALL(context, get_is_static).WillOnce(Return(true));
1130
1131 EXPECT_CALL(context, get_side_effect_states).WillOnce(ReturnRef(side_effects_states));
1132
1133 EXPECT_THROW_WITH_MESSAGE(execution.send_l2_to_l1_msg(context, recipient_addr, content_addr),
1134 "SENDL2TOL1MSG: Cannot send L2 to L1 message in static context");
1135}
1136
1137TEST_F(ExecutionSimulationTest, SendL2ToL1MsgLimitReached)
1138{
1139 MemoryAddress recipient_addr = 10;
1140 MemoryAddress content_addr = 11;
1141
1142 auto recipient = MemoryValue::from<FF>(42);
1143 auto content = MemoryValue::from<FF>(27);
1144
1145 SideEffectStates side_effects_states = {};
1146 side_effects_states.numL2ToL1Messages = MAX_L2_TO_L1_MSGS_PER_TX;
1147
1148 EXPECT_CALL(context, get_memory);
1149
1150 EXPECT_CALL(memory, get(recipient_addr)).WillOnce(ReturnRef(recipient));
1151 EXPECT_CALL(memory, get(content_addr)).WillOnce(ReturnRef(content));
1152
1153 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
1154
1155 EXPECT_CALL(context, get_is_static).WillOnce(Return(false));
1156
1157 EXPECT_CALL(context, get_side_effect_states).WillOnce(ReturnRef(side_effects_states));
1158
1159 EXPECT_THROW_WITH_MESSAGE(execution.send_l2_to_l1_msg(context, recipient_addr, content_addr),
1160 "SENDL2TOL1MSG: Maximum number of L2 to L1 messages reached");
1161}
1162
1163TEST_F(ExecutionSimulationTest, Sha256Compression)
1164{
1165 MemoryAddress state_address = 10;
1166 MemoryAddress input_address = 20;
1167 MemoryAddress dst_address = 50;
1168
1169 EXPECT_CALL(context, get_memory);
1170 EXPECT_CALL(gas_tracker, consume_gas(Gas{ 0, 0 }));
1171 EXPECT_CALL(sha256, compression(_, state_address, input_address, dst_address));
1172
1173 execution.sha256_compression(context, dst_address, state_address, input_address);
1174}
1175
1176} // namespace
1177
1178} // namespace bb::avm2::simulation
MemoryTag dst_tag
#define NOTE_HASH_TREE_LEAF_COUNT
#define L1_TO_L2_MSG_TREE_LEAF_COUNT
#define MAX_L2_TO_L1_MSGS_PER_TX
#define MAX_NOTE_HASHES_PER_TX
#define MAX_NULLIFIERS_PER_TX
#define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
StrictMock< MockHighLevelMerkleDB > merkle_db
Applies the Poseidon2 permutation function from https://eprint.iacr.org/2023/323 ....
ExecutionIdManager execution_id_manager
uint32_t dst_addr
GreaterThan gt
StrictMock< MockContext > context
FF a
FF b
InstructionInfoDB instruction_info_db
testing::StrictMock< MockGreaterThan > greater_than
smt_circuit::STerm shr(smt_circuit::STerm v0, smt_circuit::STerm v1, smt_solver::Solver *solver)
Right shift operation.
Definition helpers.cpp:40
smt_circuit::STerm shl(smt_circuit::STerm v0, smt_circuit::STerm v1, smt_solver::Solver *solver)
Left shift operation without truncation.
Definition helpers.cpp:34
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
TaggedValue MemoryValue
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
uint256_t get_tag_max_value(ValueTag tag)
uint32_t MemoryAddress
ValueTag MemoryTag
AvmFlavorSettings::FF FF
Definition field.hpp:10
Sha256Hash sha256(const ByteContainer &input)
Definition sha256.cpp:142
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:188
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44
bb::crypto::Poseidon2< bb::crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
Bitwise bitwise
DataCopy data_copy
MemoryStore memory
NiceMock< MockContextProvider > context_provider
NiceMock< MockExecution > execution