Electroneum
tools::ringdb Class Reference

#include <ringdb.h>

Inheritance diagram for tools::ringdb:

Public Member Functions

 ringdb (std::string filename, const std::string &genesis)
 
void close ()
 
 ~ringdb ()
 
bool add_rings (const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx)
 
bool remove_rings (const crypto::chacha_key &chacha_key, const std::vector< crypto::key_image > &key_images)
 
bool remove_rings (const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx)
 
bool get_ring (const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector< uint64_t > &outs)
 
bool set_ring (const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector< uint64_t > &outs, bool relative)
 
bool blackball (const std::pair< uint64_t, uint64_t > &output)
 
bool blackball (const std::vector< std::pair< uint64_t, uint64_t >> &outputs)
 
bool unblackball (const std::pair< uint64_t, uint64_t > &output)
 
bool blackballed (const std::pair< uint64_t, uint64_t > &output)
 
bool clear_blackballs ()
 

Detailed Description

Definition at line 40 of file ringdb.h.

Constructor & Destructor Documentation

◆ ringdb()

tools::ringdb::ringdb ( std::string  filename,
const std::string &  genesis 
)

Definition at line 200 of file ringdb.cpp.

200  :
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 }
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
Open a database in the environment.
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.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
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_set_maxdbs(MDB_env *env, MDB_dbi dbs)
Set the maximum number of named databases for the environment.
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
#define MDB_CREATE
Definition: lmdb.h:357
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
Open an environment handle.
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
#define MDB_INTEGERKEY
Definition: lmdb.h:349
#define MDB_DUPFIXED
Definition: lmdb.h:351
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom key comparison function for a database.
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
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.
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
bool create_directories_if_necessary(const std::string &path)
creates directories for a path
Definition: util.cpp:625
char * mdb_strerror(int err)
Return a string describing a given error code.
#define MDB_DUPSORT
Definition: lmdb.h:345
int compare_uint64(const MDB_val *a, const MDB_val *b)

◆ ~ringdb()

tools::ringdb::~ringdb ( )

Definition at line 237 of file ringdb.cpp.

238 {
239  close();
240 }
void close()
Definition: ringdb.cpp:242
Here is the call graph for this function:

Member Function Documentation

◆ add_rings()

bool tools::ringdb::add_rings ( const crypto::chacha_key &  chacha_key,
const cryptonote::transaction_prefix tx 
)

Definition at line 253 of file ringdb.cpp.

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 }
::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.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
unsigned int uint32_t
Definition: stdint.h:126
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
char * mdb_strerror(int err)
Return a string describing a given error code.

◆ blackball() [1/2]

bool tools::ringdb::blackball ( const std::pair< uint64_t, uint64_t > &  output)

Definition at line 471 of file ringdb.cpp.

472 {
473  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
474  return blackball_worker(outputs, BLACKBALL_BLACKBALL);
475 }
Here is the caller graph for this function:

◆ blackball() [2/2]

bool tools::ringdb::blackball ( const std::vector< std::pair< uint64_t, uint64_t >> &  outputs)

Definition at line 466 of file ringdb.cpp.

467 {
468  return blackball_worker(outputs, BLACKBALL_BLACKBALL);
469 }

◆ blackballed()

bool tools::ringdb::blackballed ( const std::pair< uint64_t, uint64_t > &  output)

Definition at line 483 of file ringdb.cpp.

484 {
485  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
486  return blackball_worker(outputs, BLACKBALL_QUERY);
487 }
Here is the caller graph for this function:

◆ clear_blackballs()

bool tools::ringdb::clear_blackballs ( )

Definition at line 489 of file ringdb.cpp.

490 {
491  return blackball_worker(std::vector<std::pair<uint64_t, uint64_t>>(), BLACKBALL_CLEAR);
492 }

◆ close()

void tools::ringdb::close ( )

Definition at line 242 of file ringdb.cpp.

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 }
void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
Close a database handle. Normally unnecessary. Use with care:
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_ring()

bool tools::ringdb::get_ring ( const crypto::chacha_key &  chacha_key,
const crypto::key_image key_image,
std::vector< uint64_t > &  outs 
)

Definition at line 338 of file ringdb.cpp.

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 }
#define MDB_NOTFOUND
Definition: lmdb.h:439
::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.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
const char * key
Definition: hmac_keccak.cpp:39
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
#define MDEBUG(x)
Definition: misc_log_ex.h:76
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
void * mv_data
Definition: lmdb.h:288
size_t mv_size
Definition: lmdb.h:287
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
unsigned __int64 uint64_t
Definition: stdint.h:136
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
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
Generic structure used for passing keys and data in and out of the database.
Definition: lmdb.h:286
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
char * mdb_strerror(int err)
Return a string describing a given error code.
std::string to_string(t_connection_type type)
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
Here is the caller graph for this function:

◆ remove_rings() [1/2]

bool tools::ringdb::remove_rings ( const crypto::chacha_key &  chacha_key,
const std::vector< crypto::key_image > &  key_images 
)

Definition at line 284 of file ringdb.cpp.

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 }
#define MDB_NOTFOUND
Definition: lmdb.h:439
int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Delete items from a database.
::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.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
const char * key
Definition: hmac_keccak.cpp:39
#define MDEBUG(x)
Definition: misc_log_ex.h:76
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
size_t mv_size
Definition: lmdb.h:287
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
Generic structure used for passing keys and data in and out of the database.
Definition: lmdb.h:286
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
char * mdb_strerror(int err)
Return a string describing a given error code.
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
Here is the caller graph for this function:

◆ remove_rings() [2/2]

bool tools::ringdb::remove_rings ( const crypto::chacha_key &  chacha_key,
const cryptonote::transaction_prefix tx 
)

Definition at line 321 of file ringdb.cpp.

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 }
unsigned int uint32_t
Definition: stdint.h:126
bool remove_rings(const crypto::chacha_key &chacha_key, const std::vector< crypto::key_image > &key_images)
Definition: ringdb.cpp:284
Here is the call graph for this function:

◆ set_ring()

bool tools::ringdb::set_ring ( const crypto::chacha_key &  chacha_key,
const crypto::key_image key_image,
const std::vector< uint64_t > &  outs,
bool  relative 
)

Definition at line 374 of file ringdb.cpp.

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 }
::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.
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
std::vector< uint64_t > absolute_output_offsets_to_relative(const std::vector< uint64_t > &off)
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
char * mdb_strerror(int err)
Return a string describing a given error code.
Here is the caller graph for this function:

◆ unblackball()

bool tools::ringdb::unblackball ( const std::pair< uint64_t, uint64_t > &  output)

Definition at line 477 of file ringdb.cpp.

478 {
479  std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
480  return blackball_worker(outputs, BLACKBALL_UNBLACKBALL);
481 }

The documentation for this class was generated from the following files: