#36188 crypto: plug hardware optimized SHA256 into libsecp256k1's context
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #36188 crypto: plug hardware optimized SHA256 into libsecp256k1's context | Ready | 2 | Strong | 224 + 237 tests | |||
|
|
|
| ||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | |||||||
Goal
Plugs Bitcoin Core's hardware-accelerated SHA256 compression function into libsecp256k1 contexts. It restructures `ECC_Context` into a lifecycle manager that provides both signing and verification contexts, moves ECC initialization into `common/ecc_init`, and updates call sites to use the new verification context instead of `secp256k1_context_static`.
Problem: libsecp256k1 uses its internal pure-software SHA256 compression implementation by default, bypassing available CPU hardware acceleration (such as x86 SHA-NI and ARMv8 cryptography extensions) during elliptic curve signing and verification. Additionally, `secp256k1_context_static` cannot be configured with custom compression hooks, and ECC initialization was tightly coupled to `key.h` primitives.
Evidence of importance:
- PR description benchmarks on ARM64 with SHA-NI show ECDSA signing time drops from 79.2 µs to 69.3 µs (-13%) and Schnorr signing drops from 39.9 µs to 37.1 µs (-7%).
- Commit 3104f72514 notes: 'With ours, ECDSA signing gets ~15% faster on CPUs with SHA extensions, Schnorr signing ~3%.' Verification benchmarks show negligible improvement (0% to -1%).
Scope: A significant portion of the 44 changed files is mechanical: updating fuzz targets, benchmarks, and binaries to initialize ECC state via `MakeContextECC()`, plus a scripted-diff substituting `secp256k1_context_static` with `GetSecp256k1VerifyContext()` in `src/pubkey.cpp`.
Risk of a mistake: medium (consensus, validation, wallet). A flaw in the SHA256 compression callback or context initialization could cause silent signature creation errors or misvalidate cryptographic checks across the node.
Changed since the previous assessment: The underlying approach and commit progression remain consistent with the prior description; changes reflect rebasing and test/benchmark adjustments.
Reviewability
Ready
Nothing known that would invalidate a review now.
Waiting on (from the thread read):
- author: response to fametrano's suggestion on cloning context 2026-10-25
- reviewer: re-review by theStack requested by sedited 2026-10-31
Agreement
Strong
substantive support, no open objection (fametrano)
Thread notes: sedited asked theStack to take another look; no new claims were raised.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| theStack (member) | suggestion, approach | Keep only one non-static context for both signing and verifying instead of splitting them | accepted · theStack accepted furszy's explanation that separate contexts avoid adding a mutex on verification for thread safety if re-seeding is ever needed | answered | yes | 2026-09-30: 'An alternative to this split-up would be to keep having only one "full" (i.e. non-static) context and use it for both signing and verifying' Status from: 2026-09-30: theStack: 'Fair point, I didn't consider that there could be potential use-cases where the context needs any further modification a' |
| fametrano (none) | suggestion, approach | Clone the signing context before randomizing it to create the verification context, skipping the second SHA256 self-test | open | answered | no | 2026-10-25: 'Cloning the signing context before randomizing it would skip the second SHA256 self-test.' |
| w0xlt (contributor) | suggestion, maintenance | Remove redundant SHA256AutoDetect() call since kernel::Context already runs it before ECC initialization | accepted · furszy explained it is needed for tests; w0xlt noted the overhead is negligible and dropped the suggestion with an ACK | answered | yes | 2026-10-27: 'This call appears redundant. Both `bitcoind.cpp` and `NodeImpl::baseInitialize()` construct a `kernel::Context`, which already runs `SHA256AutoDetect()` before ECC initialization.' Status from: 2026-10-28: w0xlt: 'although the extra overhead is negligible during normal startup' |
Support:
- w0xlt (contributor) (Concept ACK, 2026-09-08): Concept ACK [not substantive]
- fjahr (member) (Concept ACK, 2026-09-08): Concept ACK [not substantive]
- sedited (member) (Concept ACK, 2026-09-08): Finally! Concept ACK [not substantive]
- ismaelsadeeq (member) (Concept ACK, 2026-09-08): Awesome Concept ACK [not substantive]
- theStack (member) (Concept ACK, 2026-09-08): Splendid Concept ACK [not substantive]
- hebasto (member) (Concept ACK, 2026-09-10): Concept ACK. [not substantive]
- theStack (member) (2026-09-30) [read]: LGTM, just left two organizational comments. The MuSig and BIP352 modules could also take use of the plugged in compression function, either here or in a follow-up PR. [not substantive]
- fametrano (none) (Tested ACK, 2026-10-25) [both]: Ran a differential test harness comparing 20,000 rounds across tagged hashes, BIP340 signing, ECDSA, EllSwift, MuSig2, and silent payments labels; benchmarked speedups on Apple M5
- w0xlt (contributor) (ACK, 2026-10-28): ACK ecf779fa06cef78ca668715cba21b30a1fda8a06 [not substantive]
Participants:
- fjahr (member, support, 1 statements 2026-09-08 to 2026-09-08): Concept ACK
- ismaelsadeeq (member, support, 1 statements 2026-09-08 to 2026-09-08): Concept ACK
- sedited (member, support, 2 statements 2026-09-08 to 2026-10-31): Concept ACK; pinged theStack for re-review
- theStack (member, support, 5 statements 2026-09-08 to 2026-09-30): Concept ACK and review; suggested keeping a single context and accepted author's explanation
- w0xlt (contributor, support, 4 statements 2026-09-08 to 2026-10-28): Concept ACK and ACK; suggested removing redundant SHA256AutoDetect call and dropped it
- fanquake (member, neutral, 1 statements 2026-09-09 to 2026-09-09): pinged real-or-random for awareness
- hebasto (member, support, 1 statements 2026-09-10 to 2026-09-10): Concept ACK
- real-or-random (member, neutral, 1 statements 2026-10-01 to 2026-10-01): discussed context re-randomization and agreed it belongs in a follow-up
- fametrano (none, support, 2 statements 2026-10-25 to 2026-10-25): Tested ACK; suggested cloning signing context before randomizing
Files
262 lines under test/bench/ci.
- src/bench/ecc_sign_verify.cpp +119/-0
- src/key.cpp +14/-63
- src/test/ecc_context_tests.cpp +62/-0
- src/ecc_context.cpp +58/-0
- src/pubkey.cpp +28/-27
- src/ecc_context.h +41/-0
- src/common/ecc_init.cpp +35/-0
- src/key.h +0/-22
- src/common/ecc_init.h +21/-0
- src/bitcoin-tx.cpp +4/-4
- src/test/fuzz/script_flags.cpp +7/-1
- src/bench/sign_transaction.cpp +4/-2
- src/test/fuzz/script_assets_test_minimizer.cpp +5/-1
- src/bench/ccoins_caching.cpp +3/-2
- src/bench/checkqueue.cpp +3/-2
- src/crypto/sha256.cpp +5/-0
- src/node/context.h +3/-2
- src/bench/bip324_ecdh.cpp +3/-1
- src/bench/descriptors.cpp +2/-2
- src/bench/ellswift.cpp +3/-1
- src/bench/verify_script.cpp +3/-1
- src/bitcoin-wallet.cpp +2/-2
- src/node/interfaces.cpp +2/-2
- src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp +2/-2
- src/bitcoind.cpp +2/-1
- src/crypto/sha256.h +3/-0
- src/test/fuzz/bip324.cpp +2/-1
- src/test/fuzz/descriptor_parse.cpp +2/-1
- src/test/fuzz/key.cpp +2/-1
- src/test/fuzz/key_io.cpp +2/-1
- src/test/fuzz/message.cpp +2/-1
- src/test/fuzz/miniscript.cpp +2/-1
- src/test/fuzz/p2p_transport_serialization.cpp +2/-1
- src/test/fuzz/script_sign.cpp +2/-1
- src/test/util/setup_common.cpp +2/-1
- src/CMakeLists.txt +2/-0
- src/init.cpp +1/-1
- src/test/sanity_tests.cpp +1/-1
- src/bench/CMakeLists.txt +1/-0
- src/common/bip352.cpp +1/-0
- src/kernel/CMakeLists.txt +1/-0
- src/musig.cpp +1/-0
- src/node/context.cpp +0/-1
- src/test/CMakeLists.txt +1/-0
Card
The short text the ranking pass compares across PRs.
This PR integrates Bitcoin Core's hardware-accelerated SHA256 compression function into libsecp256k1 context instances, replacing libsecp256k1's software-only hashing fallback. It also separates ECC context initialization into dedicated signing and verification contexts managed via a unified RAII lifecycle. Benchmarks show a 7% to 13% reduction in signing latency on architectures with SHA hardware extensions, while verification performance remains essentially unchanged. No prerequisite or dependent pull requests are indicated.
Data
thread read through 2026-10-31 (23 statements), head ecf779fa06
labels: Utils/log/libs
Categories
Utilities (logging, arguments, libraries)
P2 · speedup
Plugging Bitcoin Core's hardware SHA256 implementation into libsecp256k1 provides measurable performance improvements for cryptographic signing. Benchmarks show ECDSA signing improves by ~13–15% and Schnorr signing by ~3–7% on CPUs with SHA extensions, while cleanly structuring the ECC context lifecycle across the codebase.
Membership: Has the Utils/log/libs label, updates src/crypto/sha256 and ECC initialization in src/common/, and integrates hardware SHA256 into libsecp256k1 contexts.
Factors: security/stability 1, bug 0, performance 2, user value 1, leverage 1