Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a single synchronised random pool across all threads #1758

Merged
merged 5 commits into from Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion nano/core_test/block_store.cpp
Expand Up @@ -666,7 +666,7 @@ TEST (block_store, large_iteration)
{
auto transaction (store.tx_begin (true));
nano::account account;
nano::random_pool.GenerateBlock (account.bytes.data (), account.bytes.size ());
nano::random_pool::generate_block (account.bytes.data (), account.bytes.size ());
accounts1.insert (account);
store.account_put (transaction, account, nano::account_info ());
}
Expand Down
2 changes: 1 addition & 1 deletion nano/core_test/wallet.cpp
Expand Up @@ -827,7 +827,7 @@ TEST (wallet, version_3_upgrade)
nano::keypair key;
nano::raw_key seed;
nano::uint256_union seed_ciphertext;
nano::random_pool.GenerateBlock (seed.data.bytes.data (), seed.data.bytes.size ());
nano::random_pool::generate_block (seed.data.bytes.data (), seed.data.bytes.size ());
nano::raw_key password_l;
nano::wallet_value value (wallet->store.entry_get_raw (transaction, nano::wallet_store::wallet_key_special));
nano::raw_key kdf;
Expand Down
2 changes: 1 addition & 1 deletion nano/core_test/work_pool.cpp
Expand Up @@ -76,7 +76,7 @@ TEST (work, DISABLED_opencl)
nano::uint256_union root;
for (auto i (0); i < 1; ++i)
{
nano::random_pool.GenerateBlock (root.bytes.data (), root.bytes.size ());
nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ());
auto result (pool.generate (root));
ASSERT_FALSE (nano::work_validate (root, result));
}
Expand Down
2 changes: 1 addition & 1 deletion nano/lib/blocks.cpp
Expand Up @@ -1590,7 +1590,7 @@ std::shared_ptr<nano::block> nano::block_uniquer::unique (std::shared_ptr<nano::
release_assert (std::numeric_limits<CryptoPP::word32>::max () > blocks.size ());
for (auto i (0); i < cleanup_count && blocks.size () > 0; ++i)
{
auto random_offset (nano::random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (blocks.size () - 1)));
auto random_offset (nano::random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (blocks.size () - 1)));
auto existing (std::next (blocks.begin (), random_offset));
if (existing == blocks.end ())
{
Expand Down
4 changes: 2 additions & 2 deletions nano/lib/interface.cpp
Expand Up @@ -70,7 +70,7 @@ int xrb_valid_address (const char * account_a)
void xrb_generate_random (xrb_uint256 seed)
{
auto & number (*reinterpret_cast<nano::uint256_union *> (seed));
nano::random_pool.GenerateBlock (number.bytes.data (), number.bytes.size ());
nano::random_pool::generate_block (number.bytes.data (), number.bytes.size ());
}

void xrb_seed_key (xrb_uint256 seed, int index, xrb_uint256 destination)
Expand Down Expand Up @@ -142,7 +142,7 @@ char * xrb_work_transaction (const char * transaction)
#include <crypto/ed25519-donna/ed25519-hash-custom.h>
void ed25519_randombytes_unsafe (void * out, size_t outlen)
{
nano::random_pool.GenerateBlock (reinterpret_cast<uint8_t *> (out), outlen);
nano::random_pool::generate_block (reinterpret_cast<uint8_t *> (out), outlen);
}
void ed25519_hash_init (ed25519_hash_context * ctx)
{
Expand Down
21 changes: 20 additions & 1 deletion nano/lib/numbers.cpp
Expand Up @@ -8,7 +8,26 @@
#include <crypto/cryptopp/aes.h>
#include <crypto/cryptopp/modes.h>

thread_local CryptoPP::AutoSeededRandomPool nano::random_pool;
std::mutex nano::random_pool::mutex;
CryptoPP::AutoSeededRandomPool nano::random_pool::pool;

void nano::random_pool::generate_block (unsigned char * output, size_t size)
{
std::lock_guard<std::mutex> lk (mutex);
pool.GenerateBlock (output, size);
}

unsigned nano::random_pool::generate_word32 (unsigned min, unsigned max)
{
std::lock_guard<std::mutex> lk (mutex);
return pool.GenerateWord32 (min, max);
}

unsigned char nano::random_pool::generate_byte ()
{
std::lock_guard<std::mutex> lk (mutex);
return pool.GenerateByte ();
}

namespace
{
Expand Down
27 changes: 24 additions & 3 deletions nano/lib/numbers.hpp
Expand Up @@ -6,9 +6,30 @@

namespace nano
{
// Random pool used by Nano.
// This must be thread_local as long as the AutoSeededRandomPool implementation requires it
extern thread_local CryptoPP::AutoSeededRandomPool random_pool;
/** While this uses CryptoPP do not call any of these functions from global scope, as they depend on global variables inside the CryptoPP library which may not have been initialized yet due to an undefined order for globals in different translation units. To make sure this is not an issue, there should be no ASAN warnings at startup on Mac/Clang in the CryptoPP files. */
class random_pool
{
public:
static void generate_block (unsigned char * output, size_t size);
static unsigned generate_word32 (unsigned min, unsigned max);
static unsigned char generate_byte ();

template <class Iter>
static void shuffle (Iter begin, Iter end)
{
std::lock_guard<std::mutex> lk (mutex);
pool.Shuffle (begin, end);
}

random_pool () = delete;
random_pool (random_pool const &) = delete;
random_pool & operator= (random_pool const &) = delete;

private:
static std::mutex mutex;
static CryptoPP::AutoSeededRandomPool pool;
};

using uint128_t = boost::multiprecision::uint128_t;
using uint256_t = boost::multiprecision::uint256_t;
using uint512_t = boost::multiprecision::uint512_t;
Expand Down
2 changes: 1 addition & 1 deletion nano/lib/work.cpp
Expand Up @@ -64,7 +64,7 @@ void nano::work_pool::loop (uint64_t thread)
{
// Quick RNG for work attempts.
xorshift1024star rng;
nano::random_pool.GenerateBlock (reinterpret_cast<uint8_t *> (rng.s.data ()), rng.s.size () * sizeof (decltype (rng.s)::value_type));
nano::random_pool::generate_block (reinterpret_cast<uint8_t *> (rng.s.data ()), rng.s.size () * sizeof (decltype (rng.s)::value_type));
uint64_t work;
uint64_t output;
blake2b_state hash;
Expand Down
4 changes: 2 additions & 2 deletions nano/nano_wallet/entry.cpp
Expand Up @@ -21,7 +21,7 @@ class qt_wallet_config
rpc_enable (false),
opencl_enable (false)
{
nano::random_pool.GenerateBlock (wallet.bytes.data (), wallet.bytes.size ());
nano::random_pool::generate_block (wallet.bytes.data (), wallet.bytes.size ());
assert (!wallet.is_zero ());
}
bool upgrade_json (unsigned version_a, nano::jsonconfig & json)
Expand Down Expand Up @@ -114,7 +114,7 @@ class qt_wallet_config
}
if (wallet.is_zero ())
{
nano::random_pool.GenerateBlock (wallet.bytes.data (), wallet.bytes.size ());
nano::random_pool::generate_block (wallet.bytes.data (), wallet.bytes.size ());
upgraded_a = true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion nano/node/bootstrap.cpp
Expand Up @@ -1058,7 +1058,7 @@ void nano::bootstrap_attempt::run ()
{
for (auto i = static_cast<CryptoPP::word32> (pulls.size () - 1); i > 0; --i)
{
auto k = nano::random_pool.GenerateWord32 (0, i);
auto k = nano::random_pool::generate_word32 (0, i);
std::swap (pulls[i], pulls[k]);
}
}
Expand Down
6 changes: 3 additions & 3 deletions nano/node/lmdb.cpp
Expand Up @@ -880,7 +880,7 @@ nano::raw_key nano::mdb_store::get_node_id (nano::transaction const & transactio
}
if (error)
{
nano::random_pool.GenerateBlock (node_id.data.bytes.data (), node_id.data.bytes.size ());
nano::random_pool::generate_block (node_id.data.bytes.data (), node_id.data.bytes.size ());
error = mdb_put (env.tx (transaction_a), meta, nano::mdb_val (node_id_mdb_key), nano::mdb_val (node_id.data), 0);
}
assert (!error);
Expand Down Expand Up @@ -1471,7 +1471,7 @@ template <typename T>
std::shared_ptr<nano::block> nano::mdb_store::block_random (nano::transaction const & transaction_a, MDB_dbi database)
{
nano::block_hash hash;
nano::random_pool.GenerateBlock (hash.bytes.data (), hash.bytes.size ());
nano::random_pool::generate_block (hash.bytes.data (), hash.bytes.size ());
nano::store_iterator<nano::block_hash, std::shared_ptr<T>> existing (std::make_unique<nano::mdb_iterator<nano::block_hash, std::shared_ptr<T>>> (transaction_a, database, nano::mdb_val (hash)));
if (existing == nano::store_iterator<nano::block_hash, std::shared_ptr<T>> (nullptr))
{
Expand All @@ -1486,7 +1486,7 @@ std::shared_ptr<nano::block> nano::mdb_store::block_random (nano::transaction co
{
auto count (block_count (transaction_a));
release_assert (std::numeric_limits<CryptoPP::word32>::max () > count.sum ());
auto region = static_cast<size_t> (nano::random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (count.sum () - 1)));
auto region = static_cast<size_t> (nano::random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (count.sum () - 1)));
std::shared_ptr<nano::block> result;
if (region < count.send)
{
Expand Down
2 changes: 1 addition & 1 deletion nano/node/node.cpp
Expand Up @@ -439,7 +439,7 @@ void nano::network::broadcast_confirm_req (std::shared_ptr<nano::block> block_a)
* if the votes for a block have not arrived in time.
*/
const size_t max_endpoints = 32;
random_pool.Shuffle (list->begin (), list->end ());
random_pool::shuffle (list->begin (), list->end ());
if (list->size () > max_endpoints)
{
list->erase (list->begin () + max_endpoints, list->end ());
Expand Down
2 changes: 1 addition & 1 deletion nano/node/nodeconfig.cpp
Expand Up @@ -393,7 +393,7 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
nano::account nano::node_config::random_representative ()
{
assert (preconfigured_representatives.size () > 0);
size_t index (nano::random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (preconfigured_representatives.size () - 1)));
size_t index (nano::random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (preconfigured_representatives.size () - 1)));
auto result (preconfigured_representatives[index]);
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion nano/node/openclwork.cpp
Expand Up @@ -546,7 +546,7 @@ logging (logging_a)
error_a |= config.device >= platform.devices.size ();
if (!error_a)
{
nano::random_pool.GenerateBlock (reinterpret_cast<uint8_t *> (rand.s.data ()), rand.s.size () * sizeof (decltype (rand.s)::value_type));
nano::random_pool::generate_block (reinterpret_cast<uint8_t *> (rand.s.data ()), rand.s.size () * sizeof (decltype (rand.s)::value_type));
std::array<cl_device_id, 1> selected_devices;
selected_devices[0] = platform.devices[config.device];
cl_context_properties contextProperties[] = {
Expand Down
8 changes: 4 additions & 4 deletions nano/node/peers.cpp
Expand Up @@ -98,7 +98,7 @@ std::deque<nano::endpoint> nano::peer_container::list ()
{
result.push_back (i->endpoint);
}
random_pool.Shuffle (result.begin (), result.end ());
nano::random_pool::shuffle (result.begin (), result.end ());
return result;
}

Expand All @@ -110,7 +110,7 @@ std::vector<nano::peer_information> nano::peer_container::list_vector (size_t co
{
result.push_back (*i);
}
random_pool.Shuffle (result.begin (), result.end ());
random_pool::shuffle (result.begin (), result.end ());
if (result.size () > count_a)
{
result.resize (count_a, nano::peer_information (nano::endpoint{}, 0));
Expand Down Expand Up @@ -153,7 +153,7 @@ boost::optional<nano::uint256_union> nano::peer_container::assign_syn_cookie (na
if (syn_cookies.find (endpoint) == syn_cookies.end ())
{
nano::uint256_union query;
random_pool.GenerateBlock (query.bytes.data (), query.bytes.size ());
random_pool::generate_block (query.bytes.data (), query.bytes.size ());
syn_cookie_info info{ query, std::chrono::steady_clock::now () };
syn_cookies[endpoint] = info;
++ip_cookies;
Expand Down Expand Up @@ -201,7 +201,7 @@ std::unordered_set<nano::endpoint> nano::peer_container::random_set (size_t coun
{
for (auto i (0); i < random_cutoff && result.size () < count_a; ++i)
{
auto index (random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (peers_size - 1)));
auto index (nano::random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (peers_size - 1)));
result.insert (peers.get<3> ()[index].endpoint);
}
}
Expand Down
14 changes: 7 additions & 7 deletions nano/node/testing.cpp
Expand Up @@ -36,7 +36,7 @@ work (1, nullptr)
assert (!init.error ());
node->start ();
nano::uint256_union wallet;
nano::random_pool.GenerateBlock (wallet.bytes.data (), wallet.bytes.size ());
nano::random_pool::generate_block (wallet.bytes.data (), wallet.bytes.size ());
node->wallets.create (wallet);
nodes.push_back (node);
}
Expand Down Expand Up @@ -166,7 +166,7 @@ void nano::system::generate_rollback (nano::node & node_a, std::vector<nano::acc
{
auto transaction (node_a.store.tx_begin_write ());
assert (std::numeric_limits<CryptoPP::word32>::max () > accounts_a.size ());
auto index (random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (accounts_a.size () - 1)));
auto index (random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (accounts_a.size () - 1)));
auto account (accounts_a[index]);
nano::account_info info;
auto error (node_a.store.account_get (transaction, account, info));
Expand All @@ -189,7 +189,7 @@ void nano::system::generate_receive (nano::node & node_a)
{
auto transaction (node_a.store.tx_begin_read ());
nano::uint256_union random_block;
random_pool.GenerateBlock (random_block.bytes.data (), sizeof (random_block.bytes));
random_pool::generate_block (random_block.bytes.data (), sizeof (random_block.bytes));
auto i (node_a.store.pending_begin (transaction, nano::pending_key (random_block, 0)));
if (i != node_a.store.pending_end ())
{
Expand All @@ -206,7 +206,7 @@ void nano::system::generate_receive (nano::node & node_a)

void nano::system::generate_activity (nano::node & node_a, std::vector<nano::account> & accounts_a)
{
auto what (random_pool.GenerateByte ());
auto what (random_pool::generate_byte ());
if (what < 0x1)
{
generate_rollback (node_a, accounts_a);
Expand Down Expand Up @@ -236,7 +236,7 @@ void nano::system::generate_activity (nano::node & node_a, std::vector<nano::acc
nano::account nano::system::get_random_account (std::vector<nano::account> & accounts_a)
{
assert (std::numeric_limits<CryptoPP::word32>::max () > accounts_a.size ());
auto index (random_pool.GenerateWord32 (0, static_cast<CryptoPP::word32> (accounts_a.size () - 1)));
auto index (random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (accounts_a.size () - 1)));
auto result (accounts_a[index]);
return result;
}
Expand All @@ -246,7 +246,7 @@ nano::uint128_t nano::system::get_random_amount (nano::transaction const & trans
nano::uint128_t balance (node_a.ledger.account_balance (transaction_a, account_a));
std::string balance_text (balance.convert_to<std::string> ());
nano::uint128_union random_amount;
random_pool.GenerateBlock (random_amount.bytes.data (), sizeof (random_amount.bytes));
nano::random_pool::generate_block (random_amount.bytes.data (), sizeof (random_amount.bytes));
auto result (((nano::uint256_t{ random_amount.number () } * balance) / nano::uint256_t{ std::numeric_limits<nano::uint128_t>::max () }).convert_to<nano::uint128_t> ());
std::string text (result.convert_to<std::string> ());
return result;
Expand All @@ -259,7 +259,7 @@ void nano::system::generate_send_existing (nano::node & node_a, std::vector<nano
nano::account source;
{
nano::account account;
random_pool.GenerateBlock (account.bytes.data (), sizeof (account.bytes));
random_pool::generate_block (account.bytes.data (), sizeof (account.bytes));
auto transaction (node_a.store.tx_begin_read ());
nano::store_iterator<nano::account, nano::account_info> entry (node_a.store.latest_begin (transaction, account));
if (entry == node_a.store.latest_end ())
Expand Down
12 changes: 6 additions & 6 deletions nano/node/wallet.cpp
Expand Up @@ -212,7 +212,7 @@ nano::fan::fan (nano::uint256_union const & key, size_t count_a)
for (auto i (1); i < count_a; ++i)
{
std::unique_ptr<nano::uint256_union> entry (new nano::uint256_union);
random_pool.GenerateBlock (entry->bytes.data (), entry->bytes.size ());
nano::random_pool::generate_block (entry->bytes.data (), entry->bytes.size ());
*first ^= *entry;
values.push_back (std::move (entry));
}
Expand Down Expand Up @@ -334,11 +334,11 @@ kdf (kdf_a)
{
version_put (transaction_a, version_current);
nano::uint256_union salt_l;
random_pool.GenerateBlock (salt_l.bytes.data (), salt_l.bytes.size ());
random_pool::generate_block (salt_l.bytes.data (), salt_l.bytes.size ());
entry_put_raw (transaction_a, nano::wallet_store::salt_special, nano::wallet_value (salt_l, 0));
// Wallet key is a fixed random key that encrypts all entries
nano::raw_key wallet_key;
random_pool.GenerateBlock (wallet_key.data.bytes.data (), sizeof (wallet_key.data.bytes));
random_pool::generate_block (wallet_key.data.bytes.data (), sizeof (wallet_key.data.bytes));
nano::raw_key password_l;
password_l.data.clear ();
password.value_set (password_l);
Expand All @@ -356,7 +356,7 @@ kdf (kdf_a)
entry_put_raw (transaction_a, nano::wallet_store::check_special, nano::wallet_value (check, 0));
entry_put_raw (transaction_a, nano::wallet_store::representative_special, nano::wallet_value (representative_a, 0));
nano::raw_key seed;
random_pool.GenerateBlock (seed.data.bytes.data (), seed.data.bytes.size ());
random_pool::generate_block (seed.data.bytes.data (), seed.data.bytes.size ());
seed_set (transaction_a, seed);
entry_put_raw (transaction_a, nano::wallet_store::deterministic_index_special, nano::wallet_value (nano::uint256_union (0), 0));
}
Expand Down Expand Up @@ -685,7 +685,7 @@ void nano::wallet_store::upgrade_v2_v3 (nano::transaction const & transaction_a)
{
assert (version (transaction_a) == 2);
nano::raw_key seed;
random_pool.GenerateBlock (seed.data.bytes.data (), seed.data.bytes.size ());
random_pool::generate_block (seed.data.bytes.data (), seed.data.bytes.size ());
seed_set (transaction_a, seed);
entry_put_raw (transaction_a, nano::wallet_store::deterministic_index_special, nano::wallet_value (nano::uint256_union (0), 0));
version_put (transaction_a, 3);
Expand Down Expand Up @@ -881,7 +881,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.GenerateBlock (id.bytes.data (), id.bytes.size ());
random_pool::generate_block (id.bytes.data (), id.bytes.size ());
temp.reset (new nano::wallet_store (error, wallets.node.wallets.kdf, transaction, 0, 1, id.to_string (), json_a));
}
if (!error)
Expand Down
2 changes: 1 addition & 1 deletion nano/qt_system/entry.cpp
Expand Up @@ -17,7 +17,7 @@ int main (int argc, char ** argv)
for (auto i (0); i < count; ++i)
{
nano::uint256_union wallet_id;
nano::random_pool.GenerateBlock (wallet_id.bytes.data (), wallet_id.bytes.size ());
nano::random_pool::generate_block (wallet_id.bytes.data (), wallet_id.bytes.size ());
auto wallet (system.nodes[i]->wallets.create (wallet_id));
nano::keypair key;
wallet->insert_adhoc (key.prv);
Expand Down