Some simple improvements to the RNG code #14624

pull sipa wants to merge 8 commits into bitcoin:master from sipa:201810_randfast changing 16 files +134 −82
  1. sipa commented at 10:57 PM on October 31, 2018: member

    This improves a few minor issues with the RNG code:

    • Avoid calling GetRand*() functions (which currently invoke OpenSSL, later may switch to using our own RNG pool) inside loops in addrman, networking code, KnapsackSolver, and LimitOrphanSize
    • Fix a currently unreachable bug in FastRandomContext::randbytes.
    • Make a number of simplifications to the unit tests' randomness code (some tests unnecessarily used their own RNG or the OpenSSL one, instead of using the unit test specific insecure_rand_ctx).
    • As a precaution, make it illegal to copy a FastRandomContext.
  2. fanquake added the label Refactoring on Oct 31, 2018
  3. DrahtBot commented at 11:38 PM on October 31, 2018: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #14626 (Select orphan transaction uniformly for eviction by sipa)
    • #14605 (Return of the Banman by dongcarl)
    • #13462 (Simplify common case of CHashWriter and drop SerializeHash by Empact)

    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.

  4. DrahtBot cross-referenced this on Oct 31, 2018 from issue Return of the Banman by dongcarl
  5. DrahtBot cross-referenced this on Nov 1, 2018 from issue refactor: Drop boost::thread and boost::chrono by ken2812221
  6. DrahtBot cross-referenced this on Nov 1, 2018 from issue Track best-possible-headers (TheBlueMatt) by Sjors
  7. DrahtBot cross-referenced this on Nov 1, 2018 from issue validation: Document where we are intentionally ignoring bool return values from validation related functions by practicalswift
  8. DrahtBot cross-referenced this on Nov 1, 2018 from issue Make SER_GETHASH implicit for CHashWriter and SerializeHash by Empact
  9. DrahtBot cross-referenced this on Nov 1, 2018 from issue uint256: Remove unnecessary crypto/common.h dependency by kallewoof
  10. sipa force-pushed on Nov 1, 2018
  11. sipa force-pushed on Nov 1, 2018
  12. sipa force-pushed on Nov 1, 2018
  13. sipa force-pushed on Nov 1, 2018
  14. DrahtBot cross-referenced this on Nov 1, 2018 from issue Select orphan transaction uniformly for eviction by sipa
  15. sipa force-pushed on Nov 1, 2018
  16. sipa force-pushed on Nov 1, 2018
  17. in src/test/random_tests.cpp:43 in 5b7f385597 outdated
      39 | @@ -40,9 +40,9 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
      40 |      // Check that a nondeterministic ones are not
      41 |      FastRandomContext ctx3;
      42 |      FastRandomContext ctx4;
      43 | +    BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
    


    practicalswift commented at 9:58 AM on November 1, 2018:

    Should the randbytes, rand256 and rand256 tests each get their own pair of FastRandomContext:s to properly test for non-determinism? That way the ordering of the test won't matter.


    sipa commented at 5:18 PM on November 1, 2018:

    Good idea, done.

  18. practicalswift commented at 10:00 AM on November 1, 2018: contributor

    Concept ACK @sipa Regarding randbytes – very nice find! How was that issue found?

  19. practicalswift commented at 10:12 AM on November 1, 2018: contributor

    This also works around a bug in libstdc++ std::shuffle that may cause type::operator=(type&&) to be invoked on itself, which the library's debug mode detects and panics on.

    How did you trigger this? I've built with -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC in the past and haven't encountered this. I also tried now and I was unable to reproduce.

    Assuming a build with -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC – would the issue be triggered by make check or running the test suite?

    I'm running:

    $ g++ --version
    g++ (Ubuntu 7.3.0-16ubuntu3) 7.3.0
    $ dpkg -l | grep libstd
    ii  libstdc++-7-dev:amd64                                       7.3.0-16ubuntu3                   amd64        GNU Standard C++ Library v3 (development files)
    ii  libstdc++6:amd64                                            8-20180414-1ubuntu2               amd64        GNU Standard C++ Library v3
    
  20. MarcoFalke commented at 2:00 PM on November 1, 2018: member

    Travis failure:

    /bin/bash: line 1: 27706 Aborted                 (core dumped) test/test_bitcoin -l test_suite -t "`cat wallet/test/coinselector_tests.cpp | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" > wallet/test/coinselector_tests.cpp.log 2>&1
    Running 4 test cases...
    Test cases order is shuffled using seed: 1449235911
    Entering test module "Bitcoin Test Suite"
    wallet/test/coinselector_tests.cpp(17): Entering test suite "coinselector_tests"
    wallet/test/coinselector_tests.cpp(569): Entering test case "SelectCoins_test"
    wallet/test/coinselector_tests.cpp(569): Leaving test case "SelectCoins_test"; testing time: 3726243us
    wallet/test/coinselector_tests.cpp(267): Entering test case "knapsack_solver_test"
    /usr/include/c++/7/debug/safe_iterator.h:374:
    Error: attempt to advance a past-the-end iterator 1 steps, which falls 
    outside its valid range.
    Objects involved in the operation:
        iterator @ 0x0x7fff06875e20 {
          type = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<OutputGroup*, std::__cxx1998::vector<OutputGroup, std::allocator<OutputGroup> > >, std::__debug::vector<OutputGroup, std::allocator<OutputGroup> > > (mutable iterator);
          state = past-the-end;
          references sequence with type 'std::__debug::vector<OutputGroup, std::allocator<OutputGroup> >' @ 0x0x7fff068766e0
        }
    unknown location(0): fatal error: in "coinselector_tests/knapsack_solver_test": signal: SIGABRT (application abort requested)
    wallet/test/coinselector_tests.cpp(281): last checkpoint
    wallet/test/coinselector_tests.cpp(267): Leaving test case "knapsack_solver_test"; testing time: 78734us
    wallet/test/coinselector_tests.cpp(122): Entering test case "bnb_search_test"
    test_bitcoin: key.cpp:344: void ECC_Start(): Assertion `secp256k1_context_sign == nullptr' failed.
    unknown location(0): fatal error: in "coinselector_tests/bnb_search_test": signal: SIGABRT (application abort requested)
    wallet/test/coinselector_tests.cpp(122): last checkpoint: "bnb_search_test" fixture entry.
    wallet/test/coinselector_tests.cpp(122): Leaving test case "bnb_search_test"; testing time: 271us
    wallet/test/coinselector_tests.cpp(546): Entering test case "ApproximateBestSubset"
    test_bitcoin: key.cpp:344: void ECC_Start(): Assertion `secp256k1_context_sign == nullptr' failed.
    unknown location(0): fatal error: in "coinselector_tests/ApproximateBestSubset": signal: SIGABRT (application abort requested)
    wallet/test/coinselector_tests.cpp(546): last checkpoint: "ApproximateBestSubset" fixture entry.
    wallet/test/coinselector_tests.cpp(546): Leaving test case "ApproximateBestSubset"; testing time: 158us
    wallet/test/coinselector_tests.cpp(17): Leaving test suite "coinselector_tests"; testing time: 3805580us
    Leaving test module "Bitcoin Test Suite"; testing time: 3805777us
    *** 3 failures are detected in the test module "Bitcoin Test Suite"
    
  21. sipa force-pushed on Nov 1, 2018
  22. sipa force-pushed on Nov 1, 2018
  23. sipa commented at 5:18 PM on November 1, 2018: member

    @practicalswift

    @sipa Regarding randbytes – very nice find! How was that issue found?

    In a follow-up change I was working on, which replaced more use sites of GetRand* functions with FastRandomContexts. One unit test failed which tested that the leveldb obfuscation key was not all zeroes...

    How did you trigger this? I've built with -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC in the past and haven't encountered this. I also tried now and I was unable to reproduce.

    Assuming a build with -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC – would the issue be triggered by make check or running the test suite?

    Travis failed in an earlier version of this PR, in the Qt (!) unit tests. @MarcoFalke

    Travis failure:

    Fixed now.

  24. in src/random.cpp:467 in 66e69f2e93 outdated
     463 | @@ -463,6 +464,19 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
     464 |      rng.SetKey(seed.begin(), 32);
     465 |  }
     466 |  
     467 | +FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from)
    



    sipa commented at 8:47 PM on November 9, 2018:

    Done.

  25. in src/addrman.cpp:533 in 66e69f2e93 outdated
     529 | @@ -530,8 +530,8 @@ void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices)
     530 |      info.nServices = nServices;
     531 |  }
     532 |  
     533 | -int CAddrMan::RandomInt(int nMax){
     534 | -    return GetRandInt(nMax);
     535 | +int CAddrMan::RandomInt(int max){
    


    practicalswift commented at 7:18 AM on November 2, 2018:

    Use nMax to match declaration, or change declaration to max.

    Nit: Add space before { :-)


    sipa commented at 12:15 AM on November 10, 2018:

    Done, done.

  26. sipa force-pushed on Nov 9, 2018
  27. sipa force-pushed on Nov 10, 2018
  28. sipa force-pushed on Nov 10, 2018
  29. sipa force-pushed on Nov 10, 2018
  30. sipa force-pushed on Nov 10, 2018
  31. sipa force-pushed on Nov 10, 2018
  32. gmaxwell commented at 9:39 PM on November 10, 2018: contributor

    Concept ACK

  33. in src/addrman.h:270 in 0d8797b1c7 outdated
     265 | @@ -266,8 +266,8 @@ class CAddrMan
     266 |      //! Return a random to-be-evicted tried table address.
     267 |      CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
     268 |  
     269 | -    //! Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
     270 | -    virtual int RandomInt(int nMax);
     271 | +    //! Shorthand for insecure_rand.randrange()
     272 | +    int RandomInt(int range);
    


    pstratem commented at 4:49 PM on November 14, 2018:

    Is it really worth having the wrapper function if it's not a test harness?


    sipa commented at 8:22 PM on November 14, 2018:

    Good point. Got rid of it entirely.

  34. in src/random.cpp:467 in 8a652f5586 outdated
     463 | @@ -464,6 +464,20 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
     464 |      rng.SetKey(seed.begin(), 32);
     465 |  }
     466 |  
     467 | +FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept
    


    pstratem commented at 6:01 PM on November 14, 2018:

    So this is copying, but setting the original context to reseed?


    sipa commented at 8:24 PM on November 14, 2018:

    Indeed, as documented in the .h file (the state of a moved-from object must be valid but may be unspecified, as it's not supposed to be used again; choosing to set it to reseed is both fast and safe).

  35. in src/random.h:157 in 9f92a5551a outdated
     144 | +void Shuffle(I first, I last, R&& rng)
     145 | +{
     146 | +    while (first != last) {
     147 | +        size_t j = rng.randrange(last - first);
     148 | +        if (j) {
     149 | +            using std::swap;
    


    pstratem commented at 7:00 PM on November 14, 2018:

    but why the using?


    sipa commented at 8:25 PM on November 14, 2018:

    That's the suggested idiom, as it brings std::swap into scope, but also has access to possible user-defined swap implementations outside of std.

  36. pstratem changes_requested
  37. sipa force-pushed on Nov 14, 2018
  38. in src/addrman.h:473 in f997e29a24 outdated
     469 | @@ -473,7 +470,7 @@ class CAddrMan
     470 |      {
     471 |          LOCK(cs);
     472 |          std::vector<int>().swap(vRandom);
     473 | -        nKey = GetRandHash();
     474 | +        nKey = insecure_rand.rand256();
    


    MarcoFalke commented at 7:48 PM on November 16, 2018:

    nit: Might as well rename it to m_insecure_rand, since it is only used in two places previously.

  39. gmaxwell commented at 7:29 PM on November 21, 2018: contributor

    utACK

  40. sipa commented at 6:27 PM on November 30, 2018: member

    Rebased.

  41. sipa force-pushed on Nov 30, 2018
  42. MarcoFalke commented at 9:06 PM on November 30, 2018: member

    Looks like the unit tests don't pass with the thread sanitizer enabled

  43. DrahtBot added the label Needs rebase on Dec 12, 2018
  44. Make addrman use its local RNG exclusively 9695f31d75
  45. Use a local FastRandomContext in a few more places in net 8098379be5
  46. Introduce a Shuffle for FastRandomContext and use it in wallet and coinselection 3db746beb4
  47. Use a FastRandomContext in LimitOrphanTxSize 273d02580a
  48. Bugfix: randbytes should seed when needed (non reachable issue) 8d98d42611
  49. Make unit tests use the insecure_rand_ctx exclusively fd3e7973ff
  50. Simplify testing RNG code 022cf47dd7
  51. Do not permit copying FastRandomContexts e414486d56
  52. sipa force-pushed on Dec 12, 2018
  53. sipa commented at 10:32 PM on December 12, 2018: member

    Rebased.

  54. DrahtBot removed the label Needs rebase on Dec 12, 2018
  55. laanwj commented at 12:58 PM on December 13, 2018: member

    all straightforward changes utACK e414486d56b9f06af7aeb07ce13e3c3780c2b69b

  56. laanwj added the label Utils/log/libs on Dec 13, 2018
  57. laanwj merged this on Dec 13, 2018
  58. laanwj closed this on Dec 13, 2018

  59. laanwj referenced this in commit 378fdfabba on Dec 13, 2018
  60. sipa cross-referenced this on Jan 17, 2019 from issue Switch all RNG code to the built-in PRNG by sipa
  61. bitcoinhodler cross-referenced this on Apr 3, 2019 from issue Improvement suggestions from Twitter by bitcoinhodler
  62. sickpig cross-referenced this on Oct 24, 2019 from issue [port] Update BU random number generator by sickpig
  63. PastaPastaPasta referenced this in commit 4f38f5c2ef on Jan 14, 2021
  64. Fuzzbawls cross-referenced this on Mar 30, 2021 from issue [Refactor] Update RNG code from upstream by Fuzzbawls
  65. random-zebra referenced this in commit 93f43f0f81 on Apr 14, 2021
  66. practicalswift cross-referenced this on Apr 29, 2021 from issue refactor: Avoid UB in util/asmap (advance a dereferenceable iterator outside its valid range) by MarcoFalke
  67. kwvg referenced this in commit d21ef7cb06 on Jul 2, 2021
  68. kwvg referenced this in commit 29a3d5b43e on Jul 2, 2021
  69. kwvg referenced this in commit 2b6e2d7a2a on Jul 2, 2021
  70. kwvg referenced this in commit cce296678a on Jul 4, 2021
  71. kwvg referenced this in commit 2614264ceb on Jul 9, 2021
  72. kwvg referenced this in commit b3dba89364 on Jul 9, 2021
  73. kwvg referenced this in commit 7dd3e9a1ee on Jul 15, 2021
  74. kwvg referenced this in commit 0892afd07c on Jul 16, 2021
  75. PastaPastaPasta referenced this in commit b5eb262ad4 on Jul 19, 2021
  76. PastaPastaPasta referenced this in commit 9009f57e27 on Jul 20, 2021
  77. bitcoin locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-19 06:54 UTC