Commit Graph

3440 Commits

Author SHA1 Message Date
Kgothatso Ngako
7a35fde10f frost_enrollment: correct the zeroing contract and harden the CI guard
Some checks are pending
CI / Build arm64 Docker image (push) Waiting to run
CI / Build x64 Docker image (push) Waiting to run
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFR… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROO… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORR… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes … (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:ye… (push) Blocked by required conditions
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 FROST_ENROLLMENT:yes GENERATOR:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHN… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRAC… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSI… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:ye… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RA… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes … (push) Blocked by required conditions
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 FROST_ENROLLMENT:yes GENERATOR:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNOR… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / i686: Linux (Debian stable) (clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include, map[env_vars:map[]]) (push) Blocked by required conditions
CI / i686: Linux (Debian stable) (i686-linux-gnu-gcc, map[env_vars:map[]]) (push) Blocked by required conditions
CI / s390x (big-endian): Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[ASM:arm32 EXPERIMENTAL:yes]]) (push) Blocked by required conditions
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (clang, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (gcc, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[]]) (push) Blocked by required conditions
CI / ppc64le: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / Valgrind arm64 (memcheck) (push) Blocked by required conditions
CI / Valgrind i686 (memcheck) (push) Blocked by required conditions
CI / Valgrind x64 (memcheck) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:clang]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:i686-linux-gnu-gcc HOST:i686-linux-gnu]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:clang ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:i686-linux-gnu-gcc ECMULTGENKB:2 ECMULTWINDOW:2 HOST:i686-linux-gnu]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Blocked by required conditions
CI / i686 (mingw32-w64): Windows (Debian stable, Wine) (push) Blocked by required conditions
CI / x86_64 (mingw32-w64): Windows (Debian stable, Wine) (push) Blocked by required conditions
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOV… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes FROST_ENROLLMENT:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:y… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BUILD:distcheck]) (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[RECOVERY:yes WIDEMUL:int128]) (push) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
CI / ARM64: macOS Sonoma (map[BUILD:distcheck]) (push) Waiting to run
CI / ARM64: macOS Sonoma (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Waiting to run
CI / ARM64: macOS Sonoma (map[RECOVERY:yes WIDEMUL:int128]) (push) Waiting to run
CI / x86 (MSVC): Windows (VS 2022) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, static) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, shared) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, int128_struct) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, static) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, shared) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, int128_struct) (push) Waiting to run
CI / x64 (MSVC): C++ (public headers) (push) Waiting to run
CI / C++ -fpermissive (entire project) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / C++ (public headers) (push) Blocked by required conditions
CI / SageMath prover (push) Waiting to run
CI / release (push) Waiting to run
The two findings from the second review round, plus the coverage gap and
comment error it noted.

Finding 8: the zeroing exception was narrower in the docs than in the
code.

  The previous commit's fix leaves shares32_out untouched on EVERY
  params_are_valid rejection -- duplicate ids, threshold < 2, new_id
  among the helpers, an id >= n, the mode bounds -- but the header
  scoped the exception to "when n_ids itself is out of range", and
  frost_enrollment.md still said flatly that outputs are zeroed on every
  failure path. A caller who inspects the buffer after a failed call
  would, on a duplicate-id or t = 1 rejection, read whatever was there
  before. In this protocol that can be additive shares of a secret from
  an earlier call.

  Both now state the actual invariant: not written when the parameter
  tuple is rejected, because its extent is only known to be u*32 once
  n_ids has been validated against the rest of the tuple; zeroed on
  every failure found after that point (an unusable thresh_pk, my_id not
  among the helpers, an invalid secret share). The .md adds the sentence
  a defensive caller needs: treat a rejected tuple as leaving the buffer
  unmodified, not as leaving it zeroed. Documentation only -- the
  implementation and the tests already agreed with this reading.

Finding 9: the new CMake CI step never checked that the modules landed.

  It configured, built and installed with all five module flags, then
  ran `ls -RlAh` -- which prints and does not assert -- and linked
  examples/ecdsa.c, which uses core symbols only. Deleting the
  add_compile_definitions or PUBLIC_HEADER line for a module during an
  upstream sync would keep the step green: no module code means no
  undefined references, and the install simply omits the header. The
  guard added one commit ago caught a MISORDERED block but not a
  MISSING one.

  The step now asserts both halves. `ls` of all five module headers
  fails the step under bash -e if any is absent, and
  examples/frost_enrollment.c is compiled and run against the installed
  library, which no header-only check would cover -- it needs the
  symbols to actually be in the library.

  Verified by running the step's exact command sequence under bash -e:
  it exits 0 as written, and against an install configured WITHOUT the
  modules the header assertion exits 2 and the example fails to compile
  on the missing include.

Coverage: the params-hash attribution path was still only tested where
identifier equals index. The previous commit pinned identifier
semantics for the scalar-overflow path on helper set {0, 2}, but
share_agg's other `*mismatch_id = ids[i]` -- the parameters-hash
disagreement -- was exercised only on {0, 1}. It is now pinned on
{1, 3}, corrupting each slot in turn so the mapping is fixed at both
ends: index 0 must report 1, index 1 must report 3. Verified
load-bearing by changing the assignment to `(uint32_t)i`, which fails
the new case.

Comment error: the {0, 2} overflow case carried the claim that it would
catch an implementation returning array indices. It would not -- it
corrupts slot 0, whose identifier is also 0. The discrimination comes
from the paired own-slot case at slot 1 (identifier 2), and the comment
now says so.

Correcting the record rather than rewriting it: commit 69766dd3's
message says the suite goes "from 12 cases to 16" with "six new tests".
Both counts are wrong. The contract test landed in 266c6a7c, so the
table went 13 -> 17, and that commit added four cases (api, infinity,
no_side_effects, max_size) alongside the x = 0 addition to an existing
test and the two de-confoundings. The commits are unpushed and could be
amended, but the review cites them by hash, so the numbers are corrected
here instead. With this commit the module has 17 tests.

Verification: warning-free build; 17/17 at -i=16, -i=200 and -i=1000;
./tests, ./noverify_tests and ./exhaustive_tests exit 0; `make check`
12/12; the module clean under valgrind (0 errors from 0 contexts);
ctime_tests clean under valgrind; CMake ctest 542/542; vectors.h still
regenerates byte for byte, so nothing here touched a frozen encoding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 11:35:59 +02:00
Kgothatso Ngako
98aadc121f build: give the experimental modules CMake coverage in CI
Closes the last gap the review listed, and the one the plan left as
optional: no CI job built any experimental module through CMake, so the
src/CMakeLists.txt wiring for frost, chilldkg, iceberg, prefractal and
frost_enrollment was guarded only by developers running it locally.

The plan suggested "adding the experimental modules to one existing
CMake job". There are two candidates and they are not equivalent:

- win64-native is the only job that RUNS CMake tests, but it builds with
  MSVC and clang-cl under CFLAGS="/WX". None of the five modules has
  ever been compiled by MSVC. Turning them on there would be a porting
  exercise whose first result is a wall of warnings-as-errors from code
  unrelated to any regression -- and it would land that on four modules
  this branch does not otherwise touch.
- The release job's "Check installation with CMake" step is gcc on
  Linux, the same compiler and platform where all five are known to
  build. It configures, builds and installs.

The second is where the flags go. It does not run ctest, which is fine:
the tests already run under autotools in 45 job contexts. What was
unguarded was the WIRING, and this step exercises exactly that -- the
SECP256K1_EXPERIMENTAL gate, the dependent-module block ordering, and
the PUBLIC_HEADER appends, which the install step then confirms landed
by listing the installed tree.

Verified that the guard is not decorative. Moving the frost_enrollment
block in src/CMakeLists.txt from before the FROST block to after it --
the exact trap the module's commit message describes, where a block that
force-enables a dependency runs too late for the block that emits its
compile definition -- makes this step fail with undefined references to
secp256k1_frost_derive_pubshare_at and friends. Before this change, that
mistake reached main with nothing complaining.

Also verified the command as written: configure, build and install with
all five modules on succeeds on gcc/Linux, the installed include
directory carries secp256k1_frost.h, secp256k1_chilldkg.h,
secp256k1_iceberg.h, secp256k1_prefractal.h and
secp256k1_frost_enrollment.h, and the step's follow-up compile of
examples/ecdsa.c against the installed library still links and runs. The
workflow parses, and the step really does carry all five module flags
plus the experimental gate.

This deliberately changes CI coverage for four modules beyond the one
this branch adds. It only adds coverage -- no existing job loses
anything -- but it is a one-line revert if the wider scope is unwanted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:30:21 +02:00
Kgothatso Ngako
3c962b00cc frost_enrollment: fix the example's stale n and failure-path hygiene
The last of the review findings, plus the comment and structure fixes it
listed.

The example's repair run used the pre-enrollment participant count.

  Two blocks earlier the example teaches that every participant must
  update its record of n from 3 to 4 after an enrollment, and the
  signing session duly uses N_PARTICIPANTS_AFTER. Then enroll() -- which
  hard-coded N_PARTICIPANTS -- ran the repair at n = 3. It worked only
  because the Lagrange math never involves n and every party in this
  single-process demo passed the same stale value.

  In a real post-enrollment repair it would not. n is bound into the
  parameters hash, so helpers feeding their updated n = 4 into
  shares_gen while the requester feeds n = 3 abort round 1.2 with no
  visible cause. enroll() now takes n_participants as a parameter, the
  repair passes N_PARTICIPANTS_AFTER, and both the function's contract
  comment and the repair call site say why. The repaired share is still
  byte-identical to the original, which is the point: n changes the
  hash, not the arithmetic.

The example leaked secrets on its failure paths.

  enroll() erased the delta and sigma buffers only on success; four
  early returns left them live. sign_and_verify() returned from three
  places without erasing already-generated secnonces. Both now route
  every exit through a cleanup block. This example is otherwise more
  careful about erasure than its siblings, so the asymmetry was exactly
  what a reader copying it would carry into production -- on the fault
  paths where hygiene matters most.

  The double-wipe of session_secrand is gone with it: shares_gen and
  nonce_gen both wipe the seed on every path, and doing it again read
  as uncertainty about the contract. The comment now states the
  contract instead. The fill_random failure path does erase, since
  nothing else has touched the buffer there.

The example's mismatch message asserted a cause it cannot know.

  It printed "Helper %u disagrees about the enrollment parameters" for
  what may equally be a corrupted share, per the previous commit's
  finding. It now says the helper "contributed a share this helper
  cannot use", with a comment noting that share_agg does not
  distinguish the two causes so neither can the message.

Comment and structure fixes, all noted in the review:

- The vector generator claimed case 4 was "the only case whose DERIVED
  public share has odd Y". It is not -- cases 1, 2 and 4 are odd and
  case 3 is even. The comment existed to justify a coverage choice and
  misinformed; both parity comments now describe the set accurately and
  say they document it rather than constrain it. Regenerating vectors.h
  still reproduces it byte for byte.
- The secp256k1_frost_sort_ids declaration in frost/session.h no longer
  duplicates the definition's doc comment, which was two copies to keep
  in sync. It says what the function is for and points at the
  definition for the contract.
- The t >= 2 rationale was stated in full in three places. The impl now
  states the conclusion and names frost_enrollment.md as the single
  place to edit if the policy moves.
- The ctime_tests comments read ambiguously ("the parameters hash is
  public, the delta values are not" against a header calling deltas
  secret), and computing direct_hash without asserting anything invited
  a "forgotten assertion" reading. Both are now explicit.
- The example moves next to frost_example in Makefile.am rather than
  after iceberg, matching the FROST-stack grouping used in
  configure.ac, ci.sh, ci.yml and README.
- frost_enrollment.md now distinguishes what is unstable (the C API)
  from what is frozen (the wire-visible encodings), which the two
  statements together previously left easy to conflate.

Not fixed, deliberately, and now recorded where the tree can see it: the
plan called for a CHANGELOG.md entry. That file states in its first two
lines that it is upstream libsecp256k1's changelog and not this fork's,
and none of frost, chilldkg, iceberg or prefractal has an entry. Adding
the first one is a decision about all five modules, not this one. The
README link is the fork's actual convention for announcing a module and
is in place.

Verification: autotools builds warning-free and `make check` is 12/12
including the example; ctime_tests is clean under valgrind; `make dist`
carries all nine frost_enrollment files; CMake with examples builds
warning-free and ctest is 542/542; the example source is clean under
gcc -std=c89 -pedantic -Wall -Wextra; regenerating vectors.h reproduces
it byte for byte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:27:17 +02:00
Kgothatso Ngako
69766dd331 frost_enrollment: close the review's test coverage gaps
Six new tests and repairs to two that were confounded. The suite goes
from 12 cases to 16.

Two existing tests would have stayed green with the checks they target
deleted, which is the worst kind of passing test:

- The "helper id out of range" case also passed new_id = 5 > n = 4,
  which params_are_valid rejects several lines earlier. It now uses a
  valid enrollment target (new_id = 4) and an id of 5, so the id range
  check is the sole failing condition.
- Every call in the empty-set test used (n = 1, t = 2), which fails on
  threshold > n_participants regardless of n_ids. It now uses
  (n = 2, t = 2, new_id = 2) -- a valid tuple in every respect except
  n_ids = 0.

New coverage, in the order the review ranked it:

- run_frost_enrollment_api_test: NULL for every ARG_NONNULL pointer on
  all five entry points, plus an unusable pubkey object on the four that
  take one (previously only params_hash was covered). Also asserts that
  a shares_gen call rejected at an ARG_CHECK does NOT consume the seed,
  since it never reaches the body -- the complement of the "a failed
  call always consumes it" property the previous commit pinned.
- run_frost_enrollment_infinity_test: pubshare_derive's infinity
  rejection, which nothing reached before. With u = 2 and new_id = 2 the
  Lagrange coefficients are exactly -1 and 2, so P_0 = 2*P_1 makes the
  interpolation vanish; the same two points at a different target
  succeed, which is what distinguishes the infinity check from a
  parameter rejection.
- run_frost_enrollment_max_size_test: full protocol runs at the largest
  sizes the API admits -- enrollment at n = 127 with u = 127, and repair
  in a full n = 128 group with u = 127. u cannot reach 128 in either
  mode (enrollment needs n < 128, repair excludes the target from the
  helper set), so these reach one entry below the fixed-size arrays'
  bound, which is as far as a valid tuple goes. Everything before this
  capped at n <= 7. Runs in 51 ms.
- run_frost_enrollment_no_side_effects_test: the C analogue of the
  reference implementation's test_participant_not_in_dkg, which plan
  §1.2 listed and the Phase 3 list dropped. Every existing
  participant's secret share, public share and the group key are
  byte-identical before and after an enrollment, and the new share
  differs from all of them.
- The pubshare_derive test now also pins the OTHER end of the
  polynomial. The public API cannot ask for x-coordinate 0 -- that is
  identifier -1, and new_id is a uint32_t bounded by n_participants --
  so the convention there is checked by running frost's own
  derive_thresh_pubkey over the same loaded points and requiring it to
  reproduce the group key. With the existing check at x = new_id, both
  ends of the interpolation this module depends on are now fixed.

Test-structure repairs the review called out:

- The mismatch test's disagreement now enters where it would in reality,
  at helper 0's round 1.1 call (which is made with new_id = 3 while
  helper 1 uses 4), rather than by running a clean round and
  overwriting the outputs afterwards.
- The oversized-helper-set test re-points a single dealt run at {0,1}
  and then {0,1,2} through a named helper, instead of struct-copying a
  ~540 KB run and hand-editing u and ids[2] -- which would have broken
  silently if deal()'s helper-selection rule changed.
- frost_enrollment_test_run instances in the mismatch test are now
  static. That test needs four live at once, which was over 2 MB of
  stack.
- The randomized test's `if (sub_ids[t-2] >= new_id) continue;` was
  unreachable: the loop bound gives sub_ids[t-2] <= n-1 and new_id == n
  in that branch. It is now the CHECK that states the invariant.
- The pubshare_derive test's `k` was reset and reused as both helper
  counter and aligned-array index inside the same loop body.

Verification: 16/16 pass at -i=16, -i=200 and -i=1000; ./tests,
./noverify_tests and ./exhaustive_tests exit 0; the module is clean
under valgrind (0 errors from 0 contexts).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:21:13 +02:00
Kgothatso Ngako
266c6a7c4f frost_enrollment: fix API contract issues found in review
Five review findings, all non-blocking, all in the contract between the
module and its callers rather than in the cryptography. Each fix comes
with a regression test that fails without it.

1. shares_gen zeroed shares32_out before validating n_ids.

   shares32_out is the only output in this module whose size is
   caller-supplied. A caller that takes the helper count from a
   negotiated protocol message, passes a fixed buffer, and relies on
   this API's "invalid ranges return 0" convention would have memory
   past that buffer zeroed before the call reported failure -- turning a
   recoverable length-confusion bug into memory corruption. The frost
   module validates counts first for exactly this reason
   (trusted_dealer_keygen, keygen_impl.h:228).

   Validation now happens before the memset. The early return still
   wipes session_secrand32, because "a failed call cannot be retried on
   the same randomness" is a security property and an exception to it
   would be worse than the tidier control flow. The header's zeroing
   promise is scoped accordingly: the buffer is zeroed on failure except
   when n_ids itself is out of range, where it is not written at all.

2. mismatch_id had an undocumented second cause.

   The header said mismatch_id names the helper whose PARAMETERS HASH
   disagrees and is UINT32_MAX "when the failure has another cause", but
   share_agg also sets it when a helper's share is not a valid scalar.
   The example baked the wrong reading in, printing "Helper %u disagrees
   about the enrollment parameters" for what may be a corrupted
   transmission.

   Documented rather than removed: the attribution is genuinely useful
   for both causes, and this is API- and vector-compatible. The header
   now names both, says they are not distinguished so a caller must not
   report one specifically, and calls out that the second can name the
   CALLER'S OWN identifier, since the kept share is summed with the
   rest. The example's message is corrected in a following commit.

3. params_hash's doc claimed it returns 0 on an "unparseable thresh_pk".

   It does not, and cannot: secp256k1_pubkey_load (secp256k1.c:280) only
   ARG_CHECKs that x is nonzero, so a zeroed pubkey fires the
   illegal-argument callback and any other 64-byte content is accepted
   without curve validation. A caller writing input screening around the
   documented return 0 would abort on the first malformed input. The doc
   now states that an unusable pubkey object is API misuse, matching the
   pointer/value split the impl already follows.

4. params_hash's doc listed three of its ten validity conditions.

   It is the natural pre-validation entry point -- it enforces exactly
   what the other four enforce -- but the doc mentioned only duplicate
   ids and the two n_ids bounds, so the threshold >= 2 divergence and
   the mode-specific n bounds were discoverable only from the .md or the
   source. The parameter list now carries the same constraint lines as
   shares_gen.

5. secshare_gen required a signing context even when it would not sign.

   The ecmult_gen check was unconditional, but ecmult_gen is used only
   inside the expected_pubshare != NULL branch. A caller on a
   verification-only context passing NULL -- explicitly permitted -- hit
   the illegal-argument callback for a generator multiplication that
   would never happen.

   The check is now conditional on expected_pubshare being non-NULL, and
   stays at the top of the function rather than moving into the branch:
   ARG_CHECK returns directly, and from inside the branch that would
   skip the cleanup that wipes secshare and term. Documented in the
   header.

Also in this commit, three comment/dead-code fixes the review noted:
the redundant set_int of `term` in both aggregation loops (always
written by set_b32 before it is read), the Lagrange denominator comment
crediting new_id for something only id distinctness provides, and the
comment that described the memset-before-validation ordering rather than
justifying it -- now moot.

The new run_frost_enrollment_contract_test also closes review coverage
gaps 1, 2 and 8, which overlap these findings: malformed wire scalars
into share_agg and secshare_gen, sigmas summing to zero mod the order,
an invalid secshare32 into shares_gen (the only path exercising its
declassify branch), mismatch_id asserted on a NON-CONTIGUOUS helper set
{0, 2} so an implementation returning the array index would now be
caught, mismatch_id at the caller's own slot, and successful runs with
each optional secshare_gen check skipped and with both skipped.

Both fixes were verified to be load-bearing by reverting them
individually: the F1 test fails on `guarded[i] == 0xa5` and the F5 test
fires the illegal-argument callback. ./tests, ./noverify_tests and
ctime_tests pass; the module is clean under valgrind (0 errors from 0
contexts).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:15:26 +02:00
Kgothatso Ngako
782fede2c5 frost_enrollment: finish the module documentation and integration
Sixth and last commit of the series. Completes frost_enrollment.md, adds
the README feature link, and records the results of the full
cross-build verification pass.

frost_enrollment.md gains the four sections that only made sense once
the code existed:

- A round diagram naming who sends what to whom for u = 3, because the
  transposition between round 1.1's output buffers and round 1.2's input
  buffer is the one part of this protocol that is genuinely easy to wire
  up backwards, and prose does not make it obvious.
- An API table in protocol order, plus the two array conventions stated
  once in a place a reader will find them: everything of length u is
  aligned with the caller's own ids order, and the parameters hash is
  the sole exception because it sorts a local copy; and the deliberately
  opposite own-slot conventions of share_agg's two u*32 buffers.
- The Test vectors section, saying plainly what the vectors are and are
  not. They are regression vectors: they pin the tag strings, the
  serialization, the derivation and the identifier conventions, so that
  changing any of those is loud. They are not cross-validation, because
  the protocol has no BIP and the reference proof of concept's
  randomness is not seedable. The algebraic invariants in tests_impl.h
  are what carry correctness, and the section says which ones.
- Frozen encodings, giving both tagged hashes in full so an
  interoperating implementation does not have to read the C.

The verification section also now records what the fault-injection test
demonstrates, since it is the concrete argument for the
expected_pubshare parameter: a flipped bit in one sigma makes
secshare_gen fail and wipe its output, while the same call with NULL
succeeds and returns a wrong share.

README.md gains the module link beside the other four FROST-stack
entries, pointing at the module-local document. That keeps it consistent
with EXTRA_DIST, which has carried the file since the scaffolding commit
-- the pairing 42f827a7 established and 0e5369de completed for
prefractal.

CI wiring landed with the scaffolding commit and is unchanged here.

NOT DONE, deliberately: the plan called for a CHANGELOG.md entry. That
file opens by stating it is not this fork's changelog but upstream
libsecp256k1's, and it has no "fork's experimental additions" section to
add one under. None of frost, chilldkg, iceberg or prefractal has an
entry there. Adding the first one would put fork-only content into a
file documenting upstream releases and break with four modules' worth of
precedent, so it is left out rather than done quietly. If a fork
changelog is wanted, it is a separate decision affecting all five
modules.

ALSO NOT DONE, and flagged: no CI job builds any experimental module
through CMake -- the only module flag in the workflow is
-DSECP256K1_ENABLE_MODULE_RECOVERY=ON in the MSVC job (ci.yml:702). So
the src/CMakeLists.txt block, the EXPERIMENTAL gate entry and the
PARENT_SCOPE lift added by this series have no standing CI guard, exactly
as they have none for frost, chilldkg, iceberg or prefractal. The plan
offered closing the gap as optional; it would change what an existing job
covers for five modules at once, which is wider than this series, so it
is left as a separate decision. The CMake path was therefore verified by
hand, below.

Final verification, run over the finished tree:

Autotools.
- Ordering regression: configuring with ONLY
  --enable-module-frost-enrollment emits both
  -DENABLE_MODULE_FROST_ENROLLMENT=1 and -DENABLE_MODULE_FROST=1, the
  summary reports frost = yes, the build is warning-free and ./tests
  exits 0.
- Full build with frost, chilldkg, iceberg, prefractal,
  frost-enrollment, recovery, ellswift, examples and ctime tests: zero
  warnings, `make check` reports 12/12 PASS including
  frost_enrollment_example.
- ctime_tests under valgrind: 0 errors from 0 contexts.
- make dist succeeds and the tarball carries the public header, all five
  module files including frost_enrollment.md, and the example.
- With the module off (the default), nm shows zero frost_enrollment
  symbols in libsecp256k1.so.
- --enable-module-frost-enrollment without --enable-experimental is
  rejected with the expected message.

CMake, by hand.
- Full FROST stack plus examples: configure reports frost-enrollment ON
  and frost ON (the PARENT_SCOPE lift working), the build is
  warning-free, ctest is 532/532 including
  secp256k1.example.frost_enrollment.
- -DSECP256K1_ENABLE_MODULE_FROST_ENROLLMENT=ON without
  -DSECP256K1_EXPERIMENTAL=ON is rejected with the expected message.
- The dev-mode preset that tools/check-abi.sh uses leaves both frost and
  frost-enrollment OFF, so the ABI comparison is unaffected by this
  series.

Symbols. tools/symbol-check.py derives its expected set by grepping
SECP256K1_API declarations under include/; simulating that grep yields
exactly the five new names, and nm reports exactly those five exported
from a frost-enrollment build, with no duplicates. The script itself
could not be run here because python3-lief is not installed in this
environment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:37:44 +02:00
Kgothatso Ngako
5155ee03f7 frost_enrollment: add the example program
Fifth of six commits. examples/frost_enrollment.c runs a 2-of-3 group
through an enrollment to 2-of-4, signs with the new participant, and then
repairs a lost share -- all roles in one process, following
examples/frost.c's structure.

The example exists mostly to demonstrate two things the API cannot
enforce and that a reader would otherwise have to reconstruct from the
documentation.

First, the verification flow, in the order that makes it non-circular:

  1. obtain thresh_pk from a source authenticated INDEPENDENTLY of the
     helpers (here, the dealer step, commented as the stand-in);
  2. validate the helpers' public shares against it with
     secp256k1_frost_threshold_info_validate;
  3. derive the expected public share from those validated shares;
  4. only then run round 2, passing the same authenticated thresh_pk.

Skip step 1 or 2 and every check in round 2 still passes -- on a share
from whatever polynomial t colluding helpers chose to present. The
example says so at the point where it would be tempting to skip them.

Second, the authorization gap. There is no authorization step in the
protocol: anyone who convinces t helpers to run it receives a valid
share, and in repair mode that is an existing participant's actual
share. The precondition sits in the comment on enroll(), where a reader
copying the function will see it, and again at the repair call site,
which is where it bites hardest.

Beyond that the example is a working reference for the parts that are
fiddly to get right from the header alone: the transposition between
round 1.1's output buffers and round 1.2's input buffer (helper j
collects entry j of every helper's buffer), the opposite own-slot
conventions of the two round-1.2 buffers, the n -> n+1 bookkeeping with
threshold_info_validate over the extended table, and the fact that the
resulting signature verifies against the group's ORIGINAL threshold
public key, since enrollment changes neither the polynomial nor any
existing share.

The repair half asserts byte equality with the original secret share and
the original public share, so a regression there fails the example rather
than passing quietly.

Wired into both build systems next to the iceberg example: Makefile.am
(noinst_PROGRAMS and TESTS under ENABLE_MODULE_FROST_ENROLLMENT) and
examples/CMakeLists.txt. The .gitignore entry landed with the Phase 1
scaffolding.

Verification. Autotools: builds warning-free and `make check` reports
12/12 PASS including frost_enrollment_example; five consecutive runs exit
0 (the key material is freshly random each time, so this exercises both
threshold-key parities in practice). CMake: with
-DSECP256K1_BUILD_EXAMPLES=ON, ctest runs all nine examples and
secp256k1.example.frost_enrollment passes; the full ctest suite is
523/523 with frost, chilldkg, iceberg, prefractal and frost-enrollment
all enabled. The source is clean under gcc -std=c89 -pedantic -Wall
-Wextra.

Note for anyone reproducing this: examples are OFF by default in both
build systems (--enable-examples for autotools,
-DSECP256K1_BUILD_EXAMPLES=ON for CMake), so a plain build will not
compile this file at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:30:48 +02:00
Kgothatso Ngako
303a7caeae frost_enrollment: add the test suite and the regression vectors
Fourth of six commits. Twelve tests replacing the Phase 2 smoke test, plus
a vector generator and the frozen vectors it produces.

The regression vectors are the one part of this worth being precise
about, because they are easy to over-claim. FROST enrollment has no BIP
and no published vectors, and the reference proof of concept draws its
randomness from secrets.randbits, which is not seedable -- so there is
nothing to cross-validate against. tools/test_vectors_frost_enrollment_generate.py
therefore re-implements the math independently in stdlib-only Python,
including the group arithmetic written from the secp256k1 parameters
rather than borrowed, and freezes the output. What that buys: the two tag
strings, the params hash serialization, the share-splitting derivation
and the identifier conventions are now pinned, and changing any of them
is a loud vector-breaking change. What it does not buy is evidence of
protocol correctness. The generator header comment and the generated
file both say so, as does frost_enrollment.md.

The vectors passed on the first run against the C code, which is worth
recording: two independent implementations agree byte for byte on the
params hash, every delta, every sigma, the derived public share and the
final share, across four cases (2-of-3 minimal, 2-of-3 oversized at
u = 3 > t = 2, a 3-of-5 repair with a deliberately UNSORTED helper set,
and a 4-of-6 enrollment), covering both threshold-key Y parities.

The algebraic invariants are what actually carry correctness:

- Reconstruction (PoC test_generate_frost_share): after a 2-of-3 group
  enrolls id 3, every pair {i, 3} reconstructs the original threshold
  secret, and so does the untouched pair {0, 1}.
- Signing (PoC test_sign): a real BIP340 signature from {2, 3} verifying
  against the unchanged threshold public key, with every partial
  signature individually verified, plus the n -> n+1 bookkeeping --
  secp256k1_frost_threshold_info_validate must accept the public share
  table extended with pubshare_derive's output at n+1.
- Repair: byte-for-byte equality with the lost share, and the repaired
  participant keeps its old public share.
- Oversized helper set: u = 3 and u = 2 over the same key material
  produce the same share and the same derived public share.
- Randomized: COUNT iterations over 2 <= t <= u <= n <= 7, half
  enrollment and half repair, with EVERY HELPER GIVEN THE IDENTIFIER SET
  IN ITS OWN SHUFFLED ORDER. The params hash must come out identical
  while the delta buffers stay aligned per helper -- which is the whole
  point of canonicalizing ids inside the hash and nowhere else. Each
  iteration then checks every t-subset containing the new participant.

The negative tests are organized around what each gate is actually for:

- Fault injection flips a bit in one sigma. secshare_gen fails and wipes
  its output; the same call with expected_pubshare = NULL SUCCEEDS and
  returns a wrong share. That second assertion is the point -- it is the
  evidence that the parameter is load-bearing rather than decorative.
  Tampered public shares are caught earlier, by
  secp256k1_frost_threshold_info_validate, so the test exercises the
  recommended flow and not just the module.
- Parameter mismatch, four angles: (a) one helper runs round 1.1 for a
  different target and every other helper's share_agg aborts naming it
  by identifier; (b) a caller that IGNORES that abort and finishes round
  1.2 anyway still cannot produce a usable share, because the
  public-share check catches the inconsistent sum -- defence in depth,
  not a test of the test's own control flow; (c) the helpers agree with
  each other on new_id = 3 while the target expects 4, which round 1.2
  cannot see and round 2's own recomputation does; (d) two groups with
  identical (t, n, ids, new_id) get different hashes, and a hash from one
  fails share_agg in the other.
- Own-slot semantics: filling the caller's own slot of
  received_params_hashes32 with garbage changes nothing, because it is
  never read -- but the same garbage in a slot that IS read still aborts.
  That pair is what makes "recomputation, not string comparison"
  testable rather than merely asserted.
- Invalid parameters, including both deliberate divergences: t = 1
  refused, enrollment refused at n = 128 while repair at n = 128 is
  accepted, n_ids > 128 returning 0 with the output zeroed in a
  production build.

Three bugs found while writing these, all in the tests, all worth
naming:

- pubshare_derive takes public shares ALIGNED WITH ids, and the test
  helper was handing it the participant-indexed table. Those coincide
  exactly when the helper set is 0..u-1, which every test until the
  repair case used, so the first non-contiguous helper set {0, 2} was
  what exposed it. There is now one helper that does the gather, with a
  comment saying which confusion it exists to prevent.
- The fault-injection test compared against r.new_secshare without ever
  running round 2, and the mismatch test compared against
  r.params_hashes[0] one line before round 1.1 filled it. Both were
  reads of uninitialized memory that happened to pass; valgrind found
  both.

The randomized test loops COUNT times so -i scales it, following the
iceberg module (tests_impl.h:1322) rather than prefractal's run-once
convention -- a fuzzing loop that ignores the iteration count is not
much of one.

Verification: all twelve tests pass at the default iteration count, at
-i=200 and at -i=2000; ./tests, ./noverify_tests and ./exhaustive_tests
exit 0 with all five FROST-stack modules enabled; the module runs clean
under valgrind (0 errors from 0 contexts); ctime_tests is clean under
valgrind; regenerating vectors.h reproduces it byte for byte.

One note for anyone running these locally: ctime_tests must not be run
against a CPPFLAGS='-DVERIFY' build. secp256k1_scalar_verify branches on
scalar values, which ctime_tests deliberately marks secret, so every
scalar operation in the library reports a finding -- 75997 of them, none
in this module. The CI matrix already pairs -DVERIFY with
CTIMETESTS: 'no' (.github/workflows/ci.yml:119, :596) for this reason.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:24:21 +02:00
Kgothatso Ngako
89b253b50e frost_enrollment: implement the three rounds
Third of six commits. Replaces the Phase 1 stubs with the real
arithmetic, adds a smoke test that a 2-of-3 group really does grow into
a working 2-of-4 one, and wires the entry points into ctime_tests.

The Lagrange machinery is frost's, called in place. pubshare_derive is a
skin over secp256k1_frost_derive_pubshare_at
(src/modules/frost/keygen_impl.h:150) evaluated at identifier new_id,
and the id canonicalization is secp256k1_frost_sort_ids, reached through
the declaration the previous commit added.

The one piece frost could not supply is the scalar Lagrange coefficient
at an arbitrary point. frost's secp256k1_frost_derive_interpolating_value
evaluates at x-coordinate 0, which is what reconstructing the group
secret needs; enrollment needs the basis polynomial at the TARGET
x-coordinate. secp256k1_frost_enrollment_lagrange_at is that, and it is
deliberately the same product derive_pubshare_at applies to each
pubshare, in the same identifier space -- so the scalar path and the
point path agree by construction rather than by coincidence. Working in
identifier space is what makes the id-to-x-coordinate +1 cancel: an
x-coordinate difference x_j - x_i is the identifier difference
id_j - id_i.

Round 1.1 computes v = lambda * secshare and splits it. Every share but
the one kept locally is masking randomness derived as

  Scalar.from_bytes_wrapping(
      TH("FROST enrollment/share_split",
         rand32 || params_hash32 || ser32(my_id) || ser32(recipient_id)))

with rand32 = TH(same tag, session_secrand32) XOR secshare32; the kept
share absorbs the remainder so the set sums to v. Three details:

- The reduction wraps rather than rejects, chilldkg's
  from_bytes_wrapping (src/modules/chilldkg/util_impl.h:394). A 256-bit
  hash mod the group order is about 2^-128 from uniform; rejection
  sampling would buy that back in exchange for a variable-time loop.
- Masking with the secret share is the secp256k1_frost_nonce_gen pattern
  (session_impl.h:340), so a broken RNG alone does not reveal the split.
- The derivation is indexed by the recipient's IDENTIFIER, not by its
  position in the caller's ids array. The plan called for a counter;
  identifiers are unique, so they are one, and using them makes the
  split independent of the order a caller lists the helper set in. What
  the binding buys is DOMAIN SEPARATION only: params_hash32 carries the
  group key and the whole parameter tuple, so two runs sharing a seed
  but differing in either cannot produce the same deltas. It cannot
  detect a disagreement between helpers, because nothing cross-checks
  per-helper private randomness. That is the params hash's job.

session_secrand32 is wiped whether the call succeeds or fails, so a
caller cannot retry a failed run on the same randomness.

Round 1.2 recomputes its own params hash from the group key and the
tuple, compares every received hash against it, then sums. The slot at
the caller's own position in received_params_hashes32 is skipped, while
the same position in all_shares32 is read -- the asymmetry the header
documents, and the thing that makes this a recomputation rather than a
string comparison. The mode and bounds are re-validated here rather than
trusted from the round 1.1 call site, since the full tuple is present.
An out-of-range share is reported through mismatch_id the way
secp256k1_frost_partial_sig_agg reports an unparseable partial
signature.

Round 2 compares the params hash against its own recomputation over the
authenticated group key, sums, rejects a zero share, and checks
secshare*G against the expected public share.

Three deviations from the plan, all to match what the tree already does:

- Value ranges return 0; only pointers get ARG_CHECK. The plan called
  for an ARG_CHECK on the n_ids bound, but the frost module's split is
  the one used here (secp256k1_frost_trusted_dealer_keygen,
  keygen_impl.h:227), and the header already documents these as
  return-0 conditions. The bound is still enforced in production builds
  -- params_are_valid requires 2 <= threshold <= n_ids <= n_participants
  <= 128 -- so it does not ride on the VERIFY_CHECK inside
  secp256k1_frost_sort_ids, which is what the plan was guarding against.
- The public-share check declassifies the derived point and compares
  with secp256k1_ge_eq_var, rather than comparing 33 serialized bytes in
  constant time. There is no constant-time memcmp in this tree, and
  secshare*G is a public key: secp256k1_frost_sign declassifies exactly
  this quantity before exactly this comparison
  (src/modules/frost/session_impl.h:770, :789). Inventing a primitive to
  avoid following that precedent would be the worse trade.
- params_hash's public entry point delegates to the same internal
  routine every gate uses, so the encoding has exactly one
  implementation to keep in step with the vectors.

One real bug found by the tooling rather than by reading. Accumulators
were initialized with secp256k1_scalar_clear, and
secp256k1_memclear_explicit marks its target UNDEFINED in VERIFY builds
(src/util.h:295) precisely so that reading cleared memory is caught. It
was: valgrind reported 143752 errors in share_agg's summation loop.
Accumulators now start at secp256k1_scalar_set_int(x, 0); scalar_clear
is used only where it means "done with this secret". Worth stating
plainly because the failure mode is invisible in a production build,
where memclear_explicit only zeroes.

ctime_tests gains a 2-of-3-enrolls-a-fourth block covering all three
rounds, following prefractal's b66c757b. The threshold key, the secret
shares, the session randomness and every delta and sigma on the wire are
marked secret; the identifiers, public shares, group key, parameters
hashes and derived public share are not. Under valgrind: 0 errors from 0
contexts, so no branch or memory access in the new code depends on
secret data.

Verification: ./tests, ./noverify_tests and ./exhaustive_tests exit 0;
the frost_enrollment module runs clean under valgrind (0 errors); a
separate CPPFLAGS='-DVERIFY' build compiles without warnings and passes;
the module builds warning-free alongside frost, chilldkg, iceberg and
prefractal.

The smoke test is the substantive check: after a 2-of-3 group enrolls
participant 3, every pair {i, 3} for i in 0..2 reconstructs the original
threshold secret and matches the threshold public key, and the untouched
pair {0, 1} still does too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:06:59 +02:00
Kgothatso Ngako
a7d4337778 build: wire the frost_enrollment module into both build systems
Second of six commits adding the frost_enrollment module. This one is
scaffolding only: the five entry points are stubs that validate their
pointer arguments, zero their outputs and return 0. What is being
verified here is that the module configures, compiles, links, exports
its symbols and registers its test module in both build systems -- so
that the next commit changes nothing but arithmetic.

Ordering is the one thing in this commit that can go silently wrong, and
it goes wrong in opposite directions in the two build systems:

- configure.ac executes its `if` blocks in file order, and
  enable_module_frost defaults to no (configure.ac:243). A block placed
  after the frost block at :601 that sets enable_module_frost=yes flips
  the variable too late: AM_CONDITIONAL goes true, so the header is
  installed and the Makefile fragment is pulled in, but
  -DENABLE_MODULE_FROST=1 is never appended, so src/secp256k1.c never
  includes frost's implementation and every secp256k1_frost_* symbol
  fails to link. The new block therefore goes ahead of both the frost
  block and prefractal's, which documents the same trap.

- src/CMakeLists.txt processes dependents FIRST, so the same block goes
  above the FROST block there, beside prefractal's.

Verified rather than assumed: configuring with ONLY
--enable-module-frost-enrollment emits -DENABLE_MODULE_FROST=1
alongside -DENABLE_MODULE_FROST_ENROLLMENT=1, and the CMake summary
prints "frost ON" for the same configuration -- the latter is what the
PARENT_SCOPE lift buys, since the summary runs after
add_subdirectory(src) and would otherwise report a module it is
compiling in as OFF.

The dependency guard is prefractal's implies-frost idiom, copied
verbatim along with its reasoning. frost is default-OFF, so the
`test x"$enable_module_frost" = x"no"` / `DEFINED X AND NOT X` guard
every other module uses -- which reads as "the user disabled it
explicitly" for a default-ON dependency -- is true by default here and
cannot tell an explicit --disable-module-frost from the default once
both are in the cache. Enabling frost-enrollment simply implies frost,
with no error.

The one frost-module change in the whole series is in this commit:
src/modules/frost/session.h gains a declaration for
secp256k1_frost_sort_ids, which is defined at session_impl.h:517 and
declared nowhere. The params hash needs it to canonicalize identifier
order. Prefractal reaches frost's statics through translation-unit
ordering alone; rather than inherit reuse-by-link-order, this declares
the function where keygen.h:48 already declares derive_pubshare_at, so
the reuse goes through an interface. No behavior change: it is a
declaration for an existing static definition in the same TU.

CI wiring is two files, and skipping either half fails quietly:

- ci/ci.sh gets FROST_ENROLLMENT in the reproduction header's variable
  list and --enable-module-frost-enrollment="$FROST_ENROLLMENT" after
  the prefractal line.
- .github/workflows/ci.yml gets FROST_ENROLLMENT at every PREFRACTAL
  site: the global default, 11 inline matrix entries and 10 job-level
  env blocks. Without the default, ci.sh runs under set -eux with an
  empty $FROST_ENROLLMENT, passes --enable-module-frost-enrollment="",
  `test x"" = x"yes"` is false, and the module is off in all of CI while
  ci.sh visibly has the plumbing.

Verified programmatically over the parsed workflow: across the 106
effective job contexts, PREFRACTAL and FROST_ENROLLMENT now agree in
every single one (45 set to yes, no mismatches), no context sets
FROST_ENROLLMENT without FROST or without EXPERIMENTAL, and no context
leaves it undefined. ci.sh passes sh -n.

The stub test is not a placeholder that has to be deleted later: every
entry point must reject an empty helper set and leave its output zeroed,
which is true of the stubs and stays true of the finished
implementation, so it doubles as the check that all five symbols are
reachable from the test binary.

Verification. Autotools: ./autogen.sh, then a frost-enrollment-only
configure and a full configure with frost, chilldkg, iceberg, prefractal
and frost-enrollment all on -- both build with zero warnings under the
project's -Werror-grade flag set, ./tests and ./exhaustive_tests exit 0,
and `./tests -l` lists the frost_enrollment module. CMake: configure with
-DSECP256K1_EXPERIMENTAL=ON -DSECP256K1_ENABLE_MODULE_FROST_ENROLLMENT=ON
builds clean and ctest passes 391 tests. nm shows the five new symbols
exported from libsecp256k1.so; tools/symbol-check.py could not be run
here because python3-lief is not installed in this environment, but all
five carry the required secp256k1_ prefix. make dist succeeds and the
tarball carries src/modules/frost_enrollment/frost_enrollment.md
alongside the other module documents.

One unrelated observation from this build: a stale
src/ctime_tests-ctime_tests.o left over from an earlier configure with a
different module set will fail to link, because automake does not track
CPPFLAGS changes across reconfigures. make clean between configurations
with different module sets, not a fault in this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 03:53:03 +02:00
Kgothatso Ngako
b6791ba867 frost_enrollment: freeze the API and write the module documentation
First of six commits adding a frost_enrollment module: FROST enrollment,
the protocol of Section 4.1.1 of the FROST paper, which converts a (t, n)
group into a (t, n+1) group without re-running key generation and without
any participant revealing its share. Running it at an existing
participant's identifier repairs that participant's lost share instead.

This commit is the design freeze. It adds no code and touches no build
file; nothing here is compiled yet. The header and the module document
are what the following commits implement against.

Why a separate module rather than part of frost:

- The frost module is deliberately scoped to BIP 445, whose own header
  states DKG is out of scope for the same reason. Enrollment has no BIP.
- The repo already puts one protocol per module across the FROST stack:
  chilldkg is the DKG, prefractal is the nested FROST+MuSig2 signer, and
  both are separate modules layered on frost's key material.
- Enrollment moves share-shaped secrets between participants, has no
  authorization mechanism at all, and rests on transport assumptions the
  library cannot enforce. Its own --enable-module-frost-enrollment flag
  keeps that surface opt-in.

Five functions, named after the round they run:

- params_hash        pure, public; every party recomputes it
- shares_gen         round 1.1, each helper
- share_agg          round 1.2, each helper
- pubshare_derive    pure, public; the expected public share at x_new
- secshare_gen       round 2, the target participant

Decisions frozen here, in the order they will matter to the
implementation:

Tag strings and encoding. The params hash is

  TH("FROST enrollment/params_hash",
     cbytes(thresh_pk) || ser32(n) || ser32(t) || ser32(new_id) ||
     ser32(u) || ser32(sorted_ids[0]) || ... )

mirroring chilldkg's params_hash (src/modules/chilldkg/util_impl.h:399)
in both its fixed-width u32be discipline and its commitment to key
material rather than to integers alone. Binding thresh_pk is what makes
the hash name a GROUP: two unrelated groups sharing (t, n, ids, new_id)
get different hashes, so the agreement checks prove the parties mean the
same group and not merely the same numbers. Ids are sorted before
hashing so helpers holding the same set in different orders agree; every
other array in the API stays aligned with the caller's own ids order.
The second tag, "FROST enrollment/share_split", is introduced by the
next commit. Both freeze once vectors.h exists.

params_hash returns int, not void. Void-returning public functions in
this library are lifecycle-only (context_destroy, selftest, callback
setters), and ARG_CHECK_VOID (src/secp256k1.c:73) fires the illegal
callback and returns with the output UNWRITTEN. Under a non-aborting
illegal callback -- a supported configuration -- a caller would then
compare a 32-byte buffer that was never computed, silently defeating
both hash gates while every call still appears to succeed.

The two u*32 buffers of share_agg take deliberately opposite own-slot
conventions, and the header says so loudly: all_shares32 READS the slot
at my position (the share shares_gen kept), while
received_params_hashes32 never reads it. The asymmetry is the mechanism
-- the own hash is recomputed from the group key and the parameter
tuple, never taken from a buffer, so a caller cannot copy a received
hash into its own slot and launder a mismatch into a pass.

mismatch_id carries the participant IDENTIFIER, following chilldkg's
fault_index convention (include/secp256k1_chilldkg.h:276), not an array
index: identifiers need not be 0..u-1, so an index would be ambiguous.

threshold >= 2, a deliberate divergence from the frost module, which
accepts threshold >= 1 (keygen_impl.h:231, :321, session_impl.h:541).
The rationale is not that t = 1 is a weak threshold; a lone member of a
1-of-n group can already sign anything. It is that this API permits any
threshold <= n_ids, so t = 1 admits u = 1, and at u = 1 the additive
split degenerates to one share: the lone helper sends the unsplit v_1,
which at t = 1 is the whole group secret. t >= 2 forces u >= 2, which is
what actually makes the split non-degenerate.

Mode-specific bounds. new_id == n_participants means enrollment and
requires n < 128, because the resulting n+1 group must still be one
frost_session_init accepts; new_id < n_participants means repair, which
does not change n and allows n <= 128. The id cap is id <
n_participants; 128 caps n, not id values.

Two deviations from the plan's draft signatures, both to match the frost
module rather than the draft:

- threshold is uint32_t, not size_t. Every frost entry point that takes
  a threshold takes uint32_t (trusted_dealer_keygen,
  threshold_info_validate, session_init), against size_t for
  n_participants and n_signers.
- session_secrand32 sits with the outputs as an in/out parameter rather
  than last, which is where secp256k1_frost_nonce_gen puts it
  (include/secp256k1_frost.h:365). It is wiped by the call, so grouping
  it with the inputs would misdescribe it.

frost_enrollment.md carries the protocol derivation, the two modes and
their bounds, and the four security topics the API cannot enforce on its
own: transport confidentiality for the delta and sigma values, the
missing authorization step, the circularity of the public-share check
when thresh_pk comes from the helpers themselves, and the three separate
roles of parameter binding (helper-to-helper detection, helper-to-target
detection, and seed-reuse domain separation). The verification-flow
walkthrough and the regression-vector caveat land with their code.

The header compiles clean standalone under gcc -std=c89 -pedantic -Wall
-Wextra.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 03:45:13 +02:00
Kgothatso Ngako
0e5369de7a build: wire prefractal into CI and the README feature list
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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes … (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HA… (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 PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONP… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RA… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNOR… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SCHN… (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 PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SU… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SC… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (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 PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTIONPRO… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNOR… (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 PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJ… (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 CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:ye… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes R… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNO… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes PREFRACTAL:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG… (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
The prefractal module landed on main in parallel with the branches that
established the current module conventions, so it never picked up the
integration points every other experimental module has. 01379624 covered
the CMake experimental gate and EXTRA_DIST; these two are what remained.

The CI gap is the more consequential of the pair. ci/ci.sh had no
PREFRACTAL plumbing at all, so no CI job has ever passed
--enable-module-prefractal -- the flag was reachable only by configuring
by hand, and the module has been built and tested exclusively outside CI
since it landed.

- ci/ci.sh: PREFRACTAL joins FROST, CHILLDKG and ICEBERG in the
  reproduction header's variable list, and configure gains
  --enable-module-prefractal="$PREFRACTAL" after the iceberg line.
  Unlike 2473c768 there is no bench-step counterpart: prefractal ships
  neither a bench binary nor an example program, so the BENCH block
  needs nothing.

- .github/workflows/ci.yml: a PREFRACTAL: 'no' default alongside the
  other module defaults, then PREFRACTAL: 'yes' in the 21 places that
  already enable FROST (11 inline matrix entries and 10 job-level env
  blocks). The default is not cosmetic -- ci.sh runs under set -eux, so
  an undefined PREFRACTAL would abort every job at the configure step,
  including the ones that build no modules at all.

FROST-enabled jobs are the right target because enabling prefractal
implies frost (configure.ac:539, mirrored in src/CMakeLists.txt:90):
adding PREFRACTAL to a job that sets FROST: 'no' would silently turn
frost on and change what that job covers. Every job that already builds
frost also enables musig, schnorrsig, extrakeys and experimental, which
is the remainder of prefractal's dependency chain, so no job needed any
other variable adjusted.

This is a slightly wider set than CHILLDKG and ICEBERG cover. The
x86_64-debian matrix entry at line 117 sets FROST: 'yes' without
CHILLDKG or ICEBERG, and 2473c768 deliberately left it alone; it gets
PREFRACTAL here, on the rule above. The consequence is that no job now
builds frost without prefractal. If that standalone-frost combination is
worth preserving, that one entry is the place to drop it.

README.md gains the doc/prefractal.md link beside the frost, chilldkg
and iceberg entries. This is the exact inverse of the bug 42f827a7
fixed: there the documents were linked from README.md but missing from
EXTRA_DIST, so the tarball's README pointed at files it did not carry.
Here doc/prefractal.md has been in EXTRA_DIST since 01379624 but nothing
referenced it, so it shipped unreferenced. All four module documents
this fork adds are now both linked and distributed.

Verified with ./autogen.sh, ./configure --enable-experimental
--enable-module-prefractal and make -j: all exit 0 with no warnings, and
the configure summary shows the implication chain resolving, with
prefractal = yes pulling in frost = yes and musig = yes. nm confirms
run_prefractal_api_test is linked into ./tests, and the suite passes.
make dist succeeds and the tarball carries doc/prefractal.md next to
doc/iceberg.md, src/modules/frost/frost.md and
src/modules/chilldkg/chilldkg.md. ci/ci.sh passes sh -n.

Verified programmatically for the workflow, as in 2473c768: the YAML
parses, 33 effective job contexts set FROST: 'yes', all 33 of them now
also set PREFRACTAL: 'yes', every one has MUSIG, SCHNORRSIG, EXTRAKEYS
and EXPERIMENTAL set to 'yes', and no context sets PREFRACTAL without
FROST.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 03:28:22 +02:00
Kgothatso Ngako
0137962441 build: apply the review-fixes build conventions to prefractal
The prefractal module landed on main in parallel with the review-fixes
branch, so neither of that branch's two build changes covered it:

- CMake gated frost, chilldkg and iceberg on SECP256K1_EXPERIMENTAL but
  not prefractal, leaving CMake accepting a configuration that
  configure.ac already rejects.
- doc/prefractal.md was referenced by no build file, so it would be
  absent from a release tarball alongside the other module docs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 02:59:16 +02:00
Kgothatso Ngako
0bbf50187a Merge branch 'review-fixes' 2026-09-04 02:56:23 +02:00
Kgothatso Ngako
46a59c2ad5 Merge branch 'prefractal'
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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJE… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RE… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNOR… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes … (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECT… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECO… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:ye… (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 CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCH… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:y… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (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
Adds the prefractal module: a nested FROST+MuSig2 scheme letting a FROST t-of-n
group occupy one participant slot of an ordinary MuSig2 (BIP 327) session.

Three deliberate deviations from BIP 445, all documented in doc/prefractal.md:
the nonce coefficient does not commit to the message (so a group can publish
its wire nonce before the message exists); there is no g_frost factor, because
the threshold key is an inner participant of the outer aggregation and is used
as a full point; and the frost tweak cache must be the identity.

Merged the same way the iceberg module was.
2026-09-04 01:56:08 +02:00
Kgothatso Ngako
b66c757b7f prefractal: document the deviations and add the constant-time test
Some checks are pending
CI / Build arm64 Docker image (push) Waiting to run
CI / Build x64 Docker image (push) Waiting to run
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:ye… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJE… (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RE… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNOR… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:… (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes … (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAG… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECT… (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes EXTRAKEYS:yes MUSIG:yes RECOVERY:yes SCHNORRSIG:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ASM:x86_64 ELLSWIFT:yes WIDEMUL:int128]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BENCH:no BUILD:distcheck CTIMETESTS:no WITH_VALGRIND:no]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECO… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRS… (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:ye… (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CFLAGS:-O0 CTIMETESTS:no]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[CPPFLAGS:-DDETERMINISTIC]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ECMULTGENKB:86 ECMULTWINDOW:4]]) (push) Blocked by required conditions
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) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[ELLSWIFT:yes WIDEMUL:int128_struct]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[RECOVERY:yes WIDEMUL:int64]]) (push) Blocked by required conditions
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[WIDEMUL:int128]]) (push) Blocked by required conditions
CI / i686: Linux (Debian stable) (clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include, map[env_vars:map[]]) (push) Blocked by required conditions
CI / i686: Linux (Debian stable) (i686-linux-gnu-gcc, map[env_vars:map[]]) (push) Blocked by required conditions
CI / s390x (big-endian): Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[ASM:arm32 EXPERIMENTAL:yes]]) (push) Blocked by required conditions
CI / ARM32: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (clang, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (gcc, map[env_vars:map[]]) (push) Blocked by required conditions
CI / arm64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[]]) (push) Blocked by required conditions
CI / ppc64le: Linux (Debian stable, QEMU) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / Valgrind arm64 (memcheck) (push) Blocked by required conditions
CI / Valgrind i686 (memcheck) (push) Blocked by required conditions
CI / Valgrind x64 (memcheck) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:clang]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:auto CC:i686-linux-gnu-gcc HOST:i686-linux-gnu]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:clang ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / UBSan, ASan, LSan (map[env_vars:map[ASM:no CC:i686-linux-gnu-gcc ECMULTGENKB:2 ECMULTWINDOW:2 HOST:i686-linux-gnu]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / MSan (clang, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g CTIMETESTS:no]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g -O3 CTIMETESTS:yes ECMULTGENKB:2 ECMULTWINDOW:2]]) (push) Blocked by required conditions
CI / MSan (clang-snapshot, map[env_vars:map[CFLAGS:-fsanitize=memory -fsanitize-recover=memory -g CTIMETESTS:yes]]) (push) Blocked by required conditions
CI / i686 (mingw32-w64): Windows (Debian stable, Wine) (push) Blocked by required conditions
CI / x86_64 (mingw32-w64): Windows (Debian stable, Wine) (push) Blocked by required conditions
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CC:gcc CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCH… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:y… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[BUILD:distcheck]) (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Waiting to run
CI / x86_64: macOS Sequoia, Valgrind (map[RECOVERY:yes WIDEMUL:int128]) (push) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
CI / ARM64: macOS Sonoma (map[BUILD:distcheck]) (push) Waiting to run
CI / ARM64: macOS Sonoma (map[ECMULTGENKB:2 ECMULTWINDOW:4 WIDEMUL:int128_struct]) (push) Waiting to run
CI / ARM64: macOS Sonoma (map[RECOVERY:yes WIDEMUL:int128]) (push) Waiting to run
CI / x86 (MSVC): Windows (VS 2022) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, static) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, shared) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh) (push) Waiting to run
CI / x64 (MSVC): Windows (VS 2022, int128_struct) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, static) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, shared) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh) (push) Waiting to run
CI / x64 (clang-cl): Windows (VS 2022, int128_struct) (push) Waiting to run
CI / x64 (MSVC): C++ (public headers) (push) Waiting to run
CI / C++ -fpermissive (entire project) (map[env_vars:map[]]) (push) Blocked by required conditions
CI / C++ (public headers) (push) Blocked by required conditions
CI / SageMath prover (push) Waiting to run
CI / release (push) Waiting to run
doc/prefractal.md writes down the three deliberate deviations from BIP 445
where a reviewer will find them, since none of them is visible from the API
and two of them are actively counterintuitive:

1. b_frost does not commit to the message, because the target protocols
   publish the group's wire nonce before the message exists. The outer b_musig
   does commit to it and multiplies b_frost everywhere it appears.

2. There is no g_frost factor, and the reason is NOT that the tweak cache is
   the identity. The frost key-side factor is g*gacc; an identity cache gives
   gacc = 1, but g is still -1 for every odd-Y threshold key. The doc spells
   this out because "identity cache, therefore no key term" is the plausible
   wrong reason, and acting on it yields a signer that works for even-Y groups
   and fails for odd-Y ones.

3. The frost tweak cache must be the identity, checked at signing and
   verification and not only at aggregation, so the key a member signs under
   is tied to the cache that was validated.

It also records the two caller obligations the module cannot enforce - one
secnonce per signature, and round-two signers EQUAL to round-one contributors
- and notes that iceberg tolerates a round-two subset where this module must
not, since callers moving between the two would otherwise transpose the rule.

The build section documents the three-way ordering constraint rather than
leaving the next person to copy iceberg's positions, which are wrong for
configure.ac.

The ctime test adds a 2-of-2 nested group with a stock musig cosigner, taken
as far as one signature share, marking the threshold key, the secret shares
and the session randomness as secret and everything else as public. Nonce
generation passes msg = NULL, which is how the module is actually driven.

Verified: valgrind -q ./build/bin/ctime_tests exits 0, so nothing in the
prefractal signing path branches on secret data. Full test suite green.

The example program from the plan's optional list is not included; the test
suite covers the same ground and the doc carries the usage rules.
2026-09-04 01:06:14 +02:00
Kgothatso Ngako
f0014c4c49 prefractal: add the module test suite
Ten tests covering the round trip, the three deliberate deviations from BIP
445, and the failure modes the module cannot catch for its caller.

The centrepiece is a pair of FIXED threshold secret keys, one whose threshold
public key has even Y and one whose has odd Y. The nested equation has no
g_frost factor, and the reason is NOT that the tweak cache is the identity:
stock frost's key-side factor is g*gacc with g = -1 for an odd-Y threshold key
(frost/session_impl.h:664, :797-800), so an implementation that imported
frost's key-side parity works for even-Y groups and fails for odd-Y ones. With
a randomly seeded fixture that is a coin flip per run.

This was verified by mutation rather than assumed. Injecting the pk_odd
negation into prefractal_session_values and rebuilding:

  run_prefractal_odd_y_group_key_test   FAILED
  same test with the even-Y fixture     PASSED

so the fixed odd-Y fixture is what makes the trap detectable, and the parity
of the fixture is itself asserted in the test so it cannot quietly stop
testing what it is named after.

The suite:

  midstate            pins the Prefractal/noncecoef tagged hash against a
                      freshly initialised one. Nothing else in the tree would
                      notice a changed b_frost; it would just produce
                      signatures that do not verify.
  e2e                 the round trip over {2-of-2, 3-of-2, 5-of-3, 4-of-3,
                      7-of-5} x both lexicographic positions of the group key
                      x both group-key Y parities x with and without the outer
                      BIP 341 tweak, against a stock musig cosigner, judged by
                      secp256k1_schnorrsig_verify on the outer aggregate key.
                      Both key orders matter because BIP 327 KeyAgg gives the
                      second distinct key a coefficient of exactly 1.
  odd_y_group_key     the odd-Y case alone, so a regression names its cause
                      instead of surfacing as one iteration of that matrix.
  partial_sig_verify  accepts a good share; rejects a tampered one, the right
                      share against the wrong member, a share made for a
                      different signer set (lambda_i is defined over the
                      participating set), and a different message.
  identity_cache      a tweaked frost cache is refused by sign, by
                      partial_sig_verify and by partial_sig_agg, and the same
                      agg call succeeds with the identity cache, so the
                      refusal is about the tweak and not the arguments.
  key_cache_mismatch  thresh_pk and the tweak cache must describe one key.
  infinity_nonce      both nonce columns can reach infinity independently -
                      the first is passed through unscaled, the second only
                      after the b_frost multiplication - and a musig pubnonce
                      can encode neither, so both are refused; the untouched
                      set still aggregates.
  nonce_reuse         the secnonce is wiped, including on calls that then fail
                      for another reason, so a refused member cannot retry
                      with the same nonce. Reuse takes the illegal-argument
                      path via secnonce_load's ARG_CHECK, as stock frost_sign
                      does, so it is checked with CHECK_ILLEGAL.
  negative_control    wrong key order and a missing outer tweak both produce
                      shares that are individually well formed and only fail
                      at the final BIP 340 verification. These are the
                      mistakes the module cannot catch for the caller, so the
                      tests pin where they do surface.
  api                 duplicate identifiers, out-of-range counts, an id
                      outside the signer set, a share not matching its
                      pubshare, and NULL pubshares skipping that check as
                      documented.

Also fixes the outer tweak in the identity-cache test, which declared its
throwaway output as secp256k1_pubkey where frost_pubkey_xonly_tweak_add wants
secp256k1_xonly_pubkey. Both are data[64] so it ran correctly, but it is a
type error and -Wincompatible-pointer-types flags it.

Verified:
  cmake ... -DSECP256K1_ENABLE_MODULE_PREFRACTAL=ON -> 10/10 prefractal tests
    pass, full suite green
  ./configure --enable-experimental --enable-module-prefractal && make check
    -> 3/3 pass
  -Wall -Wextra -Wcast-align -Wshadow -Wundef -std=c89 -pedantic -> no
    warnings from any prefractal file
2026-09-04 01:02:56 +02:00
Kgothatso Ngako
903da53c06 prefractal: add the nested FROST+MuSig2 module (API, implementation, wiring)
Adds `prefractal`, an experimental module that lets a FROST t-of-n group
occupy ONE participant slot of an ordinary MuSig2 (BIP 327) session. Each
member computes

    s_i = k1_i + b_frost*b_musig*k2_i + e*a*lambda_i*g*gacc*d_i

and the group publishes one ordinary MuSig2 public nonce and one ordinary
MuSig2 partial signature, so cosigners need no support for it and cannot tell
a group is involved.

Four public functions, all sessionless (every call takes its session
parameters explicitly, so there are no new opaque types, magics or *_SIZE
constants to keep synchronised):

  secp256k1_prefractal_nonce_agg           group wire nonce + unscaled aggnonce
  secp256k1_prefractal_sign                one member's partial signature
  secp256k1_prefractal_partial_sig_verify  identifiable abort
  secp256k1_prefractal_partial_sig_agg     sum -> musig partial signature

Three deliberate deviations from BIP 445, all documented in the public header:

1. b_frost does not commit to the message. The target protocols publish the
   group's wire nonce before the message exists, so a message-committing
   coefficient could not be computed in round one and rebuilt later. The outer
   b_musig does commit to the message and multiplies this one, so the product
   still binds it. Same trade the iceberg module makes, for the same reason.
   The preimage is BIP 445's with the message dropped and the group key
   carried in full rather than x-only, since it is used as a full point
   downstream.

2. There is NO g_frost factor. Stock FROST normalises its threshold key to
   even Y (g_times_gacc_parity = gacc_parity ^ pk_odd, frost/session_impl.h
   :664) because it produces a BIP 340 x-only signature. Here the threshold
   key is an inner participant of the outer key aggregation and is used as a
   full point, so all key-side parity normalisation happens once, at the
   aggregate level, off the OUTER keyagg cache. Note this is NOT implied by
   the tweak cache being the identity: with an identity cache g_frost is still
   -1 for every odd-Y group key, i.e. about half of them. Importing frost's
   key-side parity here would yield a signer that works for even-Y groups and
   fails for odd-Y ones.

3. The FROST tweak cache must be the identity (tacc == 0, gacc_parity == 0).
   Checked in sign and partial_sig_verify, not only in partial_sig_agg, so the
   key a member signs under is tied to the cache that was validated; sign and
   verify additionally require thresh_pk to equal the cache's own key so the
   two arguments cannot disagree.

The verification equation lives in one helper used both by sign's BIP 445
self-check and by partial_sig_verify, so the two cannot drift apart.

Build wiring. Three files order their module blocks differently and the
constraints point in opposite directions:

  - src/secp256k1.c: the include goes AFTER frost and musig, because the
    module calls their static internals.
  - src/CMakeLists.txt: the block goes BEFORE both, because its set() calls
    are only observed by blocks that run later.
  - configure.ac: the block likewise goes before the musig block, NOT at
    iceberg's position further down. configure.ac orders musig and frost ahead
    of iceberg, and iceberg's late enable_module_musig=yes is harmless only
    because musig defaults to yes. frost defaults to no, so a late
    force-enable would leave -DENABLE_MODULE_FROST=1 unemitted while
    AM_CONDITIONAL still observed the mutation - a library whose secp256k1.c
    never included frost, built alongside frost's own sources.

frost is also the first default-OFF module anything depends on, which breaks
the dependency-guard idiom used everywhere else in both build systems: the
existing "DEFINED X AND NOT X" (CMake) and "x$X = xno" (autotools) tests read
as "the user disabled it explicitly" only for default-ON modules, and are true
by default for a default-OFF one. Since neither build system can distinguish
an explicit disable from the default once both are in the cache, enabling
prefractal simply implies frost; the guard is kept for musig, where it still
means what it says. The CMake block additionally lifts both dependencies into
the parent scope so the top-level configuration summary reports what was
actually built rather than printing "frost OFF" while compiling frost in.

Verified on both build systems:

  cmake -B build -DSECP256K1_ENABLE_MODULE_PREFRACTAL=ON -DSECP256K1_BUILD_TESTS=ON
      -> musig/frost/prefractal all ON, tests pass, 4 prefractal symbols exported
  cmake -B build -DSECP256K1_BUILD_TESTS=ON
      -> prefractal OFF, default build unchanged, tests pass
  ./configure --enable-experimental --enable-module-prefractal && make && make check
      -> frost=yes forced on, -DENABLE_MODULE_FROST=1 emitted, 3/3 pass
  ./configure --enable-module-prefractal
      -> correctly refused: "Prefractal module is experimental"

tests_impl.h is a placeholder here so the module links; the real suite lands
next.
2026-09-04 00:44:43 +02:00
Kgothatso Ngako
42f827a7d9 build: distribute the frost, chilldkg and iceberg documentation
README.md gained three links when the modules landed -- to
src/modules/frost/frost.md, src/modules/chilldkg/chilldkg.md and
doc/iceberg.md -- and none of the three files was added to EXTRA_DIST,
so make dist produced a tarball whose README pointed at files that were
not in it.

doc/iceberg.md is the clearest case: every other file under doc/ is
listed, so it was simply missed. The two module documents follow the
existing pattern for module-local documentation, where
src/modules/surjection/surjection.md and
src/modules/whitelist/whitelist.md are equally absent and equally linked
from README.md. That pattern is inherited and is left for a separate
change; adding the two this fork introduced at least makes the fork's own
additions self-consistent.

Verified with a from-scratch autogen.sh, configure and make dist in a
clean copy of the tree: the tarball now carries doc/ellswift.md,
doc/musig.md, doc/iceberg.md, src/modules/frost/frost.md and
src/modules/chilldkg/chilldkg.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:38:15 +02:00
Kgothatso Ngako
67e9424552 build: gate the experimental modules on SECP256K1_EXPERIMENTAL in CMake
configure.ac refuses --enable-module-frost, --enable-module-chilldkg and
--enable-module-iceberg outright unless --enable-experimental is also
given. The CMake build had no equivalent, so
-DSECP256K1_ENABLE_MODULE_ICEBERG=ON produced a library with no warning
banner and no acknowledgement that anything experimental was requested.

Of the three, iceberg is the one this matters most for: doc/iceberg.md
tells the reader not to put money behind it, and the CMake path let a
build acquire it without the reader ever passing a flag that says so.

Add the three checks to the existing NOT SECP256K1_EXPERIMENTAL block,
next to the ARM32 assembly check and worded the same way. The options are
declared well above it, so the values are set by the time the block runs.
Verified both directions: the configure fails with "Iceberg module is
experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow." without the
flag, and succeeds with it.

This deliberately leaves the other zkp experimental modules alone. They
are ON by default in CMake and gating them would change every existing
CMake build; the three added here are OFF by default, so nobody is
relying on the ungated path.

While here, correct doc/iceberg.md, which claimed the module "builds by
default here". SECP_SET_DEFAULT(enable_module_iceberg, no, yes) makes it
off by default and on in dev mode, which is now what the paragraph says,
along with the experimental requirement it did not previously mention.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:38:05 +02:00
Kgothatso Ngako
7afee05de8 tools: add the iceberg test vector generator
src/modules/iceberg/vectors.h opens with regeneration instructions that
name ./tools/test_vectors_iceberg_generate.py, and that script was never
committed. The same header calls the file "the one thing in this
repository that cannot be rebuilt from what the repository contains",
which the missing generator made true twice over: neither the reference
nor the tool that reads it was reachable from a clone.

Recovered from the tree the Iceberg C is vendored in, at
sources/secp256k1-kmp/native/secp256k1 of the benchmark repository
(bitcoin-core/secp256k1 branch iceberg-module, commit 96201552, per that
repository's PINS.txt). Confirmed to be the generator that produced the
checked-in vectors before committing it:

  - its HEADER template reproduces the header of vectors.h exactly,
    including the ICEBERG_VECTOR_MAX_PARTICIPANTS 9 and
    ICEBERG_VECTOR_MAX_SEEDS 126 it computes from the configuration list;
  - its seed rule, sha256("iceberg test vectors|<label>|<rank>"),
    reproduces the checked-in 2of3 seeds byte for byte;
  - the whole of that tree's src/modules/iceberg/ matches this one byte
    for byte except tests_impl.h, which differs only because the tests
    here are ported to the unit_test.h test-module framework.

The script cannot be re-run from a clone alone, by design: it takes the
nkohen/Iceberg Python reference as its argument and that reference is
deliberately not vendored, since it is not ours and pinning a copy would
hide it drifting. Its docstring gives the clone and the pinned commit
(7b55ef6d), which is now the whole of what regenerating requires.

Also restore the executable bit on the frost and chilldkg generators.
Both carry a usage line telling the reader to run them directly, and
every other generator in tools/ is 0755.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:37:52 +02:00
Kgothatso Ngako
c9952bd10a chilldkg: enforce the tag length bounds in noverify builds
secp256k1_chilldkg_pad33 and secp256k1_chilldkg_schnorrsig_sha256_tagged
each guarded a memcpy into a fixed-size stack buffer with VERIFY_CHECK,
which is compiled out in noverify (release) builds. In pad33 the
consequence is worse than the overflowing copy: the following
memset(out33 + len, 0, 33 - len) underflows its length to a huge value
when len exceeds 33.

Neither is reachable today. Every call site passes a string literal of
this module: "BIP DKG/certeq message" (22) and "BIP DKG/recovery
acknowledgment" (31) for pad33, and at most "BIP DKG/pop message" ||
"/challenge" (29 of 64) for the tagged-hash helper. This is the same
shape as the persisted-state guards promoted in ceccb50a, without the
attacker-controlled input path -- so the change is defence in depth, to
keep a future longer tag from smashing the stack in a release build
rather than failing a debug assertion.

Enforce both bounds outside VERIFY_CHECK and keep VERIFY_CHECK(0) inside
the branch as the debug-build diagnostic, matching the existing idiom in
this module (see the point_load fallbacks in the state loaders).

The tagged-hash helper clamps rather than returning early: an early
return would leave the caller's secp256k1_sha256 uninitialized and every
call site writes into it immediately, which is a worse failure than the
one being fixed. A clamped tag changes every hash the module computes,
so the chilldkg vectors would fail loudly rather than silently.

No behaviour change on any reachable input: the full test suite,
including the chilldkg vectors, is unaffected in both verify and
noverify builds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:37:35 +02:00
Kgothatso Ngako
3765a82886 frost: document deterministic_sign's nonce derivation domain
BIP 445's det_nonce_hash commits to the secret share, my_id, u, the
sorted ids, the aggothernonce, the x-only tweaked threshold public key
and the message. It does not commit to the pubshares, to the untweaked
threshold public key, or to the accumulated tweaks. Because Q and -Q
share an x-coordinate, two tweak caches can agree on everything the
derivation hashes and still disagree on the sign g*gacc that multiplies
the secret share -- a cache initialized from thresh_pk and one
initialized from its negation being the smallest example.

Two calls differing only in that emit the same pubnonce and partial
signatures s = k + e*lambda*d and s' = k - e*lambda*d over the identical
k = k1 + b*k2, so subtracting them yields the secret share. Demonstrated
on a sole signer (u = 1, ids = {0}, pubshares = NULL) with thresh_sk =
0x11.. and msg = 0x42..:

  tweaked pk (cache A)  4f355bdc...075871aa
  tweaked pk (cache B)  4f355bdc...075871aa   same x-only key
  pubnonce A == pubnonce B                    nonce reused
  sA - sB               0d7d9c4e...aa748ffa
  -2*e*d                0d7d9c4e...aa748ffa   d recovered

Nothing inside a single call can catch this. The self-verification that
Sign performs passes in both cases, because each partial signature is
individually valid under the cache it was produced with;
validate_session_params likewise only ties the pubshares to the cache's
own Q0, which both caches satisfy by construction. Note also that
pubshares is optional, so there need not be a second value to disagree
with.

No code change: this is the specified derivation, and committing to Q0
or to gacc here would diverge from BIP 445 and invalidate the
det_sign test vectors. The obligation is the caller's, so state it where
the caller will meet it -- in the function's own documentation and
alongside the existing secnonce and session_secrand32 rules in frost.md.
The rule is that the tweak cache and the pubshares are fixed key
material settled at key generation, never per-session parameters taken
from a coordinator or a peer; under that discipline a repeated call is
byte-identical and harmless, which is the point of a deterministic
nonce.

Worth raising against the BIP: the spec could close this by hashing the
untweaked threshold public key, at the cost of new test vectors.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:37:22 +02:00
Kgothatso Ngako
34fa8e0b2e frost: zero the trusted dealer outputs when key generation fails
secp256k1_frost_trusted_dealer_keygen clears secshares32, thresh_pk and
pubshares up front, under a comment promising that "the outputs are
unusable if this function fails". The per-participant loop then fills
them in one participant at a time, and every failure after that point
leaves the shares written so far in the caller's buffer while returning
0.

The reachable failure is the zero-share check inside the loop, which has
negligible probability, so this is hygiene rather than a live leak. It
still contradicts the stated contract, and the buffer it leaves populated
holds real secret shares for participants 0..i-1 of a setup the caller
has been told to discard.

Re-zero all three outputs on the failure path. secshares32 goes through
secp256k1_memzero_explicit rather than memset because it is secret and
the buffer is dead afterwards. n_participants is validated before any
path that can reach the cleanup label, so the lengths are safe to use
there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:36:54 +02:00
Kgothatso Ngako
bf31d42486 frost: fix stack buffer overflow in frost_nonce_test
frost_nonce_test_internal declares extra_in as 16 bytes and filled it
with testrand256, which writes 32. Three iterations of the loop each
overflowed the array by 16 bytes.

AddressSanitizer is unambiguous about it:

  ERROR: AddressSanitizer: stack-buffer-overflow
  WRITE of size 1 ... in testrand256 src/testrand_impl.h:90
    #1 frost_nonce_test_internal src/modules/frost/tests_impl.h:533
  [4336, 4352) 'extra_in' (line 510)
    <== Memory access at offset 4352 overflows this variable

The plain test suite passes regardless, which is why this survived:
under the current stack layout the 16 stray bytes land on secshare,
which is re-derived into pubshare_tmp immediately afterwards, so the
two stay consistent and nothing downstream notices. That is luck, not
correctness -- the target is whatever the compiler happens to place
next, and msglen, extra_in_len or i are equally plausible.

This should have been failing CI already: the sanitizers_debian job in
.github/workflows/ci.yml sets FROST: 'yes' alongside
CFLAGS: '-fsanitize=undefined,address -g'.

Use testrand_bytes_test with an explicit length, matching how the musig
tests fill their own extra_input (src/modules/musig/tests_impl.h:578).
extra_in_len is already drawn from testrand_int(sizeof(extra_in) + 1),
so the buffer stays 16 bytes and the value range is unchanged.

Scanned all three new test files for other fixed-width writers aimed at
undersized arrays; this was the only one. With the fix, the frost,
chilldkg and iceberg suites run clean under -fsanitize=address,undefined.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:36:43 +02:00
Kgothatso Ngako
03db82815f Merge branch 'iceberg'
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 CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCH… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:y… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJE… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RE… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNOR… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes … (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECT… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECO… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:ye… (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
2026-09-01 00:31:57 +02:00
Kgothatso Ngako
ff9c49cb7b chilldkg: add regression tests for the recovery/state bounds fixes
Add chilldkg_input_bounds_test covering the two review findings that
the vector suite cannot catch (the memory-safe Python reference never
exercises fixed-size-array overflows, so no upstream vector encodes
them):

- Recovery data with t = 129 (one past MAX_PARTICIPANTS) and t =
  30000, both with n = 0: previously a stack buffer overflow in
  deserialize_recovery_data (ASan-confirmed: this test reports a
  stack-buffer-overflow on sum_coms against the unfixed code); now
  both participant_recover and coordinator_recover return
  INVALID_INPUT with outputs zeroed. Plus a t = 0 case.
- Tampered persisted state objects (valid magic, n = 100000) for all
  four state types: participant_step2, participant_finalize,
  coordinator_finalize and participant_investigate fire the
  illegal-argument callback and return INVALID_INPUT instead of
  indexing out of bounds, in both verify and noverify builds.

Verified: the test fails (ASan stack-buffer-overflow) against the
pre-fix parser and passes against the fixed code, in the default,
noverify and ASan builds.
2026-08-31 13:25:41 +02:00
Kgothatso Ngako
ceccb50a5a chilldkg: harden persisted-state bounds checks for noverify builds
The four opaque-state loaders (participant state1, state2,
coordinator state, inv_data) guarded the t/n/participant_id fields
read from the serialized object with VERIFY_CHECK, which is compiled
out in noverify (release) builds. chilldkg.md explicitly recommends
persisting state1 and the coordinator state between rounds, which
turns the persisted file into an attack surface: a state1 with n
altered to 100000 and the magic bytes left intact crashed
participant_step2 with out-of-bounds array indexing in a noverify
build.

Promote all four guards to ARG_CHECK, consistent with the magic-byte
check right above them: the illegal-argument callback fires, the load
returns 0, and the public entry points (participant_step2,
participant_finalize, coordinator_finalize, participant_investigate)
return SECP256K1_CHILLDKG_INVALID_INPUT before any state-derived size
is used -- verified in both verify and noverify builds.
2026-08-31 13:25:26 +02:00
Kgothatso Ngako
c43f645f15 chilldkg: fix out-of-bounds write in recovery data parsing
secp256k1_chilldkg_deserialize_recovery_data read the threshold t
from the first four bytes of the recovery blob and used it directly
as the loop bound writing into the fixed-size
sum_coms[SECP256K1_CHILLDKG_MAX_PARTICIPANTS] array. params_validate
would reject an out-of-range t, but it only runs after the parse --
the overflow happens first. The reference implementation is safe only
because Python lists grow dynamically; the C port lost that implicit
bound.

Reachable with attacker-supplied input from both public entry points,
secp256k1_chilldkg_participant_recover and
secp256k1_chilldkg_coordinator_recover (recovery data is untrusted by
design: participants who never received cmsg2 are expected to accept
recovery data from third parties). Confirmed with AddressSanitizer:
t = 129 with a 4261-byte blob writes one group element past the
array; t = 30000 with a ~1 MB blob writes ~1.2 MB of attacker-
controlled group elements past it. The spec's own "invalid threshold"
recovery vector cannot catch this because the memory-safe reference
never exercises a t large enough to overflow a fixed C array.

Fix: reject t < 1 and t > SECP256K1_CHILLDKG_MAX_PARTICIPANTS right
after reading t, before any use as a loop bound, and reject
recovery_len > SECP256K1_CHILLDKG_MAX_RECOVERY_LEN up front for
consistency with the recovery-ack paths (the macro moves next to the
parser; with t and n bounded the length cap is redundant, but it
documents and enforces the invariant at the single choke point).

Invalid recovery data is a plain input error (RecoveryDataError in
the reference), so this maps to SECP256K1_CHILLDKG_INVALID_INPUT with
outputs zeroed, like any other malformed blob.
2026-08-31 13:25:26 +02:00
Kgothatso Ngako
d9549a6c5a tests: raise MAX_ARGS from 200 to 400
With the chilldkg (and iceberg) modules enabled, the unit test binary
registers more than 200 tests (213 with all modules on), tripping the
"Number of tests exceeds MAX_ARGS" internal error in unit_test.c and
bailing before running anything -- both tests and noverify_tests were
unrunnable in the all-modules CI rows. MAX_ARGS must be at least the
total number of registered tests; 400 leaves headroom for future
modules and vector-suite growth.
2026-08-31 13:25:26 +02:00
Kgothatso Ngako
a68cae31ca iceberg: list the module in the README feature list
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 CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HA… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCH… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:y… (push) Has been cancelled
CI / x86_64: macOS Sequoia, Valgrind (map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECTION… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:ye… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALF… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJE… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RE… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNOR… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (clang-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECOVERY:yes … (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAG… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:yes SURJECT… (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 CHILLDKG:yes CPPFLAGS:-DVERIFY CTIMETESTS:no ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes RECO… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes ELLSWIFT:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRS… (push) Has been cancelled
CI / x86_64: Linux (Debian stable) (gcc-snapshot, map[env_vars:map[BPPP:yes CHILLDKG:yes ECDH:yes ECDSAADAPTOR:yes ECDSA_S2C:yes EXPERIMENTAL:yes EXTRAKEYS:yes FROST:yes GENERATOR:yes ICEBERG:yes MUSIG:yes RANGEPROOF:yes SCHNORRSIG:yes SCHNORRSIG_HALFAGG:ye… (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
Add the Iceberg module to the "Added features" section, after the
ChillDKG entry, linking doc/iceberg.md.
2026-08-31 12:25:55 +02:00
Kgothatso Ngako
2473c76871 iceberg: wire the module into CI
- ci/ci.sh: new ICEBERG environment variable, printed in the
  reproduction header and passed to configure as
  --enable-module-iceberg (mirroring CHILLDKG); bench_iceberg runs in
  the bench step when the module is enabled, as in the source tree's
  CI.
- .github/workflows/ci.yml: ICEBERG: 'no' default; ICEBERG: 'yes' in
  the 20 jobs that enable musig + schnorrsig + experimental (the same
  jobs that build chilldkg). Jobs that deliberately build without
  musig or its dependencies are left at 'no'. Verified
  programmatically: the YAML parses and every ICEBERG: 'yes' context
  also has MUSIG, SCHNORRSIG and EXPERIMENTAL set to 'yes'.
2026-08-31 12:25:55 +02:00
Kgothatso Ngako
8c4bf548ed iceberg: cover the module in ctime_tests
Port the source tree's own iceberg ctime_tests block (guarded by
ENABLE_MODULE_ICEBERG, after the chilldkg block): a 3-of-5 group run
through shares_gen, a share serialize/parse roundtrip,
share_cache_create (with a CHECKMEM_CHECK proving the cache holds no
secrets), pubshare_gen, pubkey_agg, nonce_gen, nonce_agg and
partial_sign, with share secrets undefined and all protocol outputs
defined, following the frost/chilldkg annotation style.

Both memory checkers pass with zero new declassifies needed -- the
module's constant-time layering (vpss variable-time but secret-free,
scalar_poly keeping secrets away from inversions) was already in
place. Verified: valgrind ./ctime_tests exits 0, and the clang
MemorySanitizer build exits 0 (with the chilldkg block unaffected).
2026-08-31 12:25:55 +02:00
Kgothatso Ngako
da13028c0d iceberg: add the bench_iceberg benchmark binary
Port src/bench_iceberg.c, the standalone benchmark binary the
module's bench_impl.h is written for (this repo's bench harness has
no per-module include pattern for it, so the source tree's own wiring
is mirrored instead): noinst_PROGRAMS under USE_BENCHMARK +
ENABLE_MODULE_ICEBERG in Makefile.am, a bench_iceberg target in
src/CMakeLists.txt, and a .gitignore entry. The benchmark covers the
group configurations 2-of-3, 3-of-5, 4-of-7, 5-of-9 and 5-of-10.

Verified: ./bench_iceberg builds and runs under both build systems.
2026-08-31 12:25:33 +02:00
Kgothatso Ngako
072f6631f3 iceberg: add the example program
Port examples/iceberg.c from the source tree: a full Iceberg session
demonstrating the call order from the module docs -- distributed key
generation, pubshare_gen/pubkey_agg to obtain the group public key,
nonce_gen/nonce_agg into an ordinary MuSig2 public nonce, and
partial_sign/partial_sig_agg into an ordinary MuSig2 partial
signature.

One content adaptation: the secp256k1_musig_nonce_process call gains
a NULL adaptor argument, matching this repo's zkp musig variant.

Wired like the chilldkg example: autotools noinst_PROGRAMS +
TESTS entry under ENABLE_MODULE_ICEBERG (the example runs as part of
make check), CMake example target in examples/CMakeLists.txt, and
iceberg_example added to .gitignore.

Verified: ./iceberg_example runs to completion (exit 0) under both
build systems.
2026-08-31 12:25:09 +02:00
Kgothatso Ngako
e581abad00 iceberg: add the Iceberg threshold-MuSig module
Port the experimental Iceberg module from the benchmark-iceberg tree
(github.com/furszy/benchmark-iceberg, sources/secp256k1-kmp/native/
secp256k1) into this repo.

Iceberg is a threshold scheme that lets a group of parties stand in
for a single MuSig2 (BIP 327) participant: the group produces one
ordinary MuSig2 public nonce and one ordinary MuSig2 partial
signature, so cosigners cannot tell a group is involved and need no
changes. Nonces are derived from a caller-chosen per-session label
(sid32) rather than stored, so no signer holds a secret nonce between
rounds; labels are public but must never be reused. A quorum of 2t-1
members (of whom up to t-1 may be corrupt) is needed in each round,
so the threshold is at most half the group rounded up; combined with
the scheme's other constraints the smallest usable group is 2-of-4.
See doc/iceberg.md and the module header for the full usage notes.

Module layout (src/modules/iceberg/, layered bottom-up, each layer
may only use the ones above it -- that ordering is also the
constant-time story):
- scalar_poly.{h,_impl.h}: secret-carrying polynomial arithmetic,
  keeping secrets away from inversions (documented in the header).
- rss.{h,_impl.h}: replicated secret sharing evaluation.
- vpss.{h,_impl.h}: verifiable public shares; variable-time by
  design, sees only participant indices and published points.
- keygen_impl.h: distributed key generation producing one share per
  member.
- session_impl.h: nonce_gen/nonce_agg and partial_sign/
  partial_sig_agg producing plain MuSig2 objects.
- tests_impl.h: 28 tests including the shipped vectors.h vector
  suite and dealer known-answer tests.
- bench_impl.h: benchmark definitions (wired in a follow-up commit).

Public headers: include/secp256k1_iceberg.h (installed) and
include/secp256k1_iceberg_dealer.h (in-tree only: a trusted dealer is
not part of the shipped API, but tests, benchmarks and the example
need to deal shares).

Content adaptations relative to the source tree (the only changes to
the ported code): three secp256k1_musig_nonce_process call sites in
tests_impl.h gained a NULL adaptor argument, because this repo's
musig is the zkp variant whose public nonce_process takes an optional
adaptor point. All musig internals the module uses (ge_parse_ext,
ge_serialize_ext, keyaggcoef, aggnonce_load, pubnonce_save,
partial_sig_save, nonce_process_internal) are identical in both
trees, as are all core headers the module touches; nothing else
needed adaptation.

Build wiring mirrors the chilldkg module:
- configure.ac: --enable-module-iceberg (default no, experimental
  gate), hard dependency on the musig module with a configure error
  if musig is explicitly disabled (musig itself pulls in schnorrsig),
  AM_CONDITIONAL(ENABLE_MODULE_ICEBERG), summary line.
- Makefile.am: include src/modules/iceberg/Makefile.am.include under
  the conditional.
- src/secp256k1.c: guarded include of modules/iceberg/main_impl.h
  after the chilldkg block (musig is included earlier, so its
  internals are in scope).
- src/tests.c: module test registration via MAKE_TEST_MODULE(iceberg).
- CMakeLists.txt / src/CMakeLists.txt: SECP256K1_ENABLE_MODULE_ICEBERG
  option (OFF) with a dependency check on SECP256K1_ENABLE_MODULE_MUSIG
  (placed before the musig block so the force-enable takes effect),
  ENABLE_MODULE_ICEBERG=1 compile definition, public header export,
  summary line.

Verified: ./configure --enable-experimental --enable-module-iceberg
&& make check passes; ./tests --target=iceberg runs the full module
suite (28/28); CMake build + ctest pass; the musig dependency error
fires correctly in both build systems.
2026-08-31 12:24:48 +02:00
Kgothatso Ngako
e9f171f197 chilldkg: list the module in the README feature list
Add the ChillDKG module to the "Added features" section of the README,
next to the FROST entry, linking to the module documentation.
2026-08-31 10:58:24 +02:00
Kgothatso Ngako
3b68633f59 chilldkg: CI wiring, ctime_tests coverage, declassify fixes
CI:
- ci/ci.sh: new CHILLDKG environment variable, passed to configure as
  --enable-module-chilldkg (mirroring FROST).
- .github/workflows/ci.yml: default CHILLDKG: 'no' and CHILLDKG: 'yes'
  in every job that enables FROST, except the x86_64 matrix entry that
  deliberately builds without the ecdh module (chilldkg requires
  schnorrsig + ecdh; the configure-time dependency error would fire
  there). YAML validity and per-job dependency presence checked
  programmatically.

ctime_tests:
- src/ctime_tests.c: run a full ChillDKG session (n = 2, t = 2) through
  the public API under the memory checker: hostpubkey_gen, params_hash,
  participant_step1, coordinator_step1, participant_step2,
  coordinator_finalize, participant_finalize, participant_recover and
  recovery_ack_sign. Host secret keys, session randomness, aux
  randomness and the resulting secret shares are undefined (secret);
  all protocol messages, the certificate, threshold public key, public
  shares, recovery data, ack signature and the secret-free state1
  objects are defined (public). state2 stays secret (contains the
  secret share).

Constant-time fixes found by running the new block under
MemorySanitizer (valgrind unavailable locally; MSan build via clang +
CMake). All are missing declassifications of secret-derived but public
(or public-outcome) values, following the frost module's
secp256k1_declassify pattern with justification comments; no real
constant-time bugs were found:
- hostpubkey_gen: declassify the computed host public key before
  serialization (public output).
- participant_step1: declassify the zero-randomness check result (only
  reveals "the RNG returned 32 zero bytes", which aborts the session).
- encpedpop participant_step1: declassify the pubnonce point before
  serialization (public, part of pmsg1).
- chilldkg_schnorrsig_sign: declassify the signer public key before
  normalization/parity branch, and declassify the return value (a
  failure only reveals a zero derived nonce, negligible probability).
- vss_commit: declassify the VSS commitments before serialization
  (public, part of pmsg1).
- vss_verify_secshare: declassify secshare*G before the infinity/eq
  checks (equals the public pubshare in honest runs; the discrete log
  is not revealed).
- simplpedpop_participant_investigate (proactive audit; not reached by
  ctime_tests): declassify the secshare-sum comparison result (the
  public fault code reveals it anyway).

Verified: MSan ctime_tests exits 0; autotools make check 10/10 (the
local tree is configured without --enable-ctime-tests because neither
valgrind nor an MSan-instrumented gcc build is available; CI runs
ctime_tests under valgrind as before); CMake ctest 428/428;
./tests --target=chilldkg and ./chilldkg_example pass.
2026-08-31 10:25:14 +02:00
Kgothatso Ngako
d1c817b528 chilldkg: Phase 6 - test vectors, FROST integration, docs, example
Final phase of the ChillDKG module: upstream test vectors, a
DKG->FROST integration test, boundary tests, full module
documentation and a runnable example.

Test vectors:
- tools/test_vectors_chilldkg_generate.py converts all 10 upstream
  bip-frost-dkg JSON vector files into src/modules/chilldkg/vectors.h
  (modeled on tools/test_vectors_frost_generate.py; takes the vectors
  directory as an argument; upstream pinned to commit
  a91896883f85b159415ecf298d5e844879af112d, recorded in the generated
  header with the exact regeneration invocation; regeneration is
  reproducible byte-for-byte).
- tests_impl.h vector runners execute 191 of 241 upstream cases
  through the public API: hostpubkey_gen, params_hash,
  participant_step1/step2/finalize/investigate,
  coordinator_step1/finalize/investigate, recover. Happy paths are
  byte-exact (pmsg1/cmsg1/pmsg2/cmsg2/dkg_output/recovery/cinv);
  error cases assert both the fault enum and fault_index against
  expectedError.participantId. The 50 skipped cases are
  wrong-length/wrong-count inputs not expressible with the
  fixed-size C API; each skip is documented in vectors.h.

Boundary/robustness tests: t=1, t=n, n=2, a full n=128/t=2 session
end-to-end with per-participant secshare*G == pubshare checks and a
recovery roundtrip, and a state1 memcpy roundtrip (step2 from a copied
state object).

DKG->FROST integration test (guarded by ENABLE_MODULE_FROST): a full
ChillDKG session (n=3, t=2) feeds (secshare, thresh_pk, pubshares)
directly into the frost module. ChillDKG's thresh_pk is already
TapTweak'ed, so frost_tweak_cache_init is called with no further
tweaks (frost's tweaked x-only key asserted equal to the x-only part
of the ChillDKG thresh_pk); signers 0 and 2 run nonce_gen, nonce_agg,
session_init with the shared x = id+1 convention, frost_sign,
partial_sig_verify and partial_sig_agg; the aggregate signature
verifies as a plain BIP-340 signature against the threshold key.

Example: examples/chilldkg.c runs a full 2-of-3 DKG session (host key
generation, params hash, participant/coordinator steps, finalize, and
a recovery roundtrip via participant_recover) with fixed-size buffers
and secret erasure. Wired into Makefile.am and
examples/CMakeLists.txt exactly like frost_example (runs as a TEST);
chilldkg_example binary added to .gitignore.

Docs: src/modules/chilldkg/chilldkg.md now documents the protocol
summary, message-flow table with exact byte sizes, blame taxonomy,
recovery workflow, security notes (host key reuse/retention, fresh
randomness per session, state secrecy, recovery-data sensitivity) and
the pinned reference commit; src/modules/frost/frost.md points at the
new module as the intended DKG.

Bug fix found by the vector runner (recover tcId 9): the internal
recover() passed a possibly-NULL fault_index from coordinator_recover
to certeq_verify, which dereferences it on failure; now uses a local.

Verified: make check 10/10 (3 test suites + 7 examples incl.
chilldkg_example, exit 0 when run); CMake ctest 428/428 with chilldkg
+ frost, and a no-frost build confirms the ENABLE_MODULE_FROST guard;
make distdir includes vectors.h, the example and the generator.

The module is feature-complete against bip-frost-dkg v0.3.0-dev at
a91896883f85b159415ecf298d5e844879af112d. The BIP is still a draft;
tagged hashes and wire formats may change upstream.
2026-08-31 06:52:58 +02:00
Kgothatso Ngako
d48a1579cf chilldkg: Phase 5 - recovery, recovery acks, investigation
Complete the ChillDKG protocol surface with the recovery and blame-
attribution procedures (bip-frost-dkg v0.3.0-dev, reference commit
a91896883f85b159415ecf298d5e844879af112d).

Recovery:
- secp256k1_chilldkg_participant_recover / _coordinator_recover: parse
  the self-delimiting recovery layout u32be(t) || sum_coms(33t) ||
  hostpubkeys(33n) || pubnonces(33n) || enc_secshares(32n, checked) ||
  cert(64n), deriving n = (len-4-33t)/162 exactly as the reference's
  deserialize_recovery_data; re-verify the certificate, recompute the
  TapTweak and the receiver's ECDH/self pads from (hostseckey,
  pubnonces, enc_context), recompute the tweaked secshare, and
  sanity-check secshare*G == pubshares[own]. Also return hostpubkeys,
  n and t so callers can re-derive session params. RecoveryDataError /
  HostSeckeyError / params failures map to INVALID_INPUT (no index,
  as in the reference); an invalid pubnonce during decrypt passes
  through as FAULTY_PARTICIPANT_OR_COORDINATOR(i), matching the
  reference leaking that exception from recover().

Recovery acks:
- secp256k1_chilldkg_recovery_ack_sign / _acks_verify: BIP-340
  (standard BIP0340 tags) over pad33("BIP DKG/recovery acknowledgment")
  || u32be(i) || recovery_data. Verification failure maps to
  FAULTY_PARTICIPANT(i) (InvalidRecoveryAckError subclasses
  FaultyParticipantError in the reference).

Investigation:
- secp256k1_chilldkg_coordinator_investigate: builds one 65n-byte
  per-participant message (per-dealer encrypted partial secshares
  (32n) + partial pubshares (33n)) per call; the reference returns all
  n at once -- equivalent, the caller iterates.
- secp256k1_chilldkg_participant_investigate: the reference's
  three-step blame attribution -- sum-of-pubshares check ->
  FAULTY_COORDINATOR; sum-of-secshares check -> FAULTY_COORDINATOR
  (covers the reference's SecshareSumError translation); per-dealer
  decrypted share vs commitment -> FAULTY_PARTICIPANT_OR_COORDINATOR(i)
  (or FAULTY_COORDINATOR for the own index); all-consistent ->
  INVALID_INPUT (the reference's uncaught RuntimeError).
- Investigation data is transported via a new opaque, secret-bearing
  secp256k1_chilldkg_participant_inv_data object (4205 bytes,
  magic-validated save/load, secret-cleared) filled by
  participant_step2 on the UNKNOWN_FAULT paths. This amends the
  Phase 3 participant_step2 signature with a nullable inv_data
  out-param -- required because recomputing inside
  participant_investigate would duplicate step2's decrypt/verify
  logic.
- New length helper secp256k1_chilldkg_investigation_msg_len (65n).

tests_impl.h: chilldkg_recovery_test (recover roundtrips byte-exact
vs the session outputs and reference vectors, tampered/truncated/
over-long recovery data, unknown/invalid hostseckey, ack sign
byte-exact + verify with wrong-index and tampered-ack blame,
params/recovery mismatch rejects, misuse) and
chilldkg_investigate_test (two end-to-end public-API scenarios
generated from the reference: dealer corrupting a participant's
encrypted share, and coordinator tampering with an enc_secshare;
cmsg1/cinv/inv_data byte-exact, blame codes and indices matching the
reference's exception type and index; malformed cinv ->
FAULTY_COORDINATOR; malformed pmsg1 -> FAULTY_PARTICIPANT(j); misuse).
The all-consistent investigate path is not constructible without
discrete logs and matches the reference's unreachable RuntimeError.

Verified: make check 3/3 (incl. noverify); CMake ctest 369/369;
make distdir clean.
2026-08-31 06:09:03 +02:00
Kgothatso Ngako
5409aae813 chilldkg: Phase 4 - public coordinator API
Add the coordinator side of the ChillDKG protocol
(bip-frost-dkg v0.3.0-dev, reference commit
a91896883f85b159415ecf298d5e844879af112d), as thin wrappers over the
Phase 2 encpedpop coordinator internals (whose cmsg1 output was
already verified byte-identical to the reference coordinator_step1).

Public API:
- secp256k1_chilldkg_coordinator_step1: takes an array of pointers to
  the n participant pmsg1 messages (musig/frost-style convention),
  parses each with checked scalar parse, aggregates SimplPedPop and
  EncPedPop, builds eq_input (including the enc_secshares suffix,
  mirroring the reference) and emits cmsg1 (162n + 33(t-1) bytes).
  PoPs are not verified coordinator-side, exactly as the reference.
- secp256k1_chilldkg_coordinator_finalize: concatenates the n CertEq
  pmsg2 signatures into the 64n-byte certificate, verifies all of them
  via certeq_verify (hostpubkeys recovered from eq_input at offset
  4+33t), and outputs the coordinator-side DKG result: threshold
  pubkey, pubshares and recovery data -- no secshare.
- secp256k1_chilldkg_coordinator_state: opaque, 21041 bytes,
  magic-validated, holds only t, n, eq_input, thresh_pk and pubshares
  -- no secret material, documented as freely copyable/persistable so
  a stateless coordinator is possible.

Blame mapping (verified against chilldkg.py):
- malformed pmsg1 (bad commitment encoding, overflowing encrypted
  share) -> FAULTY_PARTICIPANT(sender index),
- invalid CertEq signature -> FAULTY_PARTICIPANT(failing index)
  (deliberately different from participant_finalize, which maps the
  same failure to FAULTY_COORDINATOR -- matching the reference),
- invalid session params -> INVALID_INPUT; all outputs zeroed on
  failure.

tests_impl.h: chilldkg_coordinator_api_test runs a full n=3,t=2
session through only the public APIs on both sides, byte-exact
against the Python reference vectors and cross-checked against every
participant's finalize outputs; blame cases (malformed pmsg1 and
overflowing share -> FAULTY_PARTICIPANT with the right index, bad
CertEq sig -> FAULTY_PARTICIPANT(2), zeroed outputs); misuse coverage
(NULL args, corrupted state magic).

Verified: make check 3/3 (incl. noverify); CMake ctest 365/365;
./tests --target=chilldkg green.
2026-08-31 05:33:42 +02:00
Kgothatso Ngako
2a0e14d076 chilldkg: Phase 3 - public participant API and CertEq
Add the public participant-facing ChillDKG API to
include/secp256k1_chilldkg.h and the CertEq sub-protocol, completing
the participant side of the protocol (bip-frost-dkg v0.3.0-dev,
reference pinned at a91896883f85b159415ecf298d5e844879af112d).

New module files:
- certeq.h / certeq_impl.h: CertEq sub-protocol. Participants sign
  pad33("BIP DKG/certeq message") || u32be(i) || eq_input with plain
  BIP0340-tagged Schnorr signatures under their host key
  (certeq_participant_step); verification is per-index against the
  x-only hostpubkeys[i][1:33] exactly as the reference
  (certeq_verify). The coordinator side reuses certeq_verify in
  Phase 4.

Public API (all no-malloc, caller-allocated buffers, outputs zeroed on
failure, secret paths cleared):
- secp256k1_chilldkg_hostpubkey_gen: plain compressed host pubkey
  generation; rejects zero / >= group order seckeys.
- secp256k1_chilldkg_params_hash: validates session params (participant
  and threshold ranges, strictly compressed non-infinity pubkeys, no
  duplicates) and computes TH("BIP DKG/params_hash", u32be(t) ||
  hostpubkeys).
- Message-length helpers so callers can size buffers:
  participant_msg1_len (33t+32n+97), coordinator_msg1_len
  (162n+33(t-1)), participant_msg2_len (64), coordinator_msg2_len
  (64n), recovery_data_len (4+33t+162n).
- secp256k1_chilldkg_participant_step1: full EncPedPop step1 with
  seed=deckey=hostseckey; rejects zero randomness and hostseckeys not
  matching the claimed hostpubkey (input errors, not protocol faults).
- secp256k1_chilldkg_participant_step2: parses and verifies cmsg1 via
  the Phase 2 encpedpop/simplpedpop participant path, computes the
  tweaked secshare/pubshares/threshold pubkey, appends enc_secshares
  to eq_input (matching the reference for recovery consistency), and
  emits the 64-byte CertEq signature.
- secp256k1_chilldkg_participant_finalize: re-verifies all n CertEq
  signatures in the certificate, then outputs the 32-byte secshare,
  33-byte threshold pubkey, n pubshares and the self-delimiting
  recovery data (eq_input || cert).

Blame reporting without exceptions: public enum
secp256k1_chilldkg_fault (OK / FAULTY_COORDINATOR /
FAULTY_PARTICIPANT / FAULTY_PARTICIPANT_OR_COORDINATOR /
UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR / INVALID_INPUT) plus an out
fault_index, mapping the reference's exception taxonomy:
- hostseckey invalid/mismatch -> INVALID_INPUT (HostSeckeyError),
- cmsg1 scalar overflow/parse -> FAULTY_COORDINATOR (MsgParseError),
- pubnonce/commitment/PoP faults -> FAULTY_PARTICIPANT_OR_COORDINATOR(i),
- share-vs-pubshare mismatch -> UNKNOWN with fault_index = UINT32_MAX,
- certificate signature failure -> FAULTY_COORDINATOR (documented
  deviation: fault_index carries the failing signature index as
  diagnostic info; the reference discards it).
Enum-returning functions use a local CHILLDKG_ARG_CHECK that fires the
illegal-argument callback and returns INVALID_INPUT (ARG_CHECK would
return 0 = OK).

Opaque state objects with magic-validated save/load (frost idiom):
participant_state1 (4306 bytes, no secrets) and participant_state2
(21073 bytes, contains the secshare; documented keep-secret/no-copy).
Fixed-size at SECP256K1_CHILLDKG_MAX_PARTICIPANTS = 128.

Also fixes a noverify-build bug: state1_load ran point_load inside
VERIFY_CHECK, which compiles out in noverify builds and left the
commitment uninitialized; now called unconditionally.

tests_impl.h: participant_api_test with full-session reference vectors
(n=3, t=2; coordinator aggregation simulated through the internal
Phase 2 coordinator step and verified byte-identical to the
reference's coordinator_step1): msglen helpers, hostpubkey_gen and
params_hash vectors incl. duplicate/invalid/infinity rejection,
byte-exact pmsg1/cmsg1/CertEq sigs/secshare/thresh_pk/pubshares/
recovery, blame cases (tampered enc_secshare -> UNKNOWN, invalid
pubnonce -> FAULTY_PARTICIPANT_OR_COORDINATOR(1), overflowing
enc_secshare -> FAULTY_COORDINATOR, corrupted cert sig ->
FAULTY_COORDINATOR with fault_index and zeroed outputs), NULL-arg
misuse and bad-magic state rejection.

Verified: make check 3/3 (incl. noverify); CMake ctest 363/363;
make distdir includes all new files.
2026-08-31 05:22:53 +02:00
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