3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
20using ::testing::ElementsAre;
21using ::testing::Return;
22using ::testing::StrictMock;
28TEST(AvmSimulationPublicDataTree, ReadExists)
33 StrictMock<MockFieldGreaterThan>
field_gt;
44 uint64_t low_leaf_index = 30;
45 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
46 AppendOnlyTreeSnapshot snapshot = {
48 .next_available_leaf_index = 128,
53 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
56 EXPECT_CALL(merkle_check,
58 .WillRepeatedly(Return());
60 public_data_tree_check.assert_read(
slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot);
62 PublicDataTreeReadWriteEvent expect_event = {
63 .contract_address = contract_address,
66 .leaf_slot = leaf_slot,
67 .prev_snapshot = snapshot,
69 .low_leaf_hash = low_leaf_hash,
70 .low_leaf_index = low_leaf_index,
72 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
78 "Leaf value does not match value");
81TEST(AvmSimulationPublicDataTree, ReadNotExistsLowPointsToInfinity)
86 StrictMock<MockFieldGreaterThan>
field_gt;
98 uint64_t low_leaf_index = 30;
99 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
100 AppendOnlyTreeSnapshot snapshot = {
102 .next_available_leaf_index = 128,
107 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
110 EXPECT_CALL(merkle_check,
112 .WillRepeatedly(Return());
113 EXPECT_CALL(
field_gt, ff_gt(leaf_slot,
low_leaf.leaf.slot)).WillRepeatedly(Return(
true));
115 public_data_tree_check.assert_read(
slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot);
116 PublicDataTreeReadWriteEvent expect_event = {
117 .contract_address = contract_address,
120 .leaf_slot = leaf_slot,
121 .prev_snapshot = snapshot,
123 .low_leaf_hash = low_leaf_hash,
124 .low_leaf_index = low_leaf_index,
126 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
131 slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot),
132 "Value is nonzero for a non existing slot");
135 EXPECT_CALL(
field_gt, ff_gt(leaf_slot,
low_leaf.leaf.slot)).WillOnce(Return(
false));
137 slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot),
138 "Low leaf slot is GTE leaf slot");
141TEST(AvmSimulationPublicDataTree, ReadNotExistsLowPointsToAnotherLeaf)
146 StrictMock<MockFieldGreaterThan>
field_gt;
157 uint64_t low_leaf_index = 30;
158 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
159 AppendOnlyTreeSnapshot snapshot = {
161 .next_available_leaf_index = 128,
166 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
169 EXPECT_CALL(merkle_check,
171 .WillRepeatedly(Return());
172 EXPECT_CALL(
field_gt, ff_gt(leaf_slot,
low_leaf.leaf.slot)).WillRepeatedly(Return(
true));
173 EXPECT_CALL(
field_gt, ff_gt(
low_leaf.nextKey, leaf_slot)).WillRepeatedly(Return(
true));
175 public_data_tree_check.assert_read(
slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot);
176 PublicDataTreeReadWriteEvent expect_event = {
177 .contract_address = contract_address,
180 .leaf_slot = leaf_slot,
181 .prev_snapshot = snapshot,
183 .low_leaf_hash = low_leaf_hash,
184 .low_leaf_index = low_leaf_index,
186 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
191 slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot),
192 "Value is nonzero for a non existing slot");
195 EXPECT_CALL(
field_gt, ff_gt(
low_leaf.nextKey, leaf_slot)).WillOnce(Return(
false));
197 slot, contract_address,
value,
low_leaf, low_leaf_index, sibling_path, snapshot),
198 "Leaf slot is GTE low leaf next slot");
201TEST(AvmSimulationPublicDataTree, WriteExists)
206 StrictMock<MockFieldGreaterThan>
field_gt;
221 uint64_t low_leaf_index = 30;
222 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
224 AppendOnlyTreeSnapshot prev_snapshot =
225 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(), .next_available_leaf_index = 128 };
226 std::vector<FF> low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
229 updated_low_leaf.leaf.
value = new_value;
231 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
233 FF intermediate_root = public_data_tree.root();
234 std::vector<FF> insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.next_available_leaf_index);
237 AppendOnlyTreeSnapshot next_snapshot =
238 AppendOnlyTreeSnapshot{ .root = intermediate_root,
239 .next_available_leaf_index = prev_snapshot.next_available_leaf_index };
242 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
249 .WillRepeatedly(Return(intermediate_root));
251 AppendOnlyTreeSnapshot result_snapshot = public_data_tree_check.write(
slot,
256 low_leaf_sibling_path,
258 insertion_sibling_path,
261 EXPECT_EQ(next_snapshot, result_snapshot);
263 PublicDataTreeReadWriteEvent expect_event = {
264 .contract_address = contract_address,
267 .leaf_slot = leaf_slot,
268 .prev_snapshot = prev_snapshot,
270 .low_leaf_hash = low_leaf_hash,
271 .low_leaf_index = low_leaf_index,
272 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
273 .updated_low_leaf_hash = updated_low_leaf_hash,
275 .intermediate_root = intermediate_root,
276 .next_snapshot = next_snapshot },
279 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(expect_event));
282TEST(AvmSimulationPublicDataTree, WriteAndUpdate)
287 StrictMock<MockFieldGreaterThan>
field_gt;
296 FF low_leaf_slot = 40;
302 uint64_t low_leaf_index = 30;
303 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
305 AppendOnlyTreeSnapshot prev_snapshot =
306 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(), .next_available_leaf_index = 128 };
307 std::vector<FF> low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
310 updated_low_leaf.nextIndex = prev_snapshot.next_available_leaf_index;
311 updated_low_leaf.nextKey = leaf_slot;
313 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
315 FF intermediate_root = public_data_tree.root();
316 std::vector<FF> insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.next_available_leaf_index);
321 public_data_tree.update_element(prev_snapshot.next_available_leaf_index, new_leaf_hash);
323 AppendOnlyTreeSnapshot next_snapshot =
324 AppendOnlyTreeSnapshot{ .root = public_data_tree.root(),
325 .next_available_leaf_index = prev_snapshot.next_available_leaf_index + 1 };
327 uint32_t execution_id = 1;
328 EXPECT_CALL(
execution_id_manager, get_execution_id()).WillRepeatedly([&]() {
return execution_id++; });
330 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
336 .WillRepeatedly(Return(intermediate_root));
337 EXPECT_CALL(
field_gt, ff_gt(leaf_slot,
low_leaf.leaf.slot)).WillRepeatedly(Return(
true));
338 EXPECT_CALL(merkle_check,
342 prev_snapshot.next_available_leaf_index,
345 .WillRepeatedly(Return(next_snapshot.root));
347 AppendOnlyTreeSnapshot snapshot_after_write = public_data_tree_check.write(
slot,
352 low_leaf_sibling_path,
354 insertion_sibling_path,
357 EXPECT_EQ(next_snapshot, snapshot_after_write);
359 PublicDataTreeReadWriteEvent write_event = {
360 .contract_address = contract_address,
363 .leaf_slot = leaf_slot,
364 .prev_snapshot = prev_snapshot,
366 .low_leaf_hash = low_leaf_hash,
367 .low_leaf_index = low_leaf_index,
368 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
369 .updated_low_leaf_hash = updated_low_leaf_hash,
370 .new_leaf_hash = new_leaf_hash,
371 .intermediate_root = intermediate_root,
372 .next_snapshot = next_snapshot },
376 low_leaf_index = prev_snapshot.next_available_leaf_index;
377 prev_snapshot = snapshot_after_write;
381 public_data_tree.update_element(low_leaf_index, low_leaf_hash);
382 low_leaf_sibling_path = public_data_tree.get_sibling_path(low_leaf_index);
387 updated_low_leaf.leaf.
value = new_value;
389 public_data_tree.update_element(low_leaf_index, updated_low_leaf_hash);
391 intermediate_root = public_data_tree.root();
392 insertion_sibling_path = public_data_tree.get_sibling_path(prev_snapshot.next_available_leaf_index);
395 next_snapshot = AppendOnlyTreeSnapshot{ .root = intermediate_root,
396 .next_available_leaf_index = prev_snapshot.next_available_leaf_index };
401 .WillRepeatedly(Return(intermediate_root));
402 AppendOnlyTreeSnapshot snapshot_after_update = public_data_tree_check.write(
slot,
407 low_leaf_sibling_path,
409 insertion_sibling_path,
412 EXPECT_EQ(next_snapshot, snapshot_after_update);
414 PublicDataTreeReadWriteEvent update_event = {
415 .contract_address = contract_address,
418 .leaf_slot = leaf_slot,
419 .prev_snapshot = prev_snapshot,
421 .low_leaf_hash = low_leaf_hash,
422 .low_leaf_index = low_leaf_index,
423 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf,
424 .updated_low_leaf_hash = updated_low_leaf_hash,
426 .intermediate_root = intermediate_root,
427 .next_snapshot = next_snapshot },
428 .execution_id = std::numeric_limits<uint32_t>::max(),
431 EXPECT_THAT(
event_emitter.dump_events(), ElementsAre(write_event, update_event));
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define DOM_SEP__PUBLIC_LEAF_SLOT
#define DOM_SEP__PUBLIC_DATA_MERKLE
FieldGreaterThan field_gt
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
ExecutionIdManager execution_id_manager
EventEmitter< DataCopyEvent > event_emitter
IndexedTreeLeafData low_leaf
AVM range check gadget for witness generation.
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(B &buf, field2< base_field, Params > const &value)
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
std::vector< FF > get_hash_inputs() const