Files
secp256k1-zkp/.github/workflows/ci.yml
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

857 lines
30 KiB
YAML

name: CI
on:
pull_request:
push:
branches:
- '**'
tags-ignore:
- '**'
schedule:
# Run on the default branch every Monday morning.
# This also warms the Docker caches after key rotation.
- cron: '22 2 * * 1'
concurrency:
group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }}
cancel-in-progress: true
env:
### compiler options
HOST:
WRAPPER_CMD:
# Specific warnings can be disabled with -Wno-error=foo.
# -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual.
WERROR_CFLAGS: '-Werror -pedantic-errors'
MAKEFLAGS: '-j4'
BUILD: 'check'
### secp256k1 config
ECMULTWINDOW: 15
ECMULTGENKB: 86
ASM: 'no'
WIDEMUL: 'auto'
WITH_VALGRIND: 'yes'
EXTRAFLAGS:
### secp256k1 modules
EXPERIMENTAL: 'no'
ECDH: 'no'
RECOVERY: 'no'
EXTRAKEYS: 'no'
SCHNORRSIG: 'no'
MUSIG: 'no'
ELLSWIFT: 'no'
ECDSA_S2C: 'no'
GENERATOR: 'no'
RANGEPROOF: 'no'
SURJECTIONPROOF: 'no'
WHITELIST: 'no'
ECDSAADAPTOR: 'no'
BPPP: 'no'
SCHNORRSIG_HALFAGG: 'no'
FROST: 'no'
CHILLDKG: 'no'
ICEBERG: 'no'
PREFRACTAL: 'no'
FROST_ENROLLMENT: 'no'
### test options
SECP256K1_TEST_ITERS: 64
BENCH: 'yes'
SECP256K1_BENCH_ITERS: 2
CTIMETESTS: 'yes'
SYMBOL_CHECK: 'yes'
# Compile and run the examples.
EXAMPLES: 'yes'
# Disable Docker build summary generation.
# See https://github.com/docker/build-push-action/blob/master/README.md#environment-variables.
DOCKER_BUILD_SUMMARY: false
jobs:
docker_cache:
name: "Build ${{ matrix.arch }} Docker image"
runs-on: ${{ matrix.runner }}
outputs:
cache_scope: ${{ steps.cache_timestamp.outputs.period }}
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-latest
- arch: arm64
runner: ubuntu-24.04-arm
steps:
- name: Get cache validity period
id: cache_timestamp
run: echo "period=$((10#$(date +%V) / 4))" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
with:
# See: https://github.com/moby/buildkit/issues/3969.
driver-opts: |
network=host
- name: Build container
uses: docker/build-push-action@v7
with:
file: ./ci/linux-debian.Dockerfile
cache-from: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }}
cache-to: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }},mode=min
x86_64-debian:
name: "x86_64: Linux (Debian stable)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' }
- env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes'}
- env_vars: { WIDEMUL: 'int128' }
- env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' }
- env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes'}
- env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' }
- env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes'}
- env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes', CPPFLAGS: '-DVERIFY' }
- env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' }
- env_vars: { CPPFLAGS: '-DDETERMINISTIC' }
- env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' }
- env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 }
- env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 }
cc:
- 'gcc'
- 'clang'
- 'gcc-snapshot'
- 'clang-snapshot'
env:
CC: ${{ matrix.cc }}
steps:
- &CHECKOUT
name: Checkout
uses: actions/checkout@v5
- &CI_SCRIPT_IN_DOCKER
name: CI script
env: ${{ matrix.configuration.env_vars }}
uses: ./.github/actions/run-in-docker-action
with:
dockerfile: ./ci/linux-debian.Dockerfile
scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }}
command: ./ci/ci.sh
- &PRINT_LOGS
name: Print logs
uses: ./.github/actions/print-logs
if: ${{ !cancelled() }}
i686_debian:
name: "i686: Linux (Debian stable)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- env_vars: {}
cc:
- 'i686-linux-gnu-gcc'
- 'clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include'
env:
HOST: 'i686-linux-gnu'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
GENERATOR: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CC: ${{ matrix.cc }}
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
s390x_debian:
name: "s390x (big-endian): Linux (Debian stable, QEMU)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
matrix:
configuration:
- env_vars: {}
env:
WRAPPER_CMD: 'qemu-s390x'
SECP256K1_TEST_ITERS: 16
HOST: 's390x-linux-gnu'
WITH_VALGRIND: 'no'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
GENERATOR: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
arm32_debian:
name: "ARM32: Linux (Debian stable, QEMU)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- env_vars: {}
- env_vars: { EXPERIMENTAL: 'yes', ASM: 'arm32' }
env:
WRAPPER_CMD: 'qemu-arm'
SECP256K1_TEST_ITERS: 16
HOST: 'arm-linux-gnueabihf'
WITH_VALGRIND: 'no'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
arm64-debian:
name: "arm64: Linux (Debian stable)"
runs-on: ubuntu-24.04-arm
needs: docker_cache
env:
SECP256K1_TEST_ITERS: 16
WITH_VALGRIND: 'no'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
CC: ${{ matrix.cc }}
strategy:
fail-fast: false
matrix:
configuration:
- env_vars: {}
cc:
- 'gcc'
- 'clang'
- 'gcc-snapshot'
- 'clang-snapshot'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
ppc64le_debian:
name: "ppc64le: Linux (Debian stable, QEMU)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
matrix:
configuration:
- env_vars: {}
env:
WRAPPER_CMD: 'qemu-ppc64le'
SECP256K1_TEST_ITERS: 16
HOST: 'powerpc64le-linux-gnu'
WITH_VALGRIND: 'no'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
valgrind_debian:
name: "Valgrind ${{ matrix.configuration.binary_arch }} (memcheck)"
runs-on: ${{ matrix.configuration.runner }}
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- runner: ubuntu-latest
binary_arch: x64
env_vars: { CC: 'clang', ASM: 'auto' }
- runner: ubuntu-latest
binary_arch: i686
env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
- runner: ubuntu-24.04-arm
binary_arch: arm64
env_vars: { CC: 'clang', ASM: 'auto' }
- runner: ubuntu-latest
binary_arch: x64
env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
- runner: ubuntu-latest
binary_arch: i686
env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
- runner: ubuntu-24.04-arm
binary_arch: arm64
env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
env:
# The `--error-exitcode` is required to make the test fail if valgrind found errors,
# otherwise it will return 0 (https://www.valgrind.org/docs/manual/manual-core.html).
WRAPPER_CMD: 'valgrind --error-exitcode=42'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
SECP256K1_TEST_ITERS: 2
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
sanitizers_debian:
name: "UBSan, ASan, LSan"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- env_vars: { CC: 'clang', ASM: 'auto' }
- env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
- env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
- env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
env:
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
CFLAGS: '-fsanitize=undefined,address -g'
UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1'
ASAN_OPTIONS: 'strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1'
LSAN_OPTIONS: 'use_unaligned=1'
SECP256K1_TEST_ITERS: 32
SYMBOL_CHECK: 'no'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
msan_debian:
name: "MSan"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
fail-fast: false
matrix:
configuration:
- env_vars:
CTIMETESTS: 'yes'
CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g'
- env_vars:
ECMULTGENKB: 2
ECMULTWINDOW: 2
CTIMETESTS: 'yes'
CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3'
- env_vars:
# -fsanitize-memory-param-retval is clang's default, but our build system disables it
# when ctime_tests when enabled.
CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g'
CTIMETESTS: 'no'
cc:
- 'clang'
- 'clang-snapshot'
env:
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CC: ${{ matrix.cc }}
SECP256K1_TEST_ITERS: 32
ASM: 'no'
WITH_VALGRIND: 'no'
SYMBOL_CHECK: 'no'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
mingw_debian:
name: ${{ matrix.configuration.job_name }}
runs-on: ubuntu-latest
needs: docker_cache
env:
WRAPPER_CMD: 'wine'
WITH_VALGRIND: 'no'
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
CTIMETESTS: 'no'
strategy:
fail-fast: false
matrix:
configuration:
- job_name: 'x86_64 (mingw32-w64): Windows (Debian stable, Wine)'
env_vars:
HOST: 'x86_64-w64-mingw32'
- job_name: 'i686 (mingw32-w64): Windows (Debian stable, Wine)'
env_vars:
HOST: 'i686-w64-mingw32'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
x86_64-macos-native:
name: "x86_64: macOS Sequoia, Valgrind"
runs-on: macos-15-intel
env:
CC: 'clang'
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
SYMBOL_CHECK: 'no'
strategy:
fail-fast: false
matrix:
env_vars:
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes' }
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes', CC: 'gcc' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', FROST: 'yes', CHILLDKG: 'yes', ICEBERG: 'yes', PREFRACTAL: 'yes', FROST_ENROLLMENT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
- BUILD: 'distcheck'
steps:
- *CHECKOUT
- name: Install Homebrew packages
run: |
brew install --quiet automake libtool gcc
ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc
- name: Install and cache Valgrind
uses: ./.github/actions/install-homebrew-valgrind
- &CI_SCRIPT_ON_HOST
name: CI script
env: ${{ matrix.env_vars }}
run: ./ci/ci.sh
- &SYMBOL_CHECK_MACOS
name: Symbol check
env:
VIRTUAL_ENV: '${{ github.workspace }}/venv'
run: |
python3 --version
python3 -m venv $VIRTUAL_ENV
export PATH="$VIRTUAL_ENV/bin:$PATH"
python3 -m pip install lief
python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib
- *PRINT_LOGS
arm64-macos-native:
name: "ARM64: macOS Sonoma"
# See: https://github.com/actions/runner-images#available-images.
runs-on: macos-14
env:
CC: 'clang'
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
WITH_VALGRIND: 'no'
CTIMETESTS: 'no'
SYMBOL_CHECK: 'no'
strategy:
fail-fast: false
matrix:
env_vars:
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' }
- BUILD: 'distcheck'
steps:
- *CHECKOUT
- name: Install Homebrew packages
run: |
brew install --quiet automake libtool gcc
ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc
- *CI_SCRIPT_ON_HOST
- *SYMBOL_CHECK_MACOS
- *PRINT_LOGS
win64-native:
name: ${{ matrix.configuration.job_name }}
# See: https://github.com/actions/runner-images#available-images.
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
configuration:
- job_name: 'x64 (MSVC): Windows (VS 2022, shared)'
cmake_options: '-A x64 -DBUILD_SHARED_LIBS=ON'
symbol_check: 'true'
- job_name: 'x64 (MSVC): Windows (VS 2022, static)'
cmake_options: '-A x64 -DBUILD_SHARED_LIBS=OFF'
- job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct)'
cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
- job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh)'
cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE'
- job_name: 'x86 (MSVC): Windows (VS 2022)'
cmake_options: '-A Win32'
- job_name: 'x64 (clang-cl): Windows (VS 2022, shared)'
cmake_options: '-T ClangCL -DBUILD_SHARED_LIBS=ON'
symbol_check: 'true'
- job_name: 'x64 (clang-cl): Windows (VS 2022, static)'
cmake_options: '-T ClangCL -DBUILD_SHARED_LIBS=OFF'
- job_name: 'x64 (clang-cl): Windows (VS 2022, int128_struct)'
cmake_options: '-T ClangCL -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
- job_name: 'x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh)'
cmake_options: '-T ClangCL -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE'
steps:
- *CHECKOUT
- name: Generate buildsystem
run: cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" cmake -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON ${{ matrix.configuration.cmake_options }}
- name: Build
run: cmake --build build --config RelWithDebInfo -- /p:UseMultiToolTask=true /maxCpuCount
- name: Binaries info
# Use the bash shell included with Git for Windows.
shell: bash
run: |
cd build/bin/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true
- name: Symbol check
if: ${{ matrix.configuration.symbol_check }}
shell: bash
run: |
py -3 --version
py -3 -m pip install lief
py -3 ./tools/symbol-check.py build/bin/RelWithDebInfo/libsecp256k1-*.dll
- name: Check
run: |
ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1)
build\bin\RelWithDebInfo\bench_ecmult.exe
build\bin\RelWithDebInfo\bench_internal.exe
build\bin\RelWithDebInfo\bench.exe
win64-native-headers:
name: "x64 (MSVC): C++ (public headers)"
# See: https://github.com/actions/runner-images#available-images.
runs-on: windows-2022
steps:
- *CHECKOUT
- name: C++ (public headers)
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cl.exe -c -WX -TP include/*.h
cxx_fpermissive_debian:
name: "C++ -fpermissive (entire project)"
runs-on: ubuntu-latest
needs: docker_cache
strategy:
matrix:
configuration:
- env_vars: {}
env:
CC: 'g++'
CFLAGS: '-fpermissive -g'
CPPFLAGS: '-DSECP256K1_CPLUSPLUS_TEST_OVERRIDE'
WERROR_CFLAGS:
ECDH: 'yes'
RECOVERY: 'yes'
EXTRAKEYS: 'yes'
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
EXPERIMENTAL: 'yes'
ECDSA_S2C: 'yes'
GENERATOR: 'yes'
RANGEPROOF: 'yes'
SURJECTIONPROOF: 'yes'
WHITELIST: 'yes'
ECDSAADAPTOR: 'yes'
BPPP: 'yes'
SCHNORRSIG_HALFAGG: 'yes'
FROST: 'yes'
CHILLDKG: 'yes'
ICEBERG: 'yes'
PREFRACTAL: 'yes'
FROST_ENROLLMENT: 'yes'
steps:
- *CHECKOUT
- *CI_SCRIPT_IN_DOCKER
- *PRINT_LOGS
cxx_headers_debian:
name: "C++ (public headers)"
runs-on: ubuntu-latest
needs: docker_cache
steps:
- *CHECKOUT
- name: CI script
uses: ./.github/actions/run-in-docker-action
with:
dockerfile: ./ci/linux-debian.Dockerfile
scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }}
command: |
g++ -Werror include/*.h
clang -Werror -x c++-header include/*.h
sage:
name: "SageMath prover"
runs-on: ubuntu-latest
container:
image: sagemath/sagemath:latest
options: --user root
steps:
- *CHECKOUT
- name: CI script
run: |
cd sage
sage prove_group_implementations.sage
release:
runs-on: ubuntu-latest
steps:
- *CHECKOUT
- run: ./autogen.sh && ./configure --enable-dev-mode && make distcheck
- name: Check installation with Autotools
env:
CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install
run: |
./autogen.sh && ./configure --prefix=${{ env.CI_INSTALL }} && make clean && make install && ls -RlAh ${{ env.CI_INSTALL }}
gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=${{ env.CI_INSTALL }}/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"${{ env.CI_INSTALL }}/lib" && ./ecdsa
# The experimental module flags are the only CMake coverage this fork's
# modules get. Every other CMake invocation in this workflow is the
# win64-native job, which builds with MSVC and /WX and has never
# compiled any of them; turning them on there would be a first port,
# not a regression guard. This step is gcc on Linux, so it exercises
# what actually needs guarding: the SECP256K1_EXPERIMENTAL gate, the
# dependent-module block ordering in src/CMakeLists.txt (where a block
# placed after the one it force-enables silently produces a library
# whose secp256k1.c never included the module), and the PUBLIC_HEADER
# appends, which the install step then checks landed.
- name: Check installation with CMake
env:
CI_BUILD: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/build
CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install
run: |
cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} -DSECP256K1_EXPERIMENTAL=ON -DSECP256K1_ENABLE_MODULE_FROST=ON -DSECP256K1_ENABLE_MODULE_CHILLDKG=ON -DSECP256K1_ENABLE_MODULE_ICEBERG=ON -DSECP256K1_ENABLE_MODULE_PREFRACTAL=ON -DSECP256K1_ENABLE_MODULE_FROST_ENROLLMENT=ON && cmake --build ${{ env.CI_BUILD }} && cmake --install ${{ env.CI_BUILD }} && ls -RlAh ${{ env.CI_INSTALL }}
gcc -o ecdsa examples/ecdsa.c -I ${{ env.CI_INSTALL }}/include -L ${{ env.CI_INSTALL }}/lib*/ -l secp256k1 -Wl,-rpath,"${{ env.CI_INSTALL }}/lib",-rpath,"${{ env.CI_INSTALL }}/lib64" && ./ecdsa