Merge commits '29e73f4b 89096c23 c4987790 ad60ef7e 943479a7 cbbbf3bd 73a69595 7c338042 5e74086d 6037833c 020ee604 a660a497 b9313c6e ' into temp-merge-1708
This commit is contained in:
104
.cirrus.yml
104
.cirrus.yml
@@ -1,104 +0,0 @@
|
|||||||
env:
|
|
||||||
### cirrus config
|
|
||||||
CIRRUS_CLONE_DEPTH: 1
|
|
||||||
### 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: 22
|
|
||||||
ASM: no
|
|
||||||
WIDEMUL: auto
|
|
||||||
WITH_VALGRIND: yes
|
|
||||||
EXTRAFLAGS:
|
|
||||||
### secp256k1 modules
|
|
||||||
EXPERIMENTAL: no
|
|
||||||
ECDH: no
|
|
||||||
RECOVERY: no
|
|
||||||
EXTRAKEYS: no
|
|
||||||
SCHNORRSIG: no
|
|
||||||
MUSIG: no
|
|
||||||
ELLSWIFT: no
|
|
||||||
### test options
|
|
||||||
SECP256K1_TEST_ITERS: 64
|
|
||||||
BENCH: yes
|
|
||||||
SECP256K1_BENCH_ITERS: 2
|
|
||||||
CTIMETESTS: yes
|
|
||||||
SYMBOL_CHECK: yes
|
|
||||||
VIRTUAL_ENV: /root/venv
|
|
||||||
# Compile and run the tests
|
|
||||||
EXAMPLES: yes
|
|
||||||
|
|
||||||
cat_logs_snippet: &CAT_LOGS
|
|
||||||
always:
|
|
||||||
cat_tests_log_script:
|
|
||||||
- cat tests.log || true
|
|
||||||
cat_noverify_tests_log_script:
|
|
||||||
- cat noverify_tests.log || true
|
|
||||||
cat_exhaustive_tests_log_script:
|
|
||||||
- cat exhaustive_tests.log || true
|
|
||||||
cat_ctime_tests_log_script:
|
|
||||||
- cat ctime_tests.log || true
|
|
||||||
cat_bench_log_script:
|
|
||||||
- cat bench.log || true
|
|
||||||
cat_config_log_script:
|
|
||||||
- cat config.log || true
|
|
||||||
cat_test_env_script:
|
|
||||||
- cat test_env.log || true
|
|
||||||
cat_ci_env_script:
|
|
||||||
- env
|
|
||||||
|
|
||||||
linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER
|
|
||||||
env_script:
|
|
||||||
- export PATH="$VIRTUAL_ENV/bin:$PATH"
|
|
||||||
- env | tee /tmp/env
|
|
||||||
build_script:
|
|
||||||
- DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm"
|
|
||||||
- docker image prune --force # Cleanup stale layers
|
|
||||||
test_script:
|
|
||||||
- docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh"
|
|
||||||
|
|
||||||
task:
|
|
||||||
name: "ARM64: Linux (Debian stable)"
|
|
||||||
persistent_worker:
|
|
||||||
labels:
|
|
||||||
type: arm64
|
|
||||||
env:
|
|
||||||
ECDH: yes
|
|
||||||
RECOVERY: yes
|
|
||||||
EXTRAKEYS: yes
|
|
||||||
SCHNORRSIG: yes
|
|
||||||
MUSIG: yes
|
|
||||||
ELLSWIFT: yes
|
|
||||||
matrix:
|
|
||||||
# Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU
|
|
||||||
- env: { CC: 'gcc-snapshot' }
|
|
||||||
<< : *LINUX_ARM64_CONTAINER
|
|
||||||
<< : *CAT_LOGS
|
|
||||||
|
|
||||||
task:
|
|
||||||
name: "ARM64: Linux (Debian stable), Valgrind"
|
|
||||||
persistent_worker:
|
|
||||||
labels:
|
|
||||||
type: arm64
|
|
||||||
env:
|
|
||||||
ECDH: yes
|
|
||||||
RECOVERY: yes
|
|
||||||
EXTRAKEYS: yes
|
|
||||||
SCHNORRSIG: yes
|
|
||||||
MUSIG: yes
|
|
||||||
ELLSWIFT: yes
|
|
||||||
WRAPPER_CMD: 'valgrind --error-exitcode=42'
|
|
||||||
SECP256K1_TEST_ITERS: 2
|
|
||||||
matrix:
|
|
||||||
- env: { CC: 'gcc' }
|
|
||||||
- env: { CC: 'clang' }
|
|
||||||
- env: { CC: 'gcc-snapshot' }
|
|
||||||
- env: { CC: 'clang-snapshot' }
|
|
||||||
<< : *LINUX_ARM64_CONTAINER
|
|
||||||
<< : *CAT_LOGS
|
|
||||||
109
.github/workflows/ci.yml
vendored
109
.github/workflows/ci.yml
vendored
@@ -53,8 +53,18 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker_cache:
|
docker_cache:
|
||||||
name: "Build Docker image"
|
name: "Build ${{ matrix.arch }} Docker image"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: x64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
- arch: arm64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
@@ -67,11 +77,11 @@ jobs:
|
|||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
file: ./ci/linux-debian.Dockerfile
|
file: ./ci/linux-debian.Dockerfile
|
||||||
tags: linux-debian-image
|
tags: ${{ matrix.arch }}-debian-image
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=min
|
cache-to: type=gha,mode=min
|
||||||
|
|
||||||
linux_debian:
|
x86_64-debian:
|
||||||
name: "x86_64: Linux (Debian stable)"
|
name: "x86_64: Linux (Debian stable)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: docker_cache
|
needs: docker_cache
|
||||||
@@ -113,7 +123,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -157,7 +167,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -197,7 +207,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -246,21 +256,19 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
arm64_debian:
|
arm64-debian:
|
||||||
name: "ARM64: Linux (Debian stable, QEMU)"
|
name: "arm64: Linux (Debian stable)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04-arm
|
||||||
needs: docker_cache
|
needs: docker_cache
|
||||||
|
|
||||||
env:
|
env:
|
||||||
WRAPPER_CMD: 'qemu-aarch64'
|
|
||||||
SECP256K1_TEST_ITERS: 16
|
SECP256K1_TEST_ITERS: 16
|
||||||
HOST: 'aarch64-linux-gnu'
|
|
||||||
WITH_VALGRIND: 'no'
|
WITH_VALGRIND: 'no'
|
||||||
ECDH: 'yes'
|
ECDH: 'yes'
|
||||||
RECOVERY: 'yes'
|
RECOVERY: 'yes'
|
||||||
@@ -277,27 +285,26 @@ jobs:
|
|||||||
BPPP: 'yes'
|
BPPP: 'yes'
|
||||||
SCHNORRSIG_HALFAGG: 'yes'
|
SCHNORRSIG_HALFAGG: 'yes'
|
||||||
CTIMETESTS: 'no'
|
CTIMETESTS: 'no'
|
||||||
|
CC: ${{ matrix.cc }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
configuration:
|
cc:
|
||||||
- env_vars: { } # gcc
|
- 'gcc'
|
||||||
- env_vars: # clang
|
- 'clang'
|
||||||
CC: 'clang --target=aarch64-linux-gnu'
|
- 'gcc-snapshot'
|
||||||
- env_vars: # clang-snapshot
|
- 'clang-snapshot'
|
||||||
CC: 'clang-snapshot --target=aarch64-linux-gnu'
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: CI script
|
- name: CI script
|
||||||
env: ${{ matrix.configuration.env_vars }}
|
|
||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: arm64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -337,7 +344,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -345,18 +352,38 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
valgrind_debian:
|
valgrind_debian:
|
||||||
name: "Valgrind (memcheck)"
|
name: "Valgrind ${{ matrix.binary_arch }} (memcheck)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
needs: docker_cache
|
needs: docker_cache
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
configuration:
|
include:
|
||||||
- env_vars: { CC: 'clang', ASM: 'auto' }
|
- docker_arch: x64
|
||||||
- env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
|
runner: ubuntu-latest
|
||||||
- env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
|
binary_arch: x64
|
||||||
- env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
|
env_vars: { CC: 'clang', ASM: 'auto' }
|
||||||
|
- docker_arch: x64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
binary_arch: i686
|
||||||
|
env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' }
|
||||||
|
- docker_arch: arm64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
binary_arch: arm64
|
||||||
|
env_vars: { CC: 'clang', ASM: 'auto' }
|
||||||
|
- docker_arch: x64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
binary_arch: x64
|
||||||
|
env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
|
||||||
|
- docker_arch: x64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
binary_arch: i686
|
||||||
|
env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
|
||||||
|
- docker_arch: arm64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
binary_arch: arm64
|
||||||
|
env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 }
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# The `--error-exitcode` is required to make the test fail if valgrind found errors,
|
# The `--error-exitcode` is required to make the test fail if valgrind found errors,
|
||||||
@@ -384,11 +411,11 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: CI script
|
- name: CI script
|
||||||
env: ${{ matrix.configuration.env_vars }}
|
env: ${{ matrix.env_vars }}
|
||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: ${{ matrix.docker_arch }}-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -440,7 +467,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -499,7 +526,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -550,7 +577,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -628,13 +655,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
env_vars:
|
env_vars:
|
||||||
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
|
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
|
||||||
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
|
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
|
||||||
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
|
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
|
||||||
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
|
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
|
||||||
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: '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', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' }
|
||||||
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: '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', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' }
|
||||||
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' }
|
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' }
|
||||||
- BUILD: 'distcheck'
|
- BUILD: 'distcheck'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -769,7 +796,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
uses: ./.github/actions/print-logs
|
uses: ./.github/actions/print-logs
|
||||||
@@ -788,7 +815,7 @@ jobs:
|
|||||||
uses: ./.github/actions/run-in-docker-action
|
uses: ./.github/actions/run-in-docker-action
|
||||||
with:
|
with:
|
||||||
dockerfile: ./ci/linux-debian.Dockerfile
|
dockerfile: ./ci/linux-debian.Dockerfile
|
||||||
tag: linux-debian-image
|
tag: x64-debian-image
|
||||||
command: |
|
command: |
|
||||||
g++ -Werror include/*.h
|
g++ -Werror include/*.h
|
||||||
clang -Werror -x c++-header include/*.h
|
clang -Werror -x c++-header include/*.h
|
||||||
|
|||||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -10,11 +10,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.7.0] - 2025-07-21
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
- CMake: Added `secp256k1_objs` interface library to allow parent projects to embed libsecp256k1 object files into their own static libraries.
|
||||||
|
- build: Added `SECP256K1_NO_API_VISIBILITY_ATTRIBUTES` preprocessor flag (CMake option: `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES`) that disables explicit "visibility" attributes for API symbols. Defining this macro enables the user to control the visibility of the API symbols via `-fvisibility=<value>` when building libsecp256k1. (All non-API declarations will always have hidden visibility, even with `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES` defined.) For instance, `-fvisibility=hidden` can be useful even for the API symbols, e.g., when building a static libsecp256k1 which is linked into a shared library, and the latter should not re-export the libsecp256k1 API.
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
- The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` to the constant context objects are now `const`.
|
||||||
|
- Removed `SECP256K1_WARN_UNUSED_RESULT` attribute (defined as `__attribute__ ((__warn_unused_result__))`) from several API functions that always return 1. Compilers will no longer warn if the return value is unused.
|
||||||
|
- CMake: Building with CMake is no longer considered experimental.
|
||||||
|
- CMake: The minimum required CMake version was increased to 3.22.
|
||||||
|
- CMake: Shared libraries built with CMake on FreeBSD now create the full versioned filename and symlink chain, matching the behavior of autotools builds.
|
||||||
|
|
||||||
#### Removed
|
#### Removed
|
||||||
- Removed previously deprecated function aliases `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add` and
|
- Removed previously deprecated function aliases `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add` and
|
||||||
`secp256k1_ec_privkey_tweak_mul`. Use `secp256k1_ec_seckey_negate`, `secp256k1_ec_seckey_tweak_add` and
|
`secp256k1_ec_privkey_tweak_mul`. Use `secp256k1_ec_seckey_negate`, `secp256k1_ec_seckey_tweak_add` and
|
||||||
`secp256k1_ec_seckey_tweak_mul` instead.
|
`secp256k1_ec_seckey_tweak_mul` instead.
|
||||||
|
|
||||||
|
#### ABI Compatibility
|
||||||
|
The symbols `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add`, and `secp256k1_ec_privkey_tweak_mul` were removed.
|
||||||
|
The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` have been made `const`.
|
||||||
|
Otherwise, the library maintains backward compatibility with version 0.6.0.
|
||||||
|
|
||||||
## [0.6.0] - 2024-11-04
|
## [0.6.0] - 2024-11-04
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
@@ -172,7 +190,8 @@ This version was in fact never released.
|
|||||||
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
|
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
|
||||||
Therefore, this version number does not uniquely identify a set of source files.
|
Therefore, this version number does not uniquely identify a set of source files.
|
||||||
|
|
||||||
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...HEAD
|
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...HEAD
|
||||||
|
[0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0
|
||||||
[0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0
|
[0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0
|
||||||
[0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1
|
[0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1
|
||||||
[0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0
|
[0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ project(libsecp256k1
|
|||||||
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
|
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
|
||||||
# the API. All changes in experimental modules are treated as
|
# the API. All changes in experimental modules are treated as
|
||||||
# backwards-compatible and therefore at most increase the minor version.
|
# backwards-compatible and therefore at most increase the minor version.
|
||||||
VERSION 0.6.1
|
VERSION 0.7.1
|
||||||
DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
|
DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
|
||||||
HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
|
HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
|
||||||
LANGUAGES C
|
LANGUAGES C
|
||||||
)
|
)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
include(CTestUseLaunchers) # Allow users to set CTEST_USE_LAUNCHERS in custom `ctest -S` scripts.
|
||||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
# The library version is based on libtool versioning of the ABI. The set of
|
# The library version is based on libtool versioning of the ABI. The set of
|
||||||
@@ -20,7 +21,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
|||||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
# All changes in experimental modules are treated as if they don't affect the
|
# All changes in experimental modules are treated as if they don't affect the
|
||||||
# interface and therefore only increase the revision.
|
# interface and therefore only increase the revision.
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5)
|
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6)
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
|
set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
|
||||||
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
|
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
|
||||||
|
|
||||||
@@ -41,6 +42,8 @@ endif()
|
|||||||
|
|
||||||
option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
|
option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
|
||||||
|
|
||||||
|
option(SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES "Enable visibility attributes in the API." ON)
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
# We declare all options before processing them, to make sure we can express
|
# We declare all options before processing them, to make sure we can express
|
||||||
@@ -326,6 +329,7 @@ else()
|
|||||||
set(cross_status "FALSE")
|
set(cross_status "FALSE")
|
||||||
endif()
|
endif()
|
||||||
message("Cross compiling ....................... ${cross_status}")
|
message("Cross compiling ....................... ${cross_status}")
|
||||||
|
message("API visibility attributes ............. ${SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES}")
|
||||||
message("Valgrind .............................. ${SECP256K1_VALGRIND}")
|
message("Valgrind .............................. ${SECP256K1_VALGRIND}")
|
||||||
get_directory_property(definitions COMPILE_DEFINITIONS)
|
get_directory_property(definitions COMPILE_DEFINITIONS)
|
||||||
string(REPLACE ";" " " definitions "${definitions}")
|
string(REPLACE ";" " " definitions "${definitions}")
|
||||||
|
|||||||
@@ -121,45 +121,57 @@ typedef int (*secp256k1_nonce_function)(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Symbol visibility. */
|
/* Symbol visibility. */
|
||||||
#if defined(_WIN32)
|
#if !defined(SECP256K1_API) && defined(SECP256K1_NO_API_VISIBILITY_ATTRIBUTES)
|
||||||
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
|
/* The user has requested that we don't specify visibility attributes in
|
||||||
* for MSVC compatibility. A __declspec declaration implies (but is not
|
* the public API.
|
||||||
* exactly equivalent to) __attribute__ ((visibility("default"))), and so we
|
*
|
||||||
* actually want __declspec even on GCC, see "Microsoft Windows Function
|
* Since all our non-API declarations use the static qualifier, this means
|
||||||
* Attributes" in the GCC manual and the recommendations in
|
* that the user can use -fvisibility=<value> to set the visibility of the
|
||||||
* https://gcc.gnu.org/wiki/Visibility. */
|
* API symbols. For instance, -fvisibility=hidden can be useful *even for
|
||||||
# if defined(SECP256K1_BUILD)
|
* the API symbols*, e.g., when building a static library which is linked
|
||||||
# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
|
* into a shared library, and the latter should not re-export the
|
||||||
/* Building libsecp256k1 as a DLL.
|
* libsecp256k1 API.
|
||||||
* 1. If using Libtool, it defines DLL_EXPORT automatically.
|
*
|
||||||
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
|
* While visibility is a concept that applies only to shared libraries,
|
||||||
# define SECP256K1_API extern __declspec (dllexport)
|
* setting visibility will still make a difference when building a static
|
||||||
# else
|
* library: the visibility settings will be stored in the static library,
|
||||||
/* Building libsecp256k1 as a static library on Windows.
|
* solely for the potential case that the static library will be linked into
|
||||||
* No declspec is needed, and so we would want the non-Windows-specific
|
* a shared library. In that case, the stored visibility settings will
|
||||||
* logic below take care of this case. However, this may result in setting
|
* resurface and be honored for the shared library. */
|
||||||
* __attribute__ ((visibility("default"))), which is supposed to be a noop
|
# define SECP256K1_API extern
|
||||||
* on Windows but may trigger warnings when compiling with -flto due to a
|
|
||||||
* bug in GCC, see
|
|
||||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */
|
|
||||||
# define SECP256K1_API extern
|
|
||||||
# endif
|
|
||||||
/* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
|
|
||||||
* library on Windows. */
|
|
||||||
# elif !defined(SECP256K1_STATIC)
|
|
||||||
/* Consuming libsecp256k1 as a DLL. */
|
|
||||||
# define SECP256K1_API extern __declspec (dllimport)
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
#ifndef SECP256K1_API
|
#if !defined(SECP256K1_API)
|
||||||
/* All cases not captured by the Windows-specific logic. */
|
# if defined(SECP256K1_BUILD)
|
||||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
|
/* On Windows, assume a shared library only if explicitly requested.
|
||||||
/* Building libsecp256k1 using GCC or compatible. */
|
* 1. If using Libtool, it defines DLL_EXPORT automatically.
|
||||||
# define SECP256K1_API extern __attribute__ ((visibility ("default")))
|
* 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
|
||||||
# else
|
# if defined(_WIN32) && (defined(SECP256K1_DLL_EXPORT) || defined(DLL_EXPORT))
|
||||||
/* Fall back to standard C's extern. */
|
/* GCC for Windows (e.g., MinGW) accepts the __declspec syntax for
|
||||||
# define SECP256K1_API extern
|
* MSVC compatibility. A __declspec declaration implies (but is not
|
||||||
# endif
|
* exactly equivalent to) __attribute__ ((visibility("default"))),
|
||||||
|
* and so we actually want __declspec even on GCC, see "Microsoft
|
||||||
|
* Windows Function Attributes" in the GCC manual and the
|
||||||
|
* recommendations in https://gcc.gnu.org/wiki/Visibility . */
|
||||||
|
# define SECP256K1_API extern __declspec(dllexport)
|
||||||
|
/* Avoid __attribute__ ((visibility("default"))) on Windows to get rid
|
||||||
|
* of warnings when compiling with -flto due to a bug in GCC, see
|
||||||
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */
|
||||||
|
# elif !defined(_WIN32) && defined (__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define SECP256K1_API extern __attribute__ ((visibility("default")))
|
||||||
|
# else
|
||||||
|
# define SECP256K1_API extern
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
/* On Windows, SECP256K1_STATIC must be defined when consuming
|
||||||
|
* libsecp256k1 as a static library. Note that SECP256K1_STATIC is a
|
||||||
|
* "consumer-only" macro, and it has no meaning when building
|
||||||
|
* libsecp256k1. */
|
||||||
|
# if defined(_WIN32) && !defined(SECP256K1_STATIC)
|
||||||
|
# define SECP256K1_API extern __declspec(dllimport)
|
||||||
|
# else
|
||||||
|
# define SECP256K1_API extern
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Warning attributes
|
/* Warning attributes
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL
|
|||||||
# from being exported.
|
# from being exported.
|
||||||
target_sources(secp256k1 PRIVATE secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
|
target_sources(secp256k1 PRIVATE secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
|
||||||
|
|
||||||
|
if(NOT SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES)
|
||||||
|
target_compile_definitions(secp256k1 PRIVATE SECP256K1_NO_API_VISIBILITY_ATTRIBUTES)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Create a helper lib that parent projects can use to link secp256k1 into a
|
# Create a helper lib that parent projects can use to link secp256k1 into a
|
||||||
# static lib.
|
# static lib.
|
||||||
add_library(secp256k1_objs INTERFACE)
|
add_library(secp256k1_objs INTERFACE)
|
||||||
@@ -138,7 +142,8 @@ target_include_directories(secp256k1 INTERFACE
|
|||||||
$<BUILD_INTERFACE:$<$<NOT:$<BOOL:${PROJECT_IS_TOP_LEVEL}>>:${PROJECT_SOURCE_DIR}/include>>
|
$<BUILD_INTERFACE:$<$<NOT:$<BOOL:${PROJECT_IS_TOP_LEVEL}>>:${PROJECT_SOURCE_DIR}/include>>
|
||||||
)
|
)
|
||||||
set_target_properties(secp256k1_objs PROPERTIES
|
set_target_properties(secp256k1_objs PROPERTIES
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:secp256k1,INTERFACE_INCLUDE_DIRECTORIES>"
|
INTERFACE_COMPILE_DEFINITIONS "$<TARGET_PROPERTY:secp256k1,INTERFACE_COMPILE_DEFINITIONS>"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:secp256k1,INTERFACE_INCLUDE_DIRECTORIES>"
|
||||||
)
|
)
|
||||||
|
|
||||||
# This emulates Libtool to make sure Libtool and CMake agree on the ABI version,
|
# This emulates Libtool to make sure Libtool and CMake agree on the ABI version,
|
||||||
@@ -147,7 +152,7 @@ math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${
|
|||||||
set_target_properties(secp256k1 PROPERTIES
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
SOVERSION ${${PROJECT_NAME}_soversion}
|
SOVERSION ${${PROJECT_NAME}_soversion}
|
||||||
)
|
)
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$")
|
||||||
set_target_properties(secp256k1 PROPERTIES
|
set_target_properties(secp256k1 PROPERTIES
|
||||||
VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
|
VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1058,12 +1058,15 @@ static void musig_test_vectors_signverify(void) {
|
|||||||
* the signing key does not belong to any pubkey. */
|
* the signing key does not belong to any pubkey. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = c->error != MUSIG_PUBKEY;
|
expected = c->error != MUSIG_PUBKEY;
|
||||||
CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL));
|
CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL));
|
||||||
CHECK(expected || c->error == error);
|
CHECK(expected || c->error == error);
|
||||||
if (!expected) {
|
if (!expected) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0])));
|
||||||
|
CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk));
|
||||||
|
|
||||||
expected = c->error != MUSIG_AGGNONCE;
|
expected = c->error != MUSIG_AGGNONCE;
|
||||||
CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index]));
|
CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index]));
|
||||||
@@ -1072,15 +1075,10 @@ static void musig_test_vectors_signverify(void) {
|
|||||||
}
|
}
|
||||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL));
|
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL));
|
||||||
|
|
||||||
CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk));
|
|
||||||
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0])));
|
|
||||||
musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey);
|
|
||||||
expected = c->error != MUSIG_SECNONCE;
|
expected = c->error != MUSIG_SECNONCE;
|
||||||
if (expected) {
|
CHECK(!expected);
|
||||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session));
|
musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey);
|
||||||
} else {
|
CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session));
|
||||||
CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) {
|
for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) {
|
||||||
const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i];
|
const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user