Merge pull request #4311 from pwojcikdev/transaction-type-checking
Checks to ensure transactions execute in the context of their originating stores
This commit is contained in:
commit
5bc61a29a3
15 changed files with 209 additions and 154 deletions
|
@ -19,7 +19,7 @@ TEST (wallet, no_special_keys_accounts)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::keypair key1;
|
||||
ASSERT_FALSE (wallet.exists (transaction, key1.pub));
|
||||
|
@ -40,7 +40,7 @@ TEST (wallet, no_key)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::keypair key1;
|
||||
nano::raw_key prv1;
|
||||
|
@ -55,7 +55,7 @@ TEST (wallet, fetch_locked)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_TRUE (wallet.valid_password (transaction));
|
||||
nano::keypair key1;
|
||||
ASSERT_EQ (key1.pub, wallet.insert_adhoc (transaction, key1.prv));
|
||||
|
@ -77,7 +77,7 @@ TEST (wallet, retrieval)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::keypair key1;
|
||||
ASSERT_TRUE (wallet.valid_password (transaction));
|
||||
|
@ -99,7 +99,7 @@ TEST (wallet, empty_iteration)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
auto i (wallet.begin (transaction));
|
||||
auto j (wallet.end ());
|
||||
|
@ -113,7 +113,7 @@ TEST (wallet, one_item_iteration)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::keypair key1;
|
||||
wallet.insert_adhoc (transaction, key1.prv);
|
||||
|
@ -141,7 +141,7 @@ TEST (wallet, two_item_iteration)
|
|||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
{
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
wallet.insert_adhoc (transaction, key1.prv);
|
||||
wallet.insert_adhoc (transaction, key2.prv);
|
||||
|
@ -274,7 +274,7 @@ TEST (wallet, find_none)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::account account (1000);
|
||||
ASSERT_EQ (wallet.end (), wallet.find (transaction, account));
|
||||
|
@ -287,7 +287,7 @@ TEST (wallet, find_existing)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::keypair key1;
|
||||
ASSERT_FALSE (wallet.exists (transaction, key1.pub));
|
||||
|
@ -306,7 +306,7 @@ TEST (wallet, rekey)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::raw_key password;
|
||||
wallet.password.value (password);
|
||||
|
@ -378,7 +378,7 @@ TEST (wallet, hash_password)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
nano::raw_key hash1;
|
||||
wallet.derive_key (hash1, transaction, "");
|
||||
|
@ -428,25 +428,25 @@ TEST (wallet, reopen_default_password)
|
|||
ASSERT_FALSE (init);
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
{
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
ASSERT_TRUE (wallet.valid_password (transaction));
|
||||
}
|
||||
{
|
||||
bool init;
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
ASSERT_TRUE (wallet.valid_password (transaction));
|
||||
}
|
||||
{
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
wallet.rekey (transaction, "");
|
||||
ASSERT_TRUE (wallet.valid_password (transaction));
|
||||
}
|
||||
{
|
||||
bool init;
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (init);
|
||||
ASSERT_FALSE (wallet.valid_password (transaction));
|
||||
wallet.attempt_password (transaction, " ");
|
||||
|
@ -463,7 +463,7 @@ TEST (wallet, representative)
|
|||
ASSERT_FALSE (error);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (error, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (error);
|
||||
ASSERT_FALSE (wallet.is_representative (transaction));
|
||||
ASSERT_EQ (nano::dev::genesis->account (), wallet.representative (transaction));
|
||||
|
@ -484,11 +484,11 @@ TEST (wallet, serialize_json_empty)
|
|||
ASSERT_FALSE (error);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (error);
|
||||
std::string serialized;
|
||||
wallet1.serialize_json (transaction, serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
ASSERT_FALSE (error);
|
||||
nano::raw_key password1;
|
||||
nano::raw_key password2;
|
||||
|
@ -509,13 +509,13 @@ TEST (wallet, serialize_json_one)
|
|||
ASSERT_FALSE (error);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (error);
|
||||
nano::keypair key;
|
||||
wallet1.insert_adhoc (transaction, key.prv);
|
||||
std::string serialized;
|
||||
wallet1.serialize_json (transaction, serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
ASSERT_FALSE (error);
|
||||
nano::raw_key password1;
|
||||
nano::raw_key password2;
|
||||
|
@ -538,14 +538,14 @@ TEST (wallet, serialize_json_password)
|
|||
ASSERT_FALSE (error);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (error);
|
||||
nano::keypair key;
|
||||
wallet1.rekey (transaction, "password");
|
||||
wallet1.insert_adhoc (transaction, key.prv);
|
||||
std::string serialized;
|
||||
wallet1.serialize_json (transaction, serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1", serialized);
|
||||
ASSERT_FALSE (error);
|
||||
ASSERT_FALSE (wallet2.valid_password (transaction));
|
||||
ASSERT_FALSE (wallet2.attempt_password (transaction, "password"));
|
||||
|
@ -571,11 +571,11 @@ TEST (wallet_store, move)
|
|||
ASSERT_FALSE (error);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
ASSERT_FALSE (error);
|
||||
nano::keypair key1;
|
||||
wallet1.insert_adhoc (transaction, key1.prv);
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, nano::dev::genesis->account (), 1, "1");
|
||||
nano::wallet_store wallet2 (error, kdf, transaction, env, nano::dev::genesis->account (), 1, "1");
|
||||
ASSERT_FALSE (error);
|
||||
nano::keypair key2;
|
||||
wallet2.insert_adhoc (transaction, key2.prv);
|
||||
|
@ -729,7 +729,7 @@ TEST (wallet, deterministic_keys)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
auto key1 = wallet.deterministic_key (transaction, 0);
|
||||
auto key2 = wallet.deterministic_key (transaction, 0);
|
||||
ASSERT_EQ (key1, key2);
|
||||
|
@ -772,7 +772,7 @@ TEST (wallet, reseed)
|
|||
ASSERT_FALSE (init);
|
||||
auto transaction (env.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store wallet (init, kdf, transaction, nano::dev::genesis->account (), 1, "0");
|
||||
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis->account (), 1, "0");
|
||||
nano::raw_key seed1;
|
||||
seed1 = 1;
|
||||
nano::raw_key seed2;
|
||||
|
|
|
@ -37,6 +37,7 @@ add_library(
|
|||
epoch.cpp
|
||||
errors.hpp
|
||||
errors.cpp
|
||||
id_dispenser.hpp
|
||||
ipc.hpp
|
||||
ipc.cpp
|
||||
ipc_client.hpp
|
||||
|
|
62
nano/lib/id_dispenser.hpp
Normal file
62
nano/lib/id_dispenser.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <random>
|
||||
|
||||
namespace nano
|
||||
{
|
||||
class id_dispenser
|
||||
{
|
||||
public:
|
||||
enum class mode
|
||||
{
|
||||
sequential,
|
||||
random,
|
||||
};
|
||||
|
||||
// Using pointer type for prettier and more concise output in logs (hex)
|
||||
using id_t = void *;
|
||||
|
||||
public:
|
||||
explicit id_dispenser (mode mode = mode::random) :
|
||||
mode_m{ mode }
|
||||
{
|
||||
}
|
||||
|
||||
id_t next_id ()
|
||||
{
|
||||
switch (mode_m)
|
||||
{
|
||||
case mode::sequential:
|
||||
return reinterpret_cast<id_t> (current_id_m.fetch_add (1));
|
||||
case mode::random:
|
||||
auto value = get_dist () (get_rng ());
|
||||
if (value < min_m)
|
||||
{
|
||||
value += min_m;
|
||||
}
|
||||
return reinterpret_cast<id_t> (value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Avoid IDs with leading 0s for nicer output in logs
|
||||
static constexpr uint64_t min_m{ 0x1000000000000000 };
|
||||
|
||||
mode mode_m;
|
||||
std::atomic<uint64_t> current_id_m{ min_m };
|
||||
|
||||
static std::mt19937 & get_rng ()
|
||||
{
|
||||
static thread_local std::mt19937 rng{ std::random_device{}() };
|
||||
return rng;
|
||||
}
|
||||
|
||||
static std::uniform_int_distribution<uint64_t> & get_dist ()
|
||||
{
|
||||
static thread_local std::uniform_int_distribution<uint64_t> dist;
|
||||
return dist;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -255,17 +255,18 @@ int const nano::wallet_store::special_count (7);
|
|||
std::size_t const nano::wallet_store::check_iv_index (0);
|
||||
std::size_t const nano::wallet_store::seed_iv_index (1);
|
||||
|
||||
nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::transaction & transaction_a, nano::account representative_a, unsigned fanout_a, std::string const & wallet_a, std::string const & json_a) :
|
||||
nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::transaction & transaction_a, store::lmdb::env & env_a, nano::account representative_a, unsigned fanout_a, std::string const & wallet_a, std::string const & json_a) :
|
||||
password (0, fanout_a),
|
||||
wallet_key_mem (0, fanout_a),
|
||||
kdf (kdf_a)
|
||||
kdf (kdf_a),
|
||||
env{ env_a }
|
||||
{
|
||||
init_a = false;
|
||||
initialize (transaction_a, init_a, wallet_a);
|
||||
if (!init_a)
|
||||
{
|
||||
MDB_val junk;
|
||||
debug_assert (mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) == MDB_NOTFOUND);
|
||||
debug_assert (mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) == MDB_NOTFOUND);
|
||||
boost::property_tree::ptree wallet_l;
|
||||
std::stringstream istream (json_a);
|
||||
try
|
||||
|
@ -298,11 +299,11 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
|
|||
init_a = true;
|
||||
}
|
||||
}
|
||||
init_a |= mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) != 0;
|
||||
init_a |= mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (wallet_key_special), &junk) != 0;
|
||||
init_a |= mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (salt_special), &junk) != 0;
|
||||
init_a |= mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (check_special), &junk) != 0;
|
||||
init_a |= mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (representative_special), &junk) != 0;
|
||||
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) != 0;
|
||||
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (wallet_key_special), &junk) != 0;
|
||||
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (salt_special), &junk) != 0;
|
||||
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (check_special), &junk) != 0;
|
||||
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (representative_special), &junk) != 0;
|
||||
nano::raw_key key;
|
||||
key.clear ();
|
||||
password.value_set (key);
|
||||
|
@ -311,10 +312,11 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
|
|||
}
|
||||
}
|
||||
|
||||
nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::transaction & transaction_a, nano::account representative_a, unsigned fanout_a, std::string const & wallet_a) :
|
||||
nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::transaction & transaction_a, store::lmdb::env & env_a, nano::account representative_a, unsigned fanout_a, std::string const & wallet_a) :
|
||||
password (0, fanout_a),
|
||||
wallet_key_mem (0, fanout_a),
|
||||
kdf (kdf_a)
|
||||
kdf (kdf_a),
|
||||
env{ env_a }
|
||||
{
|
||||
init_a = false;
|
||||
initialize (transaction_a, init_a, wallet_a);
|
||||
|
@ -322,7 +324,7 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
|
|||
{
|
||||
int version_status;
|
||||
MDB_val version_value;
|
||||
version_status = mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &version_value);
|
||||
version_status = mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &version_value);
|
||||
if (version_status == MDB_NOTFOUND)
|
||||
{
|
||||
version_put (transaction_a, version_current);
|
||||
|
@ -377,7 +379,7 @@ void nano::wallet_store::initialize (store::transaction const & transaction_a, b
|
|||
debug_assert (strlen (path_a.c_str ()) == path_a.size ());
|
||||
auto error (0);
|
||||
MDB_dbi handle_l;
|
||||
error |= mdb_dbi_open (tx (transaction_a), path_a.c_str (), MDB_CREATE, &handle_l);
|
||||
error |= mdb_dbi_open (env.tx (transaction_a), path_a.c_str (), MDB_CREATE, &handle_l);
|
||||
handle = handle_l;
|
||||
init_a = error != 0;
|
||||
}
|
||||
|
@ -424,7 +426,7 @@ bool nano::wallet_store::insert_watch (store::transaction const & transaction_a,
|
|||
|
||||
void nano::wallet_store::erase (store::transaction const & transaction_a, nano::account const & pub)
|
||||
{
|
||||
auto status (mdb_del (tx (transaction_a), handle, nano::store::lmdb::db_val (pub), nullptr));
|
||||
auto status (mdb_del (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub), nullptr));
|
||||
(void)status;
|
||||
debug_assert (status == 0);
|
||||
}
|
||||
|
@ -433,7 +435,7 @@ nano::wallet_value nano::wallet_store::entry_get_raw (store::transaction const &
|
|||
{
|
||||
nano::wallet_value result;
|
||||
nano::store::lmdb::db_val value;
|
||||
auto status (mdb_get (tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), value));
|
||||
auto status (mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), value));
|
||||
if (status == 0)
|
||||
{
|
||||
result = nano::wallet_value (value);
|
||||
|
@ -448,7 +450,7 @@ nano::wallet_value nano::wallet_store::entry_get_raw (store::transaction const &
|
|||
|
||||
void nano::wallet_store::entry_put_raw (store::transaction const & transaction_a, nano::account const & pub_a, nano::wallet_value const & entry_a)
|
||||
{
|
||||
auto status (mdb_put (tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), nano::store::lmdb::db_val (sizeof (entry_a), const_cast<nano::wallet_value *> (&entry_a)), 0));
|
||||
auto status (mdb_put (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), nano::store::lmdb::db_val (sizeof (entry_a), const_cast<nano::wallet_value *> (&entry_a)), 0));
|
||||
(void)status;
|
||||
debug_assert (status == 0);
|
||||
}
|
||||
|
@ -542,7 +544,7 @@ bool nano::wallet_store::exists (store::transaction const & transaction_a, nano:
|
|||
void nano::wallet_store::serialize_json (store::transaction const & transaction_a, std::string & string_a)
|
||||
{
|
||||
boost::property_tree::ptree tree;
|
||||
for (store::iterator<nano::uint256_union, nano::wallet_value> i (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::wallet_value>> (transaction_a, handle)), n (nullptr); i != n; ++i)
|
||||
for (store::iterator<nano::uint256_union, nano::wallet_value> i (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::wallet_value>> (transaction_a, env, handle)), n (nullptr); i != n; ++i)
|
||||
{
|
||||
tree.put (i->first.to_string (), i->second.key.to_string ());
|
||||
}
|
||||
|
@ -659,14 +661,14 @@ void nano::kdf::phs (nano::raw_key & result_a, std::string const & password_a, n
|
|||
|
||||
nano::wallet::wallet (bool & init_a, store::transaction & transaction_a, nano::wallets & wallets_a, std::string const & wallet_a) :
|
||||
lock_observer ([] (bool, bool) {}),
|
||||
store (init_a, wallets_a.kdf, transaction_a, wallets_a.node.config.random_representative (), wallets_a.node.config.password_fanout, wallet_a),
|
||||
store (init_a, wallets_a.kdf, transaction_a, wallets_a.env, wallets_a.node.config.random_representative (), wallets_a.node.config.password_fanout, wallet_a),
|
||||
wallets (wallets_a)
|
||||
{
|
||||
}
|
||||
|
||||
nano::wallet::wallet (bool & init_a, store::transaction & transaction_a, nano::wallets & wallets_a, std::string const & wallet_a, std::string const & json) :
|
||||
lock_observer ([] (bool, bool) {}),
|
||||
store (init_a, wallets_a.kdf, transaction_a, wallets_a.node.config.random_representative (), wallets_a.node.config.password_fanout, wallet_a, json),
|
||||
store (init_a, wallets_a.kdf, transaction_a, wallets_a.env, wallets_a.node.config.random_representative (), wallets_a.node.config.password_fanout, wallet_a, json),
|
||||
wallets (wallets_a)
|
||||
{
|
||||
}
|
||||
|
@ -798,7 +800,7 @@ bool nano::wallet::import (std::string const & json_a, std::string const & passw
|
|||
auto transaction (wallets.tx_begin_write ());
|
||||
nano::uint256_union id;
|
||||
random_pool::generate_block (id.bytes.data (), id.bytes.size ());
|
||||
temp = std::make_unique<nano::wallet_store> (error, wallets.node.wallets.kdf, transaction, 0, 1, id.to_string (), json_a);
|
||||
temp = std::make_unique<nano::wallet_store> (error, wallets.node.wallets.kdf, transaction, wallets.env, 0, 1, id.to_string (), json_a);
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
|
@ -822,7 +824,7 @@ void nano::wallet::serialize (std::string & json_a)
|
|||
|
||||
void nano::wallet_store::destroy (store::transaction const & transaction_a)
|
||||
{
|
||||
auto status (mdb_drop (tx (transaction_a), handle, 1));
|
||||
auto status (mdb_drop (env.tx (transaction_a), handle, 1));
|
||||
(void)status;
|
||||
debug_assert (status == 0);
|
||||
handle = 0;
|
||||
|
@ -1343,13 +1345,12 @@ nano::wallets::wallets (bool error_a, nano::node & node_a) :
|
|||
{
|
||||
auto transaction (tx_begin_write ());
|
||||
auto status (mdb_dbi_open (env.tx (transaction), nullptr, MDB_CREATE, &handle));
|
||||
split_if_needed (transaction, node.store);
|
||||
status |= mdb_dbi_open (env.tx (transaction), "send_action_ids", MDB_CREATE, &send_action_ids);
|
||||
release_assert (status == 0);
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::wallet_id id;
|
||||
|
@ -1477,8 +1478,8 @@ void nano::wallets::reload ()
|
|||
std::unordered_set<nano::uint256_union> stored_items;
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::wallet_id id;
|
||||
|
@ -1696,80 +1697,6 @@ void nano::wallets::ongoing_compute_reps ()
|
|||
});
|
||||
}
|
||||
|
||||
void nano::wallets::split_if_needed (store::transaction & transaction_destination, nano::store::component & store_a)
|
||||
{
|
||||
auto store_l = dynamic_cast<nano::store::lmdb::component *> (&store_a);
|
||||
if (store_l != nullptr)
|
||||
{
|
||||
if (items.empty ())
|
||||
{
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
|
||||
auto get_store_it = [&handle = handle] (store::transaction const & transaction_source, std::string const & hash) {
|
||||
return store::iterator<std::array<char, 64>, nano::no_value> (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction_source, handle, nano::store::lmdb::db_val (hash.size (), const_cast<char *> (hash.c_str ()))));
|
||||
};
|
||||
|
||||
// First do a read pass to check if there are any wallets that need extracting (to save holding a write lock and potentially being blocked)
|
||||
auto wallets_need_splitting (false);
|
||||
{
|
||||
auto transaction_source (store_l->tx_begin_read ());
|
||||
auto i = get_store_it (transaction_source, beginning);
|
||||
auto n = get_store_it (transaction_source, end);
|
||||
wallets_need_splitting = (i != n);
|
||||
}
|
||||
|
||||
if (wallets_need_splitting)
|
||||
{
|
||||
auto transaction_source (store_l->tx_begin_write ());
|
||||
auto i = get_store_it (transaction_source, beginning);
|
||||
auto n = get_store_it (transaction_source, end);
|
||||
auto tx_source = static_cast<MDB_txn *> (transaction_source.get_handle ());
|
||||
auto tx_destination = static_cast<MDB_txn *> (transaction_destination.get_handle ());
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::uint256_union id;
|
||||
std::string text (i->first.data (), i->first.size ());
|
||||
auto error1 (id.decode_hex (text));
|
||||
(void)error1;
|
||||
debug_assert (!error1);
|
||||
debug_assert (strlen (text.c_str ()) == text.size ());
|
||||
move_table (text, tx_source, tx_destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nano::wallets::move_table (std::string const & name_a, MDB_txn * tx_source, MDB_txn * tx_destination)
|
||||
{
|
||||
MDB_dbi handle_source;
|
||||
auto error2 (mdb_dbi_open (tx_source, name_a.c_str (), MDB_CREATE, &handle_source));
|
||||
(void)error2;
|
||||
debug_assert (!error2);
|
||||
MDB_dbi handle_destination;
|
||||
auto error3 (mdb_dbi_open (tx_destination, name_a.c_str (), MDB_CREATE, &handle_destination));
|
||||
(void)error3;
|
||||
debug_assert (!error3);
|
||||
MDB_cursor * cursor;
|
||||
auto error4 (mdb_cursor_open (tx_source, handle_source, &cursor));
|
||||
(void)error4;
|
||||
debug_assert (!error4);
|
||||
MDB_val val_key;
|
||||
MDB_val val_value;
|
||||
auto cursor_status (mdb_cursor_get (cursor, &val_key, &val_value, MDB_FIRST));
|
||||
while (cursor_status == MDB_SUCCESS)
|
||||
{
|
||||
auto error5 (mdb_put (tx_destination, handle_destination, &val_key, &val_value, 0));
|
||||
(void)error5;
|
||||
debug_assert (!error5);
|
||||
cursor_status = mdb_cursor_get (cursor, &val_key, &val_value, MDB_NEXT);
|
||||
}
|
||||
auto error6 (mdb_drop (tx_source, handle_source, 1));
|
||||
(void)error6;
|
||||
debug_assert (!error6);
|
||||
}
|
||||
|
||||
std::unordered_map<nano::wallet_id, std::shared_ptr<nano::wallet>> nano::wallets::get_wallets ()
|
||||
{
|
||||
debug_assert (!mutex.try_lock ());
|
||||
|
@ -1781,13 +1708,13 @@ nano::uint128_t const nano::wallets::high_priority = std::numeric_limits<nano::u
|
|||
|
||||
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::begin (store::transaction const & transaction_a)
|
||||
{
|
||||
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, handle, nano::store::lmdb::db_val (nano::account (special_count))));
|
||||
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (nano::account (special_count))));
|
||||
return result;
|
||||
}
|
||||
|
||||
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key)
|
||||
{
|
||||
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, handle, nano::store::lmdb::db_val (key)));
|
||||
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (key)));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1827,11 +1754,6 @@ bool nano::mdb_wallets_store::init_error () const
|
|||
return error;
|
||||
}
|
||||
|
||||
MDB_txn * nano::wallet_store::tx (store::transaction const & transaction_a) const
|
||||
{
|
||||
return static_cast<MDB_txn *> (transaction_a.get_handle ());
|
||||
}
|
||||
|
||||
std::unique_ptr<nano::container_info_component> nano::collect_container_info (wallets & wallets, std::string const & name)
|
||||
{
|
||||
std::size_t items_count;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/id_dispenser.hpp>
|
||||
#include <nano/lib/lmdbconfig.hpp>
|
||||
#include <nano/lib/locks.hpp>
|
||||
#include <nano/lib/work.hpp>
|
||||
|
@ -13,11 +14,13 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace nano
|
||||
{
|
||||
class node;
|
||||
class node_config;
|
||||
class wallets;
|
||||
|
||||
// The fan spreads a key out over the heap to decrease the likelihood of it being recovered by memory inspection
|
||||
class fan final
|
||||
{
|
||||
|
@ -31,6 +34,7 @@ private:
|
|||
nano::mutex mutex;
|
||||
void value_get (nano::raw_key &);
|
||||
};
|
||||
|
||||
class kdf final
|
||||
{
|
||||
public:
|
||||
|
@ -42,6 +46,7 @@ public:
|
|||
nano::mutex mutex;
|
||||
unsigned & kdf_work;
|
||||
};
|
||||
|
||||
enum class key_type
|
||||
{
|
||||
not_a_type,
|
||||
|
@ -49,11 +54,12 @@ enum class key_type
|
|||
adhoc,
|
||||
deterministic
|
||||
};
|
||||
|
||||
class wallet_store final
|
||||
{
|
||||
public:
|
||||
wallet_store (bool &, nano::kdf &, store::transaction &, nano::account, unsigned, std::string const &);
|
||||
wallet_store (bool &, nano::kdf &, store::transaction &, nano::account, unsigned, std::string const &, std::string const &);
|
||||
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &);
|
||||
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &, std::string const &);
|
||||
std::vector<nano::account> accounts (store::transaction const &);
|
||||
void initialize (store::transaction const &, bool &, std::string const &);
|
||||
nano::uint256_union check (store::transaction const &);
|
||||
|
@ -118,8 +124,9 @@ public:
|
|||
std::recursive_mutex mutex;
|
||||
|
||||
private:
|
||||
MDB_txn * tx (store::transaction const &) const;
|
||||
nano::store::lmdb::env & env;
|
||||
};
|
||||
|
||||
// A wallet is a set of account keys encrypted by a common encryption key
|
||||
class wallet final : public std::enable_shared_from_this<nano::wallet>
|
||||
{
|
||||
|
@ -213,8 +220,6 @@ public:
|
|||
bool check_rep (nano::account const &, nano::uint128_t const &, bool const = true);
|
||||
void compute_reps ();
|
||||
void ongoing_compute_reps ();
|
||||
void split_if_needed (store::transaction &, nano::store::component &);
|
||||
void move_table (std::string const &, MDB_txn *, MDB_txn *);
|
||||
std::unordered_map<nano::wallet_id, std::shared_ptr<nano::wallet>> get_wallets ();
|
||||
nano::network_params & network_params;
|
||||
std::function<void (bool)> observer;
|
||||
|
@ -233,9 +238,9 @@ public:
|
|||
std::thread thread;
|
||||
static nano::uint128_t const generate_priority;
|
||||
static nano::uint128_t const high_priority;
|
||||
|
||||
/** Start read-write transaction */
|
||||
store::write_transaction tx_begin_write ();
|
||||
|
||||
/** Start read-only transaction */
|
||||
store::read_transaction tx_begin_read ();
|
||||
|
||||
|
@ -252,6 +257,7 @@ public:
|
|||
virtual ~wallets_store () = default;
|
||||
virtual bool init_error () const = 0;
|
||||
};
|
||||
|
||||
class mdb_wallets_store final : public wallets_store
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -660,7 +660,7 @@ TEST (rpc, wallet_export)
|
|||
bool error (false);
|
||||
auto transaction (node->wallets.tx_begin_write ());
|
||||
nano::kdf kdf{ nano::dev::network_params.kdf_work };
|
||||
nano::wallet_store store (error, kdf, transaction, nano::dev::genesis->account (), 1, "0", wallet_json);
|
||||
nano::wallet_store store (error, kdf, transaction, node->wallets.env, nano::dev::genesis->account (), 1, "0", wallet_json);
|
||||
ASSERT_FALSE (error);
|
||||
ASSERT_TRUE (store.exists (transaction, nano::dev::genesis_key.pub));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <nano/store/component.hpp>
|
||||
#include <nano/store/db_val.hpp>
|
||||
#include <nano/store/iterator.hpp>
|
||||
#include <nano/store/lmdb/lmdb_env.hpp>
|
||||
#include <nano/store/transaction.hpp>
|
||||
|
||||
#include <lmdb/libraries/liblmdb/lmdb.h>
|
||||
|
@ -13,9 +14,9 @@ template <typename T, typename U>
|
|||
class iterator : public iterator_impl<T, U>
|
||||
{
|
||||
public:
|
||||
iterator (store::transaction const & transaction_a, MDB_dbi db_a, MDB_val const & val_a = MDB_val{}, bool const direction_asc = true)
|
||||
iterator (store::transaction const & transaction_a, env const & env_a, MDB_dbi db_a, MDB_val const & val_a = MDB_val{}, bool const direction_asc = true)
|
||||
{
|
||||
auto status (mdb_cursor_open (tx (transaction_a), db_a, &cursor));
|
||||
auto status (mdb_cursor_open (env_a.tx (transaction_a), db_a, &cursor));
|
||||
release_assert (status == 0);
|
||||
auto operation (MDB_SET_RANGE);
|
||||
if (val_a.mv_size != 0)
|
||||
|
@ -165,12 +166,6 @@ public:
|
|||
store::iterator_impl<T, U> & operator= (store::iterator_impl<T, U> const &) = delete;
|
||||
MDB_cursor * cursor{ nullptr };
|
||||
std::pair<store::db_val<MDB_val>, store::db_val<MDB_val>> current;
|
||||
|
||||
private:
|
||||
MDB_txn * tx (store::transaction const & transaction_a) const
|
||||
{
|
||||
return static_cast<MDB_txn *> (transaction_a.get_handle ());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -372,7 +372,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
|||
MDB_dbi temp;
|
||||
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
||||
// Copy all values to temporary table
|
||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, table))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, env, table))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
||||
{
|
||||
auto s = mdb_put (env.tx (transaction_a), temp, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
|
||||
release_assert_success (s);
|
||||
|
@ -381,7 +381,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
|||
// Clear existing table
|
||||
mdb_drop (env.tx (transaction_a), table, 0);
|
||||
// Put values from copy
|
||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, temp))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, env, temp))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
||||
{
|
||||
auto s = mdb_put (env.tx (transaction_a), table, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
|
||||
release_assert_success (s);
|
||||
|
@ -395,7 +395,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
|||
MDB_dbi temp;
|
||||
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
||||
// Copy all values to temporary table
|
||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, pending_store.pending_handle))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, env, pending_store.pending_handle))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
||||
{
|
||||
auto s = mdb_put (env.tx (transaction_a), temp, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND);
|
||||
release_assert_success (s);
|
||||
|
@ -403,7 +403,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
|||
release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp));
|
||||
mdb_drop (env.tx (transaction_a), pending_store.pending_handle, 0);
|
||||
// Put values from copy
|
||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, temp))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, env, temp))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
||||
{
|
||||
auto s = mdb_put (env.tx (transaction_a), pending_store.pending_handle, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND);
|
||||
release_assert_success (s);
|
||||
|
|
|
@ -104,13 +104,13 @@ public:
|
|||
template <typename Key, typename Value>
|
||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, bool const direction_asc = true) const
|
||||
{
|
||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, table_to_dbi (table_a), nano::store::lmdb::db_val{}, direction_asc));
|
||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, env, table_to_dbi (table_a), nano::store::lmdb::db_val{}, direction_asc));
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, nano::store::lmdb::db_val const & key) const
|
||||
{
|
||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, table_to_dbi (table_a), key));
|
||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, env, table_to_dbi (table_a), key));
|
||||
}
|
||||
|
||||
bool init_error () const override;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <nano/lib/utility.hpp>
|
||||
#include <nano/store/lmdb/lmdb_env.hpp>
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
@ -105,5 +106,6 @@ nano::store::write_transaction nano::store::lmdb::env::tx_begin_write (store::lm
|
|||
|
||||
MDB_txn * nano::store::lmdb::env::tx (store::transaction const & transaction_a) const
|
||||
{
|
||||
debug_assert (transaction_a.store_id () == store_id);
|
||||
return static_cast<MDB_txn *> (transaction_a.get_handle ());
|
||||
}
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/id_dispenser.hpp>
|
||||
#include <nano/lib/lmdbconfig.hpp>
|
||||
#include <nano/store/component.hpp>
|
||||
#include <nano/store/lmdb/transaction_impl.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
nano::id_dispenser id_gen;
|
||||
}
|
||||
|
||||
namespace nano::store::lmdb
|
||||
{
|
||||
/**
|
||||
|
@ -62,5 +68,6 @@ public:
|
|||
store::write_transaction tx_begin_write (txn_callbacks callbacks = txn_callbacks{}) const;
|
||||
MDB_txn * tx (store::transaction const & transaction_a) const;
|
||||
MDB_env * environment;
|
||||
nano::id_dispenser::id_t const store_id{ id_gen.next_id () };
|
||||
};
|
||||
} // namespace nano::store::lmdb
|
||||
|
|
|
@ -36,6 +36,7 @@ private:
|
|||
}
|
||||
|
||||
nano::store::lmdb::read_transaction_impl::read_transaction_impl (nano::store::lmdb::env const & environment_a, nano::store::lmdb::txn_callbacks txn_callbacks_a) :
|
||||
store::read_transaction_impl (environment_a.store_id),
|
||||
txn_callbacks (txn_callbacks_a)
|
||||
{
|
||||
auto status (mdb_txn_begin (environment_a, nullptr, MDB_RDONLY, &handle));
|
||||
|
@ -70,6 +71,7 @@ void * nano::store::lmdb::read_transaction_impl::get_handle () const
|
|||
}
|
||||
|
||||
nano::store::lmdb::write_transaction_impl::write_transaction_impl (nano::store::lmdb::env const & environment_a, nano::store::lmdb::txn_callbacks txn_callbacks_a) :
|
||||
store::write_transaction_impl (environment_a.store_id),
|
||||
env (environment_a),
|
||||
txn_callbacks (txn_callbacks_a)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/diagnosticsconfig.hpp>
|
||||
#include <nano/lib/id_dispenser.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
#include <nano/store/component.hpp>
|
||||
#include <nano/store/transaction.hpp>
|
||||
|
@ -27,6 +28,7 @@ public:
|
|||
std::function<void (store::transaction_impl const *)> txn_start{ [] (store::transaction_impl const *) {} };
|
||||
std::function<void (store::transaction_impl const *)> txn_end{ [] (store::transaction_impl const *) {} };
|
||||
};
|
||||
|
||||
class read_transaction_impl final : public store::read_transaction_impl
|
||||
{
|
||||
public:
|
||||
|
@ -53,7 +55,7 @@ public:
|
|||
lmdb::txn_callbacks txn_callbacks;
|
||||
bool active{ true };
|
||||
};
|
||||
} // namespace nano
|
||||
} // namespace nano::store::lmdb
|
||||
|
||||
namespace nano
|
||||
{
|
||||
|
|
|
@ -2,6 +2,37 @@
|
|||
#include <nano/lib/utility.hpp>
|
||||
#include <nano/store/transaction.hpp>
|
||||
|
||||
/*
|
||||
* transaction_impl
|
||||
*/
|
||||
|
||||
nano::store::transaction_impl::transaction_impl (nano::id_dispenser::id_t const store_id_a) :
|
||||
store_id{ store_id_a }
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* read_transaction_impl
|
||||
*/
|
||||
|
||||
nano::store::read_transaction_impl::read_transaction_impl (nano::id_dispenser::id_t const store_id_a) :
|
||||
transaction_impl (store_id_a)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* write_transaction_impl
|
||||
*/
|
||||
|
||||
nano::store::write_transaction_impl::write_transaction_impl (nano::id_dispenser::id_t const store_id_a) :
|
||||
transaction_impl (store_id_a)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* read_transaction
|
||||
*/
|
||||
|
||||
nano::store::read_transaction::read_transaction (std::unique_ptr<store::read_transaction_impl> read_transaction_impl) :
|
||||
impl (std::move (read_transaction_impl))
|
||||
{
|
||||
|
@ -12,6 +43,11 @@ void * nano::store::read_transaction::get_handle () const
|
|||
return impl->get_handle ();
|
||||
}
|
||||
|
||||
nano::id_dispenser::id_t nano::store::read_transaction::store_id () const
|
||||
{
|
||||
return impl->store_id;
|
||||
}
|
||||
|
||||
void nano::store::read_transaction::reset () const
|
||||
{
|
||||
impl->reset ();
|
||||
|
@ -28,6 +64,10 @@ void nano::store::read_transaction::refresh () const
|
|||
renew ();
|
||||
}
|
||||
|
||||
/*
|
||||
* write_transaction
|
||||
*/
|
||||
|
||||
nano::store::write_transaction::write_transaction (std::unique_ptr<store::write_transaction_impl> write_transaction_impl) :
|
||||
impl (std::move (write_transaction_impl))
|
||||
{
|
||||
|
@ -42,6 +82,11 @@ void * nano::store::write_transaction::get_handle () const
|
|||
return impl->get_handle ();
|
||||
}
|
||||
|
||||
nano::id_dispenser::id_t nano::store::write_transaction::store_id () const
|
||||
{
|
||||
return impl->store_id;
|
||||
}
|
||||
|
||||
void nano::store::write_transaction::commit ()
|
||||
{
|
||||
impl->commit ();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/id_dispenser.hpp>
|
||||
#include <nano/store/tables.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
@ -9,13 +10,17 @@ namespace nano::store
|
|||
class transaction_impl
|
||||
{
|
||||
public:
|
||||
transaction_impl (nano::id_dispenser::id_t const store_id);
|
||||
virtual ~transaction_impl () = default;
|
||||
virtual void * get_handle () const = 0;
|
||||
|
||||
nano::id_dispenser::id_t const store_id;
|
||||
};
|
||||
|
||||
class read_transaction_impl : public transaction_impl
|
||||
{
|
||||
public:
|
||||
explicit read_transaction_impl (nano::id_dispenser::id_t const store_id = 0);
|
||||
virtual void reset () = 0;
|
||||
virtual void renew () = 0;
|
||||
};
|
||||
|
@ -23,6 +28,7 @@ public:
|
|||
class write_transaction_impl : public transaction_impl
|
||||
{
|
||||
public:
|
||||
explicit write_transaction_impl (nano::id_dispenser::id_t const store_id = 0);
|
||||
virtual void commit () = 0;
|
||||
virtual void renew () = 0;
|
||||
virtual bool contains (nano::tables table_a) const = 0;
|
||||
|
@ -33,6 +39,7 @@ class transaction
|
|||
public:
|
||||
virtual ~transaction () = default;
|
||||
virtual void * get_handle () const = 0;
|
||||
virtual nano::id_dispenser::id_t store_id () const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -44,6 +51,8 @@ class read_transaction final : public transaction
|
|||
public:
|
||||
explicit read_transaction (std::unique_ptr<read_transaction_impl> read_transaction_impl);
|
||||
void * get_handle () const override;
|
||||
nano::id_dispenser::id_t store_id () const override;
|
||||
|
||||
void reset () const;
|
||||
void renew () const;
|
||||
void refresh () const;
|
||||
|
@ -61,6 +70,8 @@ class write_transaction final : public transaction
|
|||
public:
|
||||
explicit write_transaction (std::unique_ptr<write_transaction_impl> write_transaction_impl);
|
||||
void * get_handle () const override;
|
||||
nano::id_dispenser::id_t store_id () const override;
|
||||
|
||||
void commit ();
|
||||
void renew ();
|
||||
void refresh ();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue