Skip to content

infrastructure: modernize vendored secp256k1 to bitcoin-core v0.6.0 - #541

Open
fpelliccioni wants to merge 1 commit into
masterfrom
feature/secp256k1-modernize
Open

infrastructure: modernize vendored secp256k1 to bitcoin-core v0.6.0#541
fpelliccioni wants to merge 1 commit into
masterfrom
feature/secp256k1-modernize

Conversation

@fpelliccioni

@fpelliccioni fpelliccioni commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

What

Replaces the old (~2018 BCH fork) vendored libsecp256k1 with bitcoin-core/secp256k1 v0.6.0, while re-grafting BCH's consensus-critical custom Schnorr scheme onto the modern internals.

Why

The upcoming SV2 Noise handshake needs ElligatorSwift and BIP340 schnorrsig, which the old fork does not provide. This also modernizes the ECDSA/EC core (recovery, extrakeys, ecdh) and drops the external precompute tooling.

BCH Schnorr re-graft

BCH's EC-Schnorr-SHA256 scheme (consensus-critical, not BIP340) is ported as a local module ENABLE_MODULE_SCHNORR_BCH:

  • secp256k1_ecmult no longer takes an ecmult_context (static now)
  • fe_is_quad_varfe_is_square_var
  • gej_has_quad_y_var (removed upstream) reimplemented as is_square(y·z)
  • fe_set_b32fe_set_b32_limit

The scheme itself is unchanged. Validated against the old fork's known-answer vector (pubkey=G, msg=0 → verify=1; tampered → 0; sign/verify round-trip) and all BCH-Schnorr consensus script vectors.

ec_signature representation

The infrastructure ECDSA wrapper used to copy the opaque secp256k1_ecdsa_signature.data blob into ec_signature. That layout is implementation-defined and differs between the two libraries. The wrapper now round-trips through the stable compact (r‖s) serialization APIs, so ec_signature holds the canonical compact form.

  • Signature verification is byte-identical (no consensus impact).
  • Deterministic generation now follows modern RFC6979 → different-but-valid signatures. The hardcoded ECDSA / message-signing / endorsement golden vectors are updated accordingly.

Build / packaging

  • Modern secp256k1 self-generates its precomputed tables → removed the secp256k1-precompute tool_requires and the gen_context generation step.
  • Removed the obsolete per-module conan options; secp256k1 no longer depends on GMP.
  • Assembly selection moves to the modern SECP256K1_ASM (conan option secp256k1_asm=auto|off; the ASan CI build uses off).

Validation

All suites pass: infrastructure (456), domain / consensus+scripts (3820, ~1.0M assertions), blockchain (133), blockchain_vmlimits (21), network (85), node (96), c-api (735). Clean conan install + fresh CMake configure verified.

Summary by CodeRabbit

  • Bug Fixes

    • Improved ECDSA signature parsing and serialization reliability.
    • Added validation for invalid compact signatures, preventing unsupported data from being processed.
  • Tests

    • Updated endorsement, message-signing, and elliptic-curve test vectors to reflect corrected signature outputs.
    • Expanded coverage for compressed and uncompressed signature formats.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@fpelliccioni, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 014873a8-50fb-414b-be4d-8347dd7bccb5

📥 Commits

Reviewing files that changed from the base of the PR and between 43bef59 and 3e49360.

⛔ Files ignored due to path filters (185)
  • .github/workflows/build-with-container.yml is excluded by !.github/** and included by none
  • conanfile.py is excluded by !**/conanfile.py and included by none
  • scripts/rebuild-asan.sh is excluded by !scripts/** and included by none
  • src/CMakeLists.txt is excluded by none and included by none
  • src/secp256k1/CMakeLists.txt is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/Makefile.am is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/README.md is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/README_KTH.md is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/SECURITY.md is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/TODO is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/autogen.sh is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/build-aux/m4/bitcoin_secp.m4 is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/CheckArm32Assembly.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/CheckMemorySanitizer.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/CheckStringOptionValue.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/CheckX86_64Assembly.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/FindValgrind.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/GeneratePkgConfigFile.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/TryAppendCFlags.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/arm-linux-gnueabihf.toolchain.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/config.cmake.in is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/modules/AddCompilerFlags.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/modules/Coverage.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/modules/InstallationHelper.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/modules/SanitizeHelper.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/modules/TestSuite.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/source_arm32.s is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/cmake/x86_64-w64-mingw32.toolchain.cmake is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/configure.ac is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/contrib/lax_der_parsing.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/contrib/lax_der_parsing.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/contrib/lax_der_privatekey_parsing.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/contrib/lax_der_privatekey_parsing.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_ecdh.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_ellswift.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_extrakeys.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_multiset.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_musig.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_preallocated.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_recovery.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/include/secp256k1_schnorrsig.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/libsecp256k1.pc.in is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/obj/.gitignore is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/sage/group_prover.sage is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/sage/secp256k1.sage is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/sage/weierstrass_prover.sage is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/CMakeLists.txt is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/asm/field_10x26_arm.s is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/assumptions.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/basic-config.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench_ecmult.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench_internal.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench_multiset.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench_sign.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/bench_verify.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/checkmem.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ctime_tests.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecdsa.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecdsa_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/eckey.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/eckey_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_compute_table.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_compute_table_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_const.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_const_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_gen.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_gen_compute_table.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_gen_compute_table_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_gen_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/ecmult_static_context.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_10x26.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_10x26_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_5x52.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_5x52_asm_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_5x52_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_5x52_int128_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/field_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/gen_context.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/group.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/group_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/hash.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/hash_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/hsort.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/hsort_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128_native.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128_native_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128_struct.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/int128_struct_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/libsecp256k1-config.h.cmake.in is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modinv32.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modinv32_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modinv64.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modinv64_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ecdh/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ecdh/bench_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ecdh/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ecdh/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ellswift/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ellswift/bench_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ellswift/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/ellswift/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/extrakeys/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/extrakeys/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/extrakeys/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/multiset/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/multiset/README.md is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/multiset/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/multiset/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/keyagg.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/keyagg_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/session.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/session_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/musig/vectors.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/recovery/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/recovery/bench_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/recovery/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/recovery/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorr/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorr/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorr/schnorr.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorr/schnorr_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorr/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorrsig/Makefile.am.include is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorrsig/bench_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorrsig/main_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/modules/schnorrsig/tests_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/num.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/num_gmp.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/num_gmp_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/num_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precompute_ecmult.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precompute_ecmult_gen.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precomputed_ecmult.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precomputed_ecmult.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precomputed_ecmult_gen.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/precomputed_ecmult_gen.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_4x64.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_4x64_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_8x32.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_8x32_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_low.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scalar_low_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scratch.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/scratch_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/secp256k1.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/selftest.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/testrand.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/testrand_impl.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/tests.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/tests_exhaustive.c is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/testutil.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/util.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/wycheproof/WYCHEPROOF_COPYING is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/travis/build_autotools.sh is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/travis/build_cmake.sh is excluded by !src/secp256k1/** and included by none
  • src/secp256k1/travis/install_cmake.sh is excluded by !src/secp256k1/** and included by none
📒 Files selected for processing (4)
  • src/domain/test/chain/script.cpp
  • src/domain/test/wallet/message.cpp
  • src/infrastructure/src/math/elliptic_curve.cpp
  • src/infrastructure/test/math/elliptic_curve.cpp
📝 Walkthrough

Walkthrough

ECDSA signature handling now uses libsecp256k1 parsing and serialization APIs instead of opaque-layout byte copies. Related endorsement, message-signing, and elliptic-curve test vectors are updated.

Changes

ECDSA signature handling

Layer / File(s) Summary
libsecp256k1 signature API migration
src/infrastructure/src/math/elliptic_curve.cpp, src/infrastructure/test/math/elliptic_curve.cpp, src/domain/test/chain/script.cpp, src/domain/test/wallet/message.cpp
Verification and encoding paths parse compact signatures through libsecp256k1, signing and parsing paths serialize them through the corresponding API, and affected expected signature vectors are replaced.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: upgrading the vendored secp256k1 to bitcoin-core v0.6.0.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/secp256k1-modernize

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Replace the old (~2018 BCH fork) libsecp256k1 with bitcoin-core/secp256k1
v0.6.0. This brings the ElligatorSwift and BIP340 schnorrsig modules that
the upcoming SV2 Noise handshake needs, plus recovery/extrakeys/ecdh.

BCH's custom EC-Schnorr-SHA256 scheme (consensus-critical, not BIP340) is
re-grafted onto the modern internals as a local module (ENABLE_MODULE_SCHNORR_BCH):
  - secp256k1_ecmult no longer takes an ecmult_context (now static),
  - fe_is_quad_var -> fe_is_square_var,
  - gej_has_quad_y_var (removed upstream) reimplemented as is_square(y*z),
  - fe_set_b32 -> fe_set_b32_limit.
The scheme is unchanged; verified against the old fork's known-answer vector
and all BCH-Schnorr consensus script vectors.

The infrastructure ECDSA wrapper stored the opaque secp256k1_ecdsa_signature
.data blob in ec_signature; that layout is implementation-defined and differs
between the two libraries. The wrapper now round-trips through the stable
compact (r||s) serialization APIs, so ec_signature holds the canonical compact
form. Signature *verification* is byte-identical; deterministic *generation*
now follows modern RFC6979, producing different-but-valid signatures, so the
hardcoded ECDSA/message/endorsement golden vectors are updated accordingly.

The modern build self-generates its precomputed tables, so the
secp256k1-precompute tool_requires, the gen_context table-generation step and
the obsolete per-module conan options are removed. secp256k1 no longer depends
on GMP. Assembly selection moves to the modern SECP256K1_ASM (option
secp256k1_asm=auto|off; the ASan CI build uses off).
@fpelliccioni
fpelliccioni force-pushed the feature/secp256k1-modernize branch from 43bef59 to 3e49360 Compare July 31, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant