Commit Graph

3398 Commits

Author SHA1 Message Date
Kgothatso Ngako
580e4f6502 chilldkg: Phase 2 - SimplPedPop and EncPedPop layers
Port the two sub-protocol layers of the ChillDKG reference
implementation (bip-frost-dkg v0.3.0-dev, upstream commit
a91896883f85b159415ecf298d5e844879af112d) to C, keeping the same
function decomposition as simplpedpop.py / encpedpop.py so the code
stays diffable against the reference.

simplpedpop.h / simplpedpop_impl.h (mirrors simplpedpop.py):
- simplpedpop_participant_step1: VSS coefficient generation and
  commitment, per-participant shares, proof of possession. The PoP is
  a BIP-340 signature with custom tag prefix "BIP DKG/pop message"
  over u32be(participant_id), signed with the constant coefficient
  f(0), using TH("BIP DKG/simplpedpop aux", simpl_seed) as aux_rand.
- simplpedpop_coordinator_step / assemble_sum_coms: echo per-dealer
  constant-term commitments, sum non-constant-term commitments,
  collect PoPs (not verified by the coordinator, as in the reference).
- simplpedpop_participant_step2: own-commitment echo check, per-dealer
  infinity rejection and PoP verification against the x-only
  coms_to_secrets[i], TapTweak applied before share verification
  (secshare vs pubshare check on tweaked values), eq_input =
  u32be(t) || sum_coms committing to the UNTWEAKED summed commitment.

encpedpop.h / encpedpop_impl.h (mirrors encpedpop.py):
- simpl_seed / aux / secnonce derivations from (hostseckey, random,
  enc_context) via "BIP DKG/encpedpop seed", "BIP DKG/simplpedpop aux"
  and "BIP DKG/encpedpop secnonce"; pubnonce = pubkey_gen_plain(secnonce).
- encaps_multi / encrypt_multi: per-recipient pad context
  u32be(i) || enc_context, self-pad at the own index (no ECDH),
  libsecp256k1-style ECDH pad otherwise with sender-first ordering;
  encryption is additive mod n so the coordinator can sum encrypted
  shares per recipient.
- decaps_multi / decrypt_sum: receiver-side pads, invalid or infinity
  pubnonce maps to FAULTY_PARTICIPANT_OR_COORDINATOR(sender).
- coordinator_step: checked scalar parse of encrypted shares
  (overflow blames the sender), per-recipient summation.
- participant_step2: pubnonce echo check (mismatch ->
  FAULTY_COORDINATOR), decrypt, delegate to simplpedpop step2,
  eq_input extended with enckeys || pubnonces.

util.h: add SECP256K1_CHILLDKG_MAX_PARTICIPANTS (128, matching frost)
and the internal fault enum mirroring the reference's exception
taxonomy (FAULTY_COORDINATOR, FAULTY_PARTICIPANT,
FAULTY_PARTICIPANT_OR_COORDINATOR,
UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR, INVALID_INPUT). The public
blame-reporting enum arrives with the Phase 3 API.

State structs are fixed-size (no malloc, cap 128 participants). All
secret temporaries are cleared; negligible-probability secret-
dependent failures are declassified before branching.

Documented deviations where the reference crashes with non-protocol
errors: infinity sum_coms[0] in invalid_taproot_commit (unreachable
after PoP verification) and tweak-hash overflow (negligible) return
UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR; a wrong cmsg length maps
to FAULTY_COORDINATOR. Investigation procedures are deferred to
Phase 5 per the plan.

tests_impl.h: byte-exact n=3/t=2 happy-path vectors for both layers
generated from the Python reference (pmsg/cmsg/eq_input/enc_secshares
and all DKG outputs), plus PoP reject cases (tampered, wrong index,
infinity commitment, wrong echo, tampered non-constant-term sum),
coordinator blame (bad commitment, overflowing encrypted share),
encaps/decaps pad symmetry for all sender/receiver pairs including
self-pad, encrypt->sum->decrypt_sum roundtrip, tampered encrypted
share, invalid pubnonce blame, and input-validation rejects.

Verified: make check 3/3 suites pass (incl. noverify_tests running the
module); CMake ctest 361/361; ./tests --target=chilldkg runs all 9
module tests green.
2026-08-31 04:47:38 +02:00
Kgothatso Ngako
e462f7c1ac chilldkg: Phase 1 - internal primitives (util, vss)
Add the byte-exact internal primitives for the ChillDKG module,
mirroring the Python reference implementation of the bip-frost-dkg
draft (v0.3.0-dev), pinned to upstream commit
a91896883f85b159415ecf298d5e844879af112d.

util.h / util_impl.h (mirrors chilldkg_ref/util.py):
- Point (de)serialization with explicit point-at-infinity support:
  33 zero bytes <-> infinity, otherwise SEC compressed. Checked parse
  rejects invalid encodings and out-of-range x coordinates
  (point_save/point_load, xonly_save/xonly_load).
- Internal parameterized-tag BIP-340 Schnorr sign/verify
  (chilldkg_schnorrsig_sign/_verify): tag prefix selects the
  <prefix>/aux, /nonce, /challenge subtags ("BIP DKG/pop message" for
  proofs of possession, "BIP0340" for CertEq signatures and recovery
  acks), arbitrary-length messages, pad33 zero-padding helper. The
  public schnorrsig API hardcodes BIP0340/32-byte messages, so the
  algorithm is replicated from secp256k1_schnorrsig_sign_internal with
  a custom tag; cross-checked against secp256k1_schnorrsig_sign32.
- Tagged hashes via secp256k1_sha256_initialize_tagged:
  "BIP DKG/params_hash", "BIP DKG/encpedpop seed",
  "BIP DKG/simplpedpop aux", "BIP DKG/encpedpop secnonce",
  "BIP DKG/encpedpop ecdh", "BIP DKG/encaps_multi self_pad",
  "BIP DKG/vss coeffs", and BIP-341 "TapTweak" (32-byte x-only input).
- params_hash = TH("BIP DKG/params_hash", u32be(t) || hostpubkeys)
  (note: plan had the operand order reversed; the reference hashes t
  first).
- ECDH pads: reuses the ecdh module's SHA256-of-compressed-shared-
  point hash, then TH("BIP DKG/encpedpop ecdh", ecdh ||
  sender_pubnonce || receiver_hostpubkey || context) with a sending
  flag fixing the sender|receiver order; self_pad for the own index.
  Pads are parsed wrapping (mod-n reduction); wire scalars, VSS
  coefficients and the TapTweak are parsed checked.

vss.h / vss_impl.h (mirrors chilldkg_ref/vss.py):
- vss_gen_coeffs: per-coefficient TH("BIP DKG/vss coeffs", seed ||
  u32be(j)), checked parse with bitwise error accumulation.
- vss_poly_eval (Horner) and vss_secshare_for with the x = id+1
  convention (safe at UINT32_MAX).
- vss_commit (constant-time ecmult_gen, zero coefficient -> infinity),
  vss_pubshare (powers-of-x over commitments, skips infinity),
  vss_commitment_add, vss_verify_secshare.
- vss_invalid_taproot_commit: TapTweak applied to the x-only constant
  term so the Taproot script path is unspendable; returns tweak and
  pubtweak.

tests_impl.h: 7 vector tests (tagged hashes, params_hash, point
serialization incl. infinity roundtrip and parity prefixes, checked
vs wrapping scalar parse at the group order boundary, custom-tag
schnorrsig incl. wrong-tag/key/msg rejection, ECDH pad sender/receiver
symmetry, VSS coeff derivation/Horner/commitment/pubshare/tweak) with
expected values generated once from the Python reference
(committed into the test file, reference commit recorded).

Verified: make check 3/3 suites pass; CMake ctest all pass;
./tests --target=chilldkg runs all 7 new tests green in both verify
and noverify builds.
2026-08-31 04:05:15 +02:00
Kgothatso Ngako
49f3eba8f5 chilldkg: Phase 0 - module scaffolding and build wiring
Add an empty, experimental `chilldkg` module as the foundation for a
ChillDKG implementation (distributed key generation for FROST) per the
bip-frost-dkg BIP draft (v0.3.0-dev):
https://github.com/BlockstreamResearch/bip-frost-dkg

The module lives in src/modules/chilldkg/ (separate from the frost
module, per the implementation plan in .idea/docs/
chilldkg-implementation-plan.md: FROST signing (BIP 445) and ChillDKG
are separate BIPs with separate reference repos, test vectors and
review cycles; the dependency between them is one-way bytes).

New files:
- include/secp256k1_chilldkg.h: public header skeleton with the same
  "EXTREMELY DANGEROUS / work in progress" warning style as
  secp256k1_frost.h, plus a note that the BIP is a draft and tagged
  hashes/wire formats may change. No API yet (Phase 3+).
- src/modules/chilldkg/main_impl.h: implementation skeleton including
  the public header.
- src/modules/chilldkg/tests_impl.h: trivial scaffolding unit test
  (chilldkg_scaffolding_test) registered via the tests_chilldkg[]
  CASE1 array used by this repo's unit-test framework.
- src/modules/chilldkg/Makefile.am.include: autotools file list,
  mirroring the frost module's.
- src/modules/chilldkg/chilldkg.md: module doc stub (purpose, draft
  status, dependency on the schnorrsig and ecdh modules).

Build wiring (mirrors the frost module exactly):
- configure.ac: --enable-module-chilldkg (default no, experimental
  gate), dependency errors when schnorrsig or ecdh are explicitly
  disabled, AM_CONDITIONAL(ENABLE_MODULE_CHILLDKG), summary line.
- Makefile.am: include src/modules/chilldkg/Makefile.am.include under
  ENABLE_MODULE_CHILLDKG.
- src/secp256k1.c: guarded include of modules/chilldkg/main_impl.h
  after the frost module.
- src/tests.c: guarded include of tests_impl.h and
  MAKE_TEST_MODULE(chilldkg) registration.
- CMakeLists.txt: SECP256K1_ENABLE_MODULE_CHILLDKG option (OFF) +
  summary line.
- src/CMakeLists.txt: dependency checks on
  SECP256K1_ENABLE_MODULE_SCHNORRSIG and SECP256K1_ENABLE_MODULE_ECDH,
  ENABLE_MODULE_CHILLDKG=1 compile definition, public header export.

Verified:
- ./autogen.sh && ./configure --enable-experimental
  --enable-module-chilldkg --enable-module-schnorrsig
  --enable-module-ecdh && make check: PASS 3/3 (tests, noverify_tests,
  exhaustive_tests).
- configure fails with a clear error when schnorrsig or ecdh are
  disabled, or when experimental is not enabled.
- CMake build with SECP256K1_ENABLE_MODULE_CHILLDKG=ON: ctest 345/345
  passed; dependency errors fire correctly when schnorrsig/ecdh OFF.
2026-08-31 01:37:22 +02:00
Kgothatso Ngako
7afaab53dc frost: close remaining gaps against the BIP 445 reference
Some checks failed
CI / Build arm64 Docker image (push) Has been cancelled
CI / Build x64 Docker image (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SECP256K1_TEST_… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SECP256K1_TEST_ITERS:2… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WH… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes W… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BUILD:distcheck]) (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[RECOVERY:yes WIDEMUL:int128]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WID… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes CPPFLAGS:-DVERIFY ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITEL… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WIDEMUL:in… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WIDEMUL:int128]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BUILD:distcheck]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[RECOVERY:yes WIDEMUL:int128]) (push) Has been cancelled
CI / x86 (MSVC): Windows (VS 2022) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, static) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, shared) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, int128_struct) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, static) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, shared) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, int128_struct) (push) Has been cancelled
CI / x64 (MSVC): C++ (public headers) (push) Has been cancelled
CI / SageMath prover (push) Has been cancelled
CI / release (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:y… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITEL… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTI… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes W… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:y… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes S… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHI… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / i686: Linux (Debian stable) (clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include, map[env_vars:map[]]) (push) Has been cancelled
CI / i686: Linux (Debian stable) (i686-linux-gnu-gcc, map[env_vars:map[]]) (push) Has been cancelled
CI / s390x (big-endian): Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[ASM:arm32 EXPERIMENTAL:yes]]) (push) Has been cancelled
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (clang, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (gcc, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[]]) (push) Has been cancelled
CI / ppc64le: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / Valgrind arm64 (memcheck) (push) Has been cancelled
CI / Valgrind i686 (memcheck) (push) Has been cancelled
CI / Valgrind x64 (memcheck) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:clang]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:i686-linux-gnu-gcc HOST:i686-linux-gnu]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:clang ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:i686-linux-gnu-gcc ECMULTGENKB:2 ECMULTWINDOW:2 HOST:i686-linux-gnu]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Has been cancelled
CI / i686 (mingw32-w64): Windows (Debian stable, Wine) (push) Has been cancelled
CI / x86_64 (mingw32-w64): Windows (Debian stable, Wine) (push) Has been cancelled
CI / C++ -fpermissive (entire project) (map[env_vars:map[]]) (push) Has been cancelled
CI / C++ (public headers) (push) Has been cancelled
Four small divergences from the reference implementation and its API
contract, none of which changes any signature: the differential harness
(240 signing + 120 deterministic-signing cases against the Python
reference) produces byte-identical output before and after.

Length prefixes that do not fit
-------------------------------

secp256k1_frost_sha256_write_prefixed asserted, via VERIFY_CHECK, that
the length fits into its prefix. VERIFY_CHECK compiles away in release
builds, so a length that does not fit was silently truncated modulo
2^(8*prefix_size) instead of being rejected, yielding a nonce that does
not follow the spec. The reference raises OverflowError instead.

Only the 4-byte extra_in prefix of nonce_hash is affected, and only where
size_t is wider than 32 bits, so this needs an extra_in of 4 GiB to
trigger. It is nevertheless a silent deviation, so write_prefixed now
returns 0 without writing anything, and the failure is propagated:
secp256k1_frost_nonce_function and secp256k1_frost_det_nonce_function
return 0, and secp256k1_frost_nonce_gen returns 0 after wiping
session_secrand32 and the nonces. Checking the shifted-out bits (which
the loop already computes) rather than comparing extra_in_len against a
32-bit bound avoids a comparison that is always true on 32-bit platforms.
The bound is now documented on the extra_in_len parameter.

Identifiers equal to UINT32_MAX
-------------------------------

BIP 445 derive_interpolating_value accepts every identifier in
0 <= id < 2^32, but secp256k1_frost_ids_are_valid rejected UINT32_MAX
because the mapping to the polynomial x-coordinate, id + 1, overflows in
uint32_t arithmetic. The +1 is now added in scalar arithmetic, where it
cannot overflow, and the identifier restriction is gone. The denominator
never needed the +1 at all, since

    x_j - x_i = (id_j + 1) - (my_id + 1) = id_j - my_id

so it is computed directly from the identifiers.

This was unreachable through the public API -- validate_session_params
already bounds identifiers by n_participants, which is at most
SECP256K1_FROST_MAX_PARTICIPANTS = 128 -- but it made an internal helper
diverge from the algorithm it implements. frost_large_id_test covers it
by reconstructing the constant term of a random degree-2 polynomial from
shares held by identifiers 0, UINT32_MAX - 1 and UINT32_MAX.

Zero-length messages
--------------------

secp256k1_frost_session_init and secp256k1_frost_deterministic_sign
required a non-NULL msg, so an empty message -- which the reference
represents as the byte string b"" -- could only be passed as a pointer
that is never dereferenced. Both now accept NULL when msglen is 0,
matching secp256k1_schnorrsig_sign_custom and the msg parameter of
secp256k1_frost_nonce_gen. secp256k1_sha256_write guards both of its
memcpy calls on a non-zero length, so it is never reached with a NULL
pointer.

NonceGen keeps its distinction between a NULL msg and a zero-length msg:
there the BIP really does distinguish msg = None (hashed as the single
byte 0x00) from msg = b"" (hashed as 0x01 followed by an eight-byte zero
length), and the API expresses that as NULL versus non-NULL.

frost_empty_msg_test runs a signing round over a zero-length message
passed both ways and checks that the two session objects are identical.
The two API tests that relied on a NULL msg always being rejected now
pass an explicit non-zero msglen; previously they passed a random msglen
that could be 0.

Header documentation
--------------------

The parameter tables of eleven doc comments had names that did not line
up with their block's continuation column. All parameter tables are now
aligned consistently, with wrapped text two columns past the colon.

Verification
------------

  - gcc and clang, -std=c89 -pedantic-errors -Werror, with and without
    -DVERIFY: clean
  - tests (multiple seeds), noverify_tests and frost_example: pass
  - ctime_tests under MemorySanitizer: exits 0 with halt_on_error=1
  - vectors.h still reproduces exactly from the spec's JSON vectors
  - 240 signing + 120 deterministic-signing differential cases against
    the BIP 445 Python reference: byte-identical to the previous commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 01:19:28 +02:00
Kgothatso Ngako
7e73badcbd frost: fix constant-time violations and C90 conformance
The module's BIP 445 logic itself is unchanged and was independently
validated against the pinned spec commit bb5396f (BIP v0.10.0), both via
the checked-in test vectors and via differential testing against the
Python reference over 360 randomised configurations (n up to 128,
shuffled non-contiguous signer ids, mixed xonly/plain tweak chains,
variable-length messages, pubshares present and absent). Every change
below is structural: the differential harness produces byte-identical
pubnonces, aggnonces, partial signatures and final signatures before and
after.

Two classes of problem prevented the module from passing CI.

1. Constant-time violations (ctime_tests)
-----------------------------------------

The CI matrix enables FROST in rows that also run
"valgrind --error-exitcode=42 ./ctime_tests" -- WITH_VALGRIND and
CTIMETESTS both default to 'yes'. With the module enabled that job
reported 639 "conditional jump depends on uninitialised value" errors,
all originating from two sites:

  - secp256k1_frost_derive_coefficient returned

        !overflow && !secp256k1_scalar_is_zero(out)

    where the short-circuiting && branches on `overflow`, which is
    derived from the threshold secret key. The caller declassifies the
    return value, but the branch has already happened inside the callee.
    Replaced with a bitwise &, matching the existing idiom in
    secp256k1_scalar_set_b32_seckey (src/scalar_impl.h).

  - secp256k1_frost_sign_internal performs the self-verification
    recommended by BIP 445, which runs the *variable-time*
    secp256k1_ecmult over the partial signature s. nonce_pts and pk were
    already declassified ahead of that call; s was not. Since s is the
    public output of the function, declassifying it before the
    self-verification is both correct and sufficient.

secp256k1_frost_deterministic_sign carried three more instances of the
same class, invisible until now because ctime_tests did not exercise
that path at all:

  - the `if (!valid)` check on secp256k1_scalar_set_b32_seckey lacked the
    declassify that the identical checks in secp256k1_frost_nonce_gen and
    secp256k1_frost_sign_internal already have;
  - secp256k1_frost_det_nonce_function used the same short-circuiting &&,
    here over the secret nonces;
  - the branch on that function's result was not declassified.

The && in det_nonce_function is rewritten via two int locals rather than
a bare bitwise &: clang's -Wbitwise-instead-of-logical fires when both
operands are `!f(...)` expressions, which would break the -Werror clang
builds.

ctime_tests now also covers secp256k1_frost_deterministic_sign, so that
path stays checked from here on.

None of these leak anything of value in practice -- they reveal only
negligible-probability events (a hash overflowing the curve order, a zero
nonce) or whether a secret share is a valid secret key -- but they
violate the project's declassification discipline and fail the ctime
test.

2. C90 conformance (-Werror -pedantic-errors)
---------------------------------------------

The project targets C90 (CMAKE_C_STANDARD 90, -std=c89 -pedantic) and CI
passes WERROR_CFLAGS='-Werror -pedantic-errors'. Compiling src/tests.c
with those flags produced 62 errors in three groups:

  - 40x "ISO C forbids empty initializer braces before C2X" in the
    generated vectors.h; empty {} initializers are C23-only. Fixed in
    tools/test_vectors_frost_generate.py so it survives regeneration:
    hexstr_to_intarray now emits "0" for an empty byte string (all six
    of its call sites wrap the result in braces), and init_group's
    `counted` helper emits "{ 0 }" for an empty group. In every affected
    slot the paired count/length field is 0, so the padding element is
    never read.

  - 1x "comma at end of enumerator list" (C99+), also in the generator.

  - 21x "initializer element is not computable at load time" across 11
    lines of tests_impl.h. C90 requires constant expressions in
    initializers for automatic aggregates, so

        const secp256k1_frost_pubnonce *ptrs[2] = { &a, &b };

    is invalid. Rewritten as a declaration plus assignments, the style
    the musig tests already use, which is why the pre-existing tree was
    green.

vectors.h is regenerated from the spec's JSON vectors. Its hex payload is
byte-identical (verified by hashing every 0xNN token) and the file still
reproduces exactly from tools/test_vectors_frost_generate.py.

Verification
------------

  - gcc and clang, -std=c89 -pedantic-errors -Werror, with and without
    -DVERIFY: clean (was 62 errors)
  - ctime_tests under MemorySanitizer: 0 reports (was 639); exits 0 with
    halt_on_error=1
  - tests, noverify_tests and frost_example: pass
  - vectors.h regenerates identically from the pinned spec vectors
  - 240 signing + 120 deterministic-signing differential cases against
    the BIP 445 Python reference: byte-identical to the pre-fix build

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 00:57:43 +02:00
Kgothatso Ngako
2d97cc2242 Frost Module logic.
Some checks failed
CI / Build arm64 Docker image (push) Has been cancelled
CI / Build x64 Docker image (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:y… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITEL… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTI… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes W… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:y… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes S… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHI… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O1 ECDH:yes ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Has been cancelled
CI / i686: Linux (Debian stable) (clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include, map[env_vars:map[]]) (push) Has been cancelled
CI / i686: Linux (Debian stable) (i686-linux-gnu-gcc, map[env_vars:map[]]) (push) Has been cancelled
CI / s390x (big-endian): Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[ASM:arm32 EXPERIMENTAL:yes]]) (push) Has been cancelled
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (clang, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (gcc, map[env_vars:map[]]) (push) Has been cancelled
CI / arm64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[]]) (push) Has been cancelled
CI / ppc64le: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Has been cancelled
CI / Valgrind arm64 (memcheck) (push) Has been cancelled
CI / Valgrind i686 (memcheck) (push) Has been cancelled
CI / Valgrind x64 (memcheck) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:clang]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:i686-linux-gnu-gcc HOST:i686-linux-gnu]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:clang ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:i686-linux-gnu-gcc ECMULTGENKB:2 ECMULTWINDOW:2 HOST:i686-linux-gnu]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Has been cancelled
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Has been cancelled
CI / i686 (mingw32-w64): Windows (Debian stable, Wine) (push) Has been cancelled
CI / x86_64 (mingw32-w64): Windows (Debian stable, Wine) (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SECP256K1_TEST_… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SECP256K1_TEST_ITERS:2… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WH… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes W… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BUILD:distcheck]) (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[RECOVERY:yes WIDEMUL:int128]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes CC:gcc ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WID… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes CPPFLAGS:-DVERIFY ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITEL… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WIDEMUL:in… (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BPPP:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes GENERATOR:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPROOF:yes WHITELIST:yes WIDEMUL:int128]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[BUILD:distcheck]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Has been cancelled
CI / ARM64: macOS Sonoma (map[RECOVERY:yes WIDEMUL:int128]) (push) Has been cancelled
CI / x86 (MSVC): Windows (VS 2022) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, static) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, shared) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh) (push) Has been cancelled
CI / x64 (MSVC): Windows (VS 2022, int128_struct) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, static) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, shared) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh) (push) Has been cancelled
CI / x64 (clang-cl): Windows (VS 2022, int128_struct) (push) Has been cancelled
CI / x64 (MSVC): C++ (public headers) (push) Has been cancelled
CI / C++ -fpermissive (entire project) (map[env_vars:map[]]) (push) Has been cancelled
CI / C++ (public headers) (push) Has been cancelled
CI / SageMath prover (push) Has been cancelled
CI / release (push) Has been cancelled
2026-08-31 00:05:16 +02:00
Andrew Poelstra
10366dbbbf Merge BlockstreamResearch/secp256k1-zkp#365: tests: Port hash context tests to zkp modules
72867fd682 tests: Port hash context tests to zkp modules (mllwchrry)

Pull request description:

  Ports the hash context tests from bitcoin-core/secp256k1#1777 to the zkp-specific modules.


ACKs for top commit:
  apoelstra:
    ACK 72867fd682279ff2c79cf13f4f8d8484048d2527; successfully ran local tests


Tree-SHA512: 1714a4c5fd793b32a0f00a92670a48709e4d01917bb81739428601c6e88e89f871cdc1294024e6df7272d6c16e681309d9b3448adcd07ce37bfa2be2dc3f4172
2026-08-19 14:32:07 +00:00
Andrew Poelstra
e166e4024f Merge BlockstreamResearch/secp256k1-zkp#371: whitelist, bppp: defensive hardening and documentation
598e22dcde whitelist: document the degenerate W = -P_i destination (DarkWindman)
7ea12c2dca whitelist: document that the parsed key count is untrusted (DarkWindman)
e8c3396597 whitelist: honour the documented parse initialization guarantee (DarkWindman)
1de3864ff9 bppp: check for overflow in generator allocation (DarkWindman)

Pull request description:

  Small defensive fixes + docs for whitelist/bppp:
  
  - bppp: overflow check in `generators_create` allocation.
  - whitelist: signature_parse always leaves `sig` in a valid-or-canonically-invalid state; guard serialize against untrusted `n_keys`.
  - whitelist: document that `n_keys` is attacker-controlled and must not be used to size the arrays passed to `_verify`.
  - whitelist: document the accepted degenerate `W = -P_i` destination.
  
  No API/format changes. New tests cover theallocation overflow and the parse-failure guarantee.


ACKs for top commit:
  apoelstra:
    ACK 598e22dcde2152003c6a60f04196cc5fe2e2a090; successfully ran local tests
  mllwchrry:
    ACK 598e22d.


Tree-SHA512: 4c218775a4c2e53091f3ac11e5d93caf17083216afa167fb5c1a1cc38c0a7a2cb1e0564cf9e63c5391d72aba9fc42d90a64b9a5f288ae763f0bf9b4b20f3b2e1
2026-08-19 14:31:55 +00:00
Andrew Poelstra
a8b5410e73 Merge BlockstreamResearch/secp256k1-zkp#367: Fix missing clears on secret values
a69a662d05 Fix missing clears on secret values (mllwchrry)

Pull request description:

  Several zkp module functions leave secret scalars and buffers live on the stack after use. 
  Adds the missing clears. Also removes a redundant `prep` clear in `secp256k1_rangeproof_sign_impl` that was already cleared earlier on the same path.


ACKs for top commit:
  apoelstra:
    ACK a69a662d052f2a3839798fdb7d98864d26ccf2cb; successfully ran local tests


Tree-SHA512: b11acfaad3bbc26b7597918afdb90aaa563eb2974bc2522626f70457fa354bad349bc698b72371de9df9004bc1e16fee3afb437135cafb1e0c85dcc2535e2987
2026-08-19 14:31:39 +00:00
mllwchrry
72867fd682 tests: Port hash context tests to zkp modules 2026-08-17 16:39:17 +03:00
mllwchrry
a69a662d05 Fix missing clears on secret values 2026-08-17 16:17:43 +03:00
DarkWindman
598e22dcde whitelist: document the degenerate W = -P_i destination 2026-08-17 13:43:52 +03:00
DarkWindman
7ea12c2dca whitelist: document that the parsed key count is untrusted 2026-08-17 13:40:33 +03:00
DarkWindman
e8c3396597 whitelist: honour the documented parse initialization guarantee 2026-08-14 12:01:58 +03:00
DarkWindman
1de3864ff9 bppp: check for overflow in generator allocation 2026-08-14 12:01:43 +03:00
Jonas Nick
a2b001cc20 Merge elementsproject/secp256k1-zkp#369: surjection: bind genrand nonce to the full statement
65093e1444 surjection: prevent s-value reuse for different proof inputs (mllwchrry)

Pull request description:

ACKs for top commit:
  jonasnick:
    ACK 65093e1444

Tree-SHA512: 563c91fc40d962064efed2fcfc70bbf6f25fc9be049feff95f88cbf62141056cfbe16ae000e828cdbde023aa271436910ed8f4930e244221fc49fb9e838fe2bd
2026-08-14 07:31:46 +00:00
Jonas Nick
f8841c14d5 Merge elementsproject/secp256k1-zkp#370: rangeproof: warn that nonce must not be reused across differing arguments
cde28971a2 rangeproof: warn that nonce must not be reused across differing arguments (mllwchrry)

Pull request description:

ACKs for top commit:
  apoelstra:
    ACK cde28971a2274beeeb2e9df27342d956b5664d44; successfully ran local tests
  jonasnick:
    ACK cde28971a2

Tree-SHA512: 890100ed778e06d1e4ed6fed03080a74676ff804c5f6844e3d2530b7f26a4ec715b8c1f81e3d1fdbbd25c28f50d966802115e493993bfc64ba336296593e7a71
2026-08-14 06:49:59 +00:00
mllwchrry
cde28971a2 rangeproof: warn that nonce must not be reused across differing arguments 2026-08-13 17:52:40 +03:00
mllwchrry
65093e1444 surjection: prevent s-value reuse for different proof inputs
The s-values produced by secp256k1_surjection_genrand previously
depended only on their indices and the difference between
input_blinding_key and output_blinding_key. Calls with the same
difference therefore reused s-values even when their proof inputs
differed.

For proofs with the same used-input selection and honest input index,
the same generated s-value was used as the signing nonce. Reusing this
nonce across different proof messages allowed recovery of the
blinding-key difference. The remaining repeated s-values also revealed
the honest input index.

This commit affects proof generation only; verification is unchanged.
2026-08-13 17:35:31 +03:00
merge-script
2af926dc30 Merge BlockstreamResearch/secp256k1-zkp#366: Upstream PRs 1851, 1852, 1861, 1855, 1864, 1867, 1860, 1865, 1859, 1879, 1881, 1845, 1877, 1882, 1884
217fe59bbf tests: register run_util_tests and run_ec_commit, remove dead print_vector (mllwchrry)
21645c03a2 SECURITY.md: remove Jonas Nick from trusted keys (Jonas Nick)
6a599a4428 scalar: correct `_scalar_get_bits_{limb32,var}` input condition docs (Sebastian Falbesoner)
994b35010d field: correct fe_equal's b magnitude bound (Lőrinc)
0cad3df503 Improve checks for scalar _get_bits methods (Peter.Dettman)
9d75769dec tests: Fix GCC 17 snapshot warning (Tim Ruffing)
66260b78a2 ci: add 'brew trust' invocation to macOS CI (fanquake)
71fcd8410e field: force-inline 5x52 mul and sqr (Lőrinc)
a77dacad9a test: enable -Wunused-function in test suite (Fix #1831) (kallal79)
1eab757207 cmake: Fix shared library versioning on OpenBSD (Hennadii Stepanov)
a401c5145a cmake: Fix shared library versioning on NetBSD (Hennadii Stepanov)
8a0f4002c7 cmake, refactor: Improve documenting in `SetLibtoolAbiVersion` module (Hennadii Stepanov)
acf2084aa7 cmake, refactor: Introduce `SetLibtoolAbiVersion` module (Hennadii Stepanov)
d7125e517d test: musig: fix dead "aggnonce encodes two points at infinity" check (Sebastian Falbesoner)
2ee79e77e6 test: add unit test for `_ecmult_gen_ge` (Sebastian Falbesoner)
ca68daf8e1 test: refactor: simplify tests by using `_ecmult_gen_ge` helper (Sebastian Falbesoner)
240578eef5 bench: add internal benchmark for `secp256k1_fe_normalize_var` (Sebastian Falbesoner)
9e017e5062 refactor: rename `_ecmult_gen` -> `_ecmult_gen_gej` for consistency (Sebastian Falbesoner)
a3296d5e23 refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks) (Sebastian Falbesoner)
5698e66c64 Add exhaustive test for ECDH module (Sebastian Falbesoner)
40a0d874a6 doc: correct API docs for ECDSA signing out-params (s/array/signature object/) (Sebastian Falbesoner)

Pull request description:

  *Note: This PR has been created by a GitHub Actions workflow without human involvement.*

  This PR syncs the following upstream PRs:
   * bitcoin-core/secp256k1#1851: doc: correct API docs for ECDSA signing out-params (s/array/signature object/)
   * bitcoin-core/secp256k1#1852: Add exhaustive test for ECDH module
   * bitcoin-core/secp256k1#1861: refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks)
   * bitcoin-core/secp256k1#1855: bench: add internal benchmark for `secp256k1_fe_normalize_var`
   * bitcoin-core/secp256k1#1864: test: refactor: simplify tests by using `_ecmult_gen_ge` helper, add test
   * bitcoin-core/secp256k1#1867: test: musig: fix dead "aggnonce encodes two points at infinity" check
   * bitcoin-core/secp256k1#1860: cmake: Emulate Libtool's behavior on NetBSD and OpenBSD
   * bitcoin-core/secp256k1#1865: test: enable -Wunused-function in test suite (Fix #1831)
   * bitcoin-core/secp256k1#1859: field: force-inline 5x52 mul and sqr
   * bitcoin-core/secp256k1#1879: ci: add 'brew trust' invocation to macOS CI
   * bitcoin-core/secp256k1#1881: tests: Fix GCC 17 snapshot warning
   * bitcoin-core/secp256k1#1845: Improve checks for scalar _get_bits methods
   * bitcoin-core/secp256k1#1877: field: correct `fe_equal` magnitude bound for `b`
   * bitcoin-core/secp256k1#1882: scalar: correct `_scalar_get_bits_{limb32,var}` input condition docs
   * bitcoin-core/secp256k1#1884: SECURITY.md: remove Jonas Nick from trusted keys

  Usage hints:
   * If this PR has merge conflicts, resolve these by switching to the PR branch and merging the base branch into it using `git merge <base-branch>`.
   * To show the conflict resolution diff from an existing merge commit, use `git show --remerge-diff <merge-commit>`.
   * In case you are recreating the PR branch locally, you can (during the conflict resolution state) replay this conflict resolution diff using `git read-tree --reset -u <merge-commit>`.
     Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree.

ACKs for top commit:
  DarkWindman:
    ACK 217fe59bbf
  real-or-random:
    ACK 217fe59bbf

Tree-SHA512: 761fb08be08afcbaa3a43f7432c92a5e65113545a2a25131baf3385d7e354d2a913856f667c8478729877a074d98c0e58fc0c92b17b70a583cbd96d1f478d7f2
2026-07-09 11:31:18 +02:00
mllwchrry
217fe59bbf tests: register run_util_tests and run_ec_commit, remove dead print_vector 2026-07-03 15:17:36 +03:00
mllwchrry
b1f9e6e360 Merge branch 'master' into sync-ebf59432 2026-07-02 18:43:56 +03:00
merge-script
ebf594320d Merge bitcoin-core/secp256k1#1884: SECURITY.md: remove Jonas Nick from trusted keys
21645c03a2 SECURITY.md: remove Jonas Nick from trusted keys (Jonas Nick)

Pull request description:

  As announced in `#bitcoin-core-dev` IRC, I’m stepping down as a libsecp256k1 maintainer because I’m no longer able to dedicate the time and attention that the project deserves. This PR removes me from the contact list in `SECURITY.md`.

ACKs for top commit:
  real-or-random:
    ACK 21645c03a2 🫡
  theStack:
    ACK 21645c03a2 🫡
  furszy:
    ACK 21645c03a2 🫡

Tree-SHA512: c7d5fc32476e377766e9f4c07f78a4d8389b213f319070810456879996c6b3ac25949ae65a500f79b9108c3fb52b53a735842b438438349a3f5e2d3df1ba0e1e
2026-06-30 08:35:53 +02:00
Jonas Nick
21645c03a2 SECURITY.md: remove Jonas Nick from trusted keys 2026-06-29 07:06:10 +00:00
merge-script
b90075a074 Merge bitcoin-core/secp256k1#1882: scalar: correct _scalar_get_bits_{limb32,var} input condition docs
6a599a4428 scalar: correct `_scalar_get_bits_{limb32,var}` input condition docs (Sebastian Falbesoner)

Pull request description:

  This PR is a small correction of documented (off-by-one) input conditions for the `scalar_get_bits_{limb32,var}`, that came up during reviewing #1845.

ACKs for top commit:
  real-or-random:
    ACK 6a599a4428

Tree-SHA512: 2f0982b6d69d2abeebe0c9d82161e85feaae317d1e3ac2f415338044c8725a0442e14d998053e62f1b5f59f785a31796b5b3c4b36d9eb516ff53e9bb11429e78
2026-06-26 08:40:47 +02:00
merge-script
5a8a411425 Merge bitcoin-core/secp256k1#1877: field: correct fe_equal magnitude bound for b
994b35010d field: correct fe_equal's b magnitude bound (Lőrinc)

Pull request description:

  **Problem:** While reviewing this area with Fable, I noticed that `secp256k1_fe_equal(a, b)` documented `b` up to magnitude 31.
  Review pointed out that the implementation negates `a` before adding `b`, so the actual internal bound is 30.

  **Fix:** Lower the documented and checked bound to 30.
  This keeps `fe_equal` unchanged at runtime and matches current callers, which use much smaller magnitudes.

  **Test:** Add a focused test with random field elements whose magnitudes are randomized within the accepted `a <= 1` and `b <= 30` bounds.

ACKs for top commit:
  theStack:
    ACK 994b35010d
  real-or-random:
    utACK 994b35010d

Tree-SHA512: 034b90b4020c65fcb335ab361341424e08355f64deefaf153d94b05304e68760c9f771e4bc3e0fd664aee164d7e9f5f533d001f21207ef968c52f67d2c23a74a
2026-06-26 08:38:37 +02:00
Sebastian Falbesoner
6a599a4428 scalar: correct _scalar_get_bits_{limb32,var} input condition docs 2026-06-26 03:04:13 +02:00
Lőrinc
994b35010d field: correct fe_equal's b magnitude bound
`secp256k1_fe_equal` negates `a` before adding `b`.
That gives the temporary value magnitude 2, and the following field addition requires the input magnitudes to sum to at most 32.
So the largest `b` magnitude the implementation can accept is 30, not 31.

Lower the documented and checked bound for `b` to 30.
Adjust the focused test to use random field elements with randomized magnitudes within the accepted `a <= 1` and `b <= 30` bounds.

Co-authored-by: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Co-authored-by: Tim Ruffing <me@real-or-random.org>
2026-06-25 09:23:38 -07:00
merge-script
2ce4f71dc5 Merge bitcoin-core/secp256k1#1845: Improve checks for scalar _get_bits methods
0cad3df503 Improve checks for scalar _get_bits methods (Peter.Dettman)

Pull request description:

  Improves the `VERIFY_CHECK`s in all `_scalar_get_bits_limb32` and `_scalar_get_bits_var` methods.

  The initial prompt was noticing that scalar_4x64_impl/`secp256k1_scalar_get_bits_limb32` was not restricting to 32-bit limbs correctly. Then missing range checks for `offset` were added and all such checks rewritten to avoid overflow.

  With these changes, the _low and _4x64 impls of `_get_bits_var` can no longer forward to `_get_bits_limb32`, so those calls were inlined instead.

ACKs for top commit:
  sipa:
    ACK 0cad3df503
  theStack:
    ACK 0cad3df503
  real-or-random:
    utACK 0cad3df503

Tree-SHA512: 753991d586fe5695dd33af6c261c5458ab659be94204626166503af7d403748abb76d791846857a16383cbd38a1f84af9fde74b4327d68d706f88b6531ee7546
2026-06-25 17:02:04 +02:00
merge-script
68b45fd4e2 Merge bitcoin-core/secp256k1#1881: tests: Fix GCC 17 snapshot warning
9d75769dec tests: Fix GCC 17 snapshot warning (Tim Ruffing)

Pull request description:

  Passing a non-malloc pointer to free() would be UB. In this case, the
  free() line is never actually reached (and GCC 17 fails to prove this)
  in a correct implementation of secp256k1_scratch_space_destroy(), but
  the test shouldn't rely on the correctness of the tested function.

  Alternative to #1880. I think this is cleaner
   - it doesn't recreate the scratch space in the middle of some other tests
   - it has an obvious matching (malloc, free) pair
   - it additionally checks that only `magic` is accessed

ACKs for top commit:
  hebasto:
    ACK 9d75769dec, I have reviewed the code and it looks OK.
  theStack:
    re-ACK 9d75769dec

Tree-SHA512: eb1a73c04e1996aeecabaa804e6a4fb1f5e6dfba4b9a775b6dd33d147be17185115a5aa9b7d9bf50260c20849e159d1b57f9ee41901d3d691dec25f2643b7cd2
2026-06-25 16:44:49 +02:00
Tim Ruffing
9d75769dec tests: Fix GCC 17 snapshot warning
Passing a non-malloc pointer to free() would be UB. In this case, the
free() line is never actually reached (and GCC 17 fails to prove this)
in a correct implementation of secp256k1_scratch_space_destroy(), but
the test shouldn't rely on the correctness of the tested function.
2026-06-25 14:57:56 +02:00
merge-script
9e3a165ad0 Merge bitcoin-core/secp256k1#1879: ci: add 'brew trust' invocation to macOS CI
66260b78a2 ci: add 'brew trust' invocation to macOS CI (fanquake)

Pull request description:

  This is probably needed to fix the issues in the macOS Valgrind jobs. i.e in #1877: https://github.com/bitcoin-core/secp256k1/actions/runs/28111568199/job/83240127830?pr=1877#step:4:199

  ```bash
  Cache restored from key: x86_64-macos-native-valgrind-6ebc928a1e40da9db2f283a1c4ac74cfcff9f06687481fd0396a7b4c26ecfb09
  Run brew link valgrind
  Error: Refusing to load formula louisbrunner/valgrind/valgrind from untrusted tap louisbrunner/valgrind.
  Run `brew trust --formula louisbrunner/valgrind/valgrind` or `brew trust louisbrunner/valgrind` to trust it.
  Error: Process completed with exit code 1.
  ```

ACKs for top commit:
  real-or-random:
    utACK 66260b78a2
  hebasto:
    ACK 66260b78a2.

Tree-SHA512: 447f7687d1cb2ed983f77efea509c7a5255e2436ee0260767b7f9faa71c2c81fca5bc24477761e36cf27c8afdd72acccbb7475371dc233f11cd35d1d1d78d268
2026-06-25 11:24:47 +02:00
fanquake
66260b78a2 ci: add 'brew trust' invocation to macOS CI
Should fix issues like:

> Error: Refusing to load formula louisbrunner/valgrind/valgrind from untrusted tap louisbrunner/valgrind.
> Run `brew trust --formula louisbrunner/valgrind/valgrind` or `brew trust louisbrunner/valgrind` to trust it.
> Error: Process completed with exit code 1.
2026-06-25 09:17:04 +01:00
merge-script
bd0287d650 Merge bitcoin-core/secp256k1#1859: field: force-inline 5x52 mul and sqr
71fcd8410e field: force-inline 5x52 mul and sqr (Lőrinc)

Pull request description:

  **Problem:** The 5x52 field multiplication and squaring routines are hot in group arithmetic and scalar multiplication. Some compilers leave the thin wrappers and int128 inner helpers out of line, which keeps a call boundary in this hot path and limits scheduling of the 64x64->128 arithmetic.

  **Fix:** Define `SECP256K1_FORCE_INLINE` next to the existing inline helper and use it for the 5x52 multiplication and squaring wrappers and `int128` inner helpers.

  For default optimized builds, this expands to `__forceinline` on MSVC-compatible compilers and to `__attribute__((always_inline))` on GCC-compatible compilers. It falls back to the existing inline spelling when inlining is disabled, when optimization is disabled, when optimizing for size on GCC/Clang, or when `_DEBUG` is defined.

  **Benchmarks:** Values are relative changes in `Min(us)`, lower is better.

  | Source | Host / CPU | Compiler | ecdsa_verify | ecdh | schnorrsig_verify | field_sqr | field_mul |
  |---|---|---|---:|---:|---:|---:|---:|
  | local | M4-Max.local | gcc-14 14.3.0 | -9.1% | -9.0% | -9.6% | -7.0% | -4.0% |
  | local | i9-ssd | GCC 16.1.0 | -5.3% | -4.1% | -5.5% | -15.7% | -11.6% |
  | local | WIN-A2EHOAU4JET / Xeon E5-2637 v2 | MSVC 19.50.35728 | -2.6% | -9.3% | -2.4% | -7.4% | -7.4% |
  | local | i7-hdd | GCC 14.2.0 | -10.9% | -11.1% | -10.5% | -9.4% | -21.6% |
  | local | umbrel / Intel N150 | GCC 12.2.0 | -4.9% | -4.3% | -4.6% | +0.6% | -1.1% |
  | local | rpi5-16-3 | GCC 14.2.0 | -0.6% | -0.7% | -0.6% | -5.5% | -1.0% |
  | local | rpi4-2-1 | GCC 14.2.0 | -2.7% | -2.3% | -2.7% | -5.6% | -4.0% |
  | local | nodl / Cortex-A53 | GCC 11.4.0 | -3.3% | -7.6% | -5.7% | -9.9% | -1.8% |
  | andrewtoth | i9-14900HX | GCC 12.3 | -5.3% | -4.2% | -5.6% | -1.5% | -6.1% |
  | theStack | Snapdragon X Elite X1E-78-100 | GCC 14.2.0 | -11.2% | n/a | -11.1% | n/a | n/a |
  | sipa | Ryzen 5950X | GCC 15.2.0 | -11.4% | -10.4% | -8.4% | n/a | n/a |

  <img width="2534" height="1104" alt="image" src="https://github.com/user-attachments/assets/218a4075-5937-4850-ab8b-c6fc5d2fee57" />

  **Tradeoffs:** The speedups reproduce most consistently with GCC and MSVC. Clang was less consistently positive.

  Inlining also increases code size:
  | Platform | Artifact | Before | After | Delta |
  |---|---|---:|---:|---:|
  | macOS GCC | `libsecp256k1.a` | 1,254,320 | 1,311,368 | +57,048 (+4.55%) |
  | Linux GCC | `libsecp256k1.a` | 1,271,040 | 1,330,808 | +59,768 (+4.70%) |
  | Windows MSVC Release | `libsecp256k1-*.dll` | 1,239,040 | 1,414,144 | +175,104 (+14.13%) |

  ---

  <details><summary>Linux benchmarking script</summary>

  ```bash
  BEFORE=8363a2d8d1b47857c437f7cf22bd11ab06c7c50f; AFTER=33b1b9c455eb2bb07eded939b36abc49859d2ccf; CC=gcc; \
  API_ITERS=10000; INT_ITERS=200000; JOBS=1; \
  BH=$(git rev-parse --short=12 "$BEFORE") && AH=$(git rev-parse --short=12 "$AFTER") && \
  RUN=$(date +%Y%m%d%H%M%S) && \
  ROOT="$PWD/.bench-builds/gcc-$BH-$AH-$RUN" && \
  RAW="$PWD/.bench-results/secp-bench-gcc-$BH-$AH-$RUN.txt" && \
  (set -e; \
    mkdir -p "$ROOT" "$(dirname "$RAW")"; \
    printf "host: %s, compiler: %s\n" "$(hostname)" "$("$CC" --version | sed -n '1p')" | tee "$RAW" >&2; \
    old=$(git symbolic-ref --short -q HEAD || git rev-parse HEAD); \
    trap 'git switch -q "$old" 2>/dev/null || git switch -q --detach "$old"' EXIT; \
    for side in before after; do \
      ref=$([ "$side" = before ] && printf %s "$BEFORE" || printf %s "$AFTER"); \
      git cat-file -e "$ref^{commit}" 2>/dev/null || git fetch -q origin "$ref"; \
      h=$(git rev-parse --short=12 "$ref"); \
      b="$ROOT/$side-$h"; \
      echo "== $side $h ==" >&2; \
      git switch -q --detach "$ref"; \
      cmake -S . -B "$b" -DCMAKE_C_COMPILER="$CC" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSECP256K1_BUILD_BENCHMARK=ON -DSECP256K1_BUILD_TESTS=OFF -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF -DSECP256K1_BUILD_CTIME_TESTS=OFF -DSECP256K1_BUILD_EXAMPLES=OFF -DSECP256K1_ENABLE_MODULE_MUSIG=OFF -DSECP256K1_VALGRIND=OFF >> "$RAW" 2>&1; \
      cmake --build "$b" -j "$JOBS" --target bench bench_internal >> "$RAW" 2>&1; \
      echo "=== $side $ref $h ===" >> "$RAW"; \
      SECP256K1_BENCH_ITERS=$API_ITERS "$b/bin/bench" ecdsa ec ecdh schnorrsig ellswift >> "$RAW"; \
      SECP256K1_BENCH_ITERS=$INT_ITERS "$b/bin/bench_internal" field group ecmult hash context >> "$RAW"; \
    done; \
    awk -F, '/^=== /{split($0,p," "); side=p[2]; next} /^[[:alnum:]_][[:alnum:]_]*[[:space:]]*,/{name=$1; val=$2+0; gsub(/^[[:space:]]+|[[:space:]]+$/,"",name); if(name!="Benchmark"){if(!(name in seen)){seen[name]=1; order[++n]=name} x[side,name]=val}} END{print "Benchmark\tBefore min(us)\tAfter min(us)\tDelta"; for(i=1;i<=n;i++){name=order[i]; b=x["before",name]; a=x["after",name]; if(b&&a) printf "%s\t%.6g\t%.6g\t%+.1f%%\n",name,b,a,100*(a-b)/b}}' "$RAW" | column -t -s $'\t'; \
    echo "raw: $RAW" >&2)
  ```
  </details>

  <details><summary>Linux size comparison script</summary>

  ```bash
  BEFORE=8363a2d8d1b47857c437f7cf22bd11ab06c7c50f; AFTER=33b1b9c455eb2bb07eded939b36abc49859d2ccf; CC=gcc; JOBS=1; \
  BH=$(git rev-parse --short=12 "$BEFORE"); AH=$(git rev-parse --short=12 "$AFTER"); RUN=$(date +%Y%m%d%H%M%S); ROOT="$PWD/.size-builds/gcc-$BH-$AH-$RUN"; \
  (set -e; old=$(git symbolic-ref --short -q HEAD || git rev-parse HEAD); trap 'git switch -q "$old" 2>/dev/null || git switch -q --detach "$old"' EXIT; \
  printf "host: %s, compiler: %s\n" "$(hostname)" "$("$CC" --version | sed -n '1p')"; \
  for side in before after; do \
    ref=$([ "$side" = before ] && printf %s "$BEFORE" || printf %s "$AFTER"); git cat-file -e "$ref^{commit}" 2>/dev/null || git fetch -q origin "$ref"; h=$(git rev-parse --short=12 "$ref"); b="$ROOT/$side-$h"; \
    git switch -q --detach "$ref"; \
    cmake -S . -B "$b" -DCMAKE_C_COMPILER="$CC" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSECP256K1_BUILD_BENCHMARK=OFF -DSECP256K1_BUILD_TESTS=OFF -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF -DSECP256K1_BUILD_CTIME_TESTS=OFF -DSECP256K1_BUILD_EXAMPLES=OFF -DSECP256K1_ENABLE_MODULE_MUSIG=OFF -DSECP256K1_VALGRIND=OFF >/dev/null; \
    cmake --build "$b" -j "$JOBS" --target secp256k1 >/dev/null; \
    lib=$(find "$b" -name 'libsecp256k1.a' -print -quit); \
    bytes=$(wc -c < "$lib" | tr -d ' '); \
    printf "%s\t%s\t%s\n" "$side" "$h" "$bytes"; \
    done | awk 'BEGIN{print "Side\tCommit\tlibsecp256k1.a bytes"} {print; size[$1]=$3} END{if(size["before"]&&size["after"]) printf "Delta\t\t%+d bytes (%+.2f%%)\n",size["after"]-size["before"],100*(size["after"]-size["before"])/size["before"]}' | column -t -s $'\t')
  ```
  </details>

  <details><summary>host: M4-Max.local, compiler: gcc-14 (Homebrew GCC 14.3.0) 14.3.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              17.5            15.9           -9.1%
  ecdsa_sign                12.3            12.1           -1.6%
  ec_keygen                 8.07            7.77           -3.7%
  ecdh                      16.6            15.1           -9.0%
  schnorrsig_sign           8.6             8.29           -3.6%
  schnorrsig_verify         17.8            16.1           -9.6%
  ellswift_encode           11.1            11.1           +0.0%
  ellswift_decode           4.68            4.69           +0.2%
  ellswift_keygen           19.4            19.1           -1.5%
  ellswift_ecdh             18.5            17.1           -7.6%
  field_half                0.00154         0.00155        +0.6%
  field_normalize           0.00665         0.00672        +1.1%
  field_normalize_weak      0.00291         0.00291        +0.0%
  field_sqr                 0.00871         0.0081         -7.0%
  field_mul                 0.00969         0.0093         -4.0%
  field_inverse             1.57            1.58           +0.6%
  field_inverse_var         0.735           0.742          +1.0%
  field_is_square_var       0.994           1              +0.6%
  field_sqrt                2.21            2.22           +0.5%
  group_double_var          0.0502          0.0447         -11.0%
  group_add_var             0.126           0.11           -12.7%
  group_add_affine          0.1             0.0922         -7.8%
  group_add_affine_var      0.0887          0.077          -13.2%
  group_add_zinv_var        0.106           0.0902         -14.9%
  group_to_affine_var       0.774           0.774          +0.0%
  ecmult_wnaf               0.334           0.334          +0.0%
  hash_sha256               0.12            0.12           +0.0%
  hash_hmac_sha256          0.464           0.463          -0.2%
  hash_rfc6979_hmac_sha256  2.55            2.55           +0.0%
  context_create            1.96            1.96           +0.0%

  Side    Commit                 libsecp256k1.a bytes
  before  8363a2d8d1           1254320
  after   33b1b9c455eb           1311368
  Delta   +57048 bytes (+4.55%)
  ```

  </details>

  <details><summary>host: WIN-A2EHOAU4JET (Intel(R) Xeon(R) CPU E5-2637 v2 @ 3.50GHz), system: Microsoft Windows NT 10.0.20348.0, compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.50.35728 for x64</summary>

  ```bash
  Benchmark                    Before min(us) After min(us)    Delta
  ecdsa_verify                           74.1          72.2    -2.6%
  ecdsa_sign                             43.3          41.4    -4.4%
  ec_keygen                              32.3            30    -7.1%
  ecdh                                     75            68    -9.3%
  schnorrsig_sign                        34.1            32    -6.2%
  schnorrsig_verify                      74.9          73.1    -2.4%
  ellswift_encode                        32.3          32.5    +0.6%
  ellswift_decode                        14.4          14.6    +1.4%
  ellswift_keygen                        64.6          62.9    -2.6%
  ellswift_ecdh                          80.2          73.7    -8.1%
  field_half                          0.00378       0.00378    +0.0%
  field_normalize                      0.0114        0.0114    +0.0%
  field_normalize_weak                0.00389       0.00389    +0.0%
  field_sqr                            0.0272        0.0252    -7.4%
  field_mul                            0.0394        0.0365    -7.4%
  field_inverse                          3.27          3.29    +0.6%
  field_inverse_var                      2.07          2.11    +1.9%
  field_is_square_var                     2.7          2.67    -1.1%
  field_sqrt                             7.47          6.98    -6.6%
  group_double_var                      0.245         0.207   -15.5%
  group_add_var                           0.6         0.525   -12.5%
  group_add_affine                      0.465         0.405   -12.9%
  group_add_affine_var                  0.418         0.358   -14.4%
  group_add_zinv_var                    0.458         0.403   -12.0%
  group_to_affine_var                    2.25          2.26    +0.4%
  ecmult_wnaf                            0.58          0.59    +1.7%
  hash_sha256                           0.332         0.333    +0.3%
  hash_hmac_sha256                       1.31          1.31    +0.0%
  hash_rfc6979_hmac_sha256               7.23           7.2    -0.4%
  context_create                         3.32          3.34    +0.6%

  Side     Commit          DLL bytes
  before   8363a2d8d1      1239040
  after    a37e34e187da      1414144
  Delta                      175104 (+14.13%)
  ```
  </details>

  <details><summary>host: i9-ssd, compiler: gcc (GCC) 16.1.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              39.6            37.5           -5.3%
  ecdsa_sign                27.1            26.4           -2.6%
  ec_keygen                 18.2            17.5           -3.8%
  ecdh                      39              37.4           -4.1%
  schnorrsig_sign           19.5            18.7           -4.1%
  schnorrsig_verify         40.3            38.1           -5.5%
  ellswift_encode           20.1            19.9           -1.0%
  ellswift_decode           8.59            8.46           -1.5%
  ellswift_keygen           38.2            37.3           -2.4%
  ellswift_ecdh             43.4            40.9           -5.8%
  field_half                0.00275         0.00275        +0.0%
  field_normalize           0.00995         0.00994        -0.1%
  field_normalize_weak      0.00378         0.00378        +0.0%
  field_sqr                 0.0178          0.015          -15.7%
  field_mul                 0.019           0.0168         -11.6%
  field_inverse             2.41            2.39           -0.8%
  field_inverse_var         1.32            1.28           -3.0%
  field_is_square_var       1.69            1.68           -0.6%
  field_sqrt                4.21            4.16           -1.2%
  group_double_var          0.121           0.115          -5.0%
  group_add_var             0.309           0.272          -12.0%
  group_add_affine          0.248           0.231          -6.9%
  group_add_affine_var      0.216           0.194          -10.2%
  group_add_zinv_var        0.245           0.213          -13.1%
  group_to_affine_var       1.41            1.36           -3.5%
  ecmult_wnaf               0.536           0.581          +8.4%
  hash_sha256               0.29            0.286          -1.4%
  hash_hmac_sha256          1.14            1.13           -0.9%
  hash_rfc6979_hmac_sha256  6.3             6.21           -1.4%
  context_create            2.68            2.68           +0.0%

  Side    Commit        libsecp256k1.a bytes
  before  8363a2d8d1  1271040
  after   33b1b9c455eb  1330808
  Delta                 +59768 bytes (+4.70%)
  ```
  </details>

  <details><summary>host: i7-hdd, compiler: gcc (Ubuntu 14.2.0-19ubuntu2) 14.2.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              43.1            38.4           -10.9%
  ecdsa_sign                28.4            27.3           -3.9%
  ec_keygen                 19.3            18             -6.7%
  ecdh                      43.2            38.4           -11.1%
  schnorrsig_sign           20.6            19.4           -5.8%
  schnorrsig_verify         43.7            39.1           -10.5%
  ellswift_encode           19.9            19.7           -1.0%
  ellswift_decode           8.48            8.41           -0.8%
  ellswift_keygen           39.2            37.8           -3.6%
  ellswift_ecdh             46.4            41.8           -9.9%
  field_half                0.00275         0.00275        +0.0%
  field_normalize           0.00998         0.00998        +0.0%
  field_normalize_weak      0.00402         0.00402        +0.0%
  field_sqr                 0.017           0.0154         -9.4%
  field_mul                 0.0218          0.0171         -21.6%
  field_inverse             2.49            2.46           -1.2%
  field_inverse_var         1.36            1.35           -0.7%
  field_is_square_var       1.66            1.67           +0.6%
  field_sqrt                4.07            4.07           +0.0%
  group_double_var          0.132           0.119          -9.8%
  group_add_var             0.346           0.28           -19.1%
  group_add_affine          0.266           0.236          -11.3%
  group_add_affine_var      0.243           0.201          -17.3%
  group_add_zinv_var        0.265           0.216          -18.5%
  group_to_affine_var       1.46            1.44           -1.4%
  ecmult_wnaf               0.554           0.604          +9.0%
  hash_sha256               0.305           0.298          -2.3%
  hash_hmac_sha256          1.18            1.17           -0.8%
  hash_rfc6979_hmac_sha256  6.47            6.43           -0.6%
  context_create            2.73            2.71           -0.7%
  ```

  </details>

  <details><summary>host: rpi5-16-3, compiler: gcc (Ubuntu 14.2.0-19ubuntu2) 14.2.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              157             156            -0.6%
  ecdsa_sign                69.5            69.3           -0.3%
  ec_keygen                 57.6            57.5           -0.2%
  ecdh                      149             148            -0.7%
  schnorrsig_sign           59.3            59             -0.5%
  schnorrsig_verify         158             157            -0.6%
  ellswift_encode           44.9            44.8           -0.2%
  ellswift_decode           24.2            24.2           +0.0%
  ellswift_keygen           103             102            -1.0%
  ellswift_ecdh             154             154            +0.0%
  field_half                0.00334         0.00334        +0.0%
  field_normalize           0.0143          0.0144         +0.7%
  field_normalize_weak      0.00543         0.00543        +0.0%
  field_sqr                 0.0654          0.0618         -5.5%
  field_mul                 0.0919          0.091          -1.0%
  field_inverse             4.8             4.78           -0.4%
  field_inverse_var         2.24            2.24           +0.0%
  field_is_square_var       2.31            2.31           +0.0%
  field_sqrt                17              17             +0.0%
  group_double_var          0.526           0.525          -0.2%
  group_add_var             1.35            1.34           -0.7%
  group_add_affine          0.988           0.984          -0.4%
  group_add_affine_var      0.926           0.915          -1.2%
  group_add_zinv_var        1.02            1.01           -1.0%
  group_to_affine_var       2.6             2.6            +0.0%
  ecmult_wnaf               0.606           0.614          +1.3%
  hash_sha256               0.316           0.315          -0.3%
  hash_hmac_sha256          1.2             1.2            +0.0%
  hash_rfc6979_hmac_sha256  6.62            6.62           +0.0%
  context_create            4.18            4.18           +0.0%
  ```
  </details>

  <details><summary>host: rpi4-2-1, compiler: gcc (Ubuntu 14.2.0-19ubuntu2) 14.2.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              222             216            -2.7%
  ecdsa_sign                111             109            -1.8%
  ec_keygen                 90.4            88.6           -2.0%
  ecdh                      216             211            -2.3%
  schnorrsig_sign           93.4            91.4           -2.1%
  schnorrsig_verify         224             218            -2.7%
  ellswift_encode           64.2            64.1           -0.2%
  ellswift_decode           33.5            33.5           +0.0%
  ellswift_keygen           156             153            -1.9%
  ellswift_ecdh             226             220            -2.7%
  field_half                0.00447         0.00447        +0.0%
  field_normalize           0.0215          0.0215         +0.0%
  field_normalize_weak      0.00783         0.00783        +0.0%
  field_sqr                 0.0871          0.0822         -5.6%
  field_mul                 0.126           0.121          -4.0%
  field_inverse             8.54            8.54           +0.0%
  field_inverse_var         3.25            3.25           +0.0%
  field_is_square_var       3.57            3.57           +0.0%
  field_sqrt                22.7            22.6           -0.4%
  group_double_var          0.72            0.71           -1.4%
  group_add_var             1.87            1.8            -3.7%
  group_add_affine          1.4             1.36           -2.9%
  group_add_affine_var      1.3             1.24           -4.6%
  group_add_zinv_var        1.42            1.37           -3.5%
  group_to_affine_var       3.76            3.75           -0.3%
  ecmult_wnaf               1.06            1.05           -0.9%
  hash_sha256               0.532           0.531          -0.2%
  hash_hmac_sha256          2.02            2.02           +0.0%
  hash_rfc6979_hmac_sha256  11.2            11.2           +0.0%
  context_create            6.8             6.8            +0.0%
  ```
  </details>

  <details><summary>host: umbrel (Intel(R) N150), compiler: gcc (Debian 12.2.0-14+deb12u1) 12.2.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              371             353            -4.9%
  ecdsa_sign                163             160            -1.8%
  ec_keygen                 129             123            -4.7%
  ecdh                      347             332            -4.3%
  schnorrsig_sign           131             126            -3.8%
  schnorrsig_verify         373             356            -4.6%
  ellswift_encode           143             142            -0.7%
  ellswift_decode           71.3            70.8           -0.7%
  ellswift_keygen           272             268            -1.5%
  ellswift_ecdh             367             352            -4.1%
  field_half                0.0124          0.0124         +0.0%
  field_normalize           0.0439          0.0439         +0.0%
  field_normalize_weak      0.0192          0.0192         +0.0%
  field_sqr                 0.168           0.169          +0.6%
  field_mul                 0.182           0.18           -1.1%
  field_inverse             11.2            11.2           +0.0%
  field_inverse_var         8.44            8.4            -0.5%
  field_is_square_var       9.56            9.55           -0.1%
  field_sqrt                45              44             -2.2%
  group_double_var          1.25            1.18           -5.6%
  group_add_var             2.92            2.68           -8.2%
  group_add_affine          2.22            2.12           -4.5%
  group_add_affine_var      2.02            1.86           -7.9%
  group_add_zinv_var        2.21            2.01           -9.0%
  group_to_affine_var       9.25            9.13           -1.3%
  ecmult_wnaf               2.51            2.45           -2.4%
  hash_sha256               1.13            1.12           -0.9%
  hash_hmac_sha256          4.44            4.44           +0.0%
  hash_rfc6979_hmac_sha256  24.4            24.4           +0.0%
  context_create            14.2            14.1           -0.7%
  ```
  </details>

  <details><summary>host: nodl (Cortex-A53), compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              632             611            -3.3%
  ecdsa_sign                308             291            -5.5%
  ec_keygen                 228             212            -7.0%
  ecdh                      633             585            -7.6%
  schnorrsig_sign           231             221            -4.3%
  schnorrsig_verify         630             594            -5.7%
  ellswift_encode           156             156            +0.0%
  ellswift_decode           80              76.1           -4.9%
  ellswift_keygen           438             455            +3.9%
  ellswift_ecdh             613             599            -2.3%
  field_half                0.0106          0.00985        -7.1%
  field_normalize           0.0483          0.0499         +3.3%
  field_normalize_weak      0.0173          0.0173         +0.0%
  field_sqr                 0.202           0.182          -9.9%
  field_mul                 0.278           0.273          -1.8%
  field_inverse             21.3            21.1           -0.9%
  field_inverse_var         7.67            7.48           -2.5%
  field_is_square_var       8.73            8.91           +2.1%
  field_sqrt                65.8            61.9           -5.9%
  group_double_var          2.04            1.9            -6.9%
  group_add_var             5.35            5.09           -4.9%
  group_add_affine          3.93            3.51           -10.7%
  group_add_affine_var      3.56            3.32           -6.7%
  group_add_zinv_var        3.94            3.65           -7.4%
  group_to_affine_var       9.56            10.4           +8.8%
  ecmult_wnaf               2.37            2.48           +4.6%
  hash_sha256               1.13            1.19           +5.3%
  hash_hmac_sha256          5.08            4.76           -6.3%
  hash_rfc6979_hmac_sha256  33.3            31.2           -6.3%
  context_create            19.3            18.8           -2.6%
  ```
  </details>

  <details><summary>Reviewer measurements</summary>

  ### andrewtoth, i9-14900HX, GCC 12.3

  ```text
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              22.7            21.5           -5.3%
  ecdsa_sign                14.3            14.0           -2.1%
  ec_keygen                 9.90            9.54           -3.6%
  ecdh                      21.6            20.7           -4.2%
  schnorrsig_sign           10.6            10.2           -3.8%
  schnorrsig_verify         23.1            21.8           -5.6%
  ellswift_ecdh             23.8            22.7           -4.6%
  field_sqr                 0.00912         0.00898        -1.5%
  field_mul                 0.0114          0.0107         -6.1%
  field_inverse             1.23            1.24           +0.8%
  field_inverse_var         0.770           0.773          +0.4%
  field_is_square_var       1.06            1.05           -0.9%
  field_sqrt                2.82            2.46           -12.8%
  group_double_var          0.0701          0.0612         -12.7%
  group_add_var             0.168           0.153          -8.9%
  group_add_affine          0.132           0.123          -6.8%
  group_add_affine_var      0.120           0.103          -14.2%
  group_add_zinv_var        0.138           0.117          -15.2%
  group_to_affine_var       0.820           0.819          -0.1%
  ```

  ### theStack, Snapdragon X Elite X1E-78-100, GCC 14.2.0

  ```text
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              24.1            21.4           -11.2%
  ecdsa_sign                19.0            18.5           -2.6%
  schnorrsig_sign           13.0            12.7           -2.3%
  schnorrsig_verify         24.4            21.7           -11.1%
  ```

  Bitcoin Core subtree `bench_bitcoin -filter=VerifyScript.*`:

  ```text
  Benchmark                   Before ns/script  After ns/script  Delta
  VerifyScriptP2TR_KeyPath    23679.52          20899.66         -11.7%
  VerifyScriptP2TR_ScriptPath 43430.71          39280.19         -9.6%
  VerifyScriptP2WPKH          23526.82          20870.22         -11.3%
  ```

  ### sipa, Ryzen 5950X, GCC 15.2.0

  ```text
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              30.8            27.3           -11.4%
  ecdsa_sign                18.7            17.2           -8.0%
  ec_keygen                 13.6            12.2           -10.3%
  ecdh                      29.8            26.7           -10.4%
  ecdsa_recover             31.0            28.2           -9.0%
  schnorrsig_sign           14.4            13.0           -9.7%
  schnorrsig_verify         31.1            28.5           -8.4%
  ellswift_encode           13.2            13.4           +1.5%
  ellswift_decode           5.79            5.84           +0.9%
  ellswift_keygen           26.8            25.7           -4.1%
  ellswift_ecdh             32.1            29.6           -7.8%
  ```
  </details>

  ---

  **clang:**
  <details><summary>host: i9-ssd, compiler: Ubuntu clang version 22.1.6 (++20260508084839+c0262e742787-1~exp1~20260508204859.77)</summary>

  ```bash
  Benchmark                 Before min(us)  After min(us)  Delta
  ecdsa_verify              40.1            39.8           -0.7%
  ecdsa_sign                29.2            29.1           -0.3%
  ec_keygen                 19.5            19.6           +0.5%
  ecdh                      40.3            39.8           -1.2%
  schnorrsig_sign           21              20.9           -0.5%
  schnorrsig_verify         40.6            40.3           -0.7%
  ellswift_encode           20.1            20.1           +0.0%
  ellswift_decode           8.43            8.41           -0.2%
  ellswift_keygen           39.8            39.7           -0.3%
  ellswift_ecdh             44.1            43.5           -1.4%
  field_half                0.0028          0.0028         +0.0%
  field_normalize           0.00889         0.00891        +0.2%
  field_normalize_weak      0.0037          0.0037         +0.0%
  field_sqr                 0.0144          0.0144         +0.0%
  field_mul                 0.021           0.019          -9.5%
  field_inverse             2.6             2.64           +1.5%
  field_inverse_var         1.34            1.35           +0.7%
  field_is_square_var       1.73            1.73           +0.0%
  field_sqrt                3.95            3.96           +0.3%
  group_double_var          0.128           0.125          -2.3%
  group_add_var             0.311           0.31           -0.3%
  group_add_affine          0.243           0.242          -0.4%
  group_add_affine_var      0.207           0.207          +0.0%
  group_add_zinv_var        0.229           0.228          -0.4%
  group_to_affine_var       1.43            1.44           +0.7%
  ecmult_wnaf               0.536           0.598          +11.6%
  hash_sha256               0.3             0.299          -0.3%
  hash_hmac_sha256          1.18            1.18           +0.0%
  hash_rfc6979_hmac_sha256  6.51            6.53           +0.3%
  context_create            2.16            2.15           -0.5%
  ```
  </details>

  **reindex-chainstate:**
  <details><summary>2026-05-28 | reindex-chainstate | 950059 blocks | dbcache 5000 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD</summary>

  ```bash
  for DBCACHE in 5000; do \
      COMMITS="67250b1d97e6159d908ef44639b6a12471e7c717 c264526415f38afb9890003003b7de39b370b745"; \
      STOP=950059; CC=gcc; CXX=g++; \
      BASE_DIR="/mnt/my_storage"; DATA_DIR="$BASE_DIR/BitcoinData"; LOG_DIR="$BASE_DIR/logs"; \
      (echo ""; for c in $COMMITS; do git fetch -q origin "$c" 2>/dev/null || true; git log -1 --pretty='%h %s' $c || exit 1; done) && \
      (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(l
  sblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
      hyperfine \
      --sort command \
      --runs 1 \
      --export-json "$BASE_DIR/rdx-$(sed -E 's/[^ ]+/\L&/g;s/[.]/_/g;s/ /-/g'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
      --parameter-list COMMIT ${COMMITS// /,} \
      --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
        cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release && ninja -C build bitcoind -j1 && \
        ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log; rm -rfd $DATA_DIR/indexes;" \
      --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block #1' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_
  DIR/debug.log | grep -q \"\$(git rev-parse --short=12 {COMMIT})\"; \
                  cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
      "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -assumevalid=0"; \
  done

  67250b1d97 parallel input fetcher
  c264526415 Refactor: optimize scalar reduction and arithmetic functions.

  2026-05-28 | reindex-chainstate | 950059 blocks | dbcache 5000 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

  Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=950059 -dbcache=5000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -assumevalid=0 (COMMIT = 67250b1d97e6159d908ef44639b6a12471e7c717)
    Time (abs ≡):        37155.108 s               [User: 375835.978 s, System: 978.929 s]

  Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=950059 -dbcache=5000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -assumevalid=0 (COMMIT = c264526415f38afb9890003003b7de39b370b745)
    Time (abs ≡):        36261.785 s               [User: 362247.387 s, System: 1002.867 s]

  Relative speed comparison
          1.02          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=950059 -dbcache=5000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -assumevalid=0 (COMMIT = 67250b1d97e6159d908ef44639b6a12471e7c717)
          1.00          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=950059 -dbcache=5000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -assumevalid=0 (COMMIT = c264526415f38afb9890003003b7de39b370b745)
  ```
  </details>

ACKs for top commit:
  real-or-random:
    utACK 71fcd8410e
  theStack:
    ACK 71fcd8410e
  hebasto:
    ACK 71fcd8410e, tested different scenarios on Linux and Windows.

Tree-SHA512: 4686badb33da4613fb43df69355354cbcbbf7cb726130670e8f97f7992332db39ca8c45c0e0944de9e2ead61c3d4b8fdd0a62b023f1cfcd2e8d9b2abb74084cd
2026-06-17 13:35:57 +02:00
merge-script
fdcf2d41e2 Merge bitcoin-core/secp256k1#1865: test: enable -Wunused-function in test suite (Fix #1831)
a77dacad9a test: enable -Wunused-function in test suite (Fix #1831) (kallal79)

Pull request description:

  This PR addresses issue #1831 by enabling the `-Wunused-function` compiler warning within the test suite.

  Currently, `-Wno-unused-function` is passed globally to disable warnings about unused functions, making it too easy to write a test case but forget to actually call it. To catch untested helper functions safely, this PR uses GCC/Clang pragmas scoped strictly to the body of the test files.

  ### Changes Made:
  - Added `#pragma GCC diagnostic warning "-Wunused-function"` directly after the `#include` statements in `src/tests.c`, `src/tests_exhaustive.c`, `src/ctime_tests.c`, and `src/unit_test.c`.
  Fixes #1831

ACKs for top commit:
  real-or-random:
    ACK a77dacad9a
  hebasto:
    ACK a77dacad9a.

Tree-SHA512: 775d633d9d2e95154b6718270ce1687a1b20c2c8cc67c909953b3395d76e6853e6be1d6a95d8aef3f15a78dec3497bea8e3864e36830977e11beb42ea9abcc31
2026-06-16 13:58:19 +02:00
merge-script
b2d2bd362d Merge bitcoin-core/secp256k1#1860: cmake: Emulate Libtool's behavior on NetBSD and OpenBSD
1eab757207 cmake: Fix shared library versioning on OpenBSD (Hennadii Stepanov)
a401c5145a cmake: Fix shared library versioning on NetBSD (Hennadii Stepanov)
8a0f4002c7 cmake, refactor: Improve documenting in `SetLibtoolAbiVersion` module (Hennadii Stepanov)
acf2084aa7 cmake, refactor: Introduce `SetLibtoolAbiVersion` module (Hennadii Stepanov)

Pull request description:

  This is a continuation of https://github.com/bitcoin-core/secp256k1/pull/1685.

  Additionally, the logic has been factored out into its own module and the documentation has been also improved.

ACKs for top commit:
  real-or-random:
    utACK 1eab757207

Tree-SHA512: 24738053d3049f0ce551b0d05d62642d7f1e6645967288fbe30ce4799f4e64594e88a8fa2dd9109efd6cfc5666d7c5fe7a3bb99f0f06766d70b2a9362721e3c9
2026-06-16 11:07:32 +02:00
merge-script
87bec430bf Merge bitcoin-core/secp256k1#1867: test: musig: fix dead "aggnonce encodes two points at infinity" check
d7125e517d test: musig: fix dead "aggnonce encodes two points at infinity" check (Sebastian Falbesoner)

Pull request description:

  Due to the missing `CHECK` around, the return values were discarded and nothing was actually checked here.

  (Fwiw I prompted two AI models (MiniMax M3 and Opus 4.8) to find more similar instances in tests with bare statements that miss a surrounding `CHECK` in tests, and both didn't find any.)

ACKs for top commit:
  real-or-random:
    utACK d7125e517d
  hebasto:
    ACK d7125e517d, I have reviewed the code and it looks OK.

Tree-SHA512: 6eab61ce51a414e0555413bde29cf582b70fbf4a24ad1aae135bf88f28e3ee25ece8c79b7ccc254288395fedf6b2547931d5e00b0090146f1b83e43acc6570d7
2026-06-16 08:27:58 +02:00
Lőrinc
71fcd8410e field: force-inline 5x52 mul and sqr
The 5x52 field multiplication and squaring routines are hot in group arithmetic and scalar multiplication.

Use the new `SECP256K1_FORCE_INLINE` for the thin wrappers and `int128` inner helpers so compilers can schedule the 64x64->128 arithmetic without a call boundary.

Across the measured GCC and MSVC Release builds, this improves ECDSA verification by 0.6% to 9.1%, ECDH by 0.7% to 9.3%, and Schnorr verification by 0.6% to 9.6%.

The direct field benchmarks generally show the intended effect on field squaring and multiplication, while Clang results are mostly flat and less consistently positive.

This is a code-size tradeoff: the tested static library builds grew by about 4.6% to 4.7%, and the tested Windows Release DLL grew by 14.1%.

Co-authored-by: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
Co-authored-by: Tim Ruffing <crypto@timruffing.de>
2026-06-15 23:56:19 +02:00
kallal79
a77dacad9a test: enable -Wunused-function in test suite (Fix #1831) 2026-06-12 19:10:33 +05:30
merge-script
aea86bc350 Merge bitcoin-core/secp256k1#1864: test: refactor: simplify tests by using _ecmult_gen_ge helper, add test
2ee79e77e6 test: add unit test for `_ecmult_gen_ge` (Sebastian Falbesoner)
ca68daf8e1 test: refactor: simplify tests by using `_ecmult_gen_ge` helper (Sebastian Falbesoner)

Pull request description:

  This PR is a small follow-up to #1861. If the generator point multiplication result in Jacobian coordinates is immediately converted to affine coordinates after and is not needed for anything else, we can deduplicate by using the new `secp256k1_ecmult_gen_ge` helper. The second commit adds a simple unit tests, verifying for random scalars that the result of `secp256k1_ecmult_gen_ge` matches the two expected steps (`secp256k1_ecmult_gen_gej` plus Jacobian->affine conersion via `secp256k1_ge_set_gej`).

  Note that in a very strict sense the first commit is not a refactor, as the Jacobian object is now cleared out which was not done on master, but for the logic in the tests this shouldn't matter at all.

ACKs for top commit:
  real-or-random:
    utACK 2ee79e77e6

Tree-SHA512: 452895b6f6e70c686063afb051d25dab1d086aac28081c4a3071a3dbe7dae964e806f9fe8052b88a7da4305a0cf636badc2dba817cae96aae0a35b2bc9675c03
2026-06-12 08:47:31 +02:00
Sebastian Falbesoner
2ee79e77e6 test: add unit test for _ecmult_gen_ge 2026-06-11 17:56:32 +02:00
Sebastian Falbesoner
d7125e517d test: musig: fix dead "aggnonce encodes two points at infinity" check 2026-06-10 00:21:24 +02:00
Hennadii Stepanov
1eab757207 cmake: Fix shared library versioning on OpenBSD 2026-06-09 13:23:25 +01:00
Hennadii Stepanov
a401c5145a cmake: Fix shared library versioning on NetBSD 2026-06-09 13:23:15 +01:00
Hennadii Stepanov
8a0f4002c7 cmake, refactor: Improve documenting in SetLibtoolAbiVersion module 2026-06-09 13:23:08 +01:00
Hennadii Stepanov
acf2084aa7 cmake, refactor: Introduce SetLibtoolAbiVersion module 2026-06-09 13:22:57 +01:00
merge-script
0f4a7e6bf9 Merge bitcoin-core/secp256k1#1855: bench: add internal benchmark for secp256k1_fe_normalize_var
240578eef5 bench: add internal benchmark for `secp256k1_fe_normalize_var` (Sebastian Falbesoner)

Pull request description:

  While addressing the review suggestion https://github.com/bitcoin-core/secp256k1/pull/1765#discussion_r3238616034 ([b10c mirror link](https://mirror.b10c.me/bitcoin-core-secp256k1/1765/#discussion_r3238616034)), I noticed that we don't have an internal benchmark for the variable-time variant of `_fe_normalize` yet, so this PR adds one. IIUC it's fine to repeatedly apply the operation on the same (already normalized at latest after the first loop iteration) field element for benchmarking purposes and don't put in an effort to reach the [final reduction code path](b11340b3ce/src/field_5x52_impl.h (L120-L132)), considering how extremely unlikely it is to reach it in practice.

  Results on my machine:
  ```
  $ ./build/bin/bench_internal normalize
  Benchmark                     ,    Min(us)    ,    Avg(us)    ,    Max(us)

  field_normalize               ,     0.0103    ,     0.0106    ,     0.0128
  field_normalize_var           ,     0.00545   ,     0.00546   ,     0.00547
  field_normalize_weak          ,     0.00352   ,     0.00354   ,     0.00363
  ```

ACKs for top commit:
  real-or-random:
    utACK 240578eef5

Tree-SHA512: 4480e65b24c9e3c498389c5faf807cc44ae2a421d4500dd95066f9bb4f4885c67d2a6e1875e93912b96422963fd1430f724d442f30eb152faf86302ba266bd94
2026-06-09 10:05:56 +02:00
Sebastian Falbesoner
ca68daf8e1 test: refactor: simplify tests by using _ecmult_gen_ge helper
If the generator point multiplication result in Jacobian coordinates is
immediately converted to affine coordinates after and is not needed for
anything else, we can deduplicate by using the helper introduced in #1861.

Note that in a very strict sense this is not a refactor, as the Jacobian
object is now cleared out which was not done on master, but for the logic
in the tests this shouldn't matter at all.
2026-06-08 18:44:58 +02:00
merge-script
13db747f2b Merge bitcoin-core/secp256k1#1861: refactor: introduce _ecmult_gen_ge helper (preventing accidental gej leaks)
9e017e5062 refactor: rename `_ecmult_gen` -> `_ecmult_gen_gej` for consistency (Sebastian Falbesoner)
a3296d5e23 refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks) (Sebastian Falbesoner)

Pull request description:

  Scalar multiplication with the generator point frequently involves a conversion to affine coordinates and clearing out the temporary Jacobian group element object after to avoid leaking secret key material (see 765ef53335 / #1579 for that last part), i.e. executing the following three functions:
  * `secp256k1_ecmult_gen(ctx, &rj, ...)`
  * `secp256k1_ge_set_gej(&r, &rj)`
  * `secp256k1_gej_clear(&rj)`

  This PR introduces a corresponding helper to deduplicate code and mitigate the risk that the last step is forgotten (which can easily happen, as it would not be detected by tests). It is applied in the code paths for ECDSA signing, Schnorr signing, public key creation and ecmult_gen blinding setup. The only remaining instance where we directly call `_ecmult_gen` is for [musig nonce generation](a39093de15/src/modules/musig/session_impl.h (L416)), as we apply batch inversion there for the two points.

  The idea came up during a conversation with furszy, who caught that the gej clearing was missing in the silentpayments module (sending function) as well (see https://github.com/bitcoin-core/secp256k1/pull/1765#issuecomment-4482838033, [b10c mirror link](https://mirror.b10c.me/bitcoin-core-secp256k1/1765/#issuecomment-4482838033)).

  If this gets conceptual support, I'd be curious to hear naming suggestions, as I'm not sure if the current one is fits well to the existing terminology (maybe `ecmult_gen_ge` or `ecmult_gen_to_affine`?).

ACKs for top commit:
  real-or-random:
    utACK 9e017e5062
  furszy:
    ACK 9e017e5062

Tree-SHA512: e9dc96c4301622e5b258de5c2cff5bd9f27d07d3a5f881d937c3db526e2c0a7ba5772ea24585af37be359e0510136916a15b39316c7c351d068c09545c003b6e
2026-06-08 17:36:17 +02:00
Sebastian Falbesoner
9e017e5062 refactor: rename _ecmult_gen -> _ecmult_gen_gej for consistency
Now that we have a function `_ecmult_gen_ge`, it makes sense to rename
the existing function `_ecmult_gen` to `_ecmult_gen_gej` for
consistency, to signal that the result is a Jacobian group element.

This diff was created by applying
```
$ sed -i s/secp256k1_ecmult_gen\(/secp256k1_ecmult_gen_gej\(/g $(git ls-files)
```
2026-06-07 20:21:18 +02:00