-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Policy for VERIFY_CHECK and #ifdef VERIFY #1381
Comments
Adding to the current situation is that VERIFY_CHECK is not side-effect safe when built with |
Agree, I think we should make I wouldn't actually rename the |
Sounds good to me. @theStack Are you interested to look into this by any chance? |
Yes, planning to tackle this within the next days. |
As suggested in issue bitcoin-core#1381, this will make things simpler and improve code readability, as we don't need to force omitting of evaluations on a case-by-case basis anymore and hence can remove lots of `#ifdef VERIFY`/`#endif` lines (see next commit). Plus, VERIFY_CHECK behaves now identical in both non-VERIFY and coverage mode, making the latter not special anymore and hopefully decreasing maintenance burden. The idea of "side-effect safety" is given up. Note that at two places in the ellswift module void-casts of return values have to be inserted for non-VERIFY builds, in order to avoid "variable ... set but not used [-Wunused-but-set-variable]" warnings.
As suggested in issue bitcoin-core#1381, this will make things simpler and improve code readability, as we don't need to force omitting of evaluations on a case-by-case basis anymore and hence can remove lots of `#ifdef VERIFY`/`#endif` lines (see next commit). Plus, VERIFY_CHECK behaves now identical in both non-VERIFY and coverage mode, making the latter not special anymore and hopefully decreasing maintenance burden. The idea of "side-effect safety" is given up. Note that at two places in the ellswift module void-casts of return values have to be inserted for non-VERIFY builds, in order to avoid "variable ... set but not used [-Wunused-but-set-variable]" warnings.
As suggested in issue bitcoin-core#1381, this will make things simpler and improve code readability, as we don't need to force omitting of evaluations on a case-by-case basis anymore and hence can remove lots of `#ifdef VERIFY`/`#endif` lines (see next commit). Plus, VERIFY_CHECK behaves now identical in both non-VERIFY and coverage mode, making the latter not special anymore and hopefully decreasing maintenance burden. The idea of "side-effect safety" is given up. Note that at two places in the ellswift module void-casts of return values have to be inserted for non-VERIFY builds, in order to avoid "variable ... set but not used [-Wunused-but-set-variable]" warnings.
As suggested in issue bitcoin-core#1381, this will make things simpler and improve code readability, as we don't need to force omitting of evaluations on a case-by-case basis anymore and hence can remove lots of `#ifdef VERIFY`/`#endif` lines (see next commit). Plus, VERIFY_CHECK behaves now identical in both non-VERIFY and coverage mode, making the latter not special anymore and hopefully decreasing maintenance burden. The idea of "side-effect safety" is given up. Note that at two places in the ellswift module void-casts of return values have to be inserted for non-VERIFY builds, in order to avoid "variable ... set but not used [-Wunused-but-set-variable]" warnings.
As suggested in issue bitcoin-core#1381, this will make things simpler and improve code readability, as we don't need to force omitting of evaluations on a case-by-case basis anymore and hence can remove lots of `#ifdef VERIFY`/`#endif` lines (see next commit). Plus, VERIFY_CHECK behaves now identical in both non-VERIFY and coverage mode, making the latter not special anymore and hopefully decreasing maintenance burden. The idea of "side-effect safety" is given up. Note that at two places in the ellswift module void-casts of return values have to be inserted for non-VERIFY builds, in order to avoid "variable ... set but not used [-Wunused-but-set-variable]" warnings.
…(issue #1381) bb46723 remove VERIFY_SETUP define (Sebastian Falbesoner) a3a3e11 remove unneeded VERIFY_SETUP uses in ECMULT_CONST_TABLE_GET_GE macro (Sebastian Falbesoner) a0fb68a introduce and use SECP256K1_SCALAR_VERIFY macro (Sebastian Falbesoner) cf25c86 introduce and use SECP256K1_{FE,GE,GEJ}_VERIFY macros (Sebastian Falbesoner) 5d89bc0 remove superfluous `#ifdef VERIFY`/`#endif` preprocessor conditions (Sebastian Falbesoner) c2688f8 redefine VERIFY_CHECK to empty in production (non-VERIFY) mode (Sebastian Falbesoner) Pull request description: As suggested in #1381, this PR reworks the policy for VERIFY_CHECK and when to use #ifdef VERIFY, by: - redefining VERIFY_CHECK to empty in production (non-VERIFY) mode - removing many then superflous #ifdef VERIFY blocks (if they exclusively contained VERIFY_CHECKs) - introducing uppercase macros around verify_ functions and using them for better readabiliy What is _not_ included yet is the proposed renaming from "_check" to "_assert": > 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...) This should be easy to achieve with simple search-and-replace (e.g. using sed), but I was hesitant as this would probably case annoying merge conflicts on some of the open PRs. Happy to add this if the rename if desired (#1381 didn't get any feedback about the renaming idea yet). ACKs for top commit: stratospher: ACK bb46723. real-or-random: utACK bb46723 Tree-SHA512: 226ca609926dea638aa3bb537d29d4fac8b8302dcd9da35acf767ba9573e5221d2dae04ea26c15d80a50ed70af1ab0dca10642c21df7dbdda432fa237a5ef2cc
This is done, except for the potential renaming to "assert", which is now tracked in #1449. |
Current situation
The purpose of
VERIFY_CHECK(cond)
is to assertcond
in test builds, i.e., whenVERIFY
is defined. Whilecond
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 thatcond
has no side effects and to omit its evaluation entirely. However, many recently introducedcond
are neither simple nor have negligible computation costs. In this case, we usually wrapVERIFY_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" ofVERIFY_CHECK
. [1]On top of this, we now have (full) functions like
secp256k1_fe_verify
, which internally performVERIFY_CHECK
s.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 redefineVERIFY_CHECK
to be empty in production, we could omit many#ifdef
lines. Even if we keep two types ofVERIFY_CHECK
s, I suggest introducing a separate macro instead to replace#ifdef
.One remaining purpose of the
#ifdef
s is to highlight the test code blocks, e.g., when we callsecp256k1_fe_verify
infield_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
VERIFY_CHECK
to be empty in production_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 reimplementedassert.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.The text was updated successfully, but these errors were encountered: