1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
32using simulation::EmitUnencryptedLogWriteEvent;
33using simulation::TrackedSideEffects;
34using testing::PublicInputsBuilder;
35using tracegen::EmitUnencryptedLogTraceBuilder;
36using tracegen::MemoryTraceBuilder;
37using tracegen::PrecomputedTraceBuilder;
38using tracegen::PublicInputsTraceBuilder;
39using tracegen::TestTraceContainer;
47 memory_values.reserve(fields.size());
48 for (
const FF&
field : fields) {
49 memory_values.push_back(MemoryValue::from<FF>(
field));
54TEST(EmitUnencryptedLogConstrainingTest, EmptyTrace)
59TEST(EmitUnencryptedLogConstrainingTest, Positive)
63 const std::vector<FF> log_fields = { 4, 5 };
64 uint32_t log_size =
static_cast<uint32_t
>(log_fields.size());
65 TrackedSideEffects side_effect_states = { .public_logs = {} };
66 TrackedSideEffects side_effect_states_after = { .public_logs = PublicLogs{ { { log_fields,
address } } } };
68 EmitUnencryptedLogWriteEvent
event = {
72 .log_address = log_address,
74 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
75 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
77 .values = to_memory_values(log_fields),
78 .error_memory_out_of_bounds =
false,
79 .error_too_many_log_fields =
false,
80 .error_tag_mismatch =
false,
83 TestTraceContainer
trace({
84 { { C::precomputed_first_row, 1 } },
87 EmitUnencryptedLogTraceBuilder trace_builder;
88 trace_builder.process({
event },
trace);
90 check_relation<emit_unencrypted_log>(trace);
93TEST(EmitUnencryptedLogConstrainingTest, PositiveEmptyLog)
98 const std::vector<FF> log_fields = {};
99 uint32_t log_size =
static_cast<uint32_t
>(log_fields.size());
100 TrackedSideEffects side_effect_states = { .public_logs = {} };
101 TrackedSideEffects side_effect_states_after = { .public_logs = PublicLogs{ { { log_fields,
address } } } };
103 EmitUnencryptedLogWriteEvent
event = {
107 .log_address = log_address,
108 .log_size = log_size,
109 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
110 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
112 .values = to_memory_values(log_fields),
113 .error_memory_out_of_bounds =
false,
114 .error_too_many_log_fields =
false,
115 .error_tag_mismatch =
false,
119 uint64_t end_log_address_upper_bound =
static_cast<uint64_t
>(log_address) +
static_cast<uint64_t
>(log_size);
121 simulation::GreaterThanEvent gt_event = {
122 .a = end_log_address_upper_bound,
127 TestTraceContainer
trace({
128 { { C::precomputed_first_row, 1 } },
131 EmitUnencryptedLogTraceBuilder trace_builder;
134 trace_builder.process({
event },
trace);
137 FF end_log_address_upper_bound_log_trace =
trace.
get(C::emit_unencrypted_log_end_log_address_upper_bound, 1);
138 FF end_log_address_upper_bound_gt_trace =
trace.
get(C::gt_input_a, 0);
139 EXPECT_EQ(end_log_address_upper_bound_log_trace, end_log_address_upper_bound_gt_trace);
141 check_relation<emit_unencrypted_log>(trace);
142 check_interaction<EmitUnencryptedLogTraceBuilder, lookup_emit_unencrypted_log_check_memory_out_of_bounds_settings>(
146TEST(EmitUnencryptedLogConstrainingTest, ErrorMemoryOutOfBounds)
150 uint32_t log_size = 2;
151 TrackedSideEffects side_effect_states = { .public_logs = PublicLogs{ { { { 4 },
address } } } };
152 const TrackedSideEffects& side_effect_states_after = side_effect_states;
154 EmitUnencryptedLogWriteEvent
event = {
158 .log_address = log_address,
159 .log_size = log_size,
160 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
161 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
164 .error_memory_out_of_bounds =
true,
165 .error_too_many_log_fields =
false,
166 .error_tag_mismatch =
false,
169 TestTraceContainer
trace({
170 { { C::precomputed_first_row, 1 } },
173 EmitUnencryptedLogTraceBuilder trace_builder;
174 trace_builder.process({
event },
trace);
176 check_relation<emit_unencrypted_log>(trace);
179TEST(EmitUnencryptedLogConstrainingTest, ErrorTooManyLogFields)
183 const std::vector<FF> log_fields = { 4, 5 };
184 uint32_t log_size =
static_cast<uint32_t
>(log_fields.size());
186 TrackedSideEffects side_effect_states = {
189 const TrackedSideEffects& side_effect_states_after = side_effect_states;
191 EmitUnencryptedLogWriteEvent
event = {
195 .log_address = log_address,
196 .log_size = log_size,
197 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
198 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
200 .values = to_memory_values(log_fields),
201 .error_memory_out_of_bounds =
false,
202 .error_too_many_log_fields =
true,
203 .error_tag_mismatch =
false,
206 TestTraceContainer
trace({
207 { { C::precomputed_first_row, 1 } },
210 EmitUnencryptedLogTraceBuilder trace_builder;
211 trace_builder.process({
event },
trace);
213 check_relation<emit_unencrypted_log>(trace);
216TEST(EmitUnencryptedLogConstrainingTest, ErrorTagMismatch)
221 uint32_t log_size =
static_cast<uint32_t
>(log_values.size());
222 TrackedSideEffects side_effect_states = { .public_logs = {} };
224 const TrackedSideEffects& side_effect_states_after = side_effect_states;
226 EmitUnencryptedLogWriteEvent
event = {
230 .log_address = log_address,
231 .log_size = log_size,
232 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
233 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
235 .values = log_values,
236 .error_memory_out_of_bounds =
false,
237 .error_too_many_log_fields =
false,
238 .error_tag_mismatch =
true,
241 TestTraceContainer
trace({
242 { { C::precomputed_first_row, 1 } },
245 EmitUnencryptedLogTraceBuilder trace_builder;
246 trace_builder.process({
event },
trace);
248 check_relation<emit_unencrypted_log>(trace);
251TEST(EmitUnencryptedLogConstrainingTest, ErrorStatic)
255 const std::vector<FF> log_fields = { 4, 5 };
256 uint32_t log_size =
static_cast<uint32_t
>(log_fields.size());
257 TrackedSideEffects side_effect_states = { .public_logs = PublicLogs{ { { { 4 },
address } } } };
258 const TrackedSideEffects& side_effect_states_after = side_effect_states;
260 EmitUnencryptedLogWriteEvent
event = {
264 .log_address = log_address,
265 .log_size = log_size,
266 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
267 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
269 .values = to_memory_values(log_fields),
270 .error_memory_out_of_bounds =
false,
271 .error_too_many_log_fields =
false,
272 .error_tag_mismatch =
false,
275 TestTraceContainer
trace({
276 { { C::precomputed_first_row, 1 } },
279 EmitUnencryptedLogTraceBuilder trace_builder;
280 trace_builder.process({
event },
trace);
283TEST(EmitUnencryptedLogConstrainingTest, Interactions)
287 const std::vector<FF> log_fields = { 4, 5 };
288 uint32_t log_size =
static_cast<uint32_t
>(log_fields.size());
289 TrackedSideEffects side_effect_states = { .public_logs = {} };
290 TrackedSideEffects side_effect_states_after = { .public_logs = PublicLogs{ { { log_fields,
address } } } };
291 AvmAccumulatedData accumulated_data = {};
292 accumulated_data.public_logs.add_log({
293 .fields = {
FF(4),
FF(5) },
296 auto public_inputs = PublicInputsBuilder().set_accumulated_data(accumulated_data).build();
300 EmitUnencryptedLogWriteEvent
event = {
304 .log_address = log_address,
305 .log_size = log_size,
306 .prev_num_unencrypted_log_fields = side_effect_states.get_num_unencrypted_log_fields(),
307 .next_num_unencrypted_log_fields = side_effect_states_after.get_num_unencrypted_log_fields(),
310 .error_memory_out_of_bounds =
false,
311 .error_too_many_log_fields =
false,
312 .error_tag_mismatch =
false,
315 TestTraceContainer
trace = TestTraceContainer({
318 { C::precomputed_first_row, 1 },
321 { C::gt_input_a, side_effect_states_after.get_num_unencrypted_log_fields() },
327 { C::execution_sel, 1 },
328 { C::execution_sel_exec_dispatch_emit_unencrypted_log, 1 },
329 { C::execution_context_id, 57 },
330 { C::execution_rop_1_, log_address },
331 { C::execution_register_0_, log_size },
332 { C::execution_contract_address,
address },
333 { C::execution_prev_num_unencrypted_log_fields, side_effect_states.get_num_unencrypted_log_fields() },
334 { C::execution_num_unencrypted_log_fields, side_effect_states_after.get_num_unencrypted_log_fields() },
335 { C::execution_is_static,
false },
336 { C::execution_sel_opcode_error, 0 },
337 { C::execution_discard, 0 },
340 { C::gt_input_a, log_address + log_size },
347 for (uint32_t i = 0; i <
inputs.size(); ++i) {
349 trace.
set(C::memory_address, i + 1, log_address + i);
351 trace.
set(C::memory_tag, i + 1,
static_cast<uint32_t
>(
inputs[i].get_tag()));
355 trace.
set(C::memory_space_id, i + 1, 57);
365 EmitUnencryptedLogTraceBuilder trace_builder;
366 trace_builder.process({
event },
trace);
368 check_relation<emit_unencrypted_log>(trace);
369 check_all_interactions<EmitUnencryptedLogTraceBuilder>(trace);
372TEST(EmitUnencryptedLogConstrainingTest, NegativeStartAfterLatch)
374 TestTraceContainer
trace = TestTraceContainer({ {
375 { C::precomputed_first_row, 1 },
378 { C::emit_unencrypted_log_sel, 1 },
379 { C::emit_unencrypted_log_start, 1 },
380 { C::emit_unencrypted_log_end, 1 },
383 { C::emit_unencrypted_log_sel, 1 },
384 { C::emit_unencrypted_log_start, 1 },
389 trace.
set(C::emit_unencrypted_log_end, 1, 0);
392 "START_AFTER_LATCH");
394 trace.
set(C::emit_unencrypted_log_end, 1, 1);
395 trace.
set(C::precomputed_first_row, 0, 0);
398 "START_AFTER_LATCH");
401TEST(EmitUnencryptedLogConstrainingTest, NegativeSelectorOnStart)
403 TestTraceContainer
trace = TestTraceContainer({ {
404 { C::emit_unencrypted_log_sel, 1 },
405 { C::emit_unencrypted_log_start, 1 },
410 trace.
set(C::emit_unencrypted_log_sel, 0, 0);
413 "SELECTOR_ON_START");
416TEST(EmitUnencryptedLogConstrainingTest, NegativeSelectorConsistency)
418 TestTraceContainer
trace = TestTraceContainer({ {
419 { C::precomputed_first_row, 1 },
422 { C::emit_unencrypted_log_sel, 1 },
423 { C::emit_unencrypted_log_start, 1 },
424 { C::emit_unencrypted_log_end, 1 },
427 { C::emit_unencrypted_log_sel, 0 },
432 trace.
set(C::emit_unencrypted_log_end, 1, 0);
436 "SELECTOR_CONSISTENCY");
439TEST(EmitUnencryptedLogConstrainingTest, NegativeSelectorOnEnd)
441 TestTraceContainer
trace = TestTraceContainer({ {
442 { C::emit_unencrypted_log_sel, 1 },
443 { C::emit_unencrypted_log_end, 1 },
448 trace.
set(C::emit_unencrypted_log_sel, 0, 0);
454TEST(EmitUnencryptedLogConstrainingTest, NegativeRemainingRowsDecrement)
456 TestTraceContainer
trace = TestTraceContainer({ {
457 { C::emit_unencrypted_log_sel, 1 },
458 { C::emit_unencrypted_log_remaining_rows, 1 },
461 { C::emit_unencrypted_log_sel, 1 },
462 { C::emit_unencrypted_log_remaining_rows, 0 },
463 { C::emit_unencrypted_log_end, 1 },
468 trace.
set(C::emit_unencrypted_log_remaining_rows, 1, 1);
472 "REMAINING_ROWS_DECREMENT");
475TEST(EmitUnencryptedLogConstrainingTest, NegativeErrorOutOfBoundsConsistency)
477 TestTraceContainer
trace = TestTraceContainer({ {
478 { C::emit_unencrypted_log_sel, 1 },
479 { C::emit_unencrypted_log_error_out_of_bounds, 1 },
482 { C::emit_unencrypted_log_sel, 1 },
483 { C::emit_unencrypted_log_error_out_of_bounds, 1 },
484 { C::emit_unencrypted_log_end, 1 },
489 trace.
set(C::emit_unencrypted_log_error_out_of_bounds, 1, 0);
493 "ERROR_OUT_OF_BOUNDS_CONSISTENCY");
496TEST(EmitUnencryptedLogConstrainingTest, NegativeErrorTagMismatchConsistency)
498 TestTraceContainer
trace = TestTraceContainer({ {
499 { C::emit_unencrypted_log_sel, 1 },
500 { C::emit_unencrypted_log_error_tag_mismatch, 1 },
503 { C::emit_unencrypted_log_sel, 1 },
504 { C::emit_unencrypted_log_error_tag_mismatch, 1 },
505 { C::emit_unencrypted_log_end, 1 },
510 trace.
set(C::emit_unencrypted_log_error_tag_mismatch, 1, 0);
514 "ERROR_TAG_MISMATCH_CONSISTENCY");
517TEST(EmitUnencryptedLogConstrainingTest, NegativeWrongTagCheck)
519 TestTraceContainer
trace = TestTraceContainer({ {
520 { C::emit_unencrypted_log_sel, 1 },
521 { C::emit_unencrypted_log_seen_wrong_tag, 0 },
524 { C::emit_unencrypted_log_sel, 1 },
525 { C::emit_unencrypted_log_seen_wrong_tag, 1 },
526 { C::emit_unencrypted_log_correct_tag, 0 },
527 { C::emit_unencrypted_log_end, 1 },
532 trace.
set(C::emit_unencrypted_log_seen_wrong_tag, 1, 0);
538TEST(EmitUnencryptedLogConstrainingTest, NegativeSelectorShouldWriteToPublicInputsConsistency)
540 TestTraceContainer
trace =
541 TestTraceContainer({ {
542 { C::emit_unencrypted_log_sel, 1 },
543 { C::emit_unencrypted_log_sel_should_write_to_public_inputs, 1 },
546 { C::emit_unencrypted_log_sel, 1 },
547 { C::emit_unencrypted_log_sel_should_write_to_public_inputs, 1 },
548 { C::emit_unencrypted_log_end, 1 },
553 trace.
set(C::emit_unencrypted_log_sel_should_write_to_public_inputs, 1, 0);
557 "SEL_SHOULD_WRITE_TO_PUBLIC_INPUTS_CONSISTENCY");
560TEST(EmitUnencryptedLogConstrainingTest, NegativeLogOffsetIncrement)
562 TestTraceContainer
trace = TestTraceContainer({ {
563 { C::emit_unencrypted_log_sel, 1 },
564 { C::emit_unencrypted_log_is_write_memory_value, 1 },
565 { C::emit_unencrypted_log_log_address, 10 },
568 { C::emit_unencrypted_log_sel, 1 },
569 { C::emit_unencrypted_log_is_write_memory_value, 1 },
570 { C::emit_unencrypted_log_log_address, 11 },
571 { C::emit_unencrypted_log_end, 1 },
576 trace.
set(C::emit_unencrypted_log_log_address, 1, 9);
580 "LOG_ADDRESS_INCREMENT");
583TEST(EmitUnencryptedLogConstrainingTest, NegativeExecutionClkConsistency)
585 TestTraceContainer
trace = TestTraceContainer({ {
586 { C::emit_unencrypted_log_sel, 1 },
587 { C::emit_unencrypted_log_execution_clk, 1 },
590 { C::emit_unencrypted_log_sel, 1 },
591 { C::emit_unencrypted_log_execution_clk, 1 },
592 { C::emit_unencrypted_log_end, 1 },
597 trace.
set(C::emit_unencrypted_log_execution_clk, 1, 0);
601 "EXEC_CLK_CONSISTENCY");
604TEST(EmitUnencryptedLogConstrainingTest, NegativeSpaceIdConsistency)
606 TestTraceContainer
trace = TestTraceContainer({ {
607 { C::emit_unencrypted_log_sel, 1 },
608 { C::emit_unencrypted_log_space_id, 17 },
611 { C::emit_unencrypted_log_sel, 1 },
612 { C::emit_unencrypted_log_space_id, 17 },
613 { C::emit_unencrypted_log_end, 1 },
618 trace.
set(C::emit_unencrypted_log_space_id, 1, 18);
622 "SPACE_ID_CONSISTENCY");
625TEST(EmitUnencryptedLogConstrainingTest, NegativeContractAddressConsistency)
627 TestTraceContainer
trace = TestTraceContainer({ {
628 { C::emit_unencrypted_log_sel, 1 },
629 { C::emit_unencrypted_log_contract_address, 42 },
632 { C::emit_unencrypted_log_sel, 1 },
633 { C::emit_unencrypted_log_contract_address, 42 },
634 { C::emit_unencrypted_log_end, 1 },
639 trace.
set(C::emit_unencrypted_log_contract_address, 1, 43);
643 "CONTRACT_ADDRESS_CONSISTENCY");
669TEST(EmitUnencryptedLogConstrainingTest, NegativeGhostRowInjectionBlocked)
671 TestTraceContainer
trace;
672 MemoryTraceBuilder memory_trace_builder;
673 PrecomputedTraceBuilder precomputed_trace_builder;
675 uint32_t malicious_clk = 42;
676 uint16_t malicious_space_id = 1;
678 FF malicious_value = 0x1337;
683 .execution_clk = malicious_clk,
685 .addr = malicious_log_addr,
686 .value = MemoryValue::from<FF>(malicious_value),
687 .space_id = malicious_space_id,
691 precomputed_trace_builder.process_sel_range_8(trace);
692 precomputed_trace_builder.process_sel_range_16(trace);
693 precomputed_trace_builder.process_misc(trace, 1 << 16);
694 precomputed_trace_builder.process_tag_parameters(trace);
695 memory_trace_builder.process(mem_events, trace);
697 uint32_t memory_row = 0;
699 if (
trace.
get(C::memory_sel, row) == 1) {
706 uint32_t ghost_row = 0;
709 { C::precomputed_first_row, 1 },
710 { C::precomputed_clk, ghost_row },
711 { C::precomputed_zero, 0 },
712 { C::emit_unencrypted_log_sel, 0 },
713 { C::emit_unencrypted_log_is_write_memory_value, 1 },
714 { C::emit_unencrypted_log_error_out_of_bounds, 0 },
715 { C::emit_unencrypted_log_sel_should_read_memory, 1 },
716 { C::emit_unencrypted_log_execution_clk, malicious_clk },
717 { C::emit_unencrypted_log_space_id, malicious_space_id },
718 { C::emit_unencrypted_log_log_address, malicious_log_addr },
719 { C::emit_unencrypted_log_value, malicious_value },
720 { C::emit_unencrypted_log_tag,
static_cast<uint8_t
>(malicious_tag) },
721 { C::emit_unencrypted_log_public_inputs_value, malicious_value },
724 trace.
set(C::memory_sel_unencrypted_log_read, memory_row, 1);
730 "SEL_SHOULD_READ_MEMORY_IS_SEL_AND_WRITE_MEM_AND_NO_ERR");
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define FLAT_PUBLIC_LOGS_PAYLOAD_LENGTH
#define AVM_HIGHEST_MEM_ADDRESS
static constexpr size_t SR_SPACE_ID_CONSISTENCY
static constexpr size_t SR_SELECTOR_ON_END
static constexpr size_t SR_START_AFTER_LATCH
static constexpr size_t SR_LOG_ADDRESS_INCREMENT
static constexpr size_t SR_SEL_SHOULD_WRITE_TO_PUBLIC_INPUTS_CONSISTENCY
static constexpr size_t SR_ERROR_TAG_MISMATCH_CONSISTENCY
static constexpr size_t SR_SELECTOR_ON_START
static constexpr size_t SR_WRONG_TAG_CHECK
static constexpr size_t SR_REMAINING_ROWS_DECREMENT
static constexpr size_t SR_ERROR_OUT_OF_BOUNDS_CONSISTENCY
static constexpr size_t SR_EXEC_CLK_CONSISTENCY
static constexpr size_t SR_SELECTOR_CONSISTENCY
static constexpr size_t SR_CONTRACT_ADDRESS_CONSISTENCY
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
const FF & get(Column col, uint32_t row) const
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
GreaterThanTraceBuilder gt_builder
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
std::variant< EmitUnencryptedLogWriteEvent, CheckPointEventType > EmitUnencryptedLogEvent
TestTraceContainer empty_trace()
std::vector< FF > random_fields(size_t n)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
tracegen::PublicInputsTraceBuilder public_inputs_builder