Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 0 additions & 55 deletions .github/ci-lint-exec.py

This file was deleted.

4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -681,4 +681,6 @@ jobs:
cache-provider: ${{ needs.runners.outputs.provider }}

- name: CI script
run: python .github/ci-lint-exec.py
run: |
git worktree add ../lint-worktree HEAD
../lint-worktree/ci/lint.py
81 changes: 81 additions & 0 deletions ci/lint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
# Copyright (c) The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.

import os
import shlex
import subprocess
import sys
import time
from pathlib import Path


def run(cmd, **kwargs):
print("+ " + shlex.join(cmd), flush=True)
kwargs.setdefault("check", True)
try:
return subprocess.run(cmd, **kwargs)
except Exception as e:
sys.exit(str(e))


def get_worktree_mounts(repo_root):
git_path = repo_root / ".git"
if not git_path.is_file():
return []
content = git_path.read_text().strip()
if not content.startswith("gitdir: "):
return []
gitdir = (repo_root / content.removeprefix("gitdir: ")).resolve()
main_gitdir = gitdir.parent.parent
return [
f"--volume={gitdir}:{gitdir}",
f"--volume={main_gitdir}:{main_gitdir}:ro",
]


def main():
repo_root = Path(__file__).resolve().parent.parent
is_ci = os.environ.get("GITHUB_ACTIONS") == "true"
container = "bitcoin-linter"

build_cmd = [
"docker",
"buildx",
"build",
f"--tag={container}",
*shlex.split(os.environ.get("DOCKER_BUILD_CACHE_ARG", "")),
f"--file={repo_root}/ci/lint_imagefile",
str(repo_root),
]
if run(build_cmd, check=False).returncode != 0:
if is_ci:
print("Retry building image after failure")
time.sleep(3)
run(build_cmd)

extra_env = []
if is_ci:
if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
extra_env = ["--env", "LINT_CI_IS_PR=1"]
elif os.environ.get("GITHUB_REPOSITORY") == "bitcoin/bitcoin":
extra_env = ["--env", "LINT_CI_SANITY_CHECK_COMMIT_SIG=1"]

run(
[
"docker",
"run",
"--rm",
*extra_env,
f"--volume={repo_root}:/bitcoin",
*get_worktree_mounts(repo_root),
*([] if is_ci else ["-it"]),
container,
*sys.argv[1:],
]
)


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion ci/lint/06_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if [ -n "${LINT_CI_IS_PR}" ]; then
fi
fi

RUST_BACKTRACE=1 cargo run --manifest-path "./test/lint/test_runner/Cargo.toml"
RUST_BACKTRACE=1 cargo run --manifest-path "./test/lint/test_runner/Cargo.toml" -- "$@"

if [ "${LINT_CI_SANITY_CHECK_COMMIT_SIG}" = "1" ] ; then
# Sanity check only the last few commits to get notified of missing sigs,
Expand Down
6 changes: 1 addition & 5 deletions ci/lint/container-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,4 @@ git config --global --add safe.directory /bitcoin

export PATH="/python_build/bin:${PATH}"

if [ -z "$1" ]; then
bash -ic "./ci/lint/06_script.sh"
else
exec "$@"
fi
./ci/lint/06_script.sh "$@"
24 changes: 9 additions & 15 deletions src/secp256k1/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,8 @@ jobs:
- *PRINT_LOGS

x86_64-macos-native:
name: "x86_64: macOS Ventura, Valgrind"
# See: https://github.com/actions/runner-images#available-images.
runs-on: macos-13
name: "x86_64: macOS Sequoia, Valgrind"
runs-on: macos-15-intel

env:
CC: 'clang'
Expand Down Expand Up @@ -470,9 +469,14 @@ jobs:
env: ${{ matrix.env_vars }}
run: ./ci/ci.sh

- name: Symbol check
- &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

Expand Down Expand Up @@ -513,17 +517,7 @@ jobs:
ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc

- *CI_SCRIPT_ON_HOST

- 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

- *SYMBOL_CHECK_MACOS
- *PRINT_LOGS

win64-native:
Expand Down
15 changes: 14 additions & 1 deletion src/secp256k1/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.7.1] - 2026-01-26

#### Changed
- Tests: Introduced a unit test framework with support for parallel test execution, selective test running, and named command-line arguments. Run `./tests -help` for usage information.

#### Fixed
- Increased the number of cases where the library attempts to clear secrets from the stack.
- build: Fixed x86_64 assembly feature check that could fail when user-provided `CFLAGS` included `-Werror`. This would cause the build to fall back to the slower C implementation instead of using the optimized x86_64 assembly.

#### ABI Compatibility
The ABI is backward compatible with version 0.7.0.

## [0.7.0] - 2025-07-21

#### Added
Expand Down Expand Up @@ -187,7 +199,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).
Therefore, this version number does not uniquely identify a set of source files.

[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.1...HEAD
[0.7.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...v0.7.1
[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.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1
Expand Down
4 changes: 2 additions & 2 deletions src/secp256k1/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ project(libsecp256k1
# 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
# backwards-compatible and therefore at most increase the minor version.
VERSION 0.7.1
VERSION 0.7.2
DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
LANGUAGES C
Expand All @@ -22,7 +22,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6)
set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)

#=============================
Expand Down
16 changes: 0 additions & 16 deletions src/secp256k1/ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,6 @@ if [ -n "$WRAPPER_CMD" ]; then
$WRAPPER_CMD --version
fi

# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0).
case "${CC:-undefined}" in
clang*)
if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ]
then
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
else
case "$WRAPPER_CMD" in
valgrind*)
export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
;;
esac
fi
;;
esac

./autogen.sh

./configure \
Expand Down
4 changes: 2 additions & 2 deletions src/secp256k1/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ AC_PREREQ([2.60])
# backwards-compatible and therefore at most increase the minor version.
define(_PKG_VERSION_MAJOR, 0)
define(_PKG_VERSION_MINOR, 7)
define(_PKG_VERSION_PATCH, 1)
define(_PKG_VERSION_PATCH, 2)
define(_PKG_VERSION_IS_RELEASE, false)

# The library version is based on libtool versioning of the ABI. The set of
Expand All @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, false)
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
define(_LIB_VERSION_CURRENT, 6)
define(_LIB_VERSION_REVISION, 1)
define(_LIB_VERSION_REVISION, 2)
define(_LIB_VERSION_AGE, 0)

AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
Expand Down
3 changes: 2 additions & 1 deletion src/secp256k1/include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ SECP256K1_API void secp256k1_context_destroy(
* writes the message to stderr and calls abort. This default callback can be
* replaced at link time if the preprocessor macro
* USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build
* has been configured with --enable-external-default-callbacks. Then the
* has been configured with --enable-external-default-callbacks (GNU Autotools) or
* -DSECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS=ON (CMake). Then the
* following two symbols must be provided to link against:
* - void secp256k1_default_illegal_callback_fn(const char *message, void *data);
* - void secp256k1_default_error_callback_fn(const char *message, void *data);
Expand Down
9 changes: 9 additions & 0 deletions src/secp256k1/sage/gen_split_lambda_constants.sage
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ assert (A1 + A2)/2 < sqrt(N)
assert B1 < sqrt(N)
assert B2 < sqrt(N)

# Verify connection to Eisenstein integers Z[w] where w = (-1 + sqrt(-3))/2.
# The group order N factors as N = pi * conj(pi) in Z[w], where pi = A - B*w
# is an Eisenstein prime with norm A^2 + A*B + B^2. The GLV endomorphism
# eigenvalue LAMBDA equals B/A mod N, which is the image of w^2 under the
# isomorphism Z[w]/(pi) -> Z/NZ (since w -> A/B and (A/B)^2 = B/A in Z/NZ).
A_EIS, B_EIS = -B1, A1
assert A_EIS**2 + A_EIS*B_EIS + B_EIS**2 == N
assert Z(B_EIS / A_EIS) == LAMBDA

G1 = round((2**384)*B2/N)
G2 = round((2**384)*(-B1)/N)

Expand Down
17 changes: 11 additions & 6 deletions src/secp256k1/src/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ int main(int argc, char** argv) {
bench_data data;

int d = argc == 1;
int default_iters = 20000;
int iters = get_iters(default_iters);

/* Check for invalid user arguments */
char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
Expand All @@ -188,6 +186,13 @@ int main(int argc, char** argv) {
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);

int default_iters = 20000;
int iters = get_iters(default_iters);
if (iters == 0) {
help(default_iters);
return EXIT_FAILURE;
}

if (argc > 1) {
if (have_flag(argc, argv, "-h")
|| have_flag(argc, argv, "--help")
Expand All @@ -205,23 +210,23 @@ int main(int argc, char** argv) {
#ifndef ENABLE_MODULE_ECDH
if (have_flag(argc, argv, "ecdh")) {
fprintf(stderr, "./bench: ECDH module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
fprintf(stderr, "See README.md for configuration instructions.\n\n");
return EXIT_FAILURE;
}
#endif

#ifndef ENABLE_MODULE_RECOVERY
if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
fprintf(stderr, "See README.md for configuration instructions.\n\n");
return EXIT_FAILURE;
}
#endif

#ifndef ENABLE_MODULE_SCHNORRSIG
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
fprintf(stderr, "See README.md for configuration instructions.\n\n");
return EXIT_FAILURE;
}
#endif
Expand All @@ -231,7 +236,7 @@ int main(int argc, char** argv) {
have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
have_flag(argc, argv, "ellswift_ecdh")) {
fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n");
fprintf(stderr, "See README.md for configuration instructions.\n\n");
return EXIT_FAILURE;
}
#endif
Expand Down
8 changes: 7 additions & 1 deletion src/secp256k1/src/bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,13 @@ static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n)
static int get_iters(int default_iters) {
char* env = getenv("SECP256K1_BENCH_ITERS");
if (env) {
return strtol(env, NULL, 0);
char* endptr;
long int iters = strtol(env, &endptr, 0);
if (*endptr != '\0' || iters <= 0) {
printf("Error: Value of SECP256K1_BENCH_ITERS is not a positive integer: %s\n\n", env);
return 0;
}
return iters;
} else {
return default_iters;
}
Expand Down
Loading
Loading