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 .next_available_leaf_index = 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 .next_available_leaf_index = 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 .next_available_leaf_index = 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(), .next_available_leaf_index = 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.next_available_leaf_index);
233 AppendOnlyTreeSnapshot next_snapshot =
234 AppendOnlyTreeSnapshot{ .root = intermediate_root,
235 .next_available_leaf_index = prev_snapshot.next_available_leaf_index };
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(), .next_available_leaf_index = 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.next_available_leaf_index;
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.next_available_leaf_index);
315 public_data_tree.update_element(prev_snapshot.next_available_leaf_index, new_leaf_hash);
317 AppendOnlyTreeSnapshot next_snapshot =
318 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(),
319 .next_available_leaf_index = prev_snapshot.next_available_leaf_index + 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,
331 write(
FF(0), new_leaf_hash, prev_snapshot.next_available_leaf_index, _, intermediate_root))
332 .WillRepeatedly(Return(next_snapshot.root));
334 AppendOnlyTreeSnapshot snapshot_after_write = public_data_tree_check.write(
slot,
339 low_leaf_sibling_path,
341 insertion_sibling_path,
344 EXPECT_EQ(next_snapshot, snapshot_after_write);
346 PublicDataTreeReadWriteEvent write_event = {
350 .leaf_slot = leaf_slot,
351 .prev_snapshot = prev_snapshot,
353 .low_leaf_hash = low_leaf_hash,
354 .low_leaf_index = low_leaf_index,
355 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
356 .updated_low_leaf_hash = updated_low_leaf_hash,
357 .new_leaf_hash = new_leaf_hash,
358 .intermediate_root = intermediate_root,
359 .next_snapshot = next_snapshot },
363 low_leaf_index = prev_snapshot.next_available_leaf_index;
364 prev_snapshot = snapshot_after_write;
368 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
369 low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
374 updated_low_leaf.
leaf.value = new_value;
376 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
378 intermediate_root = public_data_tree.root();
379 insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.next_available_leaf_index);
382 next_snapshot = AppendOnlyTreeSnapshot{ .root = intermediate_root,
383 .next_available_leaf_index = prev_snapshot.next_available_leaf_index };
385 EXPECT_CALL(merkle_check,
write(low_leaf_hash, updated_low_leaf_hash, low_leaf_index, _, prev_snapshot.root))
386 .WillRepeatedly(Return(intermediate_root));
387 AppendOnlyTreeSnapshot snapshot_after_update = public_data_tree_check.write(
slot,
392 low_leaf_sibling_path,
394 insertion_sibling_path,
397 EXPECT_EQ(next_snapshot, snapshot_after_update);
399 PublicDataTreeReadWriteEvent update_event = {
403 .leaf_slot = leaf_slot,
404 .prev_snapshot = prev_snapshot,
406 .low_leaf_hash = low_leaf_hash,
407 .low_leaf_index = low_leaf_index,
408 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
409 .updated_low_leaf_hash = updated_low_leaf_hash,
411 .intermediate_root = intermediate_root,
412 .next_snapshot = next_snapshot },
413 .execution_id = std::numeric_limits<uint32_t>::max(),
416 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(write_event, update_event));
FieldGreaterThan field_gt
#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
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
IndexedLeaf< PublicDataLeafValue > PublicDataTreeLeafPreimage
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
FF unconstrained_compute_leaf_slot(const AztecAddress &contract_address, const FF &slot)
void write(std::vector< uint8_t > &buf, Chonk::VerificationKey const &vk)
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
std::vector< fr > get_hash_inputs() const