Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
lmdb_tree_store.hpp
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
7#pragma once
21#include "lmdb.h"
22#include <cstdint>
23#include <optional>
24#include <ostream>
25#include <stdexcept>
26#include <string>
27#include <typeinfo>
28#include <unordered_map>
29#include <utility>
30
32
33using namespace bb::lmdblib;
34
36
40
42
43 bool operator==(const BlockPayload& other) const
44 {
45 return size == other.size && blockNumber == other.blockNumber && root == other.root;
46 }
47};
48
49inline std::ostream& operator<<(std::ostream& os, const BlockPayload& block)
50{
51 os << "BlockPayload{size: " << std::dec << block.size << ", blockNumber: " << std::dec << block.blockNumber
52 << ", root: " << block.root << "}";
53 return os;
54}
55
59 uint64_t ref;
60
62
63 bool operator==(const NodePayload& other) const
64 {
65 return left == other.left && right == other.right && ref == other.ref;
66 }
67};
68
70 std::vector<block_number_t> blockNumbers;
71
73
74 bool operator==(const BlockIndexPayload& other) const { return blockNumbers == other.blockNumbers; }
75
76 bool is_empty() const { return blockNumbers.empty(); }
77
79
80 bool contains(const block_number_t& blockNumber)
81 {
82 if (is_empty()) {
83 return false;
84 }
85 if (blockNumbers.size() == 1) {
86 return blockNumbers[0] == blockNumber;
87 }
88 return blockNumber >= blockNumbers[0] && blockNumber <= blockNumbers[1];
89 }
90
91 void delete_block(const block_number_t& blockNumber)
92 {
93 // Shouldn't be possible, but no need to do anything here
94 if (blockNumbers.empty()) {
95 return;
96 }
97
98 // If the size is 1, the blocknumber must match that in index 0, if it does remove it
99 if (blockNumbers.size() == 1) {
100 if (blockNumbers[0] == blockNumber) {
101 blockNumbers.pop_back();
102 }
103 return;
104 }
105
106 // we have 2 entries, we must verify that the block number is equal to the item in index 1
107 if (blockNumbers[1] != blockNumber) {
108 throw std::runtime_error(format("Unable to delete block number ",
109 blockNumber,
110 " for retrieval by index, current max block number at that index: ",
111 blockNumbers[1]));
112 }
113 // It is equal, decrement it, we know that the new block number must have been added previously
114 --blockNumbers[1];
115
116 // We have modified the high block. If it is now equal to the low block then pop it
117 if (blockNumbers[0] == blockNumbers[1]) {
118 blockNumbers.pop_back();
119 }
120 }
121
122 void add_block(const block_number_t& blockNumber)
123 {
124 // If empty, just add the block number
125 if (blockNumbers.empty()) {
126 blockNumbers.emplace_back(blockNumber);
127 return;
128 }
129
130 // If the size is 1, then we must be adding the block 1 larger than that in index 0
131 if (blockNumbers.size() == 1) {
132 if (blockNumber != blockNumbers[0] + 1) {
133 // We can't accept a block number for this index that does not immediately follow the block before
134 throw std::runtime_error(format("Unable to store block number ",
135 blockNumber,
136 " for retrieval by index, current max block number at that index: ",
137 blockNumbers[0]));
138 }
139 blockNumbers.emplace_back(blockNumber);
140 return;
141 }
142
143 // Size must be 2 here, if larger, this is an error
144 if (blockNumbers.size() != 2) {
145 throw std::runtime_error(format("Unable to store block number ",
146 blockNumber,
147 " for retrieval by index, block numbers is of invalid size: ",
148 blockNumbers.size()));
149 }
150
151 // If the size is 2, then we must be adding the block 1 larger than that in index 1
152 if (blockNumber != blockNumbers[1] + 1) {
153 // We can't accept a block number for this index that does not immediately follow the block before
154 throw std::runtime_error(format("Unable to store block number ",
155 blockNumber,
156 " for retrieval by index, current max block number at that index: ",
157 blockNumbers[1]));
158 }
159 blockNumbers[1] = blockNumber;
160 }
161};
168 public:
173 LMDBTreeStore(std::string directory, std::string name, uint64_t mapSizeKb, uint64_t maxNumReaders);
174 LMDBTreeStore(const LMDBTreeStore& other) = delete;
175 LMDBTreeStore(LMDBTreeStore&& other) = delete;
176 LMDBTreeStore& operator=(const LMDBTreeStore& other) = delete;
178 ~LMDBTreeStore() override = default;
179
180 const std::string& get_name() const;
181
182 void get_stats(TreeDBStats& stats, ReadTransaction& tx);
183
184 void write_block_data(const block_number_t& blockNumber, const BlockPayload& blockData, WriteTransaction& tx);
185
186 bool read_block_data(const block_number_t& blockNumber, BlockPayload& blockData, ReadTransaction& tx);
187
188 void delete_block_data(const block_number_t& blockNumber, WriteTransaction& tx);
189
190 void write_block_index_data(const block_number_t& blockNumber, const index_t& sizeAtBlock, WriteTransaction& tx);
191
192 // index here is 0 based
193 bool find_block_for_index(const index_t& index, block_number_t& blockNumber, ReadTransaction& tx);
194
195 void delete_block_index(const index_t& sizeAtBlock, const block_number_t& blockNumber, WriteTransaction& tx);
196
197 void write_meta_data(const TreeMeta& metaData, WriteTransaction& tx);
198
199 bool read_meta_data(TreeMeta& metaData, ReadTransaction& tx);
200
201 template <typename TxType> bool read_leaf_index(const fr& leafValue, index_t& leafIndex, TxType& tx);
202
203 fr find_low_leaf(const fr& leafValue, index_t& index, const std::optional<index_t>& sizeLimit, ReadTransaction& tx);
204
205 void write_leaf_index(const fr& leafValue, const index_t& leafIndex, WriteTransaction& tx);
206
207 void delete_leaf_index(const fr& leafValue, WriteTransaction& tx);
208
209 bool read_node(const fr& nodeHash, NodePayload& nodeData, ReadTransaction& tx);
210
211 void write_node(const fr& nodeHash, const NodePayload& nodeData, WriteTransaction& tx);
212
213 void increment_node_reference_count(const fr& nodeHash, WriteTransaction& tx);
214
215 void set_or_increment_node_reference_count(const fr& nodeHash, NodePayload& nodeData, WriteTransaction& tx);
216
217 void decrement_node_reference_count(const fr& nodeHash, NodePayload& nodeData, WriteTransaction& tx);
218
219 template <typename LeafType, typename TxType>
220 bool read_leaf_by_hash(const fr& leafHash, LeafType& leafData, TxType& tx);
221
222 template <typename LeafType>
223 void write_leaf_by_hash(const fr& leafHash, const LeafType& leafData, WriteTransaction& tx);
224
225 void delete_leaf_by_hash(const fr& leafHash, WriteTransaction& tx);
226
227 void write_leaf_key_by_index(const fr& leafKey, const index_t& index, WriteTransaction& tx);
228
229 template <typename TxType> bool read_leaf_key_by_index(const index_t& index, fr& leafKey, TxType& tx);
230
231 template <typename TxType>
232 void read_all_leaf_keys_after_or_equal_index(const index_t& index, std::vector<bb::fr>& leafKeys, TxType& tx);
233
235
236 template <typename TxType>
238
240
241 private:
242 std::string _name;
248
249 template <typename TxType> bool get_node_data(const fr& nodeHash, NodePayload& nodeData, TxType& tx);
250};
251
252template <typename TxType> bool LMDBTreeStore::read_leaf_index(const fr& leafValue, index_t& leafIndex, TxType& tx)
253{
254 FrKeyType key(leafValue);
255 return tx.template get_value<FrKeyType>(key, leafIndex, *_leafKeyToIndexDatabase);
256}
257
258template <typename LeafType, typename TxType>
259bool LMDBTreeStore::read_leaf_by_hash(const fr& leafHash, LeafType& leafData, TxType& tx)
260{
261 FrKeyType key(leafHash);
262 std::vector<uint8_t> data;
263 bool success = tx.template get_value<FrKeyType>(key, data, *_leafHashToPreImageDatabase);
264 if (success) {
265 msgpack::unpack((const char*)data.data(), data.size()).get().convert(leafData);
266 }
267 return success;
268}
269
270template <typename LeafType>
271void LMDBTreeStore::write_leaf_by_hash(const fr& leafHash, const LeafType& leafData, WriteTransaction& tx)
272{
273 msgpack::sbuffer buffer;
274 msgpack::pack(buffer, leafData);
275 std::vector<uint8_t> encoded(buffer.data(), buffer.data() + buffer.size());
276 FrKeyType key(leafHash);
278}
279
280template <typename TxType> bool LMDBTreeStore::get_node_data(const fr& nodeHash, NodePayload& nodeData, TxType& tx)
281{
282 FrKeyType key(nodeHash);
283 std::vector<uint8_t> data;
284 bool success = tx.template get_value<FrKeyType>(key, data, *_nodeDatabase);
285 if (success) {
286 msgpack::unpack((const char*)data.data(), data.size()).get().convert(nodeData);
287 }
288 return success;
289}
290} // namespace bb::crypto::merkle_tree
void write_leaf_by_hash(const fr &leafHash, const LeafType &leafData, WriteTransaction &tx)
void set_or_increment_node_reference_count(const fr &nodeHash, NodePayload &nodeData, WriteTransaction &tx)
LMDBTreeStore(const LMDBTreeStore &other)=delete
std::shared_ptr< LMDBTreeStore > SharedPtr
bool get_node_data(const fr &nodeHash, NodePayload &nodeData, TxType &tx)
std::unique_ptr< LMDBTreeStore > Ptr
void delete_block_data(const block_number_t &blockNumber, WriteTransaction &tx)
void write_leaf_key_by_index(const fr &leafKey, const index_t &index, WriteTransaction &tx)
bool find_block_for_index(const index_t &index, block_number_t &blockNumber, ReadTransaction &tx)
void delete_all_leaf_keys_before_or_equal_index(const index_t &index, WriteTransaction &tx)
void delete_all_leaf_keys_after_or_equal_index(const index_t &index, WriteTransaction &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)
void read_all_leaf_keys_after_or_equal_index(const index_t &index, std::vector< bb::fr > &leafKeys, TxType &tx)
bool read_node(const fr &nodeHash, NodePayload &nodeData, ReadTransaction &tx)
const std::string & get_name() const
bool read_leaf_key_by_index(const index_t &index, fr &leafKey, TxType &tx)
void delete_leaf_by_hash(const fr &leafHash, WriteTransaction &tx)
void decrement_node_reference_count(const fr &nodeHash, NodePayload &nodeData, WriteTransaction &tx)
LMDBTreeStore & operator=(LMDBTreeStore &&other)=delete
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 read_all_leaf_keys_before_or_equal_index(const index_t &index, std::vector< bb::fr > &leafKeys, TxType &tx)
LMDBTreeStore(LMDBTreeStore &&other)=delete
LMDBTreeStore & operator=(const LMDBTreeStore &other)=delete
bool read_leaf_by_hash(const fr &leafHash, LeafType &leafData, TxType &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)
bool read_leaf_index(const fr &leafValue, index_t &leafIndex, TxType &tx)
std::unique_ptr< LMDBDatabase > Ptr
void put_value(T &key, Value &data, const LMDBDatabase &db)
std::string format(Args... args)
Definition log.hpp:20
const std::vector< FF > data
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
#define MSGPACK_FIELDS(...)
Definition msgpack.hpp:118
uint32_t block_number_t
Definition types.hpp:19
std::ostream & operator<<(std::ostream &os, const BlockPayload &block)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
void add_block(const block_number_t &blockNumber)
bool contains(const block_number_t &blockNumber)
void delete_block(const block_number_t &blockNumber)
std::vector< block_number_t > blockNumbers