Make SHA256 compression runtime pluggable#1777
Make SHA256 compression runtime pluggable#1777real-or-random merged 3 commits intobitcoin-core:masterfrom
Conversation
16cd02b to
7fefa9c
Compare
|
I guess this is more of a draft for initial review but I will spell it out anyway: It's currently missing some CI coverage for building with an external library as well as some docs. Curious what people think in terms of docs for something like this: Should there be extensive guidance in which context this is safe to use or would users be left on their own to try it out? Or are we assuming all users that go to this length are competent enough to judge if it's a good idea to bring their own sha256 or use the systems one? |
|
Thanks for the feedback fjahr!
Yeah, can create a CI job testing the compile-time pluggable compression function very easily. Thanks for reminding that. And about the missing docs; yeah. I didn't add it because we currently don't have much documentation outside
It’s not that we’re letting people plug in whatever they want. Both introduced features have guardrails:
So you can bring your own compression function, but it still has to prove it behaves exactly like ours bit-for-bit. Also, the target user here is someone who's actually written a hardware-optimized SHA256. It’s not like they stumbled into this by accident. |
real-or-random
left a comment
There was a problem hiding this comment.
Concept ACK, great to see a PR for this!
configure.ac
Outdated
| ### Define config arguments | ||
| ### | ||
|
|
||
| AC_ARG_WITH([external-sha256], |
There was a problem hiding this comment.
nit: I think this one should also be an enable-style configure option instead of a with-style configure options; with is for compiling with external packages e.g., with-libxyz. And what the user provides here is not a package.
7fefa9c to
3683e07
Compare
furszy
left a comment
There was a problem hiding this comment.
Update pushed, thanks for the deep review real_or_random!
I haven’t fully finished addressing all the comments yet, but I'll hopefully finish tomorrow. So many good topics.
|
A few high-level comments:
|
furszy
left a comment
There was a problem hiding this comment.
Per feedback, this is how it would look if we pass the function everywhere furszy@8149fc1 vs how it looks when the function lives in the sha256 struct (an updated version of what we currently have here): furszy@eb57082
Let me know what you guys think.
|
@furszy From a quick glance, the passing of the function everywhere is fine I think. I'd suggest passing a pointer to |
3683e07 to
2413e92
Compare
There was a problem hiding this comment.
Updated per feedback. We now pass the hash context to all functions that need it, without storing any state inside the sha256 struct. The API arg "rounds" has also been renamed to "blocks" to prevent confusion with existing terms. Also, the commit introducing the compile-time feature has been removed for inclusion at a later stage (see #1777 (comment) for more details).
This comment was marked as outdated.
This comment was marked as outdated.
2413e92 to
041a621
Compare
This comment was marked as outdated.
This comment was marked as outdated.
041a621 to
fd7bf49
Compare
|
Updated per feedback. Thanks @real-or-random! |
fd7bf49 to
8b45a8f
Compare
real-or-random
left a comment
There was a problem hiding this comment.
two nits on the last commit (I like that one!)
656c7cc sync-upstream: Clarify that we merge a *single* upstream ref (Tim Ruffing) 349a94b sync-upstream: Remove "select" mode and simplify (Tim Ruffing) Pull request description: Please see individual commit messages for details. --- Here's an example session that shows why `select` doesn't make sense: ``` ### Let's find some PRs to sync (master is at 5a67b63) ❯ ./contrib/sync-upstream.sh -b master range Merging b9cb1cb 1aafe15 . Continue with y n ### Let's look at them in the order they have been merged ❯ git show b9cb1cb commit b9cb1cb Merge: c0a2aba 921b971 Author: merge-script <me@real-or-random.org> Date: Tue Mar 3 15:31:46 2026 +0100 Merge bitcoin-core/secp256k1#1824: util: introduce and use `ARRAY_SIZE` macro [...] ❯ git --no-pager show 1aafe15 commit 1aafe15 (upstream/master, upstream/HEAD) Merge: b9cb1cb 4d92a08 Author: merge-script <me@real-or-random.org> Date: Wed Mar 4 08:43:07 2026 +0100 Merge bitcoin-core/secp256k1#1777: Make SHA256 compression runtime pluggable [...] ### Let's assume I want to cherry-pick 1aafe15 but not sync b9cb1bcf ❯ ./contrib/sync-upstream.sh -b master select 1aafe15 ----------------------------------- Upstream PRs 1777 ----------------------------------- [bitcoin-core/secp256k1#1777]: Make SHA256 compression runtime pluggable This PR can be recreated with `./contrib/sync-upstream.sh -b master select 1aafe15`. [...] ### Let's check if it's really only PR #1777 ❯ git diff | grep ARRAY_SIZE + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ### Ah damn, we also got the other PR #1824... ``` ACKs for top commit: mllwchrry: ACK 656c7cc jonasnick: ACK 656c7cc Tree-SHA512: 27cdfe7c6decce840ef4f2d12fa0a5fd829b35ac24403272c4b34c0a3b0da2303cee36bcb419d0608c6b1297fd5bf8a6cd6d41672850ac092814c140638f9d83
1aafe15139 Merge bitcoin-core/secp256k1#1777: Make SHA256 compression runtime pluggable b9cb1cbfd7 Merge bitcoin-core/secp256k1#1824: util: introduce and use `ARRAY_SIZE` macro 4d92a083bc sha256: speed up writes using multi-block compression 0753f8b909 Add API to override SHA256 compression at runtime fdb6a91a5e Introduce hash context to support pluggable SHA256 compression c0a2aba088 Merge bitcoin-core/secp256k1#1811: bench: Update help functions in bench and bench_internal 10f546a2c0 Merge bitcoin-core/secp256k1#1832: testrand: Remove testrand_finish 8d0eda07e9 testrand: Remove testrand_finish 95e6815843 Merge bitcoin-core/secp256k1#1825: hash: remove redundant `secp256k1_sha256_initialize` in tagged hash midstate functions f48b1bfa5d hash: add midstate initializer and use it for tagged hashes 3019186a6d Merge bitcoin-core/secp256k1#1829: ci: Fix leftover use of old ECMULTGENPRECISION 79e9f25237 ci: Fix leftover use of old ECMULTGENPRECISION dfe042feb2 Merge bitcoin-core/secp256k1#1828: Revert "ci, docker: Fix LLVM repository signature failure" 76e92cfeea Revert "ci, docker: Fix LLVM repository signature failure" ac561601b8 Merge bitcoin-core/secp256k1#1760: cmake: Add dynamic test discovery to improve parallelism c7a7f732bd Merge bitcoin-core/secp256k1#1821: ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 921b9711ea util: introduce and use `ARRAY_SIZE` macro b99a94c382 Add tests for bad scalar inputs in ellswift XDH 307b49f1b9 ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 322d0a4358 Merge bitcoin-core/secp256k1#1823: ci: Load Docker image by ID from builder step ed02466d3f ci: Load Docker image by ID from builder step c49c9be504 bench: Update help functions in bench and bench_internal 1d146ac3ed Merge bitcoin-core/secp256k1#1819: tests: Improve secp256k1_scalar_check_overflow tests (Issue bitcoin#1812) f47bbc07f0 test: add unit tests for secp256k1_scalar_check_overflow d071aa56d5 Merge bitcoin-core/secp256k1#1815: refactor: remove unnecessary `malloc` result casts 99ab4a105e Merge bitcoin-core/secp256k1#1817: ci: Disable Docker build summary generation c5da3bde9c Merge bitcoin-core/secp256k1#1818: ci: Enforce base-10 evaluation 97de5120cf Merge bitcoin-core/secp256k1#1804: test: show both CMake and Autotools usage for ctime_tests 4fb7ccf5d4 ci: Enforce base-10 evaluation 3ae72e7867 ci: Disable Docker build summary generation 97b3c47849 refactor: remove unnecessary `malloc` result casts 1bc74a22f8 test: show both Autotools and CMake usage for ctime_tests 8354618e02 cmake: Set `LABELS` property for tests 29f26ec3cf cmake: Integrate DiscoverTests and normalize test names f95b263f23 cmake: Add DiscoverTests module 4ac651144b cmake, refactor: Deduplicate test-related code git-subtree-dir: src/secp256k1 git-subtree-split: 1aafe15139976b0142d791aaf4963de3fc1ff736
…ath spends d339884 bench: add script verification benchmark for P2TR key path spends (Sebastian Falbesoner) dd93362 bench: simplify script verification benchmark, generalize signing (Sebastian Falbesoner) Pull request description: We currently benchmark Schnorr signature verification only in the context of block validation ([`ConectBlock*`](https://github.com/bitcoin/bitcoin/blob/8bb77f348ef390b7f7c7fb6b57fdc7e86ddb4ce7/src/bench/connectblock.cpp#L107) benchmarks), but not individually for single inputs [1]. This PR adds a script verification benchmark for P2TR key path spends accordingly, by generalizing the already existing one for P2WPKH spends. This should make it easier to quantify potential performance improvements like e.g. bitcoin-core/secp256k1#1777, which allows to plug in our HW-optimized SHA256 functions to be used in libsecp256k1 (see the linked example commit furszy@f68bef0). IIRC from last CoreDev, the main speedup from this is expected for ECDSA signing though (as this involves quite a lot of hashing), but it still makes sense to have verification benchmarks available for both signature types as well. (An alternative way could be to add benchmarks for the signing/verifying member functions `CKey::Sign{,Schnorr}`, `CPubKey::Verify` and `XOnlyPubKey::VerifySchnorr` directly, if we prefer that.) [1] this claim can be practically verified by putting an `assert(false);` into `XOnlyPubKey::VerifySchnorr`: the three benchmarks crashing are `ConnectBlockAllSchnorr`, `ConnectBlockMixedEcdsaSchnorr` and `SignTransactionSchnorr` (as signing includes verification) ACKs for top commit: furszy: ACK d339884 sedited: Re-ACK d339884 w0xlt: ACK d339884 Tree-SHA512: efd20444984bdf1dab4d3d876fdbe2a3a838d7cebc0e31e26683009b81afe4dab8611e2c28c87e46fe8b7e305895c93e461b7934a5aaf293f72b19488b9cec60
ffc25a2731 Merge bitcoin-core/secp256k1#1834: ecmult: Document and test ng=NULL in ecmult 3a403639dc eckey: Call ecmult with NULL instead of zero scalar 7e68c0c88b ecmult: Document and test ng=NULL in ecmult 1aafe15139 Merge bitcoin-core/secp256k1#1777: Make SHA256 compression runtime pluggable b9cb1cbfd7 Merge bitcoin-core/secp256k1#1824: util: introduce and use `ARRAY_SIZE` macro 4d92a083bc sha256: speed up writes using multi-block compression 0753f8b909 Add API to override SHA256 compression at runtime fdb6a91a5e Introduce hash context to support pluggable SHA256 compression c0a2aba088 Merge bitcoin-core/secp256k1#1811: bench: Update help functions in bench and bench_internal 10f546a2c0 Merge bitcoin-core/secp256k1#1832: testrand: Remove testrand_finish 8d0eda07e9 testrand: Remove testrand_finish 95e6815843 Merge bitcoin-core/secp256k1#1825: hash: remove redundant `secp256k1_sha256_initialize` in tagged hash midstate functions f48b1bfa5d hash: add midstate initializer and use it for tagged hashes 3019186a6d Merge bitcoin-core/secp256k1#1829: ci: Fix leftover use of old ECMULTGENPRECISION 79e9f25237 ci: Fix leftover use of old ECMULTGENPRECISION dfe042feb2 Merge bitcoin-core/secp256k1#1828: Revert "ci, docker: Fix LLVM repository signature failure" 76e92cfeea Revert "ci, docker: Fix LLVM repository signature failure" ac561601b8 Merge bitcoin-core/secp256k1#1760: cmake: Add dynamic test discovery to improve parallelism c7a7f732bd Merge bitcoin-core/secp256k1#1821: ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 921b9711ea util: introduce and use `ARRAY_SIZE` macro b99a94c382 Add tests for bad scalar inputs in ellswift XDH 307b49f1b9 ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 322d0a4358 Merge bitcoin-core/secp256k1#1823: ci: Load Docker image by ID from builder step ed02466d3f ci: Load Docker image by ID from builder step c49c9be504 bench: Update help functions in bench and bench_internal 1d146ac3ed Merge bitcoin-core/secp256k1#1819: tests: Improve secp256k1_scalar_check_overflow tests (Issue bitcoin#1812) f47bbc07f0 test: add unit tests for secp256k1_scalar_check_overflow d071aa56d5 Merge bitcoin-core/secp256k1#1815: refactor: remove unnecessary `malloc` result casts 99ab4a105e Merge bitcoin-core/secp256k1#1817: ci: Disable Docker build summary generation c5da3bde9c Merge bitcoin-core/secp256k1#1818: ci: Enforce base-10 evaluation 97de5120cf Merge bitcoin-core/secp256k1#1804: test: show both CMake and Autotools usage for ctime_tests 4fb7ccf5d4 ci: Enforce base-10 evaluation 3ae72e7867 ci: Disable Docker build summary generation 97b3c47849 refactor: remove unnecessary `malloc` result casts 1bc74a22f8 test: show both Autotools and CMake usage for ctime_tests 8354618e02 cmake: Set `LABELS` property for tests 29f26ec3cf cmake: Integrate DiscoverTests and normalize test names f95b263f23 cmake: Add DiscoverTests module 4ac651144b cmake, refactor: Deduplicate test-related code git-subtree-dir: src/secp256k1 git-subtree-split: ffc25a2731fd277e056c6f62aa94eb0fb78e031d
ffc25a2731 Merge bitcoin-core/secp256k1#1834: ecmult: Document and test ng=NULL in ecmult 3a403639dc eckey: Call ecmult with NULL instead of zero scalar 7e68c0c88b ecmult: Document and test ng=NULL in ecmult 1aafe15139 Merge bitcoin-core/secp256k1#1777: Make SHA256 compression runtime pluggable b9cb1cbfd7 Merge bitcoin-core/secp256k1#1824: util: introduce and use `ARRAY_SIZE` macro 4d92a083bc sha256: speed up writes using multi-block compression 0753f8b909 Add API to override SHA256 compression at runtime fdb6a91a5e Introduce hash context to support pluggable SHA256 compression c0a2aba088 Merge bitcoin-core/secp256k1#1811: bench: Update help functions in bench and bench_internal 10f546a2c0 Merge bitcoin-core/secp256k1#1832: testrand: Remove testrand_finish 8d0eda07e9 testrand: Remove testrand_finish 95e6815843 Merge bitcoin-core/secp256k1#1825: hash: remove redundant `secp256k1_sha256_initialize` in tagged hash midstate functions f48b1bfa5d hash: add midstate initializer and use it for tagged hashes 3019186a6d Merge bitcoin-core/secp256k1#1829: ci: Fix leftover use of old ECMULTGENPRECISION 79e9f25237 ci: Fix leftover use of old ECMULTGENPRECISION dfe042feb2 Merge bitcoin-core/secp256k1#1828: Revert "ci, docker: Fix LLVM repository signature failure" 76e92cfeea Revert "ci, docker: Fix LLVM repository signature failure" ac561601b8 Merge bitcoin-core/secp256k1#1760: cmake: Add dynamic test discovery to improve parallelism c7a7f732bd Merge bitcoin-core/secp256k1#1821: ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 921b9711ea util: introduce and use `ARRAY_SIZE` macro b99a94c382 Add tests for bad scalar inputs in ellswift XDH 307b49f1b9 ellswift: fix overflow flag handling in secp256k1_ellswift_xdh 322d0a4358 Merge bitcoin-core/secp256k1#1823: ci: Load Docker image by ID from builder step ed02466d3f ci: Load Docker image by ID from builder step c49c9be504 bench: Update help functions in bench and bench_internal 1d146ac3ed Merge bitcoin-core/secp256k1#1819: tests: Improve secp256k1_scalar_check_overflow tests (Issue bitcoin#1812) f47bbc07f0 test: add unit tests for secp256k1_scalar_check_overflow d071aa56d5 Merge bitcoin-core/secp256k1#1815: refactor: remove unnecessary `malloc` result casts 99ab4a105e Merge bitcoin-core/secp256k1#1817: ci: Disable Docker build summary generation c5da3bde9c Merge bitcoin-core/secp256k1#1818: ci: Enforce base-10 evaluation 97de5120cf Merge bitcoin-core/secp256k1#1804: test: show both CMake and Autotools usage for ctime_tests 4fb7ccf5d4 ci: Enforce base-10 evaluation 3ae72e7867 ci: Disable Docker build summary generation 97b3c47849 refactor: remove unnecessary `malloc` result casts 1bc74a22f8 test: show both Autotools and CMake usage for ctime_tests 8354618e02 cmake: Set `LABELS` property for tests 29f26ec3cf cmake: Integrate DiscoverTests and normalize test names f95b263f23 cmake: Add DiscoverTests module 4ac651144b cmake, refactor: Deduplicate test-related code git-subtree-dir: src/secp256k1 git-subtree-split: ffc25a2731fd277e056c6f62aa94eb0fb78e031d
Tackling the long-standing request #702.
Right now we ship our own SHA256 implementation, a standard baseline version that does not take advantage of any hardware-optimized instruction, and it cannot be accessed by the embedding application - it is for internal usage only.
This means embedding applications often have to implement or include a different version for their use cases, wasting space on constrained environments, and in performance-sensitive setups it forces them to use a slower path than what the platform provides. Many projects already rely on tuned SHA-NI / ARMv8 / or other hardware-optimized code, so always using the baseline implementation we ship within the library is not ideal.
These changes allow users to supply their own SHA256 compression function at runtime, while preserving the existing default behavior for everyone else. This is primarily intended for environments where the available SHA256 implementation is detected dynamically and recompiling the library with a different implementation is not feasible (equivalent build-time functionality will come in a follow-up PR).
It introduces a new API:
This function installs the optimized SHA256 compression into the
secp256k1_context, which is then used by all internal computations. Important: The provided function is verified to be output-equivalent to the original one.As a quick example, using this functionality in Bitcoin-Core will be very straightforward: furszy/bitcoin-core@f68bef0