Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
public_data_tree_check.cpp
Go to the documentation of this file.
2
4
5namespace bb::avm2::simulation {
6
11
13 const FF& leaf_slot)
14{
15 if (!field_gt.ff_gt(leaf_slot, low_leaf_preimage.leaf.slot)) {
16 throw std::runtime_error("Low leaf slot is GTE leaf slot");
17 }
18 // indexed_leaf calls nextKey/nextSlot as nextValue, which is counter intuitive in public data tree
19 if (low_leaf_preimage.nextKey != 0 && !field_gt.ff_gt(low_leaf_preimage.nextKey, leaf_slot)) {
20 throw std::runtime_error("Leaf slot is GTE low leaf next slot");
21 }
22}
23
26 const FF& value,
27 const PublicDataTreeLeafPreimage& low_leaf_preimage,
28 uint64_t low_leaf_index,
29 std::span<const FF> sibling_path,
30 const AppendOnlyTreeSnapshot& snapshot)
31{
33 // Low leaf membership
34 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
35 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, sibling_path, snapshot.root);
36
37 // Low leaf and value validation
38 bool exists = low_leaf_preimage.leaf.slot == leaf_slot;
39 if (exists) {
40 if (low_leaf_preimage.leaf.value != value) {
41 throw std::runtime_error("Leaf value does not match value");
42 }
43 } else {
44 validate_low_leaf_jumps_over_slot(low_leaf_preimage, leaf_slot);
45
46 if (value != 0) {
47 throw std::runtime_error("Value is nonzero for a non existing slot");
48 }
49 }
50
53 .slot = slot,
54 .value = value,
55 .leaf_slot = leaf_slot,
56 .prev_snapshot = snapshot,
57 .low_leaf_preimage = low_leaf_preimage,
58 .low_leaf_hash = low_leaf_hash,
59 .low_leaf_index = low_leaf_index,
60 });
61}
62
65 const FF& value,
66 const PublicDataTreeLeafPreimage& low_leaf_preimage,
67 uint64_t low_leaf_index,
68 std::span<const FF> low_leaf_sibling_path,
69 const AppendOnlyTreeSnapshot& prev_snapshot,
70 std::span<const FF> insertion_sibling_path,
71 bool is_protocol_write)
72{
74 // Validate low leaf
75 bool exists = low_leaf_preimage.leaf.slot == leaf_slot;
76 if (!exists) {
77 validate_low_leaf_jumps_over_slot(low_leaf_preimage, leaf_slot);
78 }
79
80 // Low leaf update
81 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
82
83 PublicDataTreeLeafPreimage updated_low_leaf_preimage = low_leaf_preimage;
84 if (exists) {
85 // Update value
86 updated_low_leaf_preimage.leaf.value = value;
87 } else {
88 // Update pointers
89 updated_low_leaf_preimage.nextIndex = prev_snapshot.nextAvailableLeafIndex;
90 updated_low_leaf_preimage.nextKey = leaf_slot;
91 }
92
93 FF updated_low_leaf_hash = poseidon2.hash(updated_low_leaf_preimage.get_hash_inputs());
94
95 FF intermediate_root = merkle_check.write(
96 low_leaf_hash, updated_low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
97
99 .root = intermediate_root,
100 .nextAvailableLeafIndex = prev_snapshot.nextAvailableLeafIndex,
101 };
102 FF new_leaf_hash = 0;
104 if (!exists) {
105 // Insert new leaf
107 PublicDataLeafValue(leaf_slot, value), low_leaf_preimage.nextIndex, low_leaf_preimage.nextKey);
108
109 new_leaf_hash = poseidon2.hash(new_leaf.get_hash_inputs());
110 next_snapshot.root = merkle_check.write(
111 FF(0), new_leaf_hash, prev_snapshot.nextAvailableLeafIndex, insertion_sibling_path, intermediate_root);
112 next_snapshot.nextAvailableLeafIndex++;
113 }
114
115 // The protocol writes happen outside execution, at the end of the tx simulation.
116 uint32_t execution_id =
117 is_protocol_write ? std::numeric_limits<uint32_t>::max() : execution_id_manager.get_execution_id();
118
119 // TODO(Alvaro): Figure out a good way to handle sorting range checks
120
123 .slot = slot,
124 .value = value,
125 .leaf_slot = leaf_slot,
126 .prev_snapshot = prev_snapshot,
127 .low_leaf_preimage = low_leaf_preimage,
128 .low_leaf_hash = low_leaf_hash,
129 .low_leaf_index = low_leaf_index,
130 .write_data = PublicDataWriteData{ .updated_low_leaf_preimage = updated_low_leaf_preimage,
131 .updated_low_leaf_hash = updated_low_leaf_hash,
132 .new_leaf_hash = new_leaf_hash,
133 .intermediate_root = intermediate_root,
134 .next_snapshot = next_snapshot },
135 .execution_id = execution_id,
136 });
137
138 return next_snapshot;
139}
140
145
150
155
156} // namespace bb::avm2::simulation
#define GENERATOR_INDEX__PUBLIC_LEAF_INDEX
virtual void emit(Event &&event)=0
virtual uint32_t get_execution_id() const =0
virtual bool ff_gt(const FF &a, const FF &b)=0
FF compute_leaf_slot(const AztecAddress &contract_address, const FF &slot)
void validate_low_leaf_jumps_over_slot(const PublicDataTreeLeafPreimage &low_leaf_preimage, const FF &leaf_slot)
AppendOnlyTreeSnapshot write(const FF &slot, const AztecAddress &contract_address, const FF &value, const PublicDataTreeLeafPreimage &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > low_leaf_sibling_path, const AppendOnlyTreeSnapshot &prev_snapshot, std::span< const FF > insertion_sibling_path, bool is_protocol_write) override
void assert_read(const FF &slot, const AztecAddress &contract_address, const FF &value, const PublicDataTreeLeafPreimage &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot) override
EventEmitterInterface< PublicDataTreeCheckEvent > & events
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
IndexedLeaf< PublicDataLeafValue > PublicDataTreeLeafPreimage
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static IndexedLeaf< PublicDataLeafValue > empty()
std::vector< fr > get_hash_inputs() const