Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
lmdb_tree_store.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Nishat], commit: 22d6fc368da0fbe5412f4f7b2890a052aa48d803 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
18#include "lmdb_tree_store.hpp"
19#include <cstddef>
20#include <cstdint>
21#include <cstring>
22#include <exception>
23#include <lmdb.h>
24#include <optional>
25#include <stdexcept>
26#include <unordered_map>
27#include <vector>
28
30
36int fr_key_cmp(const MDB_val* a, const MDB_val* b)
37{
38 return value_cmp<numeric::uint256_t>(a, b);
39}
40
41int block_key_cmp(const MDB_val* a, const MDB_val* b)
42{
43 if (a->mv_size != b->mv_size) {
44 return size_cmp(a, b);
45 }
46 if (a->mv_size == 1) {
47 return value_cmp<uint8_t>(a, b);
48 }
49 return value_cmp<uint64_t>(a, b);
50}
51
52int index_key_cmp(const MDB_val* a, const MDB_val* b)
53{
54 return value_cmp<uint64_t>(a, b);
55}
56
58 std::string directory, std::string name, uint64_t mapSizeKb, uint64_t maxNumReaders, bool ephemeral)
59 : LMDBStoreBase(directory, mapSizeKb, maxNumReaders, 5, ephemeral)
60 , _name(std::move(name))
61{
62
63 {
67 tx->commit();
68 }
69
70 {
74 tx->commit();
75 }
76
77 {
81 tx->commit();
82 }
83
84 {
87 _environment, *tx, _name + LEAF_PREIMAGES_DB, false, false, false, fr_key_cmp);
88 tx->commit();
89 }
90
91 {
94 _environment, *tx, _name + BLOCK_INDICES_DB, false, false, false, index_key_cmp);
95 tx->commit();
96 }
97}
98
99const std::string& LMDBTreeStore::get_name() const
100{
101 return _name;
102}
103
105{
106 stats.mapSize = _environment->get_map_size();
107 stats.physicalFileSize = _environment->get_data_file_size();
108 stats.blocksDBStats = _blockDatabase->get_stats(tx);
110 stats.leafIndicesDBStats = _leafKeyToIndexDatabase->get_stats(tx);
111 stats.nodesDBStats = _nodeDatabase->get_stats(tx);
112 stats.blockIndicesDBStats = _indexToBlockDatabase->get_stats(tx);
113}
114
116 const BlockPayload& blockData,
118{
119 msgpack::sbuffer buffer;
120 msgpack::pack(buffer, blockData);
121 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
122 BlockMetaKeyType key(blockNumber);
124}
125
131
133 BlockPayload& blockData,
135{
136 BlockMetaKeyType key(blockNumber);
137 std::vector<uint8_t> data;
138 bool success = tx.get_value<BlockMetaKeyType>(key, data, *_blockDatabase);
139 if (success) {
140 msgpack::unpack((const char*)data.data(), data.size()).get().convert(blockData);
141 }
142 return success;
143}
144
146 const index_t& sizeAtBlock,
148{
149 // There can be multiple block numbers aganst the same index (zero size blocks)
150 LeafIndexKeyType key(sizeAtBlock);
151 std::vector<uint8_t> data;
152 // Read the block index payload
154 BlockIndexPayload payload;
155 if (success) {
156 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
157 }
158
159 payload.add_block(blockNumber);
160
161 // Write the new payload back down
162 msgpack::sbuffer buffer;
163 msgpack::pack(buffer, payload);
164 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
166}
167
169{
171 std::vector<uint8_t> data;
172 // Retrieve the payload
174 if (!success) {
175 return false;
176 }
177 BlockIndexPayload payload;
178 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
179 if (payload.is_empty()) {
180 return false;
181 }
182 // The block numbers are sorted so we simply return the lowest
183 blockNumber = payload.get_min_block_number();
184 return true;
185}
186
188 const block_number_t& blockNumber,
190{
191 // To delete a block number form an index we retieve all the block numbers from that index
192 // Then we find and remove the block number in question
193 // Then we write back down
194 LeafIndexKeyType key(sizeAtBlock);
195 std::vector<uint8_t> data;
196 // Retrieve the data
198 if (!success) {
199 return;
200 }
201 BlockIndexPayload payload;
202 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
203
204 payload.delete_block(blockNumber);
205
206 // if it's now empty, delete it
207 if (payload.is_empty()) {
209 return;
210 }
211 // not empty write it back
212 msgpack::sbuffer buffer;
213 msgpack::pack(buffer, payload);
214 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
216}
217
219{
220 msgpack::sbuffer buffer;
221 msgpack::pack(buffer, metaData);
222 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
223 MetaKeyType key(0);
224 tx.put_value<MetaKeyType>(key, encoded, *_blockDatabase);
225}
226
228{
229 MetaKeyType key(0);
230 std::vector<uint8_t> data;
231 bool success = tx.get_value<MetaKeyType>(key, data, *_blockDatabase);
232 if (success) {
233 msgpack::unpack((const char*)data.data(), data.size()).get().convert(metaData);
234 }
235 return success;
236}
237
239{
240 FrKeyType key(leafValue);
241 // std::cout << "Writing leaf indices by key " << key << std::endl;
243}
244
246{
247 FrKeyType key(leafValue);
248 // std::cout << "Deleting leaf indices by key " << key << std::endl;
250}
251
253{
254 NodePayload nodePayload;
255 bool success = get_node_data(nodeHash, nodePayload, tx);
256 if (!success) {
257 throw std::runtime_error("Failed to find node when attempting to increase reference count");
258 }
259 ++nodePayload.ref;
260 // std::cout << "Incrementing siblng at " << nodeHash << ", to " << nodePayload.ref << std::endl;
261 write_node(nodeHash, nodePayload, tx);
262}
263
265 NodePayload& nodeData,
267{
268 // Set to zero here and enrich from DB if present
269 nodeData.ref = 0;
270 get_node_data(nodeHash, nodeData, tx);
271 // Increment now to the correct value
272 ++nodeData.ref;
273 // std::cout << "Setting node at " << nodeHash << ", to " << nodeData.ref << std::endl;
274 write_node(nodeHash, nodeData, tx);
275}
276
278{
279 bool success = get_node_data(nodeHash, nodeData, tx);
280 if (!success) {
281 throw std::runtime_error("Failed to find node when attempting to decrease reference count");
282 }
283 if (--nodeData.ref == 0) {
284 // std::cout << "Deleting node at " << nodeHash << std::endl;
285 tx.delete_value(nodeHash, *_nodeDatabase);
286 return;
287 }
288 // std::cout << "Updating node at " << nodeHash << " ref is now " << nodeData.ref << std::endl;
289 write_node(nodeHash, nodeData, tx);
290}
291
297
299 index_t& index,
300 const std::optional<index_t>& sizeLimit,
301 ReadTransaction& tx)
302{
303 FrKeyType key(leafValue);
304 auto is_valid = [&](const MDB_val& data) {
305 index_t tmp = 0;
306 deserialise_key(data.mv_data, tmp);
307 return tmp < sizeLimit.value();
308 };
309 if (!sizeLimit.has_value()) {
311 } else {
313 }
314 return key;
315}
316
317bool LMDBTreeStore::read_node(const fr& nodeHash, NodePayload& nodeData, ReadTransaction& tx)
318{
319 FrKeyType key(nodeHash);
320 std::vector<uint8_t> data;
321 bool success = tx.get_value<FrKeyType>(key, data, *_nodeDatabase);
322 if (success) {
323 msgpack::unpack((const char*)data.data(), data.size()).get().convert(nodeData);
324 }
325 return success;
326}
327
328void LMDBTreeStore::write_node(const fr& nodeHash, const NodePayload& nodeData, WriteTransaction& tx)
329{
330 msgpack::sbuffer buffer;
331 msgpack::pack(buffer, nodeData);
332 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
333 FrKeyType key(nodeHash);
334 tx.put_value<FrKeyType>(key, encoded, *_nodeDatabase);
335}
336
337} // namespace bb::crypto::merkle_tree
void set_or_increment_node_reference_count(const fr &nodeHash, NodePayload &nodeData, WriteTransaction &tx)
bool get_node_data(const fr &nodeHash, NodePayload &nodeData, TxType &tx)
void delete_block_data(const block_number_t &blockNumber, WriteTransaction &tx)
bool find_block_for_index(const index_t &index, block_number_t &blockNumber, ReadTransaction &tx)
void write_node(const fr &nodeHash, const NodePayload &nodeData, WriteTransaction &tx)
void write_block_data(const block_number_t &blockNumber, const BlockPayload &blockData, WriteTransaction &tx)
void write_leaf_index(const fr &leafValue, const index_t &leafIndex, WriteTransaction &tx)
void delete_block_index(const index_t &sizeAtBlock, const block_number_t &blockNumber, WriteTransaction &tx)
bool read_node(const fr &nodeHash, NodePayload &nodeData, ReadTransaction &tx)
const std::string & get_name() const
LMDBTreeStore(std::string directory, std::string name, uint64_t mapSizeKb, uint64_t maxNumReaders, bool ephemeral=false)
void delete_leaf_by_hash(const fr &leafHash, WriteTransaction &tx)
void decrement_node_reference_count(const fr &nodeHash, NodePayload &nodeData, WriteTransaction &tx)
void write_meta_data(const TreeMeta &metaData, WriteTransaction &tx)
bool read_block_data(const block_number_t &blockNumber, BlockPayload &blockData, ReadTransaction &tx)
void get_stats(TreeDBStats &stats, ReadTransaction &tx)
void write_block_index_data(const block_number_t &blockNumber, const index_t &sizeAtBlock, WriteTransaction &tx)
void delete_leaf_index(const fr &leafValue, WriteTransaction &tx)
void increment_node_reference_count(const fr &nodeHash, WriteTransaction &tx)
fr find_low_leaf(const fr &leafValue, index_t &index, const std::optional< index_t > &sizeLimit, ReadTransaction &tx)
bool read_meta_data(TreeMeta &metaData, ReadTransaction &tx)
std::unique_ptr< LMDBDatabaseCreationTransaction > Ptr
LMDBEnvironment::SharedPtr _environment
LMDBDatabaseCreationTransaction::Ptr create_db_transaction() const
bool get_value_or_greater(T &key, K &data, const LMDBDatabase &db) const
bool get_value(T &key, std::vector< uint8_t > &data, const LMDBDatabase &db) const
bool get_value_or_previous(T &key, K &data, const LMDBDatabase &db, const std::function< bool(const MDB_val &)> &is_valid) const
void put_value(T &key, Value &data, const LMDBDatabase &db)
void delete_value(T &key, const LMDBDatabase &db)
FF a
FF b
std::unique_ptr< uint8_t[]> buffer
Definition engine.cpp:60
int block_key_cmp(const MDB_val *a, const MDB_val *b)
const std::string LEAF_PREIMAGES_DB
Definition types.hpp:64
const std::string NODES_DB
Definition types.hpp:63
uint32_t block_number_t
Definition types.hpp:19
uint64_t BlockMetaKeyType
Definition types.hpp:21
const std::string BLOCK_INDICES_DB
Definition types.hpp:66
uint64_t LeafIndexKeyType
Definition types.hpp:20
const std::string BLOCKS_DB
Definition types.hpp:62
int fr_key_cmp(const MDB_val *a, const MDB_val *b)
const std::string LEAF_INDICES_DB
Definition types.hpp:65
int index_key_cmp(const MDB_val *a, const MDB_val *b)
int size_cmp(const MDB_val *a, const MDB_val *b)
void deserialise_key(void *data, uint8_t &key)
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::byte * data
void add_block(const block_number_t &blockNumber)
void delete_block(const block_number_t &blockNumber)