diff options
author | Pieter Wuille <pieter@wuille.net> | 2024-03-10 14:50:20 -0400 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2024-07-01 10:26:46 -0400 |
commit | 8cc2f45065fc1864f879248d1e1444588e27076b (patch) | |
tree | 42262bcb5f2536a568f3bbc114ef630831ae80b7 /src | |
parent | 8f5ac0d0b608bdf396d8f2d758a792f869c2cd2a (diff) |
random: move XoRoShiRo128PlusPlus into random module
This is preparation for making it more generally accessible.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.test.include | 3 | ||||
-rw-r--r-- | src/Makefile.test_util.include | 3 | ||||
-rw-r--r-- | src/random.h | 51 | ||||
-rw-r--r-- | src/test/fuzz/bip324.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/bitset.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/crypto_chacha20.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/p2p_transport_serialization.cpp | 1 | ||||
-rw-r--r-- | src/test/fuzz/poolresource.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/vecdeque.cpp | 2 | ||||
-rw-r--r-- | src/test/random_tests.cpp | 17 | ||||
-rw-r--r-- | src/test/util/xoroshiro128plusplus.h | 63 | ||||
-rw-r--r-- | src/test/xoroshiro128plusplus_tests.cpp | 29 |
12 files changed, 75 insertions, 102 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 633d0776f5..8651eea942 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -173,8 +173,7 @@ BITCOIN_TESTS =\ test/validation_flush_tests.cpp \ test/validation_tests.cpp \ test/validationinterface_tests.cpp \ - test/versionbits_tests.cpp \ - test/xoroshiro128plusplus_tests.cpp + test/versionbits_tests.cpp if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include index 6a1fd712bd..960eb078c8 100644 --- a/src/Makefile.test_util.include +++ b/src/Makefile.test_util.include @@ -23,8 +23,7 @@ TEST_UTIL_H = \ test/util/str.h \ test/util/transaction_utils.h \ test/util/txmempool.h \ - test/util/validation.h \ - test/util/xoroshiro128plusplus.h + test/util/validation.h if ENABLE_WALLET TEST_UTIL_H += wallet/test/util.h diff --git a/src/random.h b/src/random.h index 007853bc36..e870867170 100644 --- a/src/random.h +++ b/src/random.h @@ -349,6 +349,57 @@ public: void fillrand(Span<std::byte> output) noexcept; }; +/** xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes. + * + * Memory footprint is 128bit, period is 2^128 - 1. + * This class is not thread-safe. + * + * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c + * See https://prng.di.unimi.it/ + */ +class XoRoShiRo128PlusPlus +{ + uint64_t m_s0; + uint64_t m_s1; + + [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept + { + uint64_t z = (seedval += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); + } + +public: + using result_type = uint64_t; + + constexpr explicit XoRoShiRo128PlusPlus(uint64_t seedval) noexcept + : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {} + + // no copy - that is dangerous, we don't want accidentally copy the RNG and then have two streams + // with exactly the same results. + XoRoShiRo128PlusPlus(const XoRoShiRo128PlusPlus&) = delete; + XoRoShiRo128PlusPlus& operator=(const XoRoShiRo128PlusPlus&) = delete; + + // allow moves + XoRoShiRo128PlusPlus(XoRoShiRo128PlusPlus&&) = default; + XoRoShiRo128PlusPlus& operator=(XoRoShiRo128PlusPlus&&) = default; + + constexpr result_type operator()() noexcept + { + uint64_t s0 = m_s0, s1 = m_s1; + const uint64_t result = std::rotl(s0 + s1, 17) + s0; + s1 ^= s0; + m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21); + m_s1 = std::rotl(s1, 28); + return result; + } + + static constexpr result_type min() noexcept { return std::numeric_limits<result_type>::min(); } + static constexpr result_type max() noexcept { return std::numeric_limits<result_type>::max(); } + static constexpr double entropy() noexcept { return 0.0; } +}; + /** More efficient than using std::shuffle on a FastRandomContext. * * This is more efficient as std::shuffle will consume entropy in groups of diff --git a/src/test/fuzz/bip324.cpp b/src/test/fuzz/bip324.cpp index 8210e75cee..0619916819 100644 --- a/src/test/fuzz/bip324.cpp +++ b/src/test/fuzz/bip324.cpp @@ -4,11 +4,11 @@ #include <bip324.h> #include <chainparams.h> +#include <random.h> #include <span.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> -#include <test/util/xoroshiro128plusplus.h> #include <cstdint> #include <vector> diff --git a/src/test/fuzz/bitset.cpp b/src/test/fuzz/bitset.cpp index 7684337729..cc3ed30f62 100644 --- a/src/test/fuzz/bitset.cpp +++ b/src/test/fuzz/bitset.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <random.h> #include <span.h> #include <test/fuzz/util.h> -#include <test/util/xoroshiro128plusplus.h> #include <util/bitset.h> #include <bitset> diff --git a/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp index 50c77bf699..ff3d463ca5 100644 --- a/src/test/fuzz/crypto_chacha20.cpp +++ b/src/test/fuzz/crypto_chacha20.cpp @@ -3,10 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <crypto/chacha20.h> +#include <random.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> -#include <test/util/xoroshiro128plusplus.h> #include <array> #include <cstddef> diff --git a/src/test/fuzz/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp index 767238d103..5a26fb86ce 100644 --- a/src/test/fuzz/p2p_transport_serialization.cpp +++ b/src/test/fuzz/p2p_transport_serialization.cpp @@ -10,7 +10,6 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> -#include <test/util/xoroshiro128plusplus.h> #include <util/chaintype.h> #include <cassert> diff --git a/src/test/fuzz/poolresource.cpp b/src/test/fuzz/poolresource.cpp index f764d9f8db..a3e48994c9 100644 --- a/src/test/fuzz/poolresource.cpp +++ b/src/test/fuzz/poolresource.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <random.h> #include <span.h> #include <support/allocators/pool.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> #include <test/util/poolresourcetester.h> -#include <test/util/xoroshiro128plusplus.h> #include <cstdint> #include <tuple> diff --git a/src/test/fuzz/vecdeque.cpp b/src/test/fuzz/vecdeque.cpp index 1d9a98931f..d94e6d895a 100644 --- a/src/test/fuzz/vecdeque.cpp +++ b/src/test/fuzz/vecdeque.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <random.h> #include <span.h> #include <test/fuzz/util.h> -#include <test/util/xoroshiro128plusplus.h> #include <util/vecdeque.h> #include <deque> diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 2617cc4a2a..09425c7cd7 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -219,4 +219,21 @@ BOOST_AUTO_TEST_CASE(shuffle_stat_test) BOOST_CHECK_EQUAL(sum, 12000U); } +BOOST_AUTO_TEST_CASE(xoroshiro128plusplus_reference_values) +{ + // numbers generated from reference implementation + XoRoShiRo128PlusPlus rng(0); + BOOST_TEST(0x6f68e1e7e2646ee1 == rng()); + BOOST_TEST(0xbf971b7f454094ad == rng()); + BOOST_TEST(0x48f2de556f30de38 == rng()); + BOOST_TEST(0x6ea7c59f89bbfc75 == rng()); + + // seed with a random number + rng = XoRoShiRo128PlusPlus(0x1a26f3fa8546b47a); + BOOST_TEST(0xc8dc5e08d844ac7d == rng()); + BOOST_TEST(0x5b5f1f6d499dad1b == rng()); + BOOST_TEST(0xbeb0031f93313d6f == rng()); + BOOST_TEST(0xbfbcf4f43a264497 == rng()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/xoroshiro128plusplus.h b/src/test/util/xoroshiro128plusplus.h deleted file mode 100644 index 93ab473b37..0000000000 --- a/src/test/util/xoroshiro128plusplus.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H -#define BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H - -#include <bit> -#include <cstdint> -#include <limits> - -/** xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes. - * - * Memory footprint is 128bit, period is 2^128 - 1. - * This class is not thread-safe. - * - * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c - * See https://prng.di.unimi.it/ - */ -class XoRoShiRo128PlusPlus -{ - uint64_t m_s0; - uint64_t m_s1; - - [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept - { - uint64_t z = (seedval += 0x9e3779b97f4a7c15); - z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; - z = (z ^ (z >> 27)) * 0x94d049bb133111eb; - return z ^ (z >> 31); - } - -public: - using result_type = uint64_t; - - constexpr explicit XoRoShiRo128PlusPlus(uint64_t seedval) noexcept - : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {} - - // no copy - that is dangerous, we don't want accidentally copy the RNG and then have two streams - // with exactly the same results. - XoRoShiRo128PlusPlus(const XoRoShiRo128PlusPlus&) = delete; - XoRoShiRo128PlusPlus& operator=(const XoRoShiRo128PlusPlus&) = delete; - - // allow moves - XoRoShiRo128PlusPlus(XoRoShiRo128PlusPlus&&) = default; - XoRoShiRo128PlusPlus& operator=(XoRoShiRo128PlusPlus&&) = default; - - constexpr result_type operator()() noexcept - { - uint64_t s0 = m_s0, s1 = m_s1; - const uint64_t result = std::rotl(s0 + s1, 17) + s0; - s1 ^= s0; - m_s0 = std::rotl(s0, 49) ^ s1 ^ (s1 << 21); - m_s1 = std::rotl(s1, 28); - return result; - } - - static constexpr result_type min() noexcept { return std::numeric_limits<result_type>::min(); } - static constexpr result_type max() noexcept { return std::numeric_limits<result_type>::max(); } - static constexpr double entropy() noexcept { return 0.0; } -}; - -#endif // BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H diff --git a/src/test/xoroshiro128plusplus_tests.cpp b/src/test/xoroshiro128plusplus_tests.cpp deleted file mode 100644 index ea1b3e355f..0000000000 --- a/src/test/xoroshiro128plusplus_tests.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include <test/util/setup_common.h> -#include <test/util/xoroshiro128plusplus.h> - -#include <boost/test/unit_test.hpp> - -BOOST_FIXTURE_TEST_SUITE(xoroshiro128plusplus_tests, BasicTestingSetup) - -BOOST_AUTO_TEST_CASE(reference_values) -{ - // numbers generated from reference implementation - XoRoShiRo128PlusPlus rng(0); - BOOST_TEST(0x6f68e1e7e2646ee1 == rng()); - BOOST_TEST(0xbf971b7f454094ad == rng()); - BOOST_TEST(0x48f2de556f30de38 == rng()); - BOOST_TEST(0x6ea7c59f89bbfc75 == rng()); - - // seed with a random number - rng = XoRoShiRo128PlusPlus(0x1a26f3fa8546b47a); - BOOST_TEST(0xc8dc5e08d844ac7d == rng()); - BOOST_TEST(0x5b5f1f6d499dad1b == rng()); - BOOST_TEST(0xbeb0031f93313d6f == rng()); - BOOST_TEST(0xbfbcf4f43a264497 == rng()); -} - -BOOST_AUTO_TEST_SUITE_END() |