1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
26using ::testing::NiceMock;
28using simulation::EventEmitter;
29using simulation::MerkleCheck;
30using simulation::MerkleCheckEvent;
31using simulation::MockExecutionIdManager;
32using simulation::MockGreaterThan;
33using simulation::NoopEventEmitter;
34using simulation::Poseidon2;
35using simulation::Poseidon2HashEvent;
36using simulation::Poseidon2PermutationEvent;
37using simulation::Poseidon2PermutationMemoryEvent;
40using tracegen::MerkleCheckTraceBuilder;
41using tracegen::Poseidon2TraceBuilder;
42using tracegen::TestTraceContainer;
49TEST(MerkleCheckConstrainingTest, EmptyRow)
54TEST(MerkleCheckConstrainingTest, ComputationCannotBeStoppedPrematurely)
56 TestTraceContainer
trace({
57 { { C::precomputed_first_row, 1 }, { C::merkle_check_sel, 0 } },
58 { { C::merkle_check_sel, 1 } },
59 { { C::merkle_check_sel, 1 } },
60 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 } },
61 { { C::merkle_check_sel, 0 } },
66 const uint32_t last_row_idx = 3;
68 trace.
set(C::merkle_check_end, last_row_idx, 0);
74TEST(MerkleCheckConstrainingTest, EndCannotBeOneOnFirstRow)
77 TestTraceContainer
trace({
79 { { C::precomputed_first_row, 1 }, { C::merkle_check_sel, 0 }, { C::merkle_check_end, 0 } },
83 check_relation<merkle_check>(trace);
86 trace.
set(C::merkle_check_sel, 0, 1);
87 trace.
set(C::merkle_check_end, 0, 1);
92TEST(MerkleCheckConstrainingTest, SelectorOnEnd)
96 TestTraceContainer
trace({
97 { { C::merkle_check_end, 1 }, { C::merkle_check_sel, 1 } },
103 trace.
set(C::merkle_check_sel, 0, 0);
109TEST(MerkleCheckConstrainingTest, SelectorOnStart)
113 TestTraceContainer
trace({
114 { { C::merkle_check_start, 1 }, { C::merkle_check_sel, 1 } },
120 trace.
set(C::merkle_check_sel, 0, 0);
126TEST(MerkleCheckConstrainingTest, PropagateReadRoot)
131 TestTraceContainer
trace({
132 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 0 }, { C::merkle_check_read_root, 123 } },
134 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_read_root, 123 } },
136 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_read_root, 456 } },
142 trace.
set(C::merkle_check_read_root, 1, 456);
148TEST(MerkleCheckConstrainingTest, PropagateWriteRoot)
153 TestTraceContainer
trace({
154 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 0 }, { C::merkle_check_write_root, 123 } },
156 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_write_root, 123 } },
158 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_write_root, 456 } },
164 trace.
set(C::merkle_check_write_root, 1, 456);
170TEST(MerkleCheckConstrainingTest, PropagateWrite)
175 TestTraceContainer
trace({
176 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 0 }, { C::merkle_check_write, 1 } },
178 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_write, 1 } },
180 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_write, 0 } },
186 trace.
set(C::merkle_check_write, 1, 0);
192TEST(MerkleCheckConstrainingTest, PathLenDecrements)
194 TestTraceContainer
trace({
196 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 0 }, { C::merkle_check_path_len, 3 } },
197 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 0 }, { C::merkle_check_path_len, 2 } },
198 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_path_len, 1 } },
200 { { C::merkle_check_sel, 1 }, { C::merkle_check_end, 1 }, { C::merkle_check_path_len, 5 } },
206 trace.
set(C::merkle_check_path_len, 1, 1);
212TEST(MerkleCheckConstrainingTest, EndWhenPathLenOne)
214 TestTraceContainer
trace({
215 { { C::merkle_check_sel, 1 },
216 { C::merkle_check_path_len, 2 },
217 { C::merkle_check_path_len_min_one_inv,
FF(1).invert() },
218 { C::merkle_check_end, 0 } },
219 { { C::merkle_check_sel, 1 },
220 { C::merkle_check_path_len, 1 },
221 { C::merkle_check_path_len_min_one_inv, 0 },
222 { C::merkle_check_end, 1 } },
228 trace.
set(C::merkle_check_end, 1, 0);
234TEST(MerkleCheckConstrainingTest, NextIndexIsHalved)
236 TestTraceContainer
trace({
237 { { C::merkle_check_sel, 1 },
238 { C::merkle_check_end, 0 },
239 { C::merkle_check_index, 6 },
240 { C::merkle_check_index_is_even, 1 } },
241 { { C::merkle_check_sel, 1 },
242 { C::merkle_check_end, 0 },
243 { C::merkle_check_index, 3 },
244 { C::merkle_check_index_is_even, 0 } },
245 { { C::merkle_check_sel, 1 },
246 { C::merkle_check_end, 1 },
247 { C::merkle_check_index, 1 },
248 { C::merkle_check_index_is_even, 0 } },
254 TestTraceContainer trace2({
255 { { C::merkle_check_sel, 1 },
256 { C::merkle_check_end, 0 },
257 { C::merkle_check_index, 7 },
258 { C::merkle_check_index_is_even, 0 } },
259 { { C::merkle_check_sel, 1 },
260 { C::merkle_check_end, 0 },
261 { C::merkle_check_index, 3 },
262 { C::merkle_check_index_is_even, 0 } },
263 { { C::merkle_check_sel, 1 },
264 { C::merkle_check_end, 1 },
265 { C::merkle_check_index, 1 },
266 { C::merkle_check_index_is_even, 0 } },
272 trace2.set(C::merkle_check_index, 1, 4);
278TEST(MerkleCheckConstrainingTest, AssignReadNodesEven)
281 TestTraceContainer
trace({
283 { C::merkle_check_sel, 1 },
284 { C::merkle_check_index_is_even, 1 },
285 { C::merkle_check_read_node, 123 },
286 { C::merkle_check_sibling, 456 },
287 { C::merkle_check_read_left_node, 123 },
288 { C::merkle_check_read_right_node, 456 },
295 trace.
set(C::merkle_check_read_left_node, 0, 456);
296 trace.
set(C::merkle_check_read_right_node, 0, 123);
304TEST(MerkleCheckConstrainingTest, AssignReadNodesOdd)
307 TestTraceContainer
trace({
309 { C::merkle_check_sel, 1 },
310 { C::merkle_check_index_is_even, 0 },
311 { C::merkle_check_read_node, 123 },
312 { C::merkle_check_sibling, 456 },
313 { C::merkle_check_read_left_node, 456 },
314 { C::merkle_check_read_right_node, 123 },
321 trace.
set(C::merkle_check_read_left_node, 0, 123);
322 trace.
set(C::merkle_check_read_right_node, 0, 456);
330TEST(MerkleCheckConstrainingTest, AssignWriteNodesEven)
333 TestTraceContainer
trace({
335 { C::merkle_check_sel, 1 },
336 { C::merkle_check_write, 1 },
337 { C::merkle_check_index_is_even, 1 },
338 { C::merkle_check_write_node, 123 },
339 { C::merkle_check_sibling, 456 },
340 { C::merkle_check_write_left_node, 123 },
341 { C::merkle_check_write_right_node, 456 },
348 trace.
set(C::merkle_check_write_left_node, 0, 456);
349 trace.
set(C::merkle_check_write_right_node, 0, 123);
357TEST(MerkleCheckConstrainingTest, AssignWriteNodesOdd)
360 TestTraceContainer
trace({
362 { C::merkle_check_sel, 1 },
363 { C::merkle_check_write, 1 },
364 { C::merkle_check_index_is_even, 0 },
365 { C::merkle_check_write_node, 123 },
366 { C::merkle_check_sibling, 456 },
367 { C::merkle_check_write_left_node, 456 },
368 { C::merkle_check_write_right_node, 123 },
375 trace.
set(C::merkle_check_write_left_node, 0, 123);
376 trace.
set(C::merkle_check_write_right_node, 0, 456);
384TEST(MerkleCheckConstrainingTest, ReadOutputHashIsNextRowsNode)
386 FF left_node =
FF(123);
387 FF right_node =
FF(456);
388 FF output_hash = UnconstrainedPoseidon2::hash({ left_node, right_node });
390 TestTraceContainer
trace({
391 { { C::merkle_check_sel, 1 },
392 { C::merkle_check_end, 0 },
393 { C::merkle_check_read_node, left_node },
394 { C::merkle_check_read_right_node, right_node },
395 { C::merkle_check_read_output_hash, output_hash } },
396 { { C::merkle_check_sel, 1 },
397 { C::merkle_check_end, 1 },
398 { C::merkle_check_read_node, output_hash } },
404 trace.
set(C::merkle_check_read_node, 1, output_hash + 1);
410TEST(MerkleCheckConstrainingTest, WriteOutputHashIsNextRowsNode)
412 FF left_node =
FF(123);
413 FF right_node =
FF(456);
414 FF output_hash = UnconstrainedPoseidon2::hash({ left_node, right_node });
416 TestTraceContainer
trace({
417 { { C::merkle_check_sel, 1 },
418 { C::merkle_check_end, 0 },
419 { C::merkle_check_write_node, left_node },
420 { C::merkle_check_write_right_node, right_node },
421 { C::merkle_check_write_output_hash, output_hash } },
422 { { C::merkle_check_sel, 1 },
423 { C::merkle_check_end, 1 },
424 { C::merkle_check_write_node, output_hash } },
430 trace.
set(C::merkle_check_write_node, 1, output_hash + 1);
437TEST(MerkleCheckConstrainingTest, OutputHashIsNotNextRowsCurrentNodeValueForLastRow)
439 FF output_hash =
FF(456);
440 FF next_current_node =
FF(789);
442 TestTraceContainer
trace({
443 { { C::merkle_check_sel, 1 },
444 { C::merkle_check_end, 1 },
445 { C::merkle_check_read_output_hash, output_hash },
446 { C::merkle_check_write_output_hash, output_hash } },
447 { { C::merkle_check_sel, 1 },
448 { C::merkle_check_read_node, next_current_node },
449 { C::merkle_check_write_node, next_current_node } },
456TEST(MerkleCheckConstrainingTest, ReadWithTracegen)
458 TestTraceContainer
trace({
459 { { C::precomputed_first_row, 1 } },
461 MerkleCheckTraceBuilder
builder;
464 FF leaf_value =
FF(123);
465 uint64_t leaf_index = 5;
468 std::vector<FF> sibling_path = {
FF(456),
FF(789),
FF(3333) };
473 MerkleCheckEvent
event = { .merkle_hash_domain_separator = DOM_SEP__MERKLE_HASH,
474 .leaf_value = leaf_value,
475 .leaf_index = leaf_index,
476 .sibling_path = sibling_path,
482 check_relation<merkle_check>(trace);
487 trace.
set(C::merkle_check_path_len, last_row, 66);
492TEST(MerkleCheckConstrainingTest, WriteWithTracegen)
494 TestTraceContainer
trace({
495 { { C::precomputed_first_row, 1 } },
497 MerkleCheckTraceBuilder
builder;
500 FF leaf_value =
FF(123);
501 FF new_leaf_value =
FF(456);
502 uint64_t leaf_index = 5;
505 std::vector<FF> sibling_path = {
FF(456),
FF(789),
FF(3333) };
512 MerkleCheckEvent
event = { .merkle_hash_domain_separator = DOM_SEP__MERKLE_HASH,
513 .leaf_value = leaf_value,
514 .new_leaf_value = new_leaf_value,
515 .leaf_index = leaf_index,
516 .sibling_path = sibling_path,
518 .new_root = new_root };
523 check_relation<merkle_check>(trace);
526class MerkleCheckPoseidon2Test :
public ::testing::Test {
528 MerkleCheckPoseidon2Test() =
default;
537 Poseidon2(execution_id_manager, mock_gt, hash_event_emitter, perm_event_emitter, perm_mem_event_emitter);
540TEST_F(MerkleCheckPoseidon2Test, ReadWithInteractions)
542 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
543 MerkleCheck merkle_check_sim(
poseidon2, merkle_event_emitter);
545 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
547 MerkleCheckTraceBuilder merkle_check_builder;
550 uint64_t leaf_index = 30;
551 std::vector<FF> sibling_path = { 10, 2, 30, 4, 50, 6 };
553 merkle_check_sim.assert_membership(DOM_SEP__MERKLE_HASH, leaf_value, leaf_index, sibling_path, root);
556 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
562 check_relation<merkle_check>(trace);
565 trace.
set(Column::merkle_check_read_output_hash,
static_cast<uint32_t
>(sibling_path.size()), 66);
568 (check_interaction<MerkleCheckTraceBuilder, lookup_merkle_check_merkle_poseidon2_read_settings>(trace)),
569 "Failed.*LOOKUP_MERKLE_CHECK_MERKLE_POSEIDON2.* Could not find tuple in destination");
570 check_interaction<MerkleCheckTraceBuilder, lookup_merkle_check_merkle_poseidon2_write_settings>(trace);
573TEST_F(MerkleCheckPoseidon2Test, WriteWithInteractions)
575 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
576 MerkleCheck merkle_check_sim(
poseidon2, merkle_event_emitter);
578 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
580 MerkleCheckTraceBuilder merkle_check_builder;
583 FF new_leaf_value = 444;
584 uint64_t leaf_index = 30;
585 std::vector<FF> sibling_path = { 10, 2, 30, 4, 50, 6 };
590 merkle_check_sim.write(DOM_SEP__MERKLE_HASH, leaf_value, new_leaf_value, leaf_index, sibling_path, root);
592 EXPECT_EQ(new_root, expected_new_root);
595 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
601 check_relation<merkle_check>(trace);
604 trace.
set(Column::merkle_check_read_output_hash,
static_cast<uint32_t
>(sibling_path.size()), 66);
605 trace.
set(Column::merkle_check_write_output_hash,
static_cast<uint32_t
>(sibling_path.size()), 77);
608 (check_interaction<MerkleCheckTraceBuilder, lookup_merkle_check_merkle_poseidon2_read_settings>(trace)),
609 "Failed.*LOOKUP_MERKLE_CHECK_MERKLE_POSEIDON2.* Could not find tuple in destination");
612 (check_interaction<MerkleCheckTraceBuilder, lookup_merkle_check_merkle_poseidon2_write_settings>(trace)),
613 "Failed.*LOOKUP_MERKLE_CHECK_MERKLE_POSEIDON2_WRITE.* Could not find tuple in "
617TEST_F(MerkleCheckPoseidon2Test, MultipleWithTracegen)
619 TestTraceContainer
trace({
620 { { C::precomputed_first_row, 1 } },
622 MerkleCheckTraceBuilder
builder;
625 uint64_t leaf_index = 30;
626 std::vector<FF> sibling_path = { 10, 2, 30, 4, 50, 6 };
628 MerkleCheckEvent
event = { .merkle_hash_domain_separator = DOM_SEP__MERKLE_HASH,
629 .leaf_value = leaf_value,
630 .leaf_index = leaf_index,
631 .sibling_path = sibling_path,
634 FF leaf_value2 = 444;
635 FF new_leaf_value2 = 555;
636 uint64_t leaf_index2 = 40;
637 std::vector<FF> sibling_path2 = { 11, 22, 33, 44, 55, 66 };
640 MerkleCheckEvent event2 = { .merkle_hash_domain_separator = DOM_SEP__MERKLE_HASH,
641 .leaf_value = leaf_value2,
642 .new_leaf_value = new_leaf_value2,
643 .leaf_index = leaf_index2,
644 .sibling_path = sibling_path2,
646 .new_root = new_root2 };
651 uint32_t after_last_row_index = 1 +
static_cast<uint32_t
>(sibling_path.size() + sibling_path2.size());
652 trace.
set(Column::merkle_check_sel, after_last_row_index, 0);
653 trace.
set(Column::merkle_check_write, after_last_row_index, 0);
654 trace.
set(Column::merkle_check_read_node, after_last_row_index, 0);
655 trace.
set(Column::merkle_check_write_node, after_last_row_index, 0);
656 trace.
set(Column::merkle_check_index, after_last_row_index, 0);
657 trace.
set(Column::merkle_check_path_len, after_last_row_index, 0);
658 trace.
set(Column::merkle_check_path_len_min_one_inv, after_last_row_index, 0);
659 trace.
set(Column::merkle_check_read_root, after_last_row_index, 0);
660 trace.
set(Column::merkle_check_write_root, after_last_row_index, 0);
661 trace.
set(Column::merkle_check_sibling, after_last_row_index, 0);
662 trace.
set(Column::merkle_check_start, after_last_row_index, 0);
663 trace.
set(Column::merkle_check_end, after_last_row_index, 0);
664 trace.
set(Column::merkle_check_index_is_even, after_last_row_index, 0);
665 trace.
set(Column::merkle_check_read_left_node, after_last_row_index, 0);
666 trace.
set(Column::merkle_check_read_right_node, after_last_row_index, 0);
667 trace.
set(Column::merkle_check_write_left_node, after_last_row_index, 0);
668 trace.
set(Column::merkle_check_write_right_node, after_last_row_index, 0);
669 trace.
set(Column::merkle_check_read_output_hash, after_last_row_index, 0);
670 trace.
set(Column::merkle_check_write_output_hash, after_last_row_index, 0);
672 check_relation<merkle_check>(trace);
675TEST_F(MerkleCheckPoseidon2Test, MultipleWithInteractions)
677 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
678 MerkleCheck merkle_check_sim(
poseidon2, merkle_event_emitter);
680 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
681 MerkleCheckTraceBuilder merkle_check_builder;
685 uint64_t leaf_index = 30;
686 std::vector<FF> sibling_path = { 10, 2, 30, 4, 50, 6 };
689 merkle_check_sim.assert_membership(DOM_SEP__MERKLE_HASH, leaf_value, leaf_index, sibling_path, root);
691 FF leaf_value2 = 444;
692 FF new_leaf_value2 = 555;
693 uint64_t leaf_index2 = 40;
694 std::vector<FF> sibling_path2 = { 11, 22, 33, 44, 55, 66 };
696 FF expected_new_root2 =
700 merkle_check_sim.write(DOM_SEP__MERKLE_HASH, leaf_value2, new_leaf_value2, leaf_index2, sibling_path2, root2);
701 EXPECT_EQ(new_root2, expected_new_root2);
704 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
710 check_relation<merkle_check>(trace);
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
Poseidon2TraceBuilder poseidon2_builder
static std::string get_subrelation_label(size_t index)
static constexpr size_t SR_READ_RIGHT_NODE
static constexpr size_t SR_OUTPUT_HASH_IS_NEXT_ROWS_WRITE_NODE
static constexpr size_t SR_READ_LEFT_NODE
static constexpr size_t SR_PROPAGATE_READ_ROOT
static constexpr size_t SR_PROPAGATE_WRITE
static constexpr size_t SR_WRITE_RIGHT_NODE
static constexpr size_t SR_TRACE_CONTINUITY
static constexpr size_t SR_NEXT_INDEX_IS_HALVED
static constexpr size_t SR_PROPAGATE_WRITE_ROOT
static constexpr size_t SR_PATH_LEN_DECREMENTS
static constexpr size_t SR_WRITE_LEFT_NODE
static constexpr size_t SR_OUTPUT_HASH_IS_NEXT_ROWS_READ_NODE
static constexpr size_t SR_SEL_ON_START_OR_END
static constexpr size_t SR_END_IFF_REM_PATH_EMPTY
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
Processes the hash events for the Poseidon2 hash function. It populates the columns for the poseidon2...
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
Native Poseidon2 hash function implementation.
ExecutionIdManager execution_id_manager
TEST_F(AvmRecursiveTests, TwoLayerAvmRecursion)
A test of the Two Layer AVM recursive verifier.
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
FF unconstrained_root_from_path(uint64_t domain_separator, const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > path)
TestTraceContainer empty_trace()
lookup_settings< lookup_merkle_check_merkle_poseidon2_read_settings_ > lookup_merkle_check_merkle_poseidon2_read_settings
lookup_settings< lookup_merkle_check_merkle_poseidon2_write_settings_ > lookup_merkle_check_merkle_poseidon2_write_settings
simulation::PublicDataTreeReadWriteEvent event