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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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
57LMDBTreeStore::LMDBTreeStore(std::string directory, std::string name, uint64_t mapSizeKb, uint64_t maxNumReaders)
58 : LMDBStoreBase(directory, mapSizeKb, maxNumReaders, 5)
59 , _name(std::move(name))
60{
61
62 {
66 tx->commit();
67 }
68
69 {
73 tx->commit();
74 }
75
76 {
80 tx->commit();
81 }
82
83 {
86 _environment, *tx, _name + LEAF_PREIMAGES_DB, false, false, false, fr_key_cmp);
87 tx->commit();
88 }
89
90 {
93 _environment, *tx, _name + BLOCK_INDICES_DB, false, false, false, index_key_cmp);
94 tx->commit();
95 }
96}
97
98const std::string& LMDBTreeStore::get_name() const
99{
100 return _name;
101}
102
104{
105 stats.mapSize = _environment->get_map_size();
106 stats.physicalFileSize = _environment->get_data_file_size();
107 stats.blocksDBStats = _blockDatabase->get_stats(tx);
109 stats.leafIndicesDBStats = _leafKeyToIndexDatabase->get_stats(tx);
110 stats.nodesDBStats = _nodeDatabase->get_stats(tx);
111 stats.blockIndicesDBStats = _indexToBlockDatabase->get_stats(tx);
112}
113
115 const BlockPayload& blockData,
117{
118 msgpack::sbuffer buffer;
119 msgpack::pack(buffer, blockData);
120 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
121 BlockMetaKeyType key(blockNumber);
123}
124
130
132 BlockPayload& blockData,
134{
135 BlockMetaKeyType key(blockNumber);
136 std::vector<uint8_t> data;
137 bool success = tx.get_value<BlockMetaKeyType>(key, data, *_blockDatabase);
138 if (success) {
139 msgpack::unpack((const char*)data.data(), data.size()).get().convert(blockData);
140 }
141 return success;
142}
143
145 const index_t& sizeAtBlock,
147{
148 // There can be multiple block numbers aganst the same index (zero size blocks)
149 LeafIndexKeyType key(sizeAtBlock);
150 std::vector<uint8_t> data;
151 // Read the block index payload
153 BlockIndexPayload payload;
154 if (success) {
155 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
156 }
157
158 payload.add_block(blockNumber);
159
160 // Write the new payload back down
161 msgpack::sbuffer buffer;
162 msgpack::pack(buffer, payload);
163 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
165}
166
168{
169 LeafIndexKeyType key(index + 1);
170 std::vector<uint8_t> data;
171 // Retrieve the payload
173 if (!success) {
174 return false;
175 }
176 BlockIndexPayload payload;
177 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
178 if (payload.is_empty()) {
179 return false;
180 }
181 // The block numbers are sorted so we simply return the lowest
182 blockNumber = payload.get_min_block_number();
183 return true;
184}
185
187 const block_number_t& blockNumber,
189{
190 // To delete a block number form an index we retieve all the block numbers from that index
191 // Then we find and remove the block number in question
192 // Then we write back down
193 LeafIndexKeyType key(sizeAtBlock);
194 std::vector<uint8_t> data;
195 // Retrieve the data
197 if (!success) {
198 return;
199 }
200 BlockIndexPayload payload;
201 msgpack::unpack((const char*)data.data(), data.size()).get().convert(payload);
202
203 payload.delete_block(blockNumber);
204
205 // if it's now empty, delete it
206 if (payload.is_empty()) {
208 return;
209 }
210 // not empty write it back
211 msgpack::sbuffer buffer;
212 msgpack::pack(buffer, payload);
213 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
215}
216
218{
219 msgpack::sbuffer buffer;
220 msgpack::pack(buffer, metaData);
221 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
222 MetaKeyType key(0);
223 tx.put_value<MetaKeyType>(key, encoded, *_blockDatabase);
224}
225
227{
228 MetaKeyType key(0);
229 std::vector<uint8_t> data;
230 bool success = tx.get_value<MetaKeyType>(key, data, *_blockDatabase);
231 if (success) {
232 msgpack::unpack((const char*)data.data(), data.size()).get().convert(metaData);
233 }
234 return success;
235}
236
238{
239 FrKeyType key(leafValue);
240 // std::cout << "Writing leaf indices by key " << key << std::endl;
242}
243
245{
246 FrKeyType key(leafValue);
247 // std::cout << "Deleting leaf indices by key " << key << std::endl;
249}
250
252{
253 NodePayload nodePayload;
254 bool success = get_node_data(nodeHash, nodePayload, tx);
255 if (!success) {
256 throw std::runtime_error("Failed to find node when attempting to increase reference count");
257 }
258 ++nodePayload.ref;
259 // std::cout << "Incrementing siblng at " << nodeHash << ", to " << nodePayload.ref << std::endl;
260 write_node(nodeHash, nodePayload, tx);
261}
262
264 NodePayload& nodeData,
266{
267 // Set to zero here and enrich from DB if present
268 nodeData.ref = 0;
269 get_node_data(nodeHash, nodeData, tx);
270 // Increment now to the correct value
271 ++nodeData.ref;
272 // std::cout << "Setting node at " << nodeHash << ", to " << nodeData.ref << std::endl;
273 write_node(nodeHash, nodeData, tx);
274}
275
277{
278 bool success = get_node_data(nodeHash, nodeData, tx);
279 if (!success) {
280 throw std::runtime_error("Failed to find node when attempting to decrease reference count");
281 }
282 if (--nodeData.ref == 0) {
283 // std::cout << "Deleting node at " << nodeHash << std::endl;
284 tx.delete_value(nodeHash, *_nodeDatabase);
285 return;
286 }
287 // std::cout << "Updating node at " << nodeHash << " ref is now " << nodeData.ref << std::endl;
288 write_node(nodeHash, nodeData, tx);
289}
290
296
298 index_t& index,
299 const std::optional<index_t>& sizeLimit,
300 ReadTransaction& tx)
301{
302 FrKeyType key(leafValue);
303 auto is_valid = [&](const MDB_val& data) {
304 index_t tmp = 0;
305 deserialise_key(data.mv_data, tmp);
306 return tmp < sizeLimit.value();
307 };
308 if (!sizeLimit.has_value()) {
310 } else {
312 }
313 return key;
314}
315
316bool LMDBTreeStore::read_node(const fr& nodeHash, NodePayload& nodeData, ReadTransaction& tx)
317{
318 FrKeyType key(nodeHash);
319 std::vector<uint8_t> data;
320 bool success = tx.get_value<FrKeyType>(key, data, *_nodeDatabase);
321 if (success) {
322 msgpack::unpack((const char*)data.data(), data.size()).get().convert(nodeData);
323 }
324 return success;
325}
326
327void LMDBTreeStore::write_node(const fr& nodeHash, const NodePayload& nodeData, WriteTransaction& tx)
328{
329 msgpack::sbuffer buffer;
330 msgpack::pack(buffer, nodeData);
331 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
332 FrKeyType key(nodeHash);
333 tx.put_value<FrKeyType>(key, encoded, *_nodeDatabase);
334}
335
336} // 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
void delete_leaf_by_hash(const fr &leafHash, WriteTransaction &tx)
void decrement_node_reference_count(const fr &nodeHash, NodePayload &nodeData, WriteTransaction &tx)
LMDBTreeStore(std::string directory, std::string name, uint64_t mapSizeKb, uint64_t maxNumReaders)
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)
const std::vector< FF > data
FF a
FF b
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
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
void add_block(const block_number_t &blockNumber)
void delete_block(const block_number_t &blockNumber)