Use xoshiro256++ instead of RFC6979 for tests #1052

pull sipa wants to merge 2 commits into bitcoin-core:master from sipa:202112_squares_rng changing 4 files +74 −32
  1. sipa commented at 4:22 PM on December 23, 2021: contributor

    Just some easy low-hanging fruit. It's complete overkill to use the RFC6979 RNG for our test randomness. Replace it with a modern non-cryptographic RNG with good properties. It's a few % speedup for me.

    Given the internal naming of all these functions to be "testrand", I'm not concerned about the risk of someone using this for something that needs actual cryptographic randomness.

  2. sipa force-pushed on Dec 23, 2021
  3. sipa force-pushed on Dec 23, 2021
  4. in src/testrand_impl.h:24 in 5ec7ec6d08 outdated
      24 |  
      25 | -SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
      26 | -    secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16);
      27 | +SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
      28 | +    /* RNG based on https://arxiv.org/abs/2004.06278, using two separate keys, and
      29 | +     * only using odd counters to avoid entropy loss of key1. */
    


    real-or-random commented at 5:53 PM on December 23, 2021:

    It may be worth stressing in the comment that it's for tests only, for someone who runs grep RNG...


    robot-dreams commented at 7:43 PM on December 23, 2021:

    Agreed, I think it should say non-cryptographic RNG to match the comment at the start of testrand.h


    sipa commented at 4:01 PM on December 25, 2021:

    Done.

  5. elichai commented at 5:58 PM on December 23, 2021: contributor

    I'm curious why you choose this specific Rng? How does it compare to something like XoShiRo256++?

  6. in src/testrand_impl.h:151 in 5ec7ec6d08 outdated
     138 | @@ -109,7 +139,7 @@ static void secp256k1_testrand256_test(unsigned char *b32) {
     139 |  }
     140 |  
     141 |  static void secp256k1_testrand_flip(unsigned char *b, size_t len) {
     142 | -    b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_int(8));
     143 | +    b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_bits(3));
    


    robot-dreams commented at 7:53 PM on December 23, 2021:

    (Not this PR) Looks like there's lots of calls to testrand_int with a power of two; if this is indeed a nontrivial speedup, should a future PR address all of them at once?


    sipa commented at 4:21 PM on December 24, 2021:

    Done (in a separate commit).

  7. robot-dreams commented at 8:12 PM on December 23, 2021: contributor

    Concept ACK

    If tests taking a long time is an issue then I agree it's fine to use a faster but insecure sequence generator for tests. The specific choice of Squares seems a bit arbitrary but I don't have any particular reason to prefer another one.

    • What's meant by "avoid entropy loss of key1"?
    • Section 4 of the linked paper says they ran tests with increments other than one, so no problem there. However, they didn't mention anything about using two different keys: how do you know, roughly, that doing so doesn't mess up any statistical properties?
  8. sipa commented at 8:30 PM on December 23, 2021: contributor

    I just tried to insert additional entropy in the RNG because we already have a 128-bit seed. Perhaps that's overkill though, and I should use the paper's RNG unmodified.

    The reasoning is this: the existing function uses the same key variable twice. If I replace the second use with a different key, it shouldn't worsen anything. However, if the counter is even now then key1 * cnt loses (at least) one bit of entropy (multiply by even number modulo a power of 2 is not reversible), so to counter that, only use odd counters. Neither of those changes should meaningfully impact runtime.

    To be clear: my belief is that with two keys, but without only-odd counters, the result is still at least as good as the one-key version. But with only-odd counters it's somewhat better still.

  9. robot-dreams commented at 9:51 PM on December 23, 2021: contributor

    Thanks for clarifying!

    I have a slight preference for using the paper's RNG unmodified (possibly with odd counters, which is compatible with the paper), but I don't have a stronger reason than "on principle you shouldn't modify it" 🙃 so feel free to decide either way.

  10. sipa force-pushed on Dec 24, 2021
  11. sipa force-pushed on Dec 24, 2021
  12. robot-dreams commented at 2:55 PM on December 24, 2021: contributor

    First commit looks good. Nits on second commit:

    • Should commit message say secp256k1_testrand_int(2**N) -> secp256k1_testrand_bits(N) instead?
    • It looks like testrand_flip still calls testrand_int(8)

    Wait, just double checking, how much speedup did you see? Here's what I got (% = M1 Mac, # = Linux VM):

    At bcfbebe001404ce3eeb3bf3498caa5b2a6c28795 (new):

    % time ./tests
    ./tests  28.53s user 3.27s system 99% cpu 31.878 total
    
    # time ./tests
    real	1m8.177s user	1m8.050s sys	0m0.104s
    
    # time valgrind ./tests 2
    real	11m54.970s user	10m58.498s sys	0m56.142s
    

    At 09971a3ffd053816286bcffcb2f15a10f7c3c098 (old):

    % time ./tests
    ./tests  30.23s user 3.26s system 98% cpu 33.852 total
    
    # time ./tests
    real	1m7.266s user	1m7.136s sys	0m0.112s
    
    # time valgrind ./tests 2
    real	11m49.739s user	10m53.123s sys	0m56.321s
    
  13. sipa force-pushed on Dec 24, 2021
  14. sipa commented at 3:08 PM on December 24, 2021: contributor

    Made a few changes:

    • Added a separate commit that does testrand_int(2^N) -> testrand_bits(N) replacements
    • Added a "Test-only" comment to the testrand32 implementation (the testrand.h file already mentioned this FWIW).
    • Switched to "pure" Squares rand, with 64-bit seed. Also dropped the (cnt += 2), because the one-key version has no entropy loss with even cnt. @elichai No good reason. I just googled for fast PRNGs. It has good randomness properties, and the counter-based design clearly has a 2^64 cycle, which should be enough. @robot-dreams

    On my Ryzen 5950X system, GCC 11.2.0, default config, ./tests:

    • Old: 0m36.216s
    • New: 0m34.689s
  15. in src/testrand_impl.h:145 in 6ee0f009ae outdated
     155 | -            seed16[4] ^= t >> 32;
     156 | -            seed16[5] ^= t >> 40;
     157 | -            seed16[6] ^= t >> 48;
     158 | -            seed16[7] ^= t >> 56;
     159 | +        if (frand == NULL || fread(&seed8, 1, sizeof(seed8), frand) != sizeof(seed8)) {
     160 | +            fprintf(stderr, "WARNING: could not read 8 bytes from /dev/urandom; falling back to insecure PRNG\n");
    


    robot-dreams commented at 3:15 PM on December 24, 2021:

    Nit: "falling back to time-based seed" since it's always an insecure PRNG?

  16. robot-dreams commented at 3:23 PM on December 24, 2021: contributor

    ACK 6ee0f009ae4026aabf7bde654c1a18f940f9b4ea

  17. secp256k1_testrand_int(2**N) -> secp256k1_testrand_bits(N) 5f2efe684e
  18. Use xoshiro256++ PRNG instead of RFC6979 in tests 77a19750b4
  19. sipa force-pushed on Dec 24, 2021
  20. sipa commented at 4:20 PM on December 24, 2021: contributor

    Changed to using xoshiro256++. It's even (slightly) faster now, in my benchmarks.

    Sorry for the many changes, I suspect I'm done now.

  21. sipa renamed this:
    Use Squares RNG instead of RFC6979 for tests
    Use xoshiro256++ instead of RFC6979 for tests
    on Dec 24, 2021
  22. real-or-random approved
  23. real-or-random commented at 10:50 PM on December 24, 2021: contributor

    utACK 77a19750b46916b93bb6a08837c26f585bd940fa

  24. real-or-random commented at 10:50 PM on December 24, 2021: contributor

    Changed to using xoshiro256++. It's even (slightly) faster now, in my benchmarks.

    and still trivial to review given https://prng.di.unimi.it/xoshiro256plusplus.c :)

  25. robot-dreams commented at 4:36 PM on December 25, 2021: contributor

    ACK 77a19750b46916b93bb6a08837c26f585bd940fa

    and still trivial to review given https://prng.di.unimi.it/xoshiro256plusplus.c :)

    Yes :)

    Timing (n=1 sample size) are indeed slightly faster than before:

    % time ./tests
    ./tests  28.31s user 3.28s system 99% cpu 31.766 total
    
    # time ./tests
    real	1m3.644s user	1m3.485s sys	0m0.140s
    
    # time valgrind ./tests 2
    real	11m21.063s user	10m25.844s sys	0m54.987s
    
  26. real-or-random merged this on Dec 25, 2021
  27. real-or-random closed this on Dec 25, 2021

  28. elichai commented at 9:26 PM on December 25, 2021: contributor

    Post-Merge code review ACK 77a19750b46916b93bb6a08837c26f585bd940fa

  29. jonasnick cross-referenced this on Jan 2, 2022 from issue Sync Upstream by jonasnick
  30. real-or-random referenced this in commit 21e2d65b79 on Jan 5, 2022
  31. dhruv referenced this in commit 6f7e395acc on Jan 26, 2022
  32. hebasto referenced this in commit 065b6dbf9d on Jan 30, 2022
  33. dhruv referenced this in commit 139d4b881e on Feb 1, 2022
  34. fanquake referenced this in commit 8f8631d826 on Mar 17, 2022
  35. fanquake referenced this in commit 4bb1d7e62a on Mar 17, 2022
  36. fanquake referenced this in commit 465d05253a on Mar 30, 2022
  37. stratospher referenced this in commit 4d5afc9767 on Apr 3, 2022
  38. stratospher referenced this in commit 5b18493cfa on Apr 3, 2022
  39. fanquake referenced this in commit afb7a6fe06 on Apr 6, 2022
  40. gwillen referenced this in commit 35d6112a72 on May 25, 2022
  41. patricklodder referenced this in commit 21badcf9d2 on Jul 25, 2022
  42. patricklodder referenced this in commit 03002a9013 on Jul 28, 2022
  43. janus referenced this in commit 3a0652a777 on Aug 4, 2022
  44. str4d referenced this in commit 522190d5c3 on Apr 21, 2023
  45. vmta referenced this in commit e1120c94a1 on Jun 4, 2023
  46. vmta referenced this in commit 8f03457eed on Jul 1, 2023

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-14 11:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me