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