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

Switch all RNG code to the built-in PRNG #14955

Merged
merged 14 commits into from Jan 21, 2019
Merged

Conversation

@sipa
Copy link
Member

@sipa sipa commented Dec 14, 2018

This does not remove OpenSSL, but makes our own PRNG the 'main' one; for GetStrongRandBytes, the OpenSSL RNG is still used (indirectly, by feeding its output into our PRNG state).

It includes a few policy changes (regarding what entropy is seeded when).

Before this PR:

  • GetRand*:
    • OpenSSL
  • GetStrongRand*:
    • CPU cycle counter
    • Perfmon data (on Windows, once 10 min)
    • /dev/urandom (or equivalent)
    • rdrand (if available)
  • From scheduler when idle:
    • CPU cycle counter before and after 1ms sleep
  • At startup:
    • CPU cycle counter before and after 1ms sleep

After this PR:

  • GetRand*:
    • Stack pointer (which indirectly identifies thread and some call stack information)
    • rdrand (if available)
    • CPU cycle counter
  • GetStrongRand*:
    • Stack pointer (which indirectly identifies thread and some call stack information)
    • rdrand (if available)
    • CPU cycle counter
    • /dev/urandom (or equivalent)
    • OpenSSL
    • CPU cycle counter again
  • From scheduler when idle:
    • Stack pointer (which indirectly identifies thread and some call stack information)
    • rdrand (if available)
    • CPU cycle counter before and after 1ms sleep
    • Perfmon data (on Windows, once every 10 min)
  • At startup:
    • Stack pointer (which indirectly identifies thread and some call stack information)
    • rdrand (if available)
    • CPU cycle counter
    • /dev/urandom (or equivalent)
    • OpenSSL
    • CPU cycle counter again
    • Perfmon data (on Windows, once every 10 min)

The interface of random.h is also simplified, and documentation is added.

This implements most of #14623.

@fanquake
Copy link
Member

@fanquake fanquake commented Dec 14, 2018

Compile failure on macOS (10.14.2):

./autogen.sh
./configure
make check

  CXX      libbitcoin_util_a-logging.o
  CXX      libbitcoin_util_a-random.o
random.cpp:394:41: error: expected ';' after top level declarator
static unsigned char rng_state[32] = {0} GUARDED_BY(cs_rng_state);
                                        ^
                                        ;
random.cpp:394:42: warning: declaration does not declare anything [-Wmissing-declarations]
static unsigned char rng_state[32] = {0} GUARDED_BY(cs_rng_state);
                                         ^
./threadsafety.h:18:23: note: expanded from macro 'GUARDED_BY'
#define GUARDED_BY(x) __attribute__((guarded_by(x)))
                      ^
random.cpp:395:32: error: expected ';' after top level declarator
static uint64_t rng_counter = 0 GUARDED_BY(cs_rng_state);
                               ^
                               ;
random.cpp:395:33: warning: declaration does not declare anything [-Wmissing-declarations]
static uint64_t rng_counter = 0 GUARDED_BY(cs_rng_state);
                                ^
./threadsafety.h:18:23: note: expanded from macro 'GUARDED_BY'
#define GUARDED_BY(x) __attribute__((guarded_by(x)))
                      ^
2 warnings and 2 errors generated.
make[2]: *** [libbitcoin_util_a-random.o] Error 1
make[1]: *** [check-recursive] Error 1
make: *** [check-recursive] Error 1

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Dec 14, 2018

Might be desirable to stick the openssl stuff behind a define already, I expect we'll be able to ship 0.18 without linking bitcoind to openssl.

@sipa sipa force-pushed the 201812_generic_rand branch from 0a9f297 to b2fbb03 Dec 14, 2018
@sipa
Copy link
Member Author

@sipa sipa commented Dec 14, 2018

@fanquake Hopefully fixed.

@gmaxwell There are probably a few entropy sources we want to add first, I think.

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Dec 14, 2018

@sipa I am eager to add entropy sources! (but I meant behind a ifdef that is currently on... just since I think you're touching the only remaining callsites)

@DrahtBot
Copy link
Contributor

@DrahtBot DrahtBot commented Dec 14, 2018

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #13746 (-masterdatadir for datadir bootstrapping by kallewoof)
  • #13339 (wallet: Replace %w by wallet name in -walletnotify script by promag)
  • #11082 (Add new bitcoin_rw.conf file that is used for settings modified by this software itself by luke-jr)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

src/random.cpp Show resolved Hide resolved
src/random.cpp Show resolved Hide resolved
src/random.cpp Outdated Show resolved Hide resolved
src/random.cpp Show resolved Hide resolved
src/random.cpp Show resolved Hide resolved
src/random.h Outdated Show resolved Hide resolved
@sipa sipa force-pushed the 201812_generic_rand branch from b2fbb03 to 2390b70 Dec 14, 2018
src/random.cpp Outdated Show resolved Hide resolved
src/random.cpp Outdated Show resolved Hide resolved
src/random.cpp Outdated Show resolved Hide resolved
@sipa sipa force-pushed the 201812_generic_rand branch 2 times, most recently from 75afa09 to 91367fb Dec 18, 2018
@sipa
Copy link
Member Author

@sipa sipa commented Dec 18, 2018

Made a number of improvements, and split the history out into hopefully more self-contained commits.

@ken2812221
Copy link
Contributor

@ken2812221 ken2812221 commented Dec 18, 2018

In constructor of CTxMemPool require to call random functions, but the constructor of the mutex has not being called yet. (Maybe it is an undefined behavior or it's a bug of VC++)

CTxMemPool mempool(&feeEstimator);

 	test_bitcoin.exe!SeedStartup(CSHA512 & hasher={...}) 第 417 行	C++
 	test_bitcoin.exe!ProcRand(unsigned char * out=0x00000031da8febb8, int num=8, RNGLevel level=STARTUP) 第 462 行	C++
 	test_bitcoin.exe!GetRandBytes(unsigned char * buf=0x00000031da8febb8, int num=8) 第 476 行	C++
 	test_bitcoin.exe!GetRand(unsigned __int64 nMax=18446744073709551615) 第 491 行	C++
 	test_bitcoin.exe!SaltedTxidHasher::SaltedTxidHasher() 第 1093 行	C++
 	test_bitcoin.exe!boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> >::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > >::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::cons<unsigned __int64,boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > > >::cons<unsigned __int64,boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > > >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>() 第 485 行	C++
 	test_bitcoin.exe!boost::tuples::cons<boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::null_type> > > >::cons<boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::null_type> > > >() 第 284 行	C++
 	test_bitcoin.exe!boost::multi_index::multi_index_container<CTxMemPoolEntry,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<mempoolentry_txid,SaltedTxidHasher,boost::mpl::na,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<descendant_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<entry_time,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<ancestor_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<CTxMemPoolEntry> >::multi_index_container<CTxMemPoolEntry,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<mempoolentry_txid,SaltedTxidHasher,boost::mpl::na,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<descendant_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<entry_time,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<ancestor_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<CTxMemPoolEntry> >() 第 177 行	C++
 	test_bitcoin.exe!CTxMemPool::CTxMemPool(CBlockPolicyEstimator * estimator=0x00007ff65afbfe60) 第 328 行	C++
>	test_bitcoin.exe!`dynamic initializer for 'mempool''() 第 244 行	C++
 	test_bitcoin.exe!_initterm(void(*)() * first=0x00007ff65a49c000, void(*)() * last=0x00007ff65a49f848) 第 22 行	C++
 	[外部程式碼]	

@sipa sipa force-pushed the 201812_generic_rand branch 2 times, most recently from 730d6a7 to a2a81d1 Dec 19, 2018
@sipa
Copy link
Member Author

@sipa sipa commented Dec 19, 2018

@ken2812221 That was helpful, thanks! I think I've fixed it, but the same error still appears. Can you check what line number it's on now?

@ken2812221
Copy link
Contributor

@ken2812221 ken2812221 commented Dec 19, 2018

 	test_bitcoin.exe!std::_Load_relaxed_4(volatile unsigned long * _Tgt=0x0000000000000074) 第 1338 行	C++
 	test_bitcoin.exe!std::_Atomic_load_4(volatile unsigned long * _Tgt=0x0000000000000074, std::memory_order _Order=memory_order_relaxed) 第 1357 行	C++
 	test_bitcoin.exe!std::atomic_load_explicit(const std::_Atomic_uint * _Atom=0x0000000000000074, std::memory_order _Order=memory_order_relaxed) 第 495 行	C++
 	test_bitcoin.exe!std::_Atomic_uint::load(std::memory_order _Order=memory_order_relaxed) 第 630 行	C++
 	test_bitcoin.exe!BCLog::Logger::WillLogCategory(BCLog::LogFlags category=RAND) 第 83 行	C++
 	test_bitcoin.exe!LogAcceptCategory(BCLog::LogFlags category=RAND) 第 117 行	C++
 	test_bitcoin.exe!LogPrint<char [15],char [19],unsigned long>(const BCLog::LogFlags & category=RAND, const char[15] & <args_0>=..., const char[19] & <args_1>=..., const unsigned long & <args_2>=707688) 第 150 行	C++
>	test_bitcoin.exe!RandAddSeedPerfmon(CSHA512 & hasher={...}) 第 199 行	C++
 	test_bitcoin.exe!SeedStartup(CSHA512 & hasher={...}, `anonymous-namespace'::RNGState & rng={...}) 第 456 行	C++
 	test_bitcoin.exe!ProcRand(unsigned char * out=0x0000009f8cd8eb78, int num=8, RNGLevel level=FAST) 第 493 行	C++
 	test_bitcoin.exe!GetRandBytes(unsigned char * buf=0x0000009f8cd8eb78, int num=8) 第 508 行	C++
 	test_bitcoin.exe!GetRand(unsigned __int64 nMax=18446744073709551615) 第 523 行	C++
 	test_bitcoin.exe!SaltedTxidHasher::SaltedTxidHasher() 第 1093 行	C++
 	test_bitcoin.exe!boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> >::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > >::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::cons<unsigned __int64,boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > > >::cons<unsigned __int64,boost::tuples::cons<mempoolentry_txid,boost::tuples::cons<SaltedTxidHasher,boost::tuples::cons<std::equal_to<uint256>,boost::tuples::null_type> > > >() 第 284 行	C++
 	test_bitcoin.exe!boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>() 第 485 行	C++
 	test_bitcoin.exe!boost::tuples::cons<boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::null_type> > > >::cons<boost::tuples::tuple<unsigned __int64,mempoolentry_txid,SaltedTxidHasher,std::equal_to<uint256>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::cons<boost::tuples::tuple<boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::tuples::null_type> > > >() 第 284 行	C++
 	test_bitcoin.exe!boost::multi_index::multi_index_container<CTxMemPoolEntry,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<mempoolentry_txid,SaltedTxidHasher,boost::mpl::na,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<descendant_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<entry_time,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<ancestor_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<CTxMemPoolEntry> >::multi_index_container<CTxMemPoolEntry,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<mempoolentry_txid,SaltedTxidHasher,boost::mpl::na,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<descendant_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<entry_time,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByEntryTime>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<ancestor_score,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByAncestorFee>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<CTxMemPoolEntry> >() 第 177 行	C++
 	test_bitcoin.exe!CTxMemPool::CTxMemPool(CBlockPolicyEstimator * estimator=0x00007ff689f81fb0) 第 328 行	C++
 	test_bitcoin.exe!`dynamic initializer for 'mempool''() 第 244 行	C++
 	test_bitcoin.exe!_initterm(void(*)() * first=0x00007ff68945e000, void(*)() * last=0x00007ff689461830) 第 22 行	C++
 	[外部程式碼]	

g_logger has not been newed.

BCLog::Logger* const g_logger = new BCLog::Logger();

@sipa
Copy link
Member Author

@sipa sipa commented Dec 19, 2018

@ken2812221 Thanks so much; this was an actual bug.

@sipa sipa force-pushed the 201812_generic_rand branch from 6498870 to 0644236 Dec 19, 2018
@bitcoin bitcoin deleted a comment from DrahtBot Dec 19, 2018
@bitcoin bitcoin deleted a comment Dec 19, 2018
@sipa
Copy link
Member Author

@sipa sipa commented Dec 19, 2018

I've made a few policy changes still:

  • Startup no longer includes the benchmark-1ms-sleep test, but still does strengthening.
  • The background seeding (called by the scheduler during idle times) no longer sources OpenSSL and /dev/random, as doing so every millisecond seems very much overkill. (it still includes rdrand as that has negligable CPU overhead).
  • The seeders are renamed to "fast" (called by GetRand*), "slow" (called by GetStrongRand*), "background" (called by idle scheduler), and "startup" (called only once at startup).

The global-order-independent initialization now uses a function which stores the RNG state in a local static variable. C++11 guarantees that it is initialized on first call, even if called multiple times simultaneously. I've benchmarked this approach and it's even faster than using std::call_once (2ns vs 1.8ns); I believe it's due to this approach using inline code generated by the compiler instead of a library call into pthread.

src/random.cpp Outdated Show resolved Hide resolved
@sipa sipa force-pushed the 201812_generic_rand branch from 3b001b0 to 57788fa Jan 17, 2019
sipa added 10 commits Jan 17, 2019
This guarantees that OpenSSL is initialized properly whenever randomness
is used, even when that randomness is invoked from global constructors.

Note that this patch uses Mutex directly, rather than CCriticalSection.
This is because the lock-detection code is not necessarily initialized
during global constructors.
It includes the following policy changes:
* All GetRand* functions seed the stack pointer and rdrand result
  (in addition to the performance counter)
* The periodic entropy added by the idle scheduler now seeds stack pointer,
  rdrand and perfmon data (once every 10 minutes) in addition to
  just a sleep timing.
* The entropy added when calling GetStrongRandBytes no longer includes
  the once-per-10-minutes perfmon data on windows (it is moved to the
  idle scheduler instead, where latency matters less).

Other changes:
* OpenSSL is no longer seeded directly anywhere. Instead, any generated
  randomness through our own RNG is fed back to OpenSSL (after an
  additional hashing step to prevent leaking our RNG state).
* Seeding that was previously done directly in RandAddSeedSleep is now
  moved to SeedSleep(), which is indirectly invoked through ProcRand
  from RandAddSeedSleep.
* Seeding that was previously done directly in GetStrongRandBytes()
  is now moved to SeedSlow(), which is indirectly invoked through
  ProcRand from GetStrongRandBytes().
 All access to hwrand is now gated by GetRNGState, which initializes the hwrand code.
@sipa sipa force-pushed the 201812_generic_rand branch from 57788fa to 223de8d Jan 17, 2019
@Sjors
Copy link
Member

@Sjors Sjors commented Jan 17, 2019

Wonderful, re-tACK 223de8d

@sipa
Copy link
Member Author

@sipa sipa commented Jan 17, 2019

FWIW, I've benchmarked this before and after this PR on my system. GetRandBytes goes from around ~1 μs to ~3 μs. GetStrongRandBytes stays around ~10 μs. Note that GetRandBytes is no longer called inside tight loops since #14624.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

utACK 223de8d. All changes since last review are renames or comment improvements.

@laanwj laanwj merged commit 223de8d into bitcoin:master Jan 21, 2019
2 checks passed
laanwj added a commit that referenced this issue Jan 21, 2019
223de8d Document RNG design in random.h (Pieter Wuille)
f2e60ca Use secure allocator for RNG state (Pieter Wuille)
cddb31b Encapsulate RNGState better (Pieter Wuille)
152146e DRY: Implement GetRand using FastRandomContext::randrange (Pieter Wuille)
a1f252e Sprinkle some sweet noexcepts over the RNG code (Pieter Wuille)
4ea8e50 Remove hwrand_initialized. (Pieter Wuille)
9d7032e Switch all RNG code to the built-in PRNG. (Pieter Wuille)
16e40a8 Integrate util/system's CInit into RNGState (Pieter Wuille)
2ccc3d3 Abstract out seeding/extracting entropy into RNGState::MixExtract (Pieter Wuille)
aae8b9b Add thread safety annotations to RNG state (Pieter Wuille)
d3f54d1 Rename some hardware RNG related functions (Pieter Wuille)
05fde14 Automatically initialize RNG on first use. (Pieter Wuille)
2d1cc50 Don't log RandAddSeedPerfmon details (Pieter Wuille)
6a57ca9 Use FRC::randbytes instead of reading >32 bytes from RNG (Pieter Wuille)

Pull request description:

  This does not remove OpenSSL, but makes our own PRNG the 'main' one; for GetStrongRandBytes, the OpenSSL RNG is still used (indirectly, by feeding its output into our PRNG state).

  It includes a few policy changes (regarding what entropy is seeded when).

  Before this PR:
  * GetRand*:
    * OpenSSL
  * GetStrongRand*:
    * CPU cycle counter
    * Perfmon data (on Windows, once 10 min)
    * /dev/urandom (or equivalent)
    * rdrand (if available)
  * From scheduler when idle:
    * CPU cycle counter before and after 1ms sleep
  * At startup:
    * CPU cycle counter before and after 1ms sleep

  After this PR:
  * GetRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
  * GetStrongRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
  * From scheduler when idle:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter before and after 1ms sleep
    * Perfmon data (on Windows, once every 10 min)
  * At startup:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
    * Perfmon data (on Windows, once every 10 min)

  The interface of random.h is also simplified, and documentation is added.

  This implements most of #14623.

Tree-SHA512: 0120e19bd4ce80a509b5c180a4f29497d299ce8242e25755880851344b825bc2d64a222bc245e659562fb5463fb7c70fbfcf003616be4dc59d0ed6534f93dd20
@fanquake fanquake removed this from Blockers in High-priority for review Jan 21, 2019
random-zebra added a commit to PIVX-Project/PIVX that referenced this issue Apr 14, 2021
cecbf6c Use secure.h header for secure allocators (Fuzzbawls)
d9f67da net: add ifaddrs.h include (fanquake)
e906436 build: check if -lsocket is required with *ifaddrs (fanquake)
414f405 rand: only try and use freeifaddrs if available (fanquake)
3a039d6 build: avoid getifaddrs when unavailable (Cory Fields)
77bddd7 Use GetStrongRandBytes in gmp bignum initialization (Fuzzbawls)
b70b26f Fix typo in comment in randomenv.cpp (Fuzzbawls)
fec460c Put bounds on the number of CPUID leaves explored (Pieter Wuille)
41ab1ff Fix CPUID subleaf iteration (Pieter Wuille)
8a9bbb1 Move events_hasher into RNGState() (Pieter Wuille)
88c2ae5 random: mark RandAddPeriodic and SeedPeriodic as noexcept (fanquake)
81d382f doc: correct random.h docs after bitcoin#17270 (fanquake)
f363ea9 Seed RNG with precision timestamps on receipt of net messages. (Matt Corallo)
7d6ddcb Run background seeding periodically instead of unpredictably (Pieter Wuille)
4679181 Add information gathered through getauxval() (Pieter Wuille)
88d97d0 Feed CPUID data into RNG (Pieter Wuille)
8f5b9c9 Use sysctl for seeding on MacOS/BSD (Pieter Wuille)
67de246 Gather additional entropy from the environment (Pieter Wuille)
6142e1f Seed randomness with process id / thread id / various clocks (Pieter Wuille)
7bde8b7 [MOVEONLY] Move cpuid code from random to compat/cpuid (Fuzzbawls)
52b5336 [MOVEONLY] Move perfmon data gathering to new randomenv module (Pieter Wuille)
27cf995 doc: minor corrections in random.cpp (fanquake)
fccd2b8 doc: correct function name in ReportHardwareRand() (fanquake)
909473e Fix FreeBSD build by including utilstrencodings.h (Fuzzbawls)
630931f break circular dependency: random/sync -> util -> random/sync (Fuzzbawls)
5eed08c random: remove call to RAND_screen() (Windows only) (fanquake)
ada9868 gui: remove OpenSSL PRNG seeding (Windows, Qt only) (fanquake)
22a7121 Fix non-deterministic coverage of test DoS_mapOrphans (Fuzzbawls)
79e7fd3 Add ChaCha20 bench (Jonas Schnelli)
6966aa9 Add ChaCha20 encryption option (XOR) (Jonas Schnelli)
28c9cdb tests: Add script checking for deterministic line coverage (practicalswift)
c82e359 test: Make bloom tests deterministic (MarcoFalke)
7b33223 Document strenghtening (Pieter Wuille)
0190dec Add hash strengthening to the RNG (Pieter Wuille)
67e336d Use RdSeed when available, and reduce RdRand load (Pieter Wuille)
4ffda1f Document RNG design in random.h (Pieter Wuille)
2b6381e Use secure allocator for RNG state (Pieter Wuille)
080deb3 Encapsulate RNGState better (Pieter Wuille)
787d72f DRY: Implement GetRand using FastRandomContext::randrange (Pieter Wuille)
5bc2583 Sprinkle some sweet noexcepts over the RNG code (Pieter Wuille)
774899f Remove hwrand_initialized. (Pieter Wuille)
698d133 Switch all RNG code to the built-in PRNG. (Pieter Wuille)
038a45a Integrate util/system's CInit into RNGState (Fuzzbawls)
5f20e62 Abstract out seeding/extracting entropy into RNGState::MixExtract (Pieter Wuille)
298f97c Add thread safety annotations to RNG state (Pieter Wuille)
2326535 Rename some hardware RNG related functions (Pieter Wuille)
d76ee83 Automatically initialize RNG on first use. (Pieter Wuille)
1a5dbc5 Don't log RandAddSeedPerfmon details (Pieter Wuille)
32e6c42 Simplify testing RNG code (Fuzzbawls)
972effa Make unit tests use the insecure_rand_ctx exclusively (Fuzzbawls)
af52bf5 Use a FastRandomContext in LimitOrphanTxSize (Fuzzbawls)
746d466 Introduce a Shuffle for FastRandomContext and use it in wallet (Fuzzbawls)
1cdf124 Use a local FastRandomContext in a few more places in net (Fuzzbawls)
e862564 Make addrman use its local RNG exclusively (Fuzzbawls)
94b2ead Make FastRandomContext support standard C++11 RNG interface (Pieter Wuille)

Pull request description:

  This is a collection of upstream PRs that have been backported to bring our RNG (`src/random`) code more up-to-date. The following upstream PRs have been included here:

  - bitcoin#12742
  - bitcoin#14624
    - some of this had already been merged previously
  - bitcoin#14955
  - bitcoin#15250
  - bitcoin#15224
  - bitcoin#15324
  - bitcoin#15296
  - bitcoin#15512
  - bitcoin#16878
  - bitcoin#17151
  - bitcoin#17191
  - bitcoin#13236
  - bitcoin#13314
  - bitcoin#17169
  - bitcoin#17270
    -  omitted last commit as our testing framework doesn't support it currently
    - omitted bitcoin@64e1e02, to be pulled in after our time utility is updated in a separate PR
  - bitcoin#17573
  - bitcoin#17507
  - bitcoin#17670
  - bitcoin#17527
  - bitcoin#14127
  - bitcoin#21486

ACKs for top commit:
  furszy:
    ACK cecbf6c with a minor nit that can be easily tackled later.
  random-zebra:
    rebase utACK cecbf6c and merging...

Tree-SHA512: 3463b693cc9bddc1ec15228d264a794f5c2f159073fafa2ccf6e2563abfeb4369e49505f97ca84f2478ca792bd07b66d2cd83c58044d6a0cae6af42d22f5784b
dzutte-cpp added a commit to dzutte-cpp/dash that referenced this issue Sep 10, 2021
223de8d Document RNG design in random.h (Pieter Wuille)
f2e60ca Use secure allocator for RNG state (Pieter Wuille)
cddb31b Encapsulate RNGState better (Pieter Wuille)
152146e DRY: Implement GetRand using FastRandomContext::randrange (Pieter Wuille)
a1f252e Sprinkle some sweet noexcepts over the RNG code (Pieter Wuille)
4ea8e50 Remove hwrand_initialized. (Pieter Wuille)
9d7032e Switch all RNG code to the built-in PRNG. (Pieter Wuille)
16e40a8 Integrate util/system's CInit into RNGState (Pieter Wuille)
2ccc3d3 Abstract out seeding/extracting entropy into RNGState::MixExtract (Pieter Wuille)
aae8b9b Add thread safety annotations to RNG state (Pieter Wuille)
d3f54d1 Rename some hardware RNG related functions (Pieter Wuille)
05fde14 Automatically initialize RNG on first use. (Pieter Wuille)
2d1cc50 Don't log RandAddSeedPerfmon details (Pieter Wuille)
6a57ca9 Use FRC::randbytes instead of reading >32 bytes from RNG (Pieter Wuille)

Pull request description:

  This does not remove OpenSSL, but makes our own PRNG the 'main' one; for GetStrongRandBytes, the OpenSSL RNG is still used (indirectly, by feeding its output into our PRNG state).

  It includes a few policy changes (regarding what entropy is seeded when).

  Before this PR:
  * GetRand*:
    * OpenSSL
  * GetStrongRand*:
    * CPU cycle counter
    * Perfmon data (on Windows, once 10 min)
    * /dev/urandom (or equivalent)
    * rdrand (if available)
  * From scheduler when idle:
    * CPU cycle counter before and after 1ms sleep
  * At startup:
    * CPU cycle counter before and after 1ms sleep

  After this PR:
  * GetRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
  * GetStrongRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
  * From scheduler when idle:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter before and after 1ms sleep
    * Perfmon data (on Windows, once every 10 min)
  * At startup:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
    * Perfmon data (on Windows, once every 10 min)

  The interface of random.h is also simplified, and documentation is added.

  This implements most of bitcoin#14623.

Tree-SHA512: 0120e19bd4ce80a509b5c180a4f29497d299ce8242e25755880851344b825bc2d64a222bc245e659562fb5463fb7c70fbfcf003616be4dc59d0ed6534f93dd20
UdjinM6 pushed a commit to dashpay/dash that referenced this issue Sep 11, 2021
223de8d Document RNG design in random.h (Pieter Wuille)
f2e60ca Use secure allocator for RNG state (Pieter Wuille)
cddb31b Encapsulate RNGState better (Pieter Wuille)
152146e DRY: Implement GetRand using FastRandomContext::randrange (Pieter Wuille)
a1f252e Sprinkle some sweet noexcepts over the RNG code (Pieter Wuille)
4ea8e50 Remove hwrand_initialized. (Pieter Wuille)
9d7032e Switch all RNG code to the built-in PRNG. (Pieter Wuille)
16e40a8 Integrate util/system's CInit into RNGState (Pieter Wuille)
2ccc3d3 Abstract out seeding/extracting entropy into RNGState::MixExtract (Pieter Wuille)
aae8b9b Add thread safety annotations to RNG state (Pieter Wuille)
d3f54d1 Rename some hardware RNG related functions (Pieter Wuille)
05fde14 Automatically initialize RNG on first use. (Pieter Wuille)
2d1cc50 Don't log RandAddSeedPerfmon details (Pieter Wuille)
6a57ca9 Use FRC::randbytes instead of reading >32 bytes from RNG (Pieter Wuille)

Pull request description:

  This does not remove OpenSSL, but makes our own PRNG the 'main' one; for GetStrongRandBytes, the OpenSSL RNG is still used (indirectly, by feeding its output into our PRNG state).

  It includes a few policy changes (regarding what entropy is seeded when).

  Before this PR:
  * GetRand*:
    * OpenSSL
  * GetStrongRand*:
    * CPU cycle counter
    * Perfmon data (on Windows, once 10 min)
    * /dev/urandom (or equivalent)
    * rdrand (if available)
  * From scheduler when idle:
    * CPU cycle counter before and after 1ms sleep
  * At startup:
    * CPU cycle counter before and after 1ms sleep

  After this PR:
  * GetRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
  * GetStrongRand*:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
  * From scheduler when idle:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter before and after 1ms sleep
    * Perfmon data (on Windows, once every 10 min)
  * At startup:
    * Stack pointer (which indirectly identifies thread and some call stack information)
    * rdrand (if available)
    * CPU cycle counter
    * /dev/urandom (or equivalent)
    * OpenSSL
    * CPU cycle counter again
    * Perfmon data (on Windows, once every 10 min)

  The interface of random.h is also simplified, and documentation is added.

  This implements most of bitcoin#14623.

Tree-SHA512: 0120e19bd4ce80a509b5c180a4f29497d299ce8242e25755880851344b825bc2d64a222bc245e659562fb5463fb7c70fbfcf003616be4dc59d0ed6534f93dd20

Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet