Add FastRandomContext::rand256() and ::randbytes()

FastRandomContext now provides all functionality that the real Rand* functions
provide.
This commit is contained in:
Pieter Wuille 2017-05-02 11:04:31 -07:00
parent 9fec4da0be
commit 37e864eb9f
3 changed files with 33 additions and 0 deletions

View file

@ -304,6 +304,26 @@ void FastRandomContext::RandomSeed()
requires_seed = false; requires_seed = false;
} }
uint256 FastRandomContext::rand256()
{
if (bytebuf_size < 32) {
FillByteBuffer();
}
uint256 ret;
memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32);
bytebuf_size -= 32;
return ret;
}
std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
{
std::vector<unsigned char> ret(len);
if (len > 0) {
rng.Output(&ret[0], len);
}
return ret;
}
FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{ {
rng.SetKey(seed.begin(), 32); rng.SetKey(seed.begin(), 32);

View file

@ -110,9 +110,15 @@ public:
} }
} }
/** Generate random bytes. */
std::vector<unsigned char> randbytes(size_t len);
/** Generate a random 32-bit integer. */ /** Generate a random 32-bit integer. */
uint32_t rand32() { return randbits(32); } uint32_t rand32() { return randbits(32); }
/** generate a random uint256. */
uint256 rand256();
/** Generate a random boolean. */ /** Generate a random boolean. */
bool randbool() { return randbits(1); } bool randbool() { return randbits(1); }
}; };

View file

@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64());
BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17));
BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7));
BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128));
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50));
// Check that a nondeterministic ones are not // Check that a nondeterministic ones are not
FastRandomContext ctx3; FastRandomContext ctx3;
FastRandomContext ctx4; FastRandomContext ctx4;
BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
BOOST_CHECK(ctx3.rand256() != ctx4.rand256());
BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
} }
BOOST_AUTO_TEST_CASE(fastrandom_randbits) BOOST_AUTO_TEST_CASE(fastrandom_randbits)