ci.yml raw

   1  name: CI
   2  on:
   3    pull_request:
   4    push:
   5      branches:
   6        - '**'
   7      tags-ignore:
   8        - '**'
   9  
  10  concurrency:
  11    group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }}
  12    cancel-in-progress: true
  13  
  14  env:
  15    ### compiler options
  16    HOST:
  17    WRAPPER_CMD:
  18    # Specific warnings can be disabled with -Wno-error=foo.
  19    # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual.
  20    WERROR_CFLAGS: '-Werror -pedantic-errors'
  21    MAKEFLAGS: '-j4'
  22    BUILD: 'check'
  23    ### secp256k1 config
  24    ECMULTWINDOW: 15
  25    ECMULTGENKB: 86
  26    ASM: 'no'
  27    WIDEMUL: 'auto'
  28    WITH_VALGRIND: 'yes'
  29    EXTRAFLAGS:
  30    ### secp256k1 modules
  31    EXPERIMENTAL: 'no'
  32    ECDH: 'no'
  33    RECOVERY: 'no'
  34    EXTRAKEYS: 'no'
  35    SCHNORRSIG: 'no'
  36    MUSIG: 'no'
  37    ELLSWIFT: 'no'
  38    ### test options
  39    SECP256K1_TEST_ITERS: 64
  40    BENCH: 'yes'
  41    SECP256K1_BENCH_ITERS: 2
  42    CTIMETESTS: 'yes'
  43    # Compile and run the examples.
  44    EXAMPLES: 'yes'
  45  
  46  jobs:
  47    docker_cache:
  48      name: "Build Docker image"
  49      runs-on: ubuntu-latest
  50      steps:
  51        - name: Set up Docker Buildx
  52          uses: docker/setup-buildx-action@v3
  53          with:
  54            # See: https://github.com/moby/buildkit/issues/3969.
  55            driver-opts: |
  56              network=host
  57  
  58        - name: Build container
  59          uses: docker/build-push-action@v5
  60          with:
  61            file: ./ci/linux-debian.Dockerfile
  62            tags: linux-debian-image
  63            cache-from: type=gha
  64            cache-to: type=gha,mode=min
  65  
  66    linux_debian:
  67      name: "x86_64: Linux (Debian stable)"
  68      runs-on: ubuntu-latest
  69      needs: docker_cache
  70  
  71      strategy:
  72        fail-fast: false
  73        matrix:
  74          configuration:
  75            - env_vars: { WIDEMUL: 'int64',  RECOVERY: 'yes' }
  76            - env_vars: { WIDEMUL: 'int64',                   ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
  77            - env_vars: { WIDEMUL: 'int128' }
  78            - env_vars: { WIDEMUL: 'int128_struct',                                                             ELLSWIFT: 'yes' }
  79            - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes',              EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
  80            - env_vars: { WIDEMUL: 'int128',                  ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
  81            - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64',                                                     ELLSWIFT: 'yes' }
  82            - env_vars: {                    RECOVERY: 'yes',              EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
  83            - env_vars: { CTIMETESTS: 'no',  RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', CPPFLAGS: '-DVERIFY' }
  84            - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' }
  85            - env_vars: { CPPFLAGS: '-DDETERMINISTIC' }
  86            - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' }
  87            - env_vars: { CFLAGS: '-O1',     RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
  88            - env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 }
  89            - env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 }
  90          cc:
  91            - 'gcc'
  92            - 'clang'
  93            - 'gcc-snapshot'
  94            - 'clang-snapshot'
  95  
  96      env:
  97        CC: ${{ matrix.cc }}
  98  
  99      steps:
 100        - name: Checkout
 101          uses: actions/checkout@v4
 102  
 103        - name: CI script
 104          env: ${{ matrix.configuration.env_vars }}
 105          uses: ./.github/actions/run-in-docker-action
 106          with:
 107            dockerfile: ./ci/linux-debian.Dockerfile
 108            tag: linux-debian-image
 109  
 110        - run: cat tests.log || true
 111          if: ${{ always() }}
 112        - run: cat noverify_tests.log || true
 113          if: ${{ always() }}
 114        - run: cat exhaustive_tests.log || true
 115          if: ${{ always() }}
 116        - run: cat ctime_tests.log || true
 117          if: ${{ always() }}
 118        - run: cat bench.log || true
 119          if: ${{ always() }}
 120        - run: cat config.log || true
 121          if: ${{ always() }}
 122        - run: cat test_env.log || true
 123          if: ${{ always() }}
 124        - name: CI env
 125          run: env
 126          if: ${{ always() }}
 127  
 128    i686_debian:
 129      name: "i686: Linux (Debian stable)"
 130      runs-on: ubuntu-latest
 131      needs: docker_cache
 132  
 133      strategy:
 134        fail-fast: false
 135        matrix:
 136          cc:
 137            - 'i686-linux-gnu-gcc'
 138            - 'clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include'
 139  
 140      env:
 141        HOST: 'i686-linux-gnu'
 142        ECDH: 'yes'
 143        RECOVERY: 'yes'
 144        EXTRAKEYS: 'yes'
 145        SCHNORRSIG: 'yes'
 146        MUSIG: 'yes'
 147        ELLSWIFT: 'yes'
 148        CC: ${{ matrix.cc }}
 149  
 150      steps:
 151        - name: Checkout
 152          uses: actions/checkout@v4
 153  
 154        - name: CI script
 155          uses: ./.github/actions/run-in-docker-action
 156          with:
 157            dockerfile: ./ci/linux-debian.Dockerfile
 158            tag: linux-debian-image
 159  
 160        - run: cat tests.log || true
 161          if: ${{ always() }}
 162        - run: cat noverify_tests.log || true
 163          if: ${{ always() }}
 164        - run: cat exhaustive_tests.log || true
 165          if: ${{ always() }}
 166        - run: cat ctime_tests.log || true
 167          if: ${{ always() }}
 168        - run: cat bench.log || true
 169          if: ${{ always() }}
 170        - run: cat config.log || true
 171          if: ${{ always() }}
 172        - run: cat test_env.log || true
 173          if: ${{ always() }}
 174        - name: CI env
 175          run: env
 176          if: ${{ always() }}
 177  
 178    s390x_debian:
 179      name: "s390x (big-endian): Linux (Debian stable, QEMU)"
 180      runs-on: ubuntu-latest
 181      needs: docker_cache
 182  
 183      env:
 184        WRAPPER_CMD: 'qemu-s390x'
 185        SECP256K1_TEST_ITERS: 16
 186        HOST: 's390x-linux-gnu'
 187        WITH_VALGRIND: 'no'
 188        ECDH: 'yes'
 189        RECOVERY: 'yes'
 190        EXTRAKEYS: 'yes'
 191        SCHNORRSIG: 'yes'
 192        MUSIG: 'yes'
 193        ELLSWIFT: 'yes'
 194        CTIMETESTS: 'no'
 195  
 196      steps:
 197        - name: Checkout
 198          uses: actions/checkout@v4
 199  
 200        - name: CI script
 201          uses: ./.github/actions/run-in-docker-action
 202          with:
 203            dockerfile: ./ci/linux-debian.Dockerfile
 204            tag: linux-debian-image
 205  
 206        - run: cat tests.log || true
 207          if: ${{ always() }}
 208        - run: cat noverify_tests.log || true
 209          if: ${{ always() }}
 210        - run: cat exhaustive_tests.log || true
 211          if: ${{ always() }}
 212        - run: cat ctime_tests.log || true
 213          if: ${{ always() }}
 214        - run: cat bench.log || true
 215          if: ${{ always() }}
 216        - run: cat config.log || true
 217          if: ${{ always() }}
 218        - run: cat test_env.log || true
 219          if: ${{ always() }}
 220        - name: CI env
 221          run: env
 222          if: ${{ always() }}
 223  
 224    arm32_debian:
 225      name: "ARM32: Linux (Debian stable, QEMU)"
 226      runs-on: ubuntu-latest
 227      needs: docker_cache
 228  
 229      strategy:
 230        fail-fast: false
 231        matrix:
 232          configuration:
 233            - env_vars: {}
 234            - env_vars: { EXPERIMENTAL: 'yes', ASM: 'arm32' }
 235  
 236      env:
 237        WRAPPER_CMD: 'qemu-arm'
 238        SECP256K1_TEST_ITERS: 16
 239        HOST: 'arm-linux-gnueabihf'
 240        WITH_VALGRIND: 'no'
 241        ECDH: 'yes'
 242        RECOVERY: 'yes'
 243        EXTRAKEYS: 'yes'
 244        SCHNORRSIG: 'yes'
 245        MUSIG: 'yes'
 246        ELLSWIFT: 'yes'
 247        CTIMETESTS: 'no'
 248  
 249      steps:
 250        - name: Checkout
 251          uses: actions/checkout@v4
 252  
 253        - name: CI script
 254          env: ${{ matrix.configuration.env_vars }}
 255          uses: ./.github/actions/run-in-docker-action
 256          with:
 257            dockerfile: ./ci/linux-debian.Dockerfile
 258            tag: linux-debian-image
 259  
 260        - run: cat tests.log || true
 261          if: ${{ always() }}
 262        - run: cat noverify_tests.log || true
 263          if: ${{ always() }}
 264        - run: cat exhaustive_tests.log || true
 265          if: ${{ always() }}
 266        - run: cat ctime_tests.log || true
 267          if: ${{ always() }}
 268        - run: cat bench.log || true
 269          if: ${{ always() }}
 270        - run: cat config.log || true
 271          if: ${{ always() }}
 272        - run: cat test_env.log || true
 273          if: ${{ always() }}
 274        - name: CI env
 275          run: env
 276          if: ${{ always() }}
 277  
 278    arm64_debian:
 279      name: "ARM64: Linux (Debian stable, QEMU)"
 280      runs-on: ubuntu-latest
 281      needs: docker_cache
 282  
 283      env:
 284        WRAPPER_CMD: 'qemu-aarch64'
 285        SECP256K1_TEST_ITERS: 16
 286        HOST: 'aarch64-linux-gnu'
 287        WITH_VALGRIND: 'no'
 288        ECDH: 'yes'
 289        RECOVERY: 'yes'
 290        EXTRAKEYS: 'yes'
 291        SCHNORRSIG: 'yes'
 292        MUSIG: 'yes'
 293        ELLSWIFT: 'yes'
 294        CTIMETESTS: 'no'
 295  
 296      strategy:
 297        fail-fast: false
 298        matrix:
 299          configuration:
 300            - env_vars: { } # gcc
 301            - env_vars: # clang
 302                CC: 'clang --target=aarch64-linux-gnu'
 303            - env_vars: # clang-snapshot
 304                CC: 'clang-snapshot --target=aarch64-linux-gnu'
 305  
 306      steps:
 307        - name: Checkout
 308          uses: actions/checkout@v4
 309  
 310        - name: CI script
 311          env: ${{ matrix.configuration.env_vars }}
 312          uses: ./.github/actions/run-in-docker-action
 313          with:
 314            dockerfile: ./ci/linux-debian.Dockerfile
 315            tag: linux-debian-image
 316  
 317        - run: cat tests.log || true
 318          if: ${{ always() }}
 319        - run: cat noverify_tests.log || true
 320          if: ${{ always() }}
 321        - run: cat exhaustive_tests.log || true
 322          if: ${{ always() }}
 323        - run: cat ctime_tests.log || true
 324          if: ${{ always() }}
 325        - run: cat bench.log || true
 326          if: ${{ always() }}
 327        - run: cat config.log || true
 328          if: ${{ always() }}
 329        - run: cat test_env.log || true
 330          if: ${{ always() }}
 331        - name: CI env
 332          run: env
 333          if: ${{ always() }}
 334  
 335    ppc64le_debian:
 336      name: "ppc64le: Linux (Debian stable, QEMU)"
 337      runs-on: ubuntu-latest
 338      needs: docker_cache
 339  
 340      env:
 341        WRAPPER_CMD: 'qemu-ppc64le'
 342        SECP256K1_TEST_ITERS: 16
 343        HOST: 'powerpc64le-linux-gnu'
 344        WITH_VALGRIND: 'no'
 345        ECDH: 'yes'
 346        RECOVERY: 'yes'
 347        EXTRAKEYS: 'yes'
 348        SCHNORRSIG: 'yes'
 349        MUSIG: 'yes'
 350        ELLSWIFT: 'yes'
 351        CTIMETESTS: 'no'
 352  
 353      steps:
 354        - name: Checkout
 355          uses: actions/checkout@v4
 356  
 357        - name: CI script
 358          uses: ./.github/actions/run-in-docker-action
 359          with:
 360            dockerfile: ./ci/linux-debian.Dockerfile
 361            tag: linux-debian-image
 362  
 363        - run: cat tests.log || true
 364          if: ${{ always() }}
 365        - run: cat noverify_tests.log || true
 366          if: ${{ always() }}
 367        - run: cat exhaustive_tests.log || true
 368          if: ${{ always() }}
 369        - run: cat ctime_tests.log || true
 370          if: ${{ always() }}
 371        - run: cat bench.log || true
 372          if: ${{ always() }}
 373        - run: cat config.log || true
 374          if: ${{ always() }}
 375        - run: cat test_env.log || true
 376          if: ${{ always() }}
 377        - name: CI env
 378          run: env
 379          if: ${{ always() }}
 380  
 381    valgrind_debian:
 382      name: "Valgrind (memcheck)"
 383      runs-on: ubuntu-latest
 384      needs: docker_cache
 385  
 386      strategy:
 387        fail-fast: false
 388        matrix:
 389          configuration:
 390            - env_vars: { CC: 'clang',                                      ASM: 'auto' }
 391            - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
 392            - env_vars: { CC: 'clang',                                      ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
 393            - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
 394  
 395      env:
 396        # The `--error-exitcode` is required to make the test fail if valgrind found errors,
 397        # otherwise it will return 0 (https://www.valgrind.org/docs/manual/manual-core.html).
 398        WRAPPER_CMD: 'valgrind --error-exitcode=42'
 399        ECDH: 'yes'
 400        RECOVERY: 'yes'
 401        EXTRAKEYS: 'yes'
 402        SCHNORRSIG: 'yes'
 403        MUSIG: 'yes'
 404        ELLSWIFT: 'yes'
 405        CTIMETESTS: 'no'
 406        SECP256K1_TEST_ITERS: 2
 407  
 408      steps:
 409        - name: Checkout
 410          uses: actions/checkout@v4
 411  
 412        - name: CI script
 413          env: ${{ matrix.configuration.env_vars }}
 414          uses: ./.github/actions/run-in-docker-action
 415          with:
 416            dockerfile: ./ci/linux-debian.Dockerfile
 417            tag: linux-debian-image
 418  
 419        - run: cat tests.log || true
 420          if: ${{ always() }}
 421        - run: cat noverify_tests.log || true
 422          if: ${{ always() }}
 423        - run: cat exhaustive_tests.log || true
 424          if: ${{ always() }}
 425        - run: cat ctime_tests.log || true
 426          if: ${{ always() }}
 427        - run: cat bench.log || true
 428          if: ${{ always() }}
 429        - run: cat config.log || true
 430          if: ${{ always() }}
 431        - run: cat test_env.log || true
 432          if: ${{ always() }}
 433        - name: CI env
 434          run: env
 435          if: ${{ always() }}
 436  
 437    sanitizers_debian:
 438      name: "UBSan, ASan, LSan"
 439      runs-on: ubuntu-latest
 440      needs: docker_cache
 441  
 442      strategy:
 443        fail-fast: false
 444        matrix:
 445          configuration:
 446            - env_vars: { CC: 'clang',                                      ASM: 'auto' }
 447            - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
 448            - env_vars: { CC: 'clang',                                      ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
 449            - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
 450  
 451      env:
 452        ECDH: 'yes'
 453        RECOVERY: 'yes'
 454        EXTRAKEYS: 'yes'
 455        SCHNORRSIG: 'yes'
 456        MUSIG: 'yes'
 457        ELLSWIFT: 'yes'
 458        CTIMETESTS: 'no'
 459        CFLAGS: '-fsanitize=undefined,address -g'
 460        UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1'
 461        ASAN_OPTIONS: 'strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1'
 462        LSAN_OPTIONS: 'use_unaligned=1'
 463        SECP256K1_TEST_ITERS: 32
 464  
 465      steps:
 466        - name: Checkout
 467          uses: actions/checkout@v4
 468  
 469        - name: CI script
 470          env: ${{ matrix.configuration.env_vars }}
 471          uses: ./.github/actions/run-in-docker-action
 472          with:
 473            dockerfile: ./ci/linux-debian.Dockerfile
 474            tag: linux-debian-image
 475  
 476        - run: cat tests.log || true
 477          if: ${{ always() }}
 478        - run: cat noverify_tests.log || true
 479          if: ${{ always() }}
 480        - run: cat exhaustive_tests.log || true
 481          if: ${{ always() }}
 482        - run: cat ctime_tests.log || true
 483          if: ${{ always() }}
 484        - run: cat bench.log || true
 485          if: ${{ always() }}
 486        - run: cat config.log || true
 487          if: ${{ always() }}
 488        - run: cat test_env.log || true
 489          if: ${{ always() }}
 490        - name: CI env
 491          run: env
 492          if: ${{ always() }}
 493  
 494    msan_debian:
 495      name: "MSan"
 496      runs-on: ubuntu-latest
 497      needs: docker_cache
 498  
 499      strategy:
 500        fail-fast: false
 501        matrix:
 502          configuration:
 503            - env_vars:
 504                CTIMETESTS: 'yes'
 505                CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g'
 506            - env_vars:
 507                ECMULTGENKB: 2
 508                ECMULTWINDOW: 2
 509                CTIMETESTS: 'yes'
 510                CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3'
 511            - env_vars:
 512                # -fsanitize-memory-param-retval is clang's default, but our build system disables it
 513                # when ctime_tests when enabled.
 514                CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g'
 515                CTIMETESTS: 'no'
 516  
 517      env:
 518        ECDH: 'yes'
 519        RECOVERY: 'yes'
 520        EXTRAKEYS: 'yes'
 521        SCHNORRSIG: 'yes'
 522        MUSIG: 'yes'
 523        ELLSWIFT: 'yes'
 524        CC: 'clang'
 525        SECP256K1_TEST_ITERS: 32
 526        ASM: 'no'
 527        WITH_VALGRIND: 'no'
 528  
 529      steps:
 530        - name: Checkout
 531          uses: actions/checkout@v4
 532  
 533        - name: CI script
 534          env: ${{ matrix.configuration.env_vars }}
 535          uses: ./.github/actions/run-in-docker-action
 536          with:
 537            dockerfile: ./ci/linux-debian.Dockerfile
 538            tag: linux-debian-image
 539  
 540        - run: cat tests.log || true
 541          if: ${{ always() }}
 542        - run: cat noverify_tests.log || true
 543          if: ${{ always() }}
 544        - run: cat exhaustive_tests.log || true
 545          if: ${{ always() }}
 546        - run: cat ctime_tests.log || true
 547          if: ${{ always() }}
 548        - run: cat bench.log || true
 549          if: ${{ always() }}
 550        - run: cat config.log || true
 551          if: ${{ always() }}
 552        - run: cat test_env.log || true
 553          if: ${{ always() }}
 554        - name: CI env
 555          run: env
 556          if: ${{ always() }}
 557  
 558    mingw_debian:
 559      name: ${{ matrix.configuration.job_name }}
 560      runs-on: ubuntu-latest
 561      needs: docker_cache
 562  
 563      env:
 564        WRAPPER_CMD: 'wine'
 565        WITH_VALGRIND: 'no'
 566        ECDH: 'yes'
 567        RECOVERY: 'yes'
 568        EXTRAKEYS: 'yes'
 569        SCHNORRSIG: 'yes'
 570        MUSIG: 'yes'
 571        ELLSWIFT: 'yes'
 572        CTIMETESTS: 'no'
 573  
 574      strategy:
 575        fail-fast: false
 576        matrix:
 577          configuration:
 578            - job_name: 'x86_64 (mingw32-w64): Windows (Debian stable, Wine)'
 579              env_vars:
 580                HOST: 'x86_64-w64-mingw32'
 581            - job_name: 'i686 (mingw32-w64): Windows (Debian stable, Wine)'
 582              env_vars:
 583                HOST: 'i686-w64-mingw32'
 584  
 585      steps:
 586        - name: Checkout
 587          uses: actions/checkout@v4
 588  
 589        - name: CI script
 590          env: ${{ matrix.configuration.env_vars }}
 591          uses: ./.github/actions/run-in-docker-action
 592          with:
 593            dockerfile: ./ci/linux-debian.Dockerfile
 594            tag: linux-debian-image
 595  
 596        - run: cat tests.log || true
 597          if: ${{ always() }}
 598        - run: cat noverify_tests.log || true
 599          if: ${{ always() }}
 600        - run: cat exhaustive_tests.log || true
 601          if: ${{ always() }}
 602        - run: cat ctime_tests.log || true
 603          if: ${{ always() }}
 604        - run: cat bench.log || true
 605          if: ${{ always() }}
 606        - run: cat config.log || true
 607          if: ${{ always() }}
 608        - run: cat test_env.log || true
 609          if: ${{ always() }}
 610        - name: CI env
 611          run: env
 612          if: ${{ always() }}
 613  
 614    x86_64-macos-native:
 615      name: "x86_64: macOS Ventura, Valgrind"
 616      # See: https://github.com/actions/runner-images#available-images.
 617      runs-on: macos-13
 618  
 619      env:
 620        CC: 'clang'
 621        HOMEBREW_NO_AUTO_UPDATE: 1
 622        HOMEBREW_NO_INSTALL_CLEANUP: 1
 623  
 624      strategy:
 625        fail-fast: false
 626        matrix:
 627          env_vars:
 628            - { WIDEMUL: 'int64',  RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
 629            - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
 630            - { WIDEMUL: 'int128',                  ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
 631            - { WIDEMUL: 'int128', RECOVERY: 'yes' }
 632            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
 633            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' }
 634            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes',            WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
 635            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
 636            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
 637            - BUILD: 'distcheck'
 638  
 639      steps:
 640        - name: Checkout
 641          uses: actions/checkout@v4
 642  
 643        - name: Install Homebrew packages
 644          run: |
 645            brew install --quiet automake libtool gcc
 646            ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc
 647  
 648        - name: Install and cache Valgrind
 649          uses: ./.github/actions/install-homebrew-valgrind
 650  
 651        - name: CI script
 652          env: ${{ matrix.env_vars }}
 653          run: ./ci/ci.sh
 654  
 655        - run: cat tests.log || true
 656          if: ${{ always() }}
 657        - run: cat noverify_tests.log || true
 658          if: ${{ always() }}
 659        - run: cat exhaustive_tests.log || true
 660          if: ${{ always() }}
 661        - run: cat ctime_tests.log || true
 662          if: ${{ always() }}
 663        - run: cat bench.log || true
 664          if: ${{ always() }}
 665        - run: cat config.log || true
 666          if: ${{ always() }}
 667        - run: cat test_env.log || true
 668          if: ${{ always() }}
 669        - name: CI env
 670          run: env
 671          if: ${{ always() }}
 672  
 673    arm64-macos-native:
 674      name: "ARM64: macOS Sonoma"
 675      # See: https://github.com/actions/runner-images#available-images.
 676      runs-on: macos-14
 677  
 678      env:
 679        CC: 'clang'
 680        HOMEBREW_NO_AUTO_UPDATE: 1
 681        HOMEBREW_NO_INSTALL_CLEANUP: 1
 682        WITH_VALGRIND: 'no'
 683        CTIMETESTS: 'no'
 684  
 685      strategy:
 686        fail-fast: false
 687        matrix:
 688          env_vars:
 689            - { WIDEMUL: 'int64',  RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' }
 690            - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 }
 691            - { WIDEMUL: 'int128',                  ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' }
 692            - { WIDEMUL: 'int128', RECOVERY: 'yes' }
 693            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' }
 694            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' }
 695            - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' }
 696            - BUILD: 'distcheck'
 697  
 698      steps:
 699        - name: Checkout
 700          uses: actions/checkout@v4
 701  
 702        - name: Install Homebrew packages
 703          run: |
 704            brew install --quiet automake libtool gcc
 705            ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc
 706  
 707        - name: CI script
 708          env: ${{ matrix.env_vars }}
 709          run: ./ci/ci.sh
 710  
 711        - run: cat tests.log || true
 712          if: ${{ always() }}
 713        - run: cat noverify_tests.log || true
 714          if: ${{ always() }}
 715        - run: cat exhaustive_tests.log || true
 716          if: ${{ always() }}
 717        - run: cat ctime_tests.log || true
 718          if: ${{ always() }}
 719        - run: cat bench.log || true
 720          if: ${{ always() }}
 721        - run: cat config.log || true
 722          if: ${{ always() }}
 723        - run: cat test_env.log || true
 724          if: ${{ always() }}
 725        - name: CI env
 726          run: env
 727          if: ${{ always() }}
 728  
 729    win64-native:
 730      name: ${{ matrix.configuration.job_name }}
 731      # See: https://github.com/actions/runner-images#available-images.
 732      runs-on: windows-2022
 733  
 734      strategy:
 735        fail-fast: false
 736        matrix:
 737          configuration:
 738            - job_name: 'x64 (MSVC): Windows (VS 2022, shared)'
 739              cmake_options: '-A x64 -DBUILD_SHARED_LIBS=ON'
 740            - job_name: 'x64 (MSVC): Windows (VS 2022, static)'
 741              cmake_options: '-A x64 -DBUILD_SHARED_LIBS=OFF'
 742            - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct)'
 743              cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
 744            - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct with __(u)mulh)'
 745              cmake_options: '-A x64 -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct'
 746              cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE'
 747            - job_name: 'x86 (MSVC): Windows (VS 2022)'
 748              cmake_options: '-A Win32'
 749  
 750      steps:
 751        - name: Checkout
 752          uses: actions/checkout@v4
 753  
 754        - name: Generate buildsystem
 755          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 }}
 756  
 757        - name: Build
 758          run: cmake --build build --config RelWithDebInfo -- /p:UseMultiToolTask=true /maxCpuCount
 759  
 760        - name: Binaries info
 761          # Use the bash shell included with Git for Windows.
 762          shell: bash
 763          run: |
 764            cd build/bin/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true
 765  
 766        - name: Check
 767          run: |
 768            ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1)
 769            build\bin\RelWithDebInfo\bench_ecmult.exe
 770            build\bin\RelWithDebInfo\bench_internal.exe
 771            build\bin\RelWithDebInfo\bench.exe
 772  
 773    win64-native-headers:
 774      name: "x64 (MSVC): C++ (public headers)"
 775      # See: https://github.com/actions/runner-images#available-images.
 776      runs-on: windows-2022
 777  
 778      steps:
 779        - name: Checkout
 780          uses: actions/checkout@v4
 781  
 782        - name: Add cl.exe to PATH
 783          uses: ilammy/msvc-dev-cmd@v1
 784  
 785        - name: C++ (public headers)
 786          run: |
 787            cl.exe -c -WX -TP include/*.h
 788  
 789    cxx_fpermissive_debian:
 790      name: "C++ -fpermissive (entire project)"
 791      runs-on: ubuntu-latest
 792      needs: docker_cache
 793  
 794      env:
 795        CC: 'g++'
 796        CFLAGS: '-fpermissive -g'
 797        CPPFLAGS: '-DSECP256K1_CPLUSPLUS_TEST_OVERRIDE'
 798        WERROR_CFLAGS:
 799        ECDH: 'yes'
 800        RECOVERY: 'yes'
 801        EXTRAKEYS: 'yes'
 802        SCHNORRSIG: 'yes'
 803        MUSIG: 'yes'
 804        ELLSWIFT: 'yes'
 805  
 806      steps:
 807        - name: Checkout
 808          uses: actions/checkout@v4
 809  
 810        - name: CI script
 811          uses: ./.github/actions/run-in-docker-action
 812          with:
 813            dockerfile: ./ci/linux-debian.Dockerfile
 814            tag: linux-debian-image
 815  
 816        - run: cat tests.log || true
 817          if: ${{ always() }}
 818        - run: cat noverify_tests.log || true
 819          if: ${{ always() }}
 820        - run: cat exhaustive_tests.log || true
 821          if: ${{ always() }}
 822        - run: cat ctime_tests.log || true
 823          if: ${{ always() }}
 824        - run: cat bench.log || true
 825          if: ${{ always() }}
 826        - run: cat config.log || true
 827          if: ${{ always() }}
 828        - run: cat test_env.log || true
 829          if: ${{ always() }}
 830        - name: CI env
 831          run: env
 832          if: ${{ always() }}
 833  
 834    cxx_headers_debian:
 835      name: "C++ (public headers)"
 836      runs-on: ubuntu-latest
 837      needs: docker_cache
 838  
 839      steps:
 840        - name: Checkout
 841          uses: actions/checkout@v4
 842  
 843        - name: CI script
 844          uses: ./.github/actions/run-in-docker-action
 845          with:
 846            dockerfile: ./ci/linux-debian.Dockerfile
 847            tag: linux-debian-image
 848            command: |
 849              g++ -Werror include/*.h
 850              clang -Werror -x c++-header include/*.h
 851  
 852    sage:
 853      name: "SageMath prover"
 854      runs-on: ubuntu-latest
 855      container:
 856        image: sagemath/sagemath:latest
 857        options: --user root
 858  
 859      steps:
 860        - name: Checkout
 861          uses: actions/checkout@v4
 862  
 863        - name: CI script
 864          run: |
 865            cd sage
 866            sage prove_group_implementations.sage
 867  
 868    release:
 869      runs-on: ubuntu-latest
 870  
 871      steps:
 872        - name: Checkout
 873          uses: actions/checkout@v4
 874  
 875        - run: ./autogen.sh && ./configure --enable-dev-mode && make distcheck
 876  
 877        - name: Check installation with Autotools
 878          env:
 879            CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install
 880          run: |
 881            ./autogen.sh && ./configure --prefix=${{ env.CI_INSTALL }} && make clean && make install && ls -RlAh ${{ env.CI_INSTALL }}
 882            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
 883  
 884        - name: Check installation with CMake
 885          env:
 886            CI_BUILD: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/build
 887            CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install
 888          run: |
 889            cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} && cmake --build ${{ env.CI_BUILD }} && cmake --install ${{ env.CI_BUILD }} && ls -RlAh ${{ env.CI_INSTALL }}
 890            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
 891