Skip to content

Commit

Permalink
Checks to ensure transactions execute in the context of their origina…
Browse files Browse the repository at this point in the history
…ting stores (#4297)

* Introduce `id_dispenser` class

* Checks to ensure transactions execute in the context of their originating stores

* Remove legacy `nano::wallets::split_if_needed`
  • Loading branch information
pwojcikdev authored Oct 8, 2023
1 parent 3b22533 commit cff51c4
Show file tree
Hide file tree
Showing 15 changed files with 209 additions and 154 deletions.
52 changes: 26 additions & 26 deletions nano/core_test/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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 ());
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand All @@ -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);
Expand Down Expand Up @@ -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, "");
Expand Down Expand Up @@ -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, " ");
Expand All @@ -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));
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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"));
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions nano/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_library(
epoch.cpp
errors.hpp
errors.cpp
id_dispenser.hpp
ipc.hpp
ipc.cpp
ipc_client.hpp
Expand Down
62 changes: 62 additions & 0 deletions nano/lib/id_dispenser.hpp
Original file line number Diff line number Diff line change
@@ -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;
}
};
}
Loading

0 comments on commit cff51c4

Please sign in to comment.