Add VERIFY_CHECKs and documentation that flags must be 0 or 1 #1783

pull john-moffett wants to merge 1 commits into bitcoin-core:master from john-moffett:internal_bounds_checks changing 11 files +30 −8
  1. john-moffett commented at 8:54 pm on December 9, 2025: contributor

    Flags for constant-time masking rely on the values being exactly 0 or 1 rather than 0 or true (any nonzero). One function, secp256k1_fe_cmov documents and VERIFY_CHECKs this, but most don’t.

    This updates the documentation and adds VERIFY_CHECKs enforcing flag == 0 || flag == 1 for:

    secp256k1_fe_storage_cmov secp256k1_gej_cmov secp256k1_ge_storage_cmov secp256k1_scalar_cadd_bit secp256k1_scalar_cond_negate secp256k1_scalar_cmov secp256k1_int_cmov

  2. furszy commented at 9:01 pm on December 9, 2025: member
    Wondering if it worth adding a macro for this; something like VERIFY_BOOL_ARG.
  3. real-or-random approved
  4. real-or-random commented at 10:10 am on December 10, 2025: contributor

    utACK 0a6ebe0b24c247aebfa63ccb0017d4de93e2e5a8

    If you want to touch this again: I like “flag must be 0 or 1.” because it’s so clear. It would be good to add it even to the comments in “If flag is 1…” style.

  5. real-or-random commented at 10:17 am on December 10, 2025: contributor

    Wondering if it worth adding a macro for this; something like VERIFY_BOOL_ARG.

    Weak Concept NACK for the reasons laid out in #1779. There, it was a Concept ~0, but here I deem the value below 0 because we don’t even save lines. VERIFY_BOOL_ARG(flag) is not simpler to read than VERIFY_CHECK(flag == 0 || flag == 1). If anything, it’s harder to read because it’s less explicit (unless you look up the macro).

    If we really want to improve this, then let’s switch to C99 and use bool. But I’m not sure if I really want to have this discussion. :D

    edit: Sorry, Concept NACK. I had typed “Concept ACK” first.

  6. john-moffett force-pushed on Dec 10, 2025
  7. real-or-random approved
  8. real-or-random commented at 2:18 pm on December 10, 2025: contributor
    utACK 9fa11a76eacbe4774ade813f9c25c2c348cb9086
  9. furszy commented at 3:56 pm on December 10, 2025: member

    Wondering if it worth adding a macro for this; something like VERIFY_BOOL_ARG.

    Weak Concept NACK for the reasons laid out in #1779. There, it was a Concept ~0, but here I deem the value below 0 because we don’t even save lines. VERIFY_BOOL_ARG(flag) is not simpler to read than VERIFY_CHECK(flag == 0 || flag == 1). If anything, it’s harder to read because it’s less explicit (unless you look up the macro).

    That’s probably because VERIFY_BOOL_ARG is not explicit/readable enough? My broader thought is that argument checks should come from well-named, established helpers at this point, so we don’t have to keep worrying about the raw checks in every function. We should understand what the function does just by reading its name.

    Furthermore, if you push me a bit, I’d even say we should aim for a more generic mechanism for argument validation altogether (some sort of decorator), so validating args becomes a no-brainer entirely.

    If we really want to improve this, then let’s switch to C99 and use bool. But I’m not sure if I really want to have this discussion. :D

    hehe, not planning to go that far. I just think we should focus on what actually matters and minimize the time we spend reviewing malformed input-arg checks.

  10. real-or-random commented at 7:55 am on December 11, 2025: contributor

    That’s probably because VERIFY_BOOL_ARG is not explicit/readable enough?

    It’s just that spelling out the condition, as in VERIFY_CHECK(flag == 0 || flag == 1) is, by the meaning of the word, more explicit, and it’s still short enough to be read with a single glimpse. This gives VERIFY_BOOL_ARG a tiny disadvantage because readers may need to look it up. But this is not about the name of the macro. I like the name. The name is rather explicit and probably as good as it can get.

    My broader thought is that argument checks should come from well-named, established helpers at this point, so we don’t have to keep worrying about the raw checks in every function. We should understand what the function does just by reading its name.

    Furthermore, if you push me a bit, I’d even say we should aim for a more generic mechanism for argument validation altogether (some sort of decorator), so validating args becomes a no-brainer entirely.

    This is a different direction, of course. If we had macros for almost every type (or even some more clever thing, but that seems difficult in C89), then the tiny disadvantage of VERIFY_BOOL_ARG would most likely be outweighed by the advantage of having a consistent framework. Curious to see proposals if you have something in mind!

    Still, the raw checks are mostly easy to read, and they keep the advantage of being very explicit. So I think in the current state of the code base, they make sense.

  11. furszy commented at 11:54 pm on December 14, 2025: member

    ACK 9fa11a76eacbe4774ade813f9c25c2c348cb9086

    It seems you could also do it for secp256k1_musig_secnonce_invalidate (at least the comment update).

  12. real-or-random added the label assurance on Dec 15, 2025
  13. real-or-random added the label tweak/refactor on Dec 15, 2025
  14. hebasto approved
  15. hebasto commented at 1:46 pm on December 15, 2025: member

    ACK 9fa11a76eacbe4774ade813f9c25c2c348cb9086, I have reviewed the code and it looks OK.

    We should understand what the function does just by reading its name.

    Perhaps this would be a good time to rename secp256k1_scalar_cond_negate to reflect its constant-time behaviour?

  16. Add VERIFY_CHECKs that flags are 0 or 1
    Flags for constant-time masking rely
    on the values being exactly 0 or 1 rather
    than 0 or true. Add VERIFY_CHECKs to enforce
    in VERIFY builds as a preventative
    measure and add documentation where relevant.
    ae00c552df
  17. john-moffett force-pushed on Dec 15, 2025
  18. furszy commented at 2:14 pm on December 15, 2025: member
    ACK ae00c55
  19. hebasto approved
  20. hebasto commented at 2:21 pm on December 15, 2025: member
    re-ACK ae00c552df55f4d170175903855901d640b92761.
  21. john-moffett commented at 2:22 pm on December 15, 2025: contributor
    Thank you for the reviews. @furszy thanks for the catch; I updated the docs for that function. @hebasto, my impression is that most functions don’t have their constant-time-ness included in the function name, eg - secp256k1_scalar_add, secp256k1_scalar_mul, secp256k1_scalar_cond_negate. It seems like only variable-time ones are marked as such with a _var suffix. Let me know if you had something else in mind, though.
  22. real-or-random merged this on Dec 15, 2025
  23. real-or-random closed this on Dec 15, 2025


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: 2025-12-17 18:15 UTC

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