benchmarks: fix bench_scalar_split #1172

pull jonasnick wants to merge 3 commits into bitcoin-core:master from jonasnick:fix-bench-verify changing 4 files +14 −7
  1. jonasnick commented at 11:24 PM on December 9, 2022: contributor

    scalar_split_lambda requires that the input pointer is different to both output pointers. Without this fix, the internal benchmarks crash when compiled with -DVERIFY.

    This was introduced in commit https://github.com/bitcoin-core/secp256k1/commit/362bb25608dbcd724a07dd5170c4ebe081c3dd84 (which requires configuring with --enable-endomorphism to exhibit the crash).

    I tested that the new CI job would have caught this bug.

  2. jonasnick commented at 11:48 PM on December 9, 2022: contributor

    The new CI job is failing. Looks like the ctime_test doesn't like being compiled with VERIFY.

  3. jonasnick force-pushed on Dec 10, 2022
  4. real-or-random commented at 8:40 AM on December 20, 2022: contributor

    Concept ACK

    We have the VERIFY_CHECKs in secp256k1_scalar_split_lambda already but I think this can be documented better. Can you add restrict to the pointers in secp256k1_scalar_split_lambda, or alternatively add a comment to the function?

    And can you add the same VERIFY_CHECKs to the exhaustive test variant of secp256k1_scalar_split_lambda. The code there has similar aliasing problems (though it's not a big deal in the end because the result of this function is anyway arbitrary in the exhaustive tests...)

  5. jonasnick commented at 4:29 PM on January 3, 2023: contributor

    I added better documentation and the same VERIFY_CHECKs to the exhaustive test variant of secp256k1_scalar_split_lambda.

  6. in src/scalar_impl.h:82 in 95fe2151cd outdated
      73 | @@ -71,6 +74,14 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con
      74 |  #endif
      75 |  
      76 |  /*
      77 | + * The function below splits k into r1 and r2, such that
      78 | + * - r1 + lambda * r2 == k (mod n)
      79 | + * - either r1 < 2^128 or -r1 mod n < 2^128
      80 | + * - either r2 < 2^128 or -r2 mod n < 2^128
      81 | + *
      82 | + * It is required that `r1`, `r2`, and `k` all point to different objects. An
    


    real-or-random commented at 4:30 PM on January 3, 2023:

    nit: I think this should be documented in scalar.h instead.


    jonasnick commented at 11:22 AM on January 4, 2023:

    Thanks. I totally missed the declaration there. Fixed.

  7. jonasnick force-pushed on Jan 4, 2023
  8. real-or-random approved
  9. real-or-random commented at 12:35 PM on January 4, 2023: contributor

    utACK e9a3d3f35dc4e0ba3124d34e4885373d927a3a39

  10. benchmarks: fix bench_scalar_split
    scalar_split_lambda requires that the input pointer is different to both output
    pointers. Without this fix, the internal benchmarks crash when compiled with
    -DVERIFY.
    
    This was introduced in commit 362bb25608dbcd724a07dd5170c4ebe081c3dd84 (which
    requires configuring with --enable-endomorphism to exhibit the crash).
    620ba3d74b
  11. in src/scalar.h:93 in e9a3d3f35d outdated
      91 | @@ -92,8 +92,9 @@ static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar
      92 |  
      93 |  /** Find r1 and r2 such that r1+r2*2^128 = k. */
      94 |  static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
      95 | -/** Find r1 and r2 such that r1+r2*lambda = k,
      96 | - * where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */
      97 | +/** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their
      98 | + *  negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). It is
      99 | + *  required that r1, r2, and k all point to different objects. */
    


    sipa commented at 9:59 PM on January 10, 2023:

    Add SECP256K1_RESTRICTs to the function declaration (allowing the compiler to complain about incorrect usage statically).


    real-or-random commented at 9:20 AM on January 11, 2023:

    Fwiw, I had discussed this with @jonasnick somewhere else.

    TL;DR: The promise you give by restrict is more involved than we assumed.

    He had tried just restrict k but that it turns out that doesn't change anything at all (and the compiler won't complain about incorrect usage), because *k is not modified in the function. After looking up the standard and other explanation, at least I was pretty convinced that restrict r1, restrict r2, restrict k is correct and meaningful, but @jonasnick preferred not to use it to keep things simple (which is a reasonable conclusion, I think).

    The best simple but precise explanation we found is this:

    The restrict modifier means that the compiler can assume that the object to which that pointer points either is not modified or is not referenced in any other way in the function. If the object is modified, then all access to that object must be done through that pointer. (https://www.reddit.com/r/C_Programming/comments/1xqf90/comment/cfdoon2/?context=3)

    I wasn't aware about the "modified" part at all, I had assumed restrict has only to do with references.


    sipa commented at 9:14 PM on January 11, 2023:

    Yes, restrict r1, restrict r2, restrict k is what I'd have suggested is added. I don't really see the downside, as it seems exactly what we want to convey? These pointers are the only pointers to their respective objects, and the objects pointed to are not modified through any other mechanism.


    real-or-random commented at 9:39 AM on January 12, 2023:

    Fwiw, I'm happy to ACK either solution.


    jonasnick commented at 5:54 PM on January 19, 2023:

    As far as I can see, if restrict is added and there's a violation (some pointers point to the same object), then

    VERIFY_CHECK(r1 != k);
    VERIFY_CHECK(r2 != k);
    VERIFY_CHECK(r1 != r2);
    

    may not actually abort the program because we told the compiler that these conditions will never happen. It's not guaranteed that the compiler will be able to determine that violation statically and warn us about it. On the other hand, if we don't add restrict then the VERIFY_CHECKs will always (in the tests) find violations of the function's contract.


    sipa commented at 5:56 PM on January 19, 2023:

    That's why SECP256K1_RESTRICT is #define'd as nothing in VERIFY mode.


    jonasnick commented at 6:04 PM on January 19, 2023:

    Great, then I don't see a downside either!


    jonasnick commented at 6:15 PM on January 19, 2023:

    Ok, I added the restricts.

  12. jonasnick force-pushed on Jan 19, 2023
  13. sipa commented at 7:48 PM on January 19, 2023: contributor

    CI seems unhappy here with asm=no for valgrind-based ctime_tests, though I can't reproduce it...

  14. ci: add test job with -DVERIFY
    This detects benchmarks that crash when VERIFY is defined.
    7f49aa7f2d
  15. scalar: restrict split_lambda args, improve doc and VERIFY_CHECKs
    VERIFY_CHECK(r1 != r2) is added because otherwise the verify_scalar_split fails.
    eb6bebaee3
  16. jonasnick force-pushed on Jan 19, 2023
  17. jonasnick commented at 9:19 PM on January 19, 2023: contributor

    Should be fixed now. I missed the CTIMETEST -> CTIMETESTS rename when rebasing. (I was able to reproduce this issue by copying the print_environment output of cirrus.sh. So seems like the PR that added this did indeed end up being useful)

  18. real-or-random approved
  19. real-or-random commented at 9:23 PM on January 19, 2023: contributor

    utACK eb6bebaee3947f8bca46816fa6bf6182085f1b56

  20. sipa commented at 10:40 PM on January 19, 2023: contributor

    utACK eb6bebaee3947f8bca46816fa6bf6182085f1b56

  21. sipa merged this on Jan 19, 2023
  22. sipa closed this on Jan 19, 2023

  23. dhruv referenced this in commit 4d33046ce3 on Feb 1, 2023
  24. dhruv referenced this in commit 55e7f2cf2b on Feb 2, 2023
  25. stratospher referenced this in commit 647f63669e on Feb 6, 2023
  26. dhruv referenced this in commit a4351c0df6 on Feb 20, 2023
  27. stratospher referenced this in commit 23f825fc8b on Feb 21, 2023
  28. hebasto referenced this in commit 7c0cc5d976 on Mar 7, 2023
  29. dhruv referenced this in commit a5df79db12 on Mar 7, 2023
  30. dhruv referenced this in commit 77b510d84c on Mar 7, 2023
  31. sipa referenced this in commit 763079a3f1 on Mar 8, 2023
  32. div72 referenced this in commit 945b094575 on Mar 14, 2023
  33. vmta referenced this in commit e1120c94a1 on Jun 4, 2023
  34. 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-18 19:15 UTC

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