3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
19using ::testing::ElementsAre;
20using ::testing::Return;
21using ::testing::StrictMock;
27TEST(AvmSimulationPublicDataTree, ReadExists)
31 StrictMock<MockMerkleCheck> merkle_check;
32 StrictMock<MockFieldGreaterThan>
field_gt;
43 uint64_t low_leaf_index = 30;
44 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
45 AppendOnlyTreeSnapshot snapshot = {
47 .nextAvailableLeafIndex = 128,
52 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
55 EXPECT_CALL(merkle_check, assert_membership(low_leaf_hash, low_leaf_index, _, snapshot.root))
56 .WillRepeatedly(Return());
60 PublicDataTreeReadWriteEvent expect_event = {
64 .leaf_slot = leaf_slot,
65 .prev_snapshot = snapshot,
67 .low_leaf_hash = low_leaf_hash,
68 .low_leaf_index = low_leaf_index,
70 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
76 "Leaf value does not match value");
79TEST(AvmSimulationPublicDataTree, ReadNotExistsLowPointsToInfinity)
83 StrictMock<MockMerkleCheck> merkle_check;
84 StrictMock<MockFieldGreaterThan>
field_gt;
96 uint64_t low_leaf_index = 30;
97 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
98 AppendOnlyTreeSnapshot snapshot = {
100 .nextAvailableLeafIndex = 128,
105 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
108 EXPECT_CALL(merkle_check, assert_membership(low_leaf_hash, low_leaf_index, _, snapshot.root))
109 .WillRepeatedly(Return());
113 PublicDataTreeReadWriteEvent expect_event = {
117 .leaf_slot = leaf_slot,
118 .prev_snapshot = snapshot,
120 .low_leaf_hash = low_leaf_hash,
121 .low_leaf_index = low_leaf_index,
123 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
129 "Value is nonzero for a non existing slot");
135 "Low leaf slot is GTE leaf slot");
138TEST(AvmSimulationPublicDataTree, ReadNotExistsLowPointsToAnotherLeaf)
142 StrictMock<MockMerkleCheck> merkle_check;
143 StrictMock<MockFieldGreaterThan>
field_gt;
154 uint64_t low_leaf_index = 30;
155 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
156 AppendOnlyTreeSnapshot snapshot = {
158 .nextAvailableLeafIndex = 128,
163 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
166 EXPECT_CALL(merkle_check, assert_membership(low_leaf_hash, low_leaf_index, _, snapshot.root))
167 .WillRepeatedly(Return());
172 PublicDataTreeReadWriteEvent expect_event = {
176 .leaf_slot = leaf_slot,
177 .prev_snapshot = snapshot,
179 .low_leaf_hash = low_leaf_hash,
180 .low_leaf_index = low_leaf_index,
182 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
188 "Value is nonzero for a non existing slot");
194 "Leaf slot is GTE low leaf next slot");
197TEST(AvmSimulationPublicDataTree, WriteExists)
201 StrictMock<MockMerkleCheck> merkle_check;
202 StrictMock<MockFieldGreaterThan>
field_gt;
217 uint64_t low_leaf_index = 30;
218 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
220 AppendOnlyTreeSnapshot prev_snapshot =
221 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(), .nextAvailableLeafIndex = 128 };
222 std::vector<FF> low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
225 updated_low_leaf.
leaf.value = new_value;
227 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
229 FF intermediate_root = public_data_tree.root();
230 std::vector<FF> insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.nextAvailableLeafIndex);
233 AppendOnlyTreeSnapshot next_snapshot =
234 AppendOnlyTreeSnapshot{ .root = intermediate_root,
235 .nextAvailableLeafIndex = prev_snapshot.nextAvailableLeafIndex };
238 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
242 EXPECT_CALL(merkle_check,
write(low_leaf_hash, updated_low_leaf_hash, low_leaf_index, _, prev_snapshot.root))
243 .WillRepeatedly(Return(intermediate_root));
245 AppendOnlyTreeSnapshot result_snapshot = public_data_tree_check.write(
slot,
250 low_leaf_sibling_path,
252 insertion_sibling_path,
255 EXPECT_EQ(next_snapshot, result_snapshot);
257 PublicDataTreeReadWriteEvent expect_event = {
261 .leaf_slot = leaf_slot,
262 .prev_snapshot = prev_snapshot,
264 .low_leaf_hash = low_leaf_hash,
265 .low_leaf_index = low_leaf_index,
266 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
267 .updated_low_leaf_hash = updated_low_leaf_hash,
269 .intermediate_root = intermediate_root,
270 .next_snapshot = next_snapshot },
273 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
276TEST(AvmSimulationPublicDataTree, WriteAndUpdate)
280 StrictMock<MockMerkleCheck> merkle_check;
281 StrictMock<MockFieldGreaterThan>
field_gt;
290 FF low_leaf_slot = 40;
296 uint64_t low_leaf_index = 30;
297 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
299 AppendOnlyTreeSnapshot prev_snapshot =
300 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(), .nextAvailableLeafIndex = 128 };
301 std::vector<FF> low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
304 updated_low_leaf.
nextIndex = prev_snapshot.nextAvailableLeafIndex;
305 updated_low_leaf.nextKey = leaf_slot;
307 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
309 FF intermediate_root = public_data_tree.root();
310 std::vector<FF> insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.nextAvailableLeafIndex);
315 public_data_tree.update_element(prev_snapshot.nextAvailableLeafIndex, new_leaf_hash);
317 AppendOnlyTreeSnapshot next_snapshot =
318 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(),
319 .nextAvailableLeafIndex = prev_snapshot.nextAvailableLeafIndex + 1 };
321 uint32_t execution_id = 1;
322 EXPECT_CALL(
execution_id_manager, get_execution_id()).WillRepeatedly([&]() {
return execution_id++; });
324 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
327 EXPECT_CALL(merkle_check,
write(low_leaf_hash, updated_low_leaf_hash, low_leaf_index, _, prev_snapshot.root))
328 .WillRepeatedly(Return(intermediate_root));
330 EXPECT_CALL(merkle_check,
write(
FF(0), new_leaf_hash, prev_snapshot.nextAvailableLeafIndex, _, intermediate_root))
331 .WillRepeatedly(Return(next_snapshot.root));
333 AppendOnlyTreeSnapshot snapshot_after_write = public_data_tree_check.write(
slot,
338 low_leaf_sibling_path,
340 insertion_sibling_path,
343 EXPECT_EQ(next_snapshot, snapshot_after_write);
345 PublicDataTreeReadWriteEvent write_event = {
349 .leaf_slot = leaf_slot,
350 .prev_snapshot = prev_snapshot,
352 .low_leaf_hash = low_leaf_hash,
353 .low_leaf_index = low_leaf_index,
354 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
355 .updated_low_leaf_hash = updated_low_leaf_hash,
356 .new_leaf_hash = new_leaf_hash,
357 .intermediate_root = intermediate_root,
358 .next_snapshot = next_snapshot },
362 low_leaf_index = prev_snapshot.nextAvailableLeafIndex;
363 prev_snapshot = snapshot_after_write;
367 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
368 low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
373 updated_low_leaf.
leaf.value = new_value;
375 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
377 intermediate_root = public_data_tree.root();
378 insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.nextAvailableLeafIndex);
381 next_snapshot = AppendOnlyTreeSnapshot{ .root = intermediate_root,
382 .nextAvailableLeafIndex = prev_snapshot.nextAvailableLeafIndex };
384 EXPECT_CALL(merkle_check,
write(low_leaf_hash, updated_low_leaf_hash, low_leaf_index, _, prev_snapshot.root))
385 .WillRepeatedly(Return(intermediate_root));
386 AppendOnlyTreeSnapshot snapshot_after_update = public_data_tree_check.write(
slot,
391 low_leaf_sibling_path,
393 insertion_sibling_path,
396 EXPECT_EQ(next_snapshot, snapshot_after_update);
398 PublicDataTreeReadWriteEvent update_event = {
402 .leaf_slot = leaf_slot,
403 .prev_snapshot = prev_snapshot,
405 .low_leaf_hash = low_leaf_hash,
406 .low_leaf_index = low_leaf_index,
407 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
408 .updated_low_leaf_hash = updated_low_leaf_hash,
410 .intermediate_root = intermediate_root,
411 .next_snapshot = next_snapshot },
412 .execution_id = std::numeric_limits<uint32_t>::max(),
415 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(write_event, update_event));
#define GENERATOR_INDEX__PUBLIC_LEAF_INDEX
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
ExecutionIdManager execution_id_manager
EventEmitter< DataCopyEvent > event_emitter
NullifierTreeLeafPreimage low_leaf
AztecAddress contract_address
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
void hash(State &state) noexcept
IndexedLeaf< PublicDataLeafValue > PublicDataTreeLeafPreimage
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
TEST(EmitUnencryptedLogTest, Basic)
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
FF unconstrained_compute_leaf_slot(const AztecAddress &contract_address, const FF &slot)
void write(B &buf, field2< base_field, Params > const &value)
std::vector< fr > get_hash_inputs() const
NiceMock< MockFieldGreaterThan > field_gt