Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
nullifier_exists.test.cpp
Go to the documentation of this file.
1#include <gtest/gtest.h>
2
3#include <cstdint>
4
23
24namespace bb::avm2::constraining {
25namespace {
26
27using tracegen::ExecutionTraceBuilder;
28using tracegen::IndexedTreeCheckTraceBuilder;
29using tracegen::TestTraceContainer;
30
31using simulation::DeduplicatingEventEmitter;
32using simulation::EventEmitter;
33using simulation::FieldGreaterThan;
34using simulation::FieldGreaterThanEvent;
35using simulation::IndexedTreeCheck;
37using simulation::IndexedTreeLeafData;
38using simulation::MockMerkleCheck;
39using simulation::MockPoseidon2;
40using simulation::MockRangeCheck;
43
44using testing::NiceMock;
45
47using C = Column;
48using nullifier_exists = bb::avm2::nullifier_exists<FF>;
50
51TEST(NullifierExistsConstrainingTest, PositiveTest)
52{
53 TestTraceContainer trace({ { { C::execution_sel, 1 },
54 { C::execution_sel_execute_nullifier_exists, 1 },
55 { C::execution_register_0_, /*siloed_nullifier=*/FF(0x123456) },
56 { C::execution_register_1_, /*exists=*/1 },
57 { C::execution_prev_nullifier_tree_root, FF(0xabc) },
58 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
59 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U1) },
60 { C::execution_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
61 { C::execution_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
62 { C::execution_sel_opcode_error, 0 },
63 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_NULLIFIER_EXISTS } } });
64 check_relation<nullifier_exists>(trace);
65}
66
67TEST(NullifierExistsConstrainingTest, PositiveNullifierNotExists)
68{
69 TestTraceContainer trace({ { { C::execution_sel, 1 },
70 { C::execution_sel_execute_nullifier_exists, 1 },
71 { C::execution_register_0_, /*siloed_nullifier=*/FF(0x123456) },
72 { C::execution_register_1_, /*exists=*/0 }, // nullifier does not exist!
73 { C::execution_prev_nullifier_tree_root, FF(0xabc) },
74 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
75 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U1) },
76 { C::execution_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
77 { C::execution_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
78 { C::execution_sel_opcode_error, 0 },
79 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_NULLIFIER_EXISTS } } });
80 check_relation<nullifier_exists>(trace);
81}
82
83TEST(NullifierExistsConstrainingTest, NegativeInvalidOutputTag)
84{
85 TestTraceContainer trace({ { { C::execution_sel, 1 },
86 { C::execution_sel_execute_nullifier_exists, 1 },
87 { C::execution_register_0_, /*siloed_nullifier=*/FF(0x123456) },
88 { C::execution_register_1_, /*exists=*/0 }, // nullifier does not exist!
89 { C::execution_prev_nullifier_tree_root, FF(0xabc) },
90 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
91 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U8) }, // WRONG!
92 { C::execution_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
93 { C::execution_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
94 { C::execution_sel_opcode_error, 0 },
95 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_NULLIFIER_EXISTS } } });
97 check_relation<nullifier_exists>(trace, nullifier_exists::SR_NULLIFIER_EXISTS_U1_OUTPUT_TAG),
98 "NULLIFIER_EXISTS_U1_OUTPUT_TAG");
99}
100
101TEST(NullifierExistsConstrainingTest, NegativeNullifierExistsSuccess)
102{
103 TestTraceContainer trace({ {
104 { C::execution_sel_execute_nullifier_exists, 1 },
105 { C::execution_sel_opcode_error, 1 },
106 } });
107
109 "INFALLIBLE_OPCODES_SUCCESS");
110}
111
112TEST(NullifierExistsConstrainingTest, Interactions)
113{
114 NiceMock<MockPoseidon2> poseidon2;
115 NiceMock<MockMerkleCheck> merkle_check;
116
117 NiceMock<MockRangeCheck> range_check;
118 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
119 FieldGreaterThan field_gt(range_check, event_emitter);
120
121 EventEmitter<IndexedTreeCheckEvent> indexed_tree_check_event_emitter;
122 IndexedTreeCheck indexed_tree_check(
124
125 // Siloed nullifier (no siloing happens in the opcode now)
126 FF siloed_nullifier = 42;
127
128 // For exists=true, the low leaf's nullifier must match the searched nullifier
129 IndexedTreeLeafData low_leaf = {
130 .value = siloed_nullifier,
131 .next_value = 0,
132 .next_index = 0,
133 };
134
135 AppendOnlyTreeSnapshot nullifier_tree_snapshot = AppendOnlyTreeSnapshot{
136 .root = 42,
137 .next_available_leaf_index = 128,
138 };
139
140 std::vector<FF> sibling_path(NULLIFIER_TREE_HEIGHT);
141
142 // sel_silo=false
143 indexed_tree_check.assert_read(siloed_nullifier,
144 /*siloing_params=*/std::nullopt,
145 /*exists=*/true,
146 low_leaf,
147 0,
148 sibling_path,
149 nullifier_tree_snapshot);
150
151 TestTraceContainer trace({ {
152 { C::execution_sel_execute_nullifier_exists, 1 },
153 { C::execution_register_0_, siloed_nullifier },
154 { C::execution_register_1_, /*exists=*/1 },
155 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
156 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::U1) },
157 { C::execution_prev_nullifier_tree_root, nullifier_tree_snapshot.root },
158 { C::execution_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
159 { C::execution_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
160 { C::execution_sel_opcode_error, 0 },
161 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_NULLIFIER_EXISTS },
162 } });
163
164 IndexedTreeCheckTraceBuilder indexed_tree_check_trace_builder;
165 indexed_tree_check_trace_builder.process(indexed_tree_check_event_emitter.dump_events(), trace);
166
167 check_relation<nullifier_exists>(trace);
168
169 check_interaction<ExecutionTraceBuilder, lookup_nullifier_exists_nullifier_exists_check_settings>(trace);
170}
171
172// TODO(dbanks12): interaction tests
173
174} // namespace
175} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#define AVM_EXEC_OP_ID_NULLIFIER_EXISTS
#define NULLIFIER_TREE_HEIGHT
#define DOM_SEP__NULLIFIER_MERKLE
FieldGreaterThan field_gt
MerkleCheck merkle_check
IndexedTreeCheck indexed_tree_check
EventEmitter< simulation::IndexedTreeCheckEvent > indexed_tree_check_event_emitter
RangeCheck range_check
static constexpr size_t SR_INFALLIBLE_OPCODES_SUCCESS
Definition execution.hpp:78
static constexpr size_t SR_NULLIFIER_EXISTS_U1_OUTPUT_TAG
void assert_read(const FF &value, std::optional< IndexedTreeSiloingParameters > siloing_params, bool exists, const IndexedTreeLeafData &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot) override
Performs a membership/non-membership read check on an indexed tree.
Native Poseidon2 hash function implementation.
Definition poseidon2.hpp:22
EventEmitter< DataCopyEvent > event_emitter
TestTraceContainer trace
IndexedTreeLeafData low_leaf
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
crypto::merkle_tree::IndexedLeaf< crypto::merkle_tree::NullifierLeafValue > NullifierTreeLeafPreimage
Definition db_types.hpp:12
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
std::variant< IndexedTreeReadWriteEvent, CheckPointEventType > IndexedTreeCheckEvent
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
NiceMock< MockExecution > execution