Electroneum
ringdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include <lmdb.h>
30 #include <boost/algorithm/string.hpp>
31 #include <boost/range/adaptor/transformed.hpp>
32 #include <boost/filesystem.hpp>
33 #include "common/util.h"
34 #include "misc_log_ex.h"
35 #include "misc_language.h"
36 #include "wallet_errors.h"
37 #include "ringdb.h"
38 
39 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
40 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "wallet.ringdb"
41 
42 static const char zerokey[8] = {0};
43 static const MDB_val zerokeyval = { sizeof(zerokey), (void *)zerokey };
44 
45 static int compare_hash32(const MDB_val *a, const MDB_val *b)
46 {
47  uint32_t *va = (uint32_t*) a->mv_data;
48  uint32_t *vb = (uint32_t*) b->mv_data;
49  for (int n = 7; n >= 0; n--)
50  {
51  if (va[n] == vb[n])
52  continue;
53  return va[n] < vb[n] ? -1 : 1;
54  }
55 
56  return 0;
57 }
58 
59 static int compare_uint64(const MDB_val *a, const MDB_val *b)
60 {
61  const uint64_t va = *(const uint64_t*) a->mv_data;
62  const uint64_t vb = *(const uint64_t*) b->mv_data;
63  return va < vb ? -1 : va > vb;
64 }
65 
66 static std::string compress_ring(const std::vector<uint64_t> &ring)
67 {
68  std::string s;
69  for (uint64_t out: ring)
70  s += tools::get_varint_data(out);
71  return s;
72 }
73 
74 static std::vector<uint64_t> decompress_ring(const std::string &s)
75 {
76  std::vector<uint64_t> ring;
77  int read = 0;
78  for (std::string::const_iterator i = s.begin(); i != s.cend(); std::advance(i, read))
79  {
80  uint64_t out;
81  std::string tmp(i, s.cend());
82  read = tools::read_varint(tmp.begin(), tmp.end(), out);
83  THROW_WALLET_EXCEPTION_IF(read <= 0 || read > 256, tools::error::wallet_internal_error, "Internal error decompressing ring");
84  ring.push_back(out);
85  }
86  return ring;
87 }
88 
89 std::string get_rings_filename(boost::filesystem::path filename)
90 {
91  if (!boost::filesystem::is_directory(filename))
92  filename.remove_filename();
93  return filename.string();
94 }
95 
96 static crypto::chacha_iv make_iv(const crypto::key_image &key_image, const crypto::chacha_key &key)
97 {
98  static const char salt[] = "ringdsb";
99 
100  uint8_t buffer[sizeof(key_image) + sizeof(key) + sizeof(salt)];
101  memcpy(buffer, &key_image, sizeof(key_image));
102  memcpy(buffer + sizeof(key_image), &key, sizeof(key));
103  memcpy(buffer + sizeof(key_image) + sizeof(key), salt, sizeof(salt));
105  crypto::cn_fast_hash(buffer, sizeof(buffer), hash.data);
106  static_assert(sizeof(hash) >= CHACHA_IV_SIZE, "Incompatible hash and chacha IV sizes");
107  crypto::chacha_iv iv;
108  memcpy(&iv, &hash, CHACHA_IV_SIZE);
109  return iv;
110 }
111 
112 static std::string encrypt(const std::string &plaintext, const crypto::key_image &key_image, const crypto::chacha_key &key)
113 {
114  const crypto::chacha_iv iv = make_iv(key_image, key);
115  std::string ciphertext;
116  ciphertext.resize(plaintext.size() + sizeof(iv));
117  crypto::chacha20(plaintext.data(), plaintext.size(), key, iv, &ciphertext[sizeof(iv)]);
118  memcpy(&ciphertext[0], &iv, sizeof(iv));
119  return ciphertext;
120 }
121 
122 static std::string encrypt(const crypto::key_image &key_image, const crypto::chacha_key &key)
123 {
124  return encrypt(std::string((const char*)&key_image, sizeof(key_image)), key_image, key);
125 }
126 
127 static std::string decrypt(const std::string &ciphertext, const crypto::key_image &key_image, const crypto::chacha_key &key)
128 {
129  const crypto::chacha_iv iv = make_iv(key_image, key);
130  std::string plaintext;
131  THROW_WALLET_EXCEPTION_IF(ciphertext.size() < sizeof(iv), tools::error::wallet_internal_error, "Bad ciphertext text");
132  plaintext.resize(ciphertext.size() - sizeof(iv));
133  crypto::chacha20(ciphertext.data() + sizeof(iv), ciphertext.size() - sizeof(iv), key, iv, &plaintext[0]);
134  return plaintext;
135 }
136 
137 static void store_relative_ring(MDB_txn *txn, MDB_dbi &dbi, const crypto::key_image &key_image, const std::vector<uint64_t> &relative_ring, const crypto::chacha_key &chacha_key)
138 {
139  MDB_val key, data;
140  std::string key_ciphertext = encrypt(key_image, chacha_key);
141  key.mv_data = (void*)key_ciphertext.data();
142  key.mv_size = key_ciphertext.size();
143  std::string compressed_ring = compress_ring(relative_ring);
144  std::string data_ciphertext = encrypt(compressed_ring, key_image, chacha_key);
145  data.mv_size = data_ciphertext.size();
146  data.mv_data = (void*)data_ciphertext.c_str();
147  int dbr = mdb_put(txn, dbi, &key, &data, 0);
148  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set ring for key image in LMDB table: " + std::string(mdb_strerror(dbr)));
149 }
150 
151 static int resize_env(MDB_env *env, const char *db_path, size_t needed)
152 {
153  MDB_envinfo mei;
154  MDB_stat mst;
155  int ret;
156 
157  needed = std::max(needed, (size_t)(100ul * 1024 * 1024)); // at least 100 MB
158 
159  ret = mdb_env_info(env, &mei);
160  if (ret)
161  return ret;
162  ret = mdb_env_stat(env, &mst);
163  if (ret)
164  return ret;
165  uint64_t size_used = mst.ms_psize * mei.me_last_pgno;
166  uint64_t mapsize = mei.me_mapsize;
167  if (size_used + needed > mei.me_mapsize)
168  {
169  try
170  {
171  boost::filesystem::path path(db_path);
172  boost::filesystem::space_info si = boost::filesystem::space(path);
173  if(si.available < needed)
174  {
175  MERROR("!! WARNING: Insufficient free space to extend database !!: " << (si.available >> 20L) << " MB available");
176  return ENOSPC;
177  }
178  }
179  catch(...)
180  {
181  // print something but proceed.
182  MWARNING("Unable to query free disk space.");
183  }
184 
185  mapsize += needed;
186  }
187  return mdb_env_set_mapsize(env, mapsize);
188 }
189 
190 static size_t get_ring_data_size(size_t n_entries)
191 {
192  return n_entries * (32 + 1024); // highball 1kB for the ring data to make sure
193 }
194 
196 
197 namespace tools
198 {
199 
200 ringdb::ringdb(std::string filename, const std::string &genesis):
201  filename(filename),
202  env(NULL)
203 {
204  MDB_txn *txn;
205  bool tx_active = false;
206  int dbr;
207 
209 
210  dbr = mdb_env_create(&env);
211  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
212  dbr = mdb_env_set_maxdbs(env, 2);
213  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set max env dbs: " + std::string(mdb_strerror(dbr)));
214  const std::string actual_filename = get_rings_filename(filename);
215  dbr = mdb_env_open(env, actual_filename.c_str(), 0, 0664);
216  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to open rings database file '"
217  + actual_filename + "': " + std::string(mdb_strerror(dbr)));
218 
219  dbr = mdb_txn_begin(env, NULL, 0, &txn);
220  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
222  tx_active = true;
223 
224  dbr = mdb_dbi_open(txn, ("rings-" + genesis).c_str(), MDB_CREATE, &dbi_rings);
226  mdb_set_compare(txn, dbi_rings, compare_hash32);
227 
228  dbr = mdb_dbi_open(txn, ("blackballs2-" + genesis).c_str(), MDB_CREATE | MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, &dbi_blackballs);
230  mdb_set_dupsort(txn, dbi_blackballs, compare_uint64);
231 
232  dbr = mdb_txn_commit(txn);
233  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn creating/opening database: " + std::string(mdb_strerror(dbr)));
234  tx_active = false;
235 }
236 
238 {
239  close();
240 }
241 
243 {
244  if (env)
245  {
246  mdb_dbi_close(env, dbi_rings);
247  mdb_dbi_close(env, dbi_blackballs);
248  mdb_env_close(env);
249  env = NULL;
250  }
251 }
252 
253 bool ringdb::add_rings(const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx)
254 {
255  MDB_txn *txn;
256  int dbr;
257  bool tx_active = false;
258 
259  dbr = resize_env(env, filename.c_str(), get_ring_data_size(tx.vin.size()));
260  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size");
261  dbr = mdb_txn_begin(env, NULL, 0, &txn);
262  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
264  tx_active = true;
265 
266  for (const auto &in: tx.vin)
267  {
268  if (in.type() != typeid(cryptonote::txin_to_key))
269  continue;
270  const auto &txin = boost::get<cryptonote::txin_to_key>(in);
271  const uint32_t ring_size = txin.key_offsets.size();
272  if (ring_size == 1)
273  continue;
274 
275  store_relative_ring(txn, dbi_rings, txin.k_image, txin.key_offsets, chacha_key);
276  }
277 
278  dbr = mdb_txn_commit(txn);
279  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn adding ring to database: " + std::string(mdb_strerror(dbr)));
280  tx_active = false;
281  return true;
282 }
283 
284 bool ringdb::remove_rings(const crypto::chacha_key &chacha_key, const std::vector<crypto::key_image> &key_images)
285 {
286  MDB_txn *txn;
287  int dbr;
288  bool tx_active = false;
289 
290  dbr = resize_env(env, filename.c_str(), 0);
291  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size");
292  dbr = mdb_txn_begin(env, NULL, 0, &txn);
293  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
295  tx_active = true;
296 
297  for (const crypto::key_image &key_image: key_images)
298  {
299  MDB_val key, data;
300  std::string key_ciphertext = encrypt(key_image, chacha_key);
301  key.mv_data = (void*)key_ciphertext.data();
302  key.mv_size = key_ciphertext.size();
303 
304  dbr = mdb_get(txn, dbi_rings, &key, &data);
305  THROW_WALLET_EXCEPTION_IF(dbr && dbr != MDB_NOTFOUND, tools::error::wallet_internal_error, "Failed to look for key image in LMDB table: " + std::string(mdb_strerror(dbr)));
306  if (dbr == MDB_NOTFOUND)
307  continue;
308  THROW_WALLET_EXCEPTION_IF(data.mv_size <= 0, tools::error::wallet_internal_error, "Invalid ring data size");
309 
310  MDEBUG("Removing ring data for key image " << key_image);
311  dbr = mdb_del(txn, dbi_rings, &key, NULL);
312  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to remove ring to database: " + std::string(mdb_strerror(dbr)));
313  }
314 
315  dbr = mdb_txn_commit(txn);
316  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn removing ring to database: " + std::string(mdb_strerror(dbr)));
317  tx_active = false;
318  return true;
319 }
320 
321 bool ringdb::remove_rings(const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx)
322 {
323  std::vector<crypto::key_image> key_images;
324  key_images.reserve(tx.vin.size());
325  for (const auto &in: tx.vin)
326  {
327  if (in.type() != typeid(cryptonote::txin_to_key))
328  continue;
329  const auto &txin = boost::get<cryptonote::txin_to_key>(in);
330  const uint32_t ring_size = txin.key_offsets.size();
331  if (ring_size == 1)
332  continue;
333  key_images.push_back(txin.k_image);
334  }
335  return remove_rings(chacha_key, key_images);
336 }
337 
338 bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector<uint64_t> &outs)
339 {
340  MDB_txn *txn;
341  int dbr;
342  bool tx_active = false;
343 
344  dbr = resize_env(env, filename.c_str(), 0);
345  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
346  dbr = mdb_txn_begin(env, NULL, 0, &txn);
347  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
349  tx_active = true;
350 
351  MDB_val key, data;
352  std::string key_ciphertext = encrypt(key_image, chacha_key);
353  key.mv_data = (void*)key_ciphertext.data();
354  key.mv_size = key_ciphertext.size();
355  dbr = mdb_get(txn, dbi_rings, &key, &data);
356  THROW_WALLET_EXCEPTION_IF(dbr && dbr != MDB_NOTFOUND, tools::error::wallet_internal_error, "Failed to look for key image in LMDB table: " + std::string(mdb_strerror(dbr)));
357  if (dbr == MDB_NOTFOUND)
358  return false;
359  THROW_WALLET_EXCEPTION_IF(data.mv_size <= 0, tools::error::wallet_internal_error, "Invalid ring data size");
360 
361  std::string data_plaintext = decrypt(std::string((const char*)data.mv_data, data.mv_size), key_image, chacha_key);
362  outs = decompress_ring(data_plaintext);
363  MDEBUG("Found ring for key image " << key_image << ":");
364  MDEBUG("Relative: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
366  MDEBUG("Absolute: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
367 
368  dbr = mdb_txn_commit(txn);
369  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn getting ring from database: " + std::string(mdb_strerror(dbr)));
370  tx_active = false;
371  return true;
372 }
373 
374 bool ringdb::set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative)
375 {
376  MDB_txn *txn;
377  int dbr;
378  bool tx_active = false;
379 
380  dbr = resize_env(env, filename.c_str(), outs.size() * 64);
381  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
382  dbr = mdb_txn_begin(env, NULL, 0, &txn);
383  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
385  tx_active = true;
386 
387  store_relative_ring(txn, dbi_rings, key_image, relative ? outs : cryptonote::absolute_output_offsets_to_relative(outs), chacha_key);
388 
389  dbr = mdb_txn_commit(txn);
390  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn setting ring to database: " + std::string(mdb_strerror(dbr)));
391  tx_active = false;
392  return true;
393 }
394 
395 bool ringdb::blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, int op)
396 {
397  MDB_txn *txn;
398  MDB_cursor *cursor;
399  int dbr;
400  bool tx_active = false;
401  bool ret = true;
402 
403  THROW_WALLET_EXCEPTION_IF(outputs.size() > 1 && op == BLACKBALL_QUERY, tools::error::wallet_internal_error, "Blackball query only makes sense for a single output");
404 
405  dbr = resize_env(env, filename.c_str(), 32 * 2 * outputs.size()); // a pubkey, and some slack
406  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
407  dbr = mdb_txn_begin(env, NULL, 0, &txn);
408  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
410  tx_active = true;
411 
412  dbr = mdb_cursor_open(txn, dbi_blackballs, &cursor);
413  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create cursor for blackballs table: " + std::string(mdb_strerror(dbr)));
414 
415  MDB_val key, data;
416  for (const std::pair<uint64_t, uint64_t> &output: outputs)
417  {
418  key.mv_data = (void*)&output.first;
419  key.mv_size = sizeof(output.first);
420  data.mv_data = (void*)&output.second;
421  data.mv_size = sizeof(output.second);
422 
423  switch (op)
424  {
425  case BLACKBALL_BLACKBALL:
426  MDEBUG("Marking output " << output.first << "/" << output.second << " as spent");
427  dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP);
428  if (dbr == MDB_KEYEXIST)
429  dbr = 0;
430  break;
432  MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent");
433  dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
434  if (dbr == 0)
435  dbr = mdb_cursor_del(cursor, 0);
436  break;
437  case BLACKBALL_QUERY:
438  dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
439  THROW_WALLET_EXCEPTION_IF(dbr && dbr != MDB_NOTFOUND, tools::error::wallet_internal_error, "Failed to lookup in blackballs table: " + std::string(mdb_strerror(dbr)));
440  ret = dbr != MDB_NOTFOUND;
441  if (dbr == MDB_NOTFOUND)
442  dbr = 0;
443  break;
444  case BLACKBALL_CLEAR:
445  break;
446  default:
448  }
449  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to query blackballs table: " + std::string(mdb_strerror(dbr)));
450  }
451 
452  mdb_cursor_close(cursor);
453 
454  if (op == BLACKBALL_CLEAR)
455  {
456  dbr = mdb_drop(txn, dbi_blackballs, 0);
457  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to clear blackballs table: " + std::string(mdb_strerror(dbr)));
458  }
459 
460  dbr = mdb_txn_commit(txn);
461  THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn blackballing output to database: " + std::string(mdb_strerror(dbr)));
462  tx_active = false;
463  return ret;
464 }
465 
466 bool ringdb::blackball(const std::vector<std::pair<uint64_t, uint64_t>> &outputs)
467 {
468  return blackball_worker(outputs, BLACKBALL_BLACKBALL);
469 }
470 
471 bool ringdb::blackball(const std::pair<uint64_t, uint64_t> &output)
472 {
473  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
474  return blackball_worker(outputs, BLACKBALL_BLACKBALL);
475 }
476 
477 bool ringdb::unblackball(const std::pair<uint64_t, uint64_t> &output)
478 {
479  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
480  return blackball_worker(outputs, BLACKBALL_UNBLACKBALL);
481 }
482 
483 bool ringdb::blackballed(const std::pair<uint64_t, uint64_t> &output)
484 {
485  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
486  return blackball_worker(outputs, BLACKBALL_QUERY);
487 }
488 
490 {
491  return blackball_worker(std::vector<std::pair<uint64_t, uint64_t>>(), BLACKBALL_CLEAR);
492 }
493 
494 }
#define MDB_NOTFOUND
Definition: lmdb.h:439
#define MERROR(x)
Definition: misc_log_ex.h:73
int mdb_env_set_mapsize(MDB_env *env, mdb_size_t size)
Set the size of the memory map to use for this environment.
void mdb_cursor_close(MDB_cursor *cursor)
Close a cursor handle.
int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Delete items from a database.
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
Open a database in the environment.
Lightning memory-mapped database library.
std::string get_rings_filename(boost::filesystem::path filename)
Definition: ringdb.cpp:89
::std::string string
Definition: gtest-port.h:1097
int mdb_txn_commit(MDB_txn *txn)
Commit all the operations of a transaction into the database.
int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data, unsigned int flags)
Store by cursor.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
Close a database handle. Normally unnecessary. Use with care:
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const char * key
Definition: hmac_keccak.cpp:39
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom data comparison function for a MDB_DUPSORT database.
int mdb_env_info(MDB_env *env, MDB_envinfo *stat)
Return information about the LMDB environment.
int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
Set the maximum number of named databases for the environment.
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
struct MDB_env MDB_env
Opaque structure for a database environment.
Definition: lmdb.h:260
unsigned char uint8_t
Definition: stdint.h:124
bool unblackball(const std::pair< uint64_t, uint64_t > &output)
Definition: ringdb.cpp:477
#define MDEBUG(x)
Definition: misc_log_ex.h:76
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
#define MDB_CREATE
Definition: lmdb.h:357
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
Empty or delete+close a database.
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
Open an environment handle.
Statistics for a database in the environment.
Definition: lmdb.h:490
Information about the environment.
Definition: lmdb.h:501
void * mv_data
Definition: lmdb.h:288
bool blackball(const std::pair< uint64_t, uint64_t > &output)
Definition: ringdb.cpp:471
unsigned int uint32_t
Definition: stdint.h:126
Various Tools.
Definition: tools.cpp:31
size_t mv_size
Definition: lmdb.h:287
std::string get_varint_data(const T &v)
Returns the string that represents the varint.
Definition: varint.h:85
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
bool get_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector< uint64_t > &outs)
Definition: ringdb.cpp:338
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
mdb_size_t me_last_pgno
Definition: lmdb.h:504
unsigned __int64 uint64_t
Definition: stdint.h:136
#define MDB_INTEGERKEY
Definition: lmdb.h:349
#define MDB_DUPFIXED
Definition: lmdb.h:351
ringdb(std::string filename, const std::string &genesis)
Definition: ringdb.cpp:200
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom key comparison function for a database.
unsigned int MDB_dbi
A handle for an individual database in the DB environment.
Definition: lmdb.h:270
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
#define MWARNING(x)
Definition: misc_log_ex.h:74
void cn_fast_hash(const void *data, size_t length, char *hash)
int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Retrieve by cursor.
bool blackballed(const std::pair< uint64_t, uint64_t > &output)
Definition: ringdb.cpp:483
int mdb_env_create(MDB_env **env)
Create an LMDB environment handle.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
void decrypt(const void *ciphertext, size_t length, const uint8_t *key, const uint8_t *iv, char *plaintext, size_t *plaintext_len)
Definition: protocol.cpp:120
struct MDB_cursor MDB_cursor
Opaque structure for navigating through a database.
Definition: lmdb.h:273
Generic structure used for passing keys and data in and out of the database.
Definition: lmdb.h:286
unsigned int ms_psize
Definition: lmdb.h:491
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void * memcpy(void *a, const void *b, size_t c)
#define CHACHA_IV_SIZE
Definition: chacha.h:37
#define MDB_KEYEXIST
Definition: lmdb.h:437
void close()
Definition: ringdb.cpp:242
bool create_directories_if_necessary(const std::string &path)
creates directories for a path
Definition: util.cpp:625
int mdb_env_stat(MDB_env *env, MDB_stat *stat)
Return statistics about the LMDB environment.
char * mdb_strerror(int err)
Return a string describing a given error code.
mdb_size_t me_mapsize
Definition: lmdb.h:503
bool remove_rings(const crypto::chacha_key &chacha_key, const std::vector< crypto::key_image > &key_images)
Definition: ringdb.cpp:284
int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags)
Delete current key/data pair.
POD_CLASS hash
Definition: hash.h:50
#define THROW_WALLET_EXCEPTION(err_type,...)
std::string to_string(t_connection_type type)
#define MDB_DUPSORT
Definition: lmdb.h:345
int compare_uint64(const MDB_val *a, const MDB_val *b)
bool clear_blackballs()
Definition: ringdb.cpp:489
bool set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector< uint64_t > &outs, bool relative)
Definition: ringdb.cpp:374
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags)
Store items into a database.
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor)
Create a cursor handle.
#define MDB_APPENDDUP
Definition: lmdb.h:379
bool add_rings(const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx)
Definition: ringdb.cpp:253