Policy for VERIFY_CHECK and #ifdef VERIFY #1381

issue real-or-random openend this issue on July 24, 2023
  1. real-or-random commented at 9:08 am on July 24, 2023: contributor

    Current situation

    The purpose of VERIFY_CHECK(cond) is to assert cond in test builds, i.e., when VERIFY is defined. While cond is supposed to have no side effects, VERIFY_CHECK will evaluate it even in production builds, to make sure that no side effects are masked in production builds.

    In the case of simple cond, we can rely on the ability of the compiler to detect that cond has no side effects and to omit its evaluation entirely. However, many recently introduced cond are neither simple nor have negligible computation costs. In this case, we usually wrap VERIFY_CHECK(cond) in an #ifdef VERIFY block, which forces the evaluation to be omitted in production, at the cost of foregoing the aforementioned “side-effect safety” of VERIFY_CHECK. [1]

    On top of this, we now have (full) functions like secp256k1_fe_verify, which internally perform VERIFY_CHECKs.

    I don’t think anything we currently do is wrong, but sometimes the borders are a bit arbitrary, and with a mix of #ifdef VERIFY and no #ifdef VERIFY, and a mix of uppercase and lowercase, also readability and consistency suffer.

    Options

    When it comes to forcing evaluations to be omitted, we can either keep the current convention and force omitting on a case-by-case basis. Alternatively, we could just always force omitting, e.g., by defining VERIFY_CHECK to be empty in production. That will keep things simple and save us the decision of whether to force omitting. The comment in #904 (comment) appears to agree with this.

    When it comes to readability, I think that #ifdef blocks tend to clutter the code. If we redefine VERIFY_CHECK to be empty in production, we could omit many #ifdef lines. Even if we keep two types of VERIFY_CHECKs, I suggest introducing a separate macro instead to replace #ifdef.

    One remaining purpose of the #ifdefs is to highlight the test code blocks, e.g., when we call secp256k1_fe_verify in field_impl.h. But then we could just make these function names uppercase. And if we want blocks/grouping for better readability, we can simply use empty lines instead of #ifdef lines.

    So I suggest

    • redefining VERIFY_CHECK to be empty in production
    • renaming _check functions to uppercase.

    And while we’re touching this anyway, we could consider renaming “check” to “assert”, which is a more precise term. (In fact, if we redefine VERIFY_CHECK to be empty in production, we have almost reimplemented assert.h…)

    Does this make sense?


    [1] One idea was to improve this situation was to introduce a C hack that will tell us whether a compiler is able to determine that a check has no side effects, but I agree with #904 (comment) that this is not the way to go. In addition to the points brought up by @sipa, relying on the compiler is just very brittle, with optimizations depending on compiler versions and flags.

  2. real-or-random added the label assurance on Jul 24, 2023
  3. real-or-random added the label refactor/smell on Jul 24, 2023
  4. real-or-random cross-referenced this on Jul 24, 2023 from issue tighten group magnitude limits, save normalize_weak calls in group add methods (revival of #1032) by theStack
  5. jonasnick commented at 7:29 am on July 26, 2023: contributor
    Adding to the current situation is that VERIFY_CHECK is not side-effect safe when built with --enable-coverage which lead to bugs in coverage mode in the past. In fact, there are again unused variable warnings right now when compiling master with --enable-coverage. So an additional advantage of your suggestion is that VERIFY_CHECK in coverage mode isn’t special anymore which would hopefully reduce maintenance of that mode.
  6. sipa commented at 3:23 pm on July 26, 2023: contributor

    Agree, I think we should make VERIFY_CHECK compile to nothing in non-VERIFY mode. It was worthwhile to aim for side-effect freeness, but the way to codebase has evolved I believe makes the benefit not worth the cost. As pointed out in #904, the benefit is effectively restricted already to the simplest cases, where arguably it doesn’t matter much anyway.

    I wouldn’t actually rename the verify_ functions to be upper case, but instead leave them as lowercase functions, but with an uppercase macro around them (maybe one that also compiles to nothing in non-VERIFY mode, so that not even a dummy verify_ function is needed in that case). This is just for style reasons - I think it’s good that a reader can guess what is a function and what is a macro just on the name.

  7. real-or-random commented at 1:17 pm on August 3, 2023: contributor

    I wouldn’t actually rename the verify_ functions to be upper case, but instead leave them as lowercase functions, but with an uppercase macro around them […]

    Sounds good to me. @theStack Are you interested to look into this by any chance?

  8. theStack commented at 7:01 pm on August 3, 2023: contributor

    I wouldn’t actually rename the verify_ functions to be upper case, but instead leave them as lowercase functions, but with an uppercase macro around them […]

    Sounds good to me.

    @theStack Are you interested to look into this by any chance?

    Yes, planning to tackle this within the next days.

  9. theStack referenced this in commit e8126c9c4a on Aug 4, 2023
  10. theStack cross-referenced this on Aug 4, 2023 from issue Implement new policy for VERIFY_CHECK and #ifdef VERIFY (issue #1381) by theStack
  11. theStack referenced this in commit 79e9bcf463 on Aug 16, 2023
  12. theStack referenced this in commit 5bb45804af on Aug 18, 2023
  13. theStack referenced this in commit c723b85285 on Sep 21, 2023
  14. theStack referenced this in commit c2688f8de9 on Dec 1, 2023
  15. real-or-random referenced this in commit 07687e811d on Dec 1, 2023
  16. real-or-random closed this on Dec 1, 2023

  17. real-or-random commented at 12:09 pm on December 1, 2023: contributor
    This is done, except for the potential renaming to “assert”, which is now tracked in #1449.
  18. real-or-random cross-referenced this on Dec 1, 2023 from issue Prefix all macros with SECP256K1_ by real-or-random

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: 2024-12-21 17:15 UTC

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