Getter secp256k1_get_hash_context
The long getter name still looks a bit weird to me. It makes it hard for the eye to parse lines such as this:
0secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, seckey32, 32);
I admit I contributed to this by suggesting that the hash context object should go first. After reconsidering this, I prefer what we do for the ecmult_gen context:
0secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]);
In fact, there are a few calls that just read ctx instead of &ctx->ecmult_gen_ctx. These are certainly code smells because they rely on the order of members in the struct….
In a potential follow-up PR, we could make the way of getting the subcontext consistent across ecmult_gen and hash consistent and also solve these smells. As said above, I’d prefer &ctx->... which is short, and direct accesses to field members are not uncommon in C. The setters still make sense because they validate the args. I don’t insist on that solution, but I think we should at least make it consistent across modules.
An entirely different option will be to pass just ctx and do the unfolding only inside the hash and ecmult_gen modules. But perhaps this makes testing and other stuff harder: now you’ll need a full context to call these functions.
Self-test
I’m not entirely happy with what this PR does to the selftest module. (Again, the current code may have been based on my previous feedback – sorry, if that’s the case.)
At first glance, it feels a bit weird that the API call secp256k1_selftest now uses the built-in implementation even if the caller has set an override. This may be a questionable scenario anyway (secp256k1_selftest is there only for the static context), but nothing in the API says you can’t call it with a proper context. And if you think about it, the behavior in this PR actually makes sense: The docs of secp256k1_selftest say that this function checks for wrong endianness builds, etc., so we probably want to always use the built-in SHA256 implementation in the self-test.
But with that in mind, the function secp256k1_selftest_sha256 should live in the hash module (perhaps with the name secp256k1_sha256_selftest, and the selftest module should call it deliberately (i.e., with an explanatory comment) with the built-in hash implementation.
edit: This may also be an opportunity to split selftest module in selftest.h and selftest_impl.h like every other module.
edit edit: Or get rid of it if only one function remains left in there…
Originally posted by @real-or-random in #1777 (comment)