Fix: Allow block count > UINT32_MAX (#3979)
The method `ledger::hash_root_random()` required the block count to fit into a uint32_t. This limit is too small to be future-proof. This commit increases the limit to UINT64_MAX, so that it matches the other places where block count is a uint64_t.
This commit is contained in:
parent
5da8ad2043
commit
18308657b7
4 changed files with 48 additions and 2 deletions
|
@ -600,3 +600,29 @@ TEST (random_pool, multithreading)
|
|||
i.join ();
|
||||
}
|
||||
}
|
||||
|
||||
// Test that random 64bit numbers are within the given range
|
||||
TEST (random_pool, generate_word64)
|
||||
{
|
||||
int occurrences[10] = { 0 };
|
||||
for (auto i = 0; i < 1000; ++i)
|
||||
{
|
||||
auto random = nano::random_pool::generate_word64 (1, 9);
|
||||
ASSERT_TRUE (random >= 1 && random <= 9);
|
||||
occurrences[random] += 1;
|
||||
}
|
||||
|
||||
for (auto i = 1; i < 10; ++i)
|
||||
{
|
||||
ASSERT_TRUE (occurrences[i] > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Test random numbers > uint32 max
|
||||
TEST (random_pool, generate_word64_big_number)
|
||||
{
|
||||
uint64_t min = static_cast<uint64_t> (std::numeric_limits<uint32_t>::max ()) + 1;
|
||||
uint64_t max = std::numeric_limits<uint64_t>::max ();
|
||||
auto big_random = nano::random_pool::generate_word64 (min, max);
|
||||
ASSERT_TRUE (big_random >= min);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <nano/crypto_lib/random_pool.hpp>
|
||||
|
||||
#include <crypto/cryptopp/misc.h>
|
||||
#include <crypto/cryptopp/osrng.h>
|
||||
|
||||
void nano::random_pool::generate_block (unsigned char * output, size_t size)
|
||||
|
@ -14,6 +15,24 @@ unsigned nano::random_pool::generate_word32 (unsigned min, unsigned max)
|
|||
return pool.GenerateWord32 (min, max);
|
||||
}
|
||||
|
||||
uint64_t nano::random_pool::generate_word64 (uint64_t min, uint64_t max)
|
||||
{
|
||||
auto & pool = get_pool ();
|
||||
|
||||
const auto range = max - min;
|
||||
const auto max_bits = CryptoPP::BitPrecision (range);
|
||||
|
||||
uint64_t value;
|
||||
|
||||
do
|
||||
{
|
||||
pool.GenerateBlock ((unsigned char *)&value, sizeof (value));
|
||||
value = CryptoPP::Crop (value, max_bits);
|
||||
} while (value > range);
|
||||
|
||||
return value + min;
|
||||
}
|
||||
|
||||
unsigned char nano::random_pool::generate_byte ()
|
||||
{
|
||||
auto & pool = get_pool ();
|
||||
|
|
|
@ -15,6 +15,8 @@ class random_pool
|
|||
public:
|
||||
static void generate_block (unsigned char * output, size_t size);
|
||||
static unsigned generate_word32 (unsigned min, unsigned max);
|
||||
/** Generates a random uint64_t in the range min to max. min and max are inclusive. */
|
||||
static uint64_t generate_word64 (uint64_t min, uint64_t max);
|
||||
static unsigned char generate_byte ();
|
||||
|
||||
random_pool () = delete;
|
||||
|
|
|
@ -1004,8 +1004,7 @@ std::pair<nano::block_hash, nano::block_hash> nano::ledger::hash_root_random (na
|
|||
else
|
||||
{
|
||||
uint64_t count (cache.block_count);
|
||||
release_assert (std::numeric_limits<CryptoPP::word32>::max () > count);
|
||||
auto region = static_cast<size_t> (nano::random_pool::generate_word32 (0, static_cast<CryptoPP::word32> (count - 1)));
|
||||
auto region = nano::random_pool::generate_word64 (0, count - 1);
|
||||
// Pruned cache cannot guarantee that pruned blocks are already commited
|
||||
if (region < cache.pruned_count)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue