aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/secp256k1/.cirrus.yml159
-rw-r--r--src/secp256k1/.gitignore4
-rw-r--r--src/secp256k1/CHANGELOG.md28
-rw-r--r--src/secp256k1/Makefile.am21
-rw-r--r--src/secp256k1/README.md8
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m42
-rwxr-xr-xsrc/secp256k1/ci/cirrus.sh44
-rw-r--r--src/secp256k1/ci/linux-debian.Dockerfile31
-rw-r--r--src/secp256k1/configure.ac89
-rw-r--r--src/secp256k1/contrib/lax_der_privatekey_parsing.h3
-rw-r--r--src/secp256k1/doc/CHANGELOG.md12
-rw-r--r--src/secp256k1/doc/release-process.md62
-rw-r--r--src/secp256k1/examples/ecdh.c8
-rw-r--r--src/secp256k1/examples/ecdsa.c8
-rw-r--r--src/secp256k1/examples/schnorr.c8
-rw-r--r--src/secp256k1/include/secp256k1.h175
-rw-r--r--src/secp256k1/include/secp256k1_extrakeys.h8
-rw-r--r--src/secp256k1/include/secp256k1_preallocated.h2
-rw-r--r--src/secp256k1/include/secp256k1_recovery.h4
-rw-r--r--src/secp256k1/include/secp256k1_schnorrsig.h4
-rw-r--r--src/secp256k1/src/assumptions.h7
-rw-r--r--src/secp256k1/src/basic-config.h17
-rw-r--r--src/secp256k1/src/bench.c15
-rw-r--r--src/secp256k1/src/bench.h18
-rw-r--r--src/secp256k1/src/bench_ecmult.c6
-rw-r--r--src/secp256k1/src/bench_internal.c15
-rw-r--r--src/secp256k1/src/ecmult.h11
-rw-r--r--src/secp256k1/src/ecmult_gen.h12
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h17
-rw-r--r--src/secp256k1/src/ecmult_impl.h12
-rw-r--r--src/secp256k1/src/field_5x52_int128_impl.h252
-rw-r--r--src/secp256k1/src/group.h5
-rw-r--r--src/secp256k1/src/group_impl.h7
-rw-r--r--src/secp256k1/src/int128.h85
-rw-r--r--src/secp256k1/src/int128_impl.h18
-rw-r--r--src/secp256k1/src/int128_native.h19
-rw-r--r--src/secp256k1/src/int128_native_impl.h87
-rw-r--r--src/secp256k1/src/int128_struct.h14
-rw-r--r--src/secp256k1/src/int128_struct_impl.h192
-rw-r--r--src/secp256k1/src/modinv64_impl.h212
-rw-r--r--src/secp256k1/src/modules/ecdh/bench_impl.h2
-rw-r--r--src/secp256k1/src/modules/ecdh/tests_impl.h2
-rw-r--r--src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/extrakeys/tests_impl.h236
-rw-r--r--src/secp256k1/src/modules/recovery/bench_impl.h4
-rw-r--r--src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/recovery/tests_impl.h84
-rw-r--r--src/secp256k1/src/modules/schnorrsig/bench_impl.h12
-rw-r--r--src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/schnorrsig/tests_impl.h72
-rw-r--r--src/secp256k1/src/precompute_ecmult.c3
-rw-r--r--src/secp256k1/src/precompute_ecmult_gen.c3
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h150
-rw-r--r--src/secp256k1/src/scratch_impl.h2
-rw-r--r--src/secp256k1/src/secp256k1.c36
-rw-r--r--src/secp256k1/src/selftest.h2
-rw-r--r--src/secp256k1/src/tests.c699
-rw-r--r--src/secp256k1/src/tests_exhaustive.c8
-rw-r--r--src/secp256k1/src/util.h41
-rw-r--r--src/secp256k1/src/valgrind_ctime_test.c4
60 files changed, 2032 insertions, 1035 deletions
diff --git a/src/secp256k1/.cirrus.yml b/src/secp256k1/.cirrus.yml
index a2e7f36d1f..51e3bc9484 100644
--- a/src/secp256k1/.cirrus.yml
+++ b/src/secp256k1/.cirrus.yml
@@ -26,6 +26,11 @@ env:
# Compile and run the tests
EXAMPLES: yes
+# https://cirrus-ci.org/pricing/#compute-credits
+credits_snippet: &CREDITS
+ # Don't use any credits for now.
+ use_compute_credits: false
+
cat_logs_snippet: &CAT_LOGS
always:
cat_tests_log_script:
@@ -36,7 +41,6 @@ cat_logs_snippet: &CAT_LOGS
- cat valgrind_ctime_test.log || true
cat_bench_log_script:
- cat bench.log || true
- on_failure:
cat_config_log_script:
- cat config.log || true
cat_test_env_script:
@@ -69,6 +73,7 @@ task:
- env: {WIDEMUL: int64, RECOVERY: yes}
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128}
+ - env: {WIDEMUL: int128_struct}
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, ASM: x86_64}
@@ -107,65 +112,32 @@ task:
<< : *CAT_LOGS
task:
- name: "x86_64: macOS Catalina"
+ name: "arm64: macOS Ventura"
macos_instance:
- image: catalina-base
+ image: ghcr.io/cirruslabs/macos-ventura-base:latest
env:
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
- # Cirrus gives us a fixed number of 12 virtual CPUs. Not that we even have that many jobs at the moment...
- MAKEFLAGS: -j13
+ # Cirrus gives us a fixed number of 4 virtual CPUs. Not that we even have that many jobs at the moment...
+ MAKEFLAGS: -j5
matrix:
<< : *ENV_MATRIX
+ env:
+ ASM: no
+ WITH_VALGRIND: no
+ CTIMETEST: no
matrix:
- env:
- CC: gcc-9
+ CC: gcc
- env:
CC: clang
- # Update Command Line Tools
- # Uncomment this if the Command Line Tools on the CirrusCI macOS image are too old to brew valgrind.
- # See https://apple.stackexchange.com/a/195963 for the implementation.
- ## update_clt_script:
- ## - system_profiler SPSoftwareDataType
- ## - touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
- ## - |-
- ## PROD=$(softwareupdate -l | grep "*.*Command Line" | tail -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | sed 's/Label: //g' | tr -d '\n')
- ## # For debugging
- ## - softwareupdate -l && echo "PROD: $PROD"
- ## - softwareupdate -i "$PROD" --verbose
- ## - rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
- ##
- brew_valgrind_pre_script:
- # Retry a few times because this tends to fail randomly.
- - for i in {1..5}; do brew update && break || sleep 15; done
- - brew config
- - brew tap LouisBrunner/valgrind
- # Fetch valgrind source but don't build it yet.
- - brew fetch --HEAD LouisBrunner/valgrind/valgrind
- brew_valgrind_cache:
- # This is $(brew --cellar valgrind) but command substition does not work here.
- folder: /usr/local/Cellar/valgrind
- # Rebuild cache if ...
- fingerprint_script:
- # ... macOS version changes:
- - sw_vers
- # ... brew changes:
- - brew config
- # ... valgrind changes:
- - git -C "$(brew --cache)/valgrind--git" rev-parse HEAD
- populate_script:
- # If there's no hit in the cache, build and install valgrind.
- - brew install --HEAD LouisBrunner/valgrind/valgrind
- brew_valgrind_post_script:
- # If we have restored valgrind from the cache, tell brew to create symlink to the PATH.
- # If we haven't restored from cached (and just run brew install), this is a no-op.
- - brew link valgrind
brew_script:
- - brew install automake libtool gcc@9
+ - brew install automake libtool gcc
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
+ << : *CREDITS
task:
name: "s390x (big-endian): Linux (Debian stable, QEMU)"
@@ -241,17 +213,63 @@ task:
<< : *CAT_LOGS
task:
- name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)"
<< : *LINUX_CONTAINER
env:
- WRAPPER_CMD: wine64-stable
- SECP256K1_TEST_ITERS: 16
- HOST: x86_64-w64-mingw32
+ WRAPPER_CMD: wine
WITH_VALGRIND: no
ECDH: yes
RECOVERY: yes
SCHNORRSIG: yes
CTIMETEST: no
+ matrix:
+ - name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)"
+ env:
+ HOST: x86_64-w64-mingw32
+ - name: "i686 (mingw32-w64): Windows (Debian stable, Wine)"
+ env:
+ HOST: i686-w64-mingw32
+ << : *MERGE_BASE
+ test_script:
+ - ./ci/cirrus.sh
+ << : *CAT_LOGS
+
+task:
+ << : *LINUX_CONTAINER
+ env:
+ WRAPPER_CMD: wine
+ WERROR_CFLAGS: -WX
+ WITH_VALGRIND: no
+ ECDH: yes
+ RECOVERY: yes
+ EXPERIMENTAL: yes
+ SCHNORRSIG: yes
+ CTIMETEST: no
+ # Use a MinGW-w64 host to tell ./configure we're building for Windows.
+ # This will detect some MinGW-w64 tools but then make will need only
+ # the MSVC tools CC, AR and NM as specified below.
+ HOST: x86_64-w64-mingw32
+ CC: /opt/msvc/bin/x64/cl
+ AR: /opt/msvc/bin/x64/lib
+ NM: /opt/msvc/bin/x64/dumpbin -symbols -headers
+ # Set non-essential options that affect the CLI messages here.
+ # (They depend on the user's taste, so we don't want to set them automatically in configure.ac.)
+ CFLAGS: -nologo -diagnostics:caret
+ LDFLAGS: -XCClinker -nologo -XCClinker -diagnostics:caret
+ matrix:
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine)"
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct)"
+ env:
+ WIDEMUL: int128_struct
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct with __(u)mulh)"
+ env:
+ WIDEMUL: int128_struct
+ CPPFLAGS: -DSECP256K1_MSVC_MULH_TEST_OVERRIDE
+ - name: "i686 (MSVC): Windows (Debian stable, Wine)"
+ env:
+ HOST: i686-w64-mingw32
+ CC: /opt/msvc/bin/x86/cl
+ AR: /opt/msvc/bin/x86/lib
+ NM: /opt/msvc/bin/x86/dumpbin -symbols -headers
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
@@ -301,14 +319,39 @@ task:
- ./ci/cirrus.sh
<< : *CAT_LOGS
+# Memory sanitizers
task:
- name: "C++ -fpermissive"
<< : *LINUX_CONTAINER
+ name: "MSan"
env:
- # ./configure correctly errors out when given CC=g++.
- # We hack around this by passing CC=g++ only to make.
- CC: gcc
- MAKEFLAGS: -j4 CC=g++ CFLAGS=-fpermissive\ -g
+ ECDH: yes
+ RECOVERY: yes
+ SCHNORRSIG: yes
+ CTIMETEST: no
+ CC: clang
+ SECP256K1_TEST_ITERS: 32
+ ASM: no
+ container:
+ memory: 2G
+ matrix:
+ - env:
+ CFLAGS: "-fsanitize=memory -g"
+ - env:
+ ECMULTGENPRECISION: 2
+ ECMULTWINDOW: 2
+ CFLAGS: "-fsanitize=memory -g -O3"
+ << : *MERGE_BASE
+ test_script:
+ - ./ci/cirrus.sh
+ << : *CAT_LOGS
+
+task:
+ name: "C++ -fpermissive (entire project)"
+ << : *LINUX_CONTAINER
+ env:
+ CC: g++
+ CFLAGS: -fpermissive -g
+ CPPFLAGS: -DSECP256K1_CPLUSPLUS_TEST_OVERRIDE
WERROR_CFLAGS:
ECDH: yes
RECOVERY: yes
@@ -319,6 +362,14 @@ task:
<< : *CAT_LOGS
task:
+ name: "C++ (public headers)"
+ << : *LINUX_CONTAINER
+ test_script:
+ - g++ -Werror include/*.h
+ - clang -Werror -x c++-header include/*.h
+ - /opt/msvc/bin/x64/cl.exe -c -WX -TP include/*.h
+
+task:
name: "sage prover"
<< : *LINUX_CONTAINER
test_script:
diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore
index d88627d72e..80c646b771 100644
--- a/src/secp256k1/.gitignore
+++ b/src/secp256k1/.gitignore
@@ -13,9 +13,9 @@ schnorr_example
*.so
*.a
*.csv
-!.gitignore
*.log
*.trs
+*.sage.py
Makefile
configure
@@ -34,8 +34,6 @@ libtool
*.lo
*.o
*~
-*.log
-*.trs
coverage/
coverage.html
diff --git a/src/secp256k1/CHANGELOG.md b/src/secp256k1/CHANGELOG.md
new file mode 100644
index 0000000000..7443483423
--- /dev/null
+++ b/src/secp256k1/CHANGELOG.md
@@ -0,0 +1,28 @@
+# Changelog
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## [Unreleased]
+
+## [0.2.0] - 2022-12-12
+
+### Added
+ - Added `secp256k1_selftest`, to be used in conjunction with `secp256k1_context_static`.
+
+### Changed
+ - Enabled modules schnorrsig, extrakeys and ECDH by default in `./configure`.
+
+### Deprecated
+ - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead.
+ - Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`.
+
+### ABI Compatibility
+
+Since this is the first release, we do not compare application binary interfaces.
+However, there are unreleased versions of libsecp256k1 that are *not* ABI compatible with this version.
+
+## [0.1.0] - 2013-03-05 to 2021-12-25
+
+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.
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index 51c5960301..ad50504f7e 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -48,6 +48,12 @@ noinst_HEADERS += src/precomputed_ecmult.h
noinst_HEADERS += src/precomputed_ecmult_gen.h
noinst_HEADERS += src/assumptions.h
noinst_HEADERS += src/util.h
+noinst_HEADERS += src/int128.h
+noinst_HEADERS += src/int128_impl.h
+noinst_HEADERS += src/int128_native.h
+noinst_HEADERS += src/int128_native_impl.h
+noinst_HEADERS += src/int128_struct.h
+noinst_HEADERS += src/int128_struct_impl.h
noinst_HEADERS += src/scratch.h
noinst_HEADERS += src/scratch_impl.h
noinst_HEADERS += src/selftest.h
@@ -58,7 +64,6 @@ noinst_HEADERS += src/hash_impl.h
noinst_HEADERS += src/field.h
noinst_HEADERS += src/field_impl.h
noinst_HEADERS += src/bench.h
-noinst_HEADERS += src/basic-config.h
noinst_HEADERS += contrib/lax_der_parsing.h
noinst_HEADERS += contrib/lax_der_parsing.c
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
@@ -87,7 +92,7 @@ endif
endif
libsecp256k1_la_SOURCES = src/secp256k1.c
-libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES)
+libsecp256k1_la_CPPFLAGS = $(SECP_INCLUDES)
libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE)
@@ -112,7 +117,7 @@ TESTS =
if USE_TESTS
noinst_PROGRAMS += tests
tests_SOURCES = src/tests.c
-tests_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
+tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
if VALGRIND_ENABLED
tests_CPPFLAGS += -DVALGRIND
noinst_PROGRAMS += valgrind_ctime_test
@@ -211,7 +216,15 @@ maintainer-clean-local: clean-precomp
clean-precomp:
rm -f $(PRECOMP)
-EXTRA_DIST = autogen.sh SECURITY.md
+EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
+EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
+EXTRA_DIST += examples/EXAMPLES_COPYING
+EXTRA_DIST += sage/gen_exhaustive_groups.sage
+EXTRA_DIST += sage/gen_split_lambda_constants.sage
+EXTRA_DIST += sage/group_prover.sage
+EXTRA_DIST += sage/prove_group_implementations.sage
+EXTRA_DIST += sage/secp256k1_params.sage
+EXTRA_DIST += sage/weierstrass_prover.sage
if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md
index f5db915e83..ffdc9aeaee 100644
--- a/src/secp256k1/README.md
+++ b/src/secp256k1/README.md
@@ -2,6 +2,8 @@ libsecp256k1
============
[![Build Status](https://api.cirrus-ci.com/github/bitcoin-core/secp256k1.svg?branch=master)](https://cirrus-ci.com/github/bitcoin-core/secp256k1)
+![Dependencies: None](https://img.shields.io/badge/dependencies-none-success)
+[![irc.libera.chat #secp256k1](https://img.shields.io/badge/irc.libera.chat-%23secp256k1-success)](https://web.libera.chat/#secp256k1)
Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1.
@@ -15,6 +17,7 @@ Features:
* Derandomized ECDSA (via RFC6979 or with a caller provided function.)
* Very efficient implementation.
* Suitable for embedded systems.
+* No runtime dependencies.
* Optional module for public key recovery.
* Optional module for ECDH key exchange.
* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
@@ -72,11 +75,12 @@ To compile optional modules (such as Schnorr signatures), you need to run `./con
Usage examples
-----------
- Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`.
+Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`.
* [ECDSA example](examples/ecdsa.c)
* [Schnorr signatures example](examples/schnorr.c)
* [Deriving a shared secret (ECDH) example](examples/ecdh.c)
- To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`.
+
+To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`.
Test coverage
-----------
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index 9cb54de098..98be915b67 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -10,6 +10,7 @@ AC_MSG_RESULT([$has_64bit_asm])
])
AC_DEFUN([SECP_VALGRIND_CHECK],[
+AC_MSG_CHECKING([for valgrind support])
if test x"$has_valgrind" != x"yes"; then
CPPFLAGS_TEMP="$CPPFLAGS"
CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS"
@@ -21,6 +22,7 @@ if test x"$has_valgrind" != x"yes"; then
#endif
]])], [has_valgrind=yes; AC_DEFINE(HAVE_VALGRIND,1,[Define this symbol if valgrind is installed, and it supports the host platform])])
fi
+AC_MSG_RESULT($has_valgrind)
])
dnl SECP_TRY_APPEND_CFLAGS(flags, VAR)
diff --git a/src/secp256k1/ci/cirrus.sh b/src/secp256k1/ci/cirrus.sh
index b85f012d3f..fb5854a777 100755
--- a/src/secp256k1/ci/cirrus.sh
+++ b/src/secp256k1/ci/cirrus.sh
@@ -5,10 +5,47 @@ set -x
export LC_ALL=C
+# Print relevant CI environment to allow reproducing the job outside of CI.
+print_environment() {
+ # Turn off -x because it messes up the output
+ set +x
+ # There are many ways to print variable names and their content. This one
+ # does not rely on bash.
+ for i in WERROR_CFLAGS MAKEFLAGS BUILD \
+ ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
+ EXPERIMENTAL ECDH RECOVERY SCHNORRSIG \
+ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETEST\
+ EXAMPLES \
+ WRAPPER_CMD CC AR NM HOST
+ do
+ eval 'printf "%s %s " "$i=\"${'"$i"'}\""'
+ done
+ echo "$0"
+ set -x
+}
+print_environment
+
+# Start persistent wineserver if necessary.
+# This speeds up jobs with many invocations of wine (e.g., ./configure with MSVC) tremendously.
+case "$WRAPPER_CMD" in
+ *wine*)
+ # This is apparently only reliable when we run a dummy command such as "hh.exe" afterwards.
+ wineserver -p && wine hh.exe
+ ;;
+esac
+
env >> test_env.log
-$CC -v || true
-valgrind --version || true
+if [ -n "$CC" ]; then
+ # The MSVC compiler "cl" doesn't understand "-v"
+ $CC -v || true
+fi
+if [ "$WITH_VALGRIND" = "yes" ]; then
+ valgrind --version
+fi
+if [ -n "$WRAPPER_CMD" ]; then
+ $WRAPPER_CMD --version
+fi
./autogen.sh
@@ -63,6 +100,9 @@ then
make precomp
fi
+# Shutdown wineserver again
+wineserver -k || true
+
# Check that no repo files have been modified by the build.
# (This fails for example if the precomp files need to be updated in the repo.)
git diff --exit-code
diff --git a/src/secp256k1/ci/linux-debian.Dockerfile b/src/secp256k1/ci/linux-debian.Dockerfile
index 5cccbb5565..a83a4e36db 100644
--- a/src/secp256k1/ci/linux-debian.Dockerfile
+++ b/src/secp256k1/ci/linux-debian.Dockerfile
@@ -1,15 +1,14 @@
FROM debian:stable
-RUN dpkg --add-architecture i386
-RUN dpkg --add-architecture s390x
-RUN dpkg --add-architecture armhf
-RUN dpkg --add-architecture arm64
-RUN dpkg --add-architecture ppc64el
-RUN apt-get update
+RUN dpkg --add-architecture i386 && \
+ dpkg --add-architecture s390x && \
+ dpkg --add-architecture armhf && \
+ dpkg --add-architecture arm64 && \
+ dpkg --add-architecture ppc64el
# dkpg-dev: to make pkg-config work in cross-builds
# llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces
-RUN apt-get install --no-install-recommends --no-upgrade -y \
+RUN apt-get update && apt-get install --no-install-recommends -y \
git ca-certificates \
make automake libtool pkg-config dpkg-dev valgrind qemu-user \
gcc clang llvm libc6-dbg \
@@ -19,8 +18,20 @@ RUN apt-get install --no-install-recommends --no-upgrade -y \
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \
gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \
- wine gcc-mingw-w64-x86-64 \
+ gcc-mingw-w64-x86-64-win32 wine64 wine \
+ gcc-mingw-w64-i686-win32 wine32 \
sagemath
-# Run a dummy command in wine to make it set up configuration
-RUN wine64-stable xcopy || true
+WORKDIR /root
+# The "wine" package provides a convience wrapper that we need
+RUN apt-get update && apt-get install --no-install-recommends -y \
+ git ca-certificates wine64 wine python3-simplejson python3-six msitools winbind procps && \
+ git clone https://github.com/mstorsjo/msvc-wine && \
+ mkdir /opt/msvc && \
+ python3 msvc-wine/vsdownload.py --accept-license --dest /opt/msvc Microsoft.VisualStudio.Workload.VCTools && \
+ msvc-wine/install.sh /opt/msvc
+
+# Initialize the wine environment. Wait until the wineserver process has
+# exited before closing the session, to avoid corrupting the wine prefix.
+RUN wine64 wineboot --init && \
+ while (ps -A | grep wineserver) > /dev/null; do sleep 1; done
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 2db59a8ff3..68f279b17b 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -4,20 +4,20 @@ AC_PREREQ([2.60])
# the API. All changes in experimental modules are treated as
# backwards-compatible and therefore at most increase the minor version.
define(_PKG_VERSION_MAJOR, 0)
-define(_PKG_VERSION_MINOR, 1)
-define(_PKG_VERSION_BUILD, 0)
-define(_PKG_VERSION_IS_RELEASE, false)
+define(_PKG_VERSION_MINOR, 2)
+define(_PKG_VERSION_PATCH, 0)
+define(_PKG_VERSION_IS_RELEASE, true)
# The library version is based on libtool versioning of the ABI. The set of
# rules for updating the version can be found here:
# 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
# interface and therefore only increase the revision.
-define(_LIB_VERSION_CURRENT, 0)
+define(_LIB_VERSION_CURRENT, 1)
define(_LIB_VERSION_REVISION, 0)
define(_LIB_VERSION_AGE, 0)
-AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_BUILD)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-pre]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
+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])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
@@ -33,12 +33,14 @@ AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PROG_CC
-if test x"$ac_cv_prog_cc_c89" = x"no"; then
- AC_MSG_ERROR([c89 compiler support required])
-fi
AM_PROG_AS
AM_PROG_AR
+# Clear some cache variables as a workaround for a bug that appears due to a bad
+# interaction between AM_PROG_AR and LT_INIT when combining MSVC's archiver lib.exe.
+# https://debbugs.gnu.org/cgi/bugreport.cgi?bug=54421
+AS_UNSET(ac_cv_prog_AR)
+AS_UNSET(ac_cv_prog_ac_ct_AR)
LT_INIT([win32-dll])
build_windows=no
@@ -87,23 +89,35 @@ esac
#
# TODO We should analogously not touch CPPFLAGS and LDFLAGS but currently there are no issues.
AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
- # Try to append -Werror=unknown-warning-option to CFLAGS temporarily. Otherwise clang will
- # not error out if it gets unknown warning flags and the checks here will always succeed
- # no matter if clang knows the flag or not.
- SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS="$CFLAGS"
- SECP_TRY_APPEND_CFLAGS([-Werror=unknown-warning-option], CFLAGS)
-
- SECP_TRY_APPEND_CFLAGS([-std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef], $1) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
- SECP_TRY_APPEND_CFLAGS([-Wno-overlength-strings], $1) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
- SECP_TRY_APPEND_CFLAGS([-Wall], $1) # GCC >= 2.95 and probably many other compilers
- SECP_TRY_APPEND_CFLAGS([-Wno-unused-function], $1) # GCC >= 3.0, -Wunused-function is implied by -Wall.
- SECP_TRY_APPEND_CFLAGS([-Wextra], $1) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
- SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95
- SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0
- SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only
- SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0
-
- CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS"
+ # GCC and compatible (incl. clang)
+ if test "x$GCC" = "xyes"; then
+ # Try to append -Werror=unknown-warning-option to CFLAGS temporarily. Otherwise clang will
+ # not error out if it gets unknown warning flags and the checks here will always succeed
+ # no matter if clang knows the flag or not.
+ SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS="$CFLAGS"
+ SECP_TRY_APPEND_CFLAGS([-Werror=unknown-warning-option], CFLAGS)
+
+ SECP_TRY_APPEND_CFLAGS([-std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef], $1) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
+ SECP_TRY_APPEND_CFLAGS([-Wno-overlength-strings], $1) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
+ SECP_TRY_APPEND_CFLAGS([-Wall], $1) # GCC >= 2.95 and probably many other compilers
+ SECP_TRY_APPEND_CFLAGS([-Wno-unused-function], $1) # GCC >= 3.0, -Wunused-function is implied by -Wall.
+ SECP_TRY_APPEND_CFLAGS([-Wextra], $1) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
+ SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95
+ SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0
+ SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only
+ SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0
+
+ CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS"
+ fi
+
+ # MSVC
+ # Assume MSVC if we're building for Windows but not with GCC or compatible;
+ # libtool makes the same assumption internally.
+ # Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path.
+ if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
+ SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
+ SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files
+ fi
])
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)
@@ -141,27 +155,31 @@ AC_ARG_ENABLE(examples,
[SECP_SET_DEFAULT([enable_examples], [no], [yes])])
AC_ARG_ENABLE(module_ecdh,
- AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_ecdh], [no], [yes])])
+ AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_ecdh], [yes], [yes])])
AC_ARG_ENABLE(module_recovery,
AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), [],
[SECP_SET_DEFAULT([enable_module_recovery], [no], [yes])])
AC_ARG_ENABLE(module_extrakeys,
- AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_extrakeys], [no], [yes])])
+ AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_extrakeys], [yes], [yes])])
AC_ARG_ENABLE(module_schnorrsig,
- AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_schnorrsig], [no], [yes])])
+ AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])])
AC_ARG_ENABLE(external_default_callbacks,
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [],
[SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])])
# Test-only override of the (autodetected by the C code) "widemul" setting.
-# Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default).
+# Legal values are:
+# * int64 (for [u]int64_t),
+# * int128 (for [unsigned] __int128),
+# * int128_struct (for int128 implemented as a structure),
+# * and auto (the default).
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
@@ -271,6 +289,9 @@ fi
# Select wide multiplication implementation
case $set_widemul in
+int128_struct)
+ AC_DEFINE(USE_FORCE_WIDEMUL_INT128_STRUCT, 1, [Define this symbol to force the use of the structure for simulating (unsigned) int128 based wide multiplication])
+ ;;
int128)
AC_DEFINE(USE_FORCE_WIDEMUL_INT128, 1, [Define this symbol to force the use of the (unsigned) __int128 based wide multiplication implementation])
;;
@@ -326,7 +347,9 @@ if test x"$enable_valgrind" = x"yes"; then
SECP_INCLUDES="$SECP_INCLUDES $VALGRIND_CPPFLAGS"
fi
-# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI)
+# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI).
+# We don't want to set the user variable CFLAGS in CI because this would disable
+# autoconf's logic for setting default CFLAGS, which we would like to test in CI.
SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS"
###
diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h
index 1a8ad8ae0c..3749e418fe 100644
--- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h
+++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h
@@ -43,8 +43,7 @@ extern "C" {
/** Export a private key in DER format.
*
* Returns: 1 if the private key was valid.
- * Args: ctx: pointer to a context object, initialized for signing (cannot
- * be NULL)
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: privkey: pointer to an array for storing the private key in BER.
* Should have space for 279 bytes, and cannot be NULL.
* privkeylen: Pointer to an int where the length of the private key in
diff --git a/src/secp256k1/doc/CHANGELOG.md b/src/secp256k1/doc/CHANGELOG.md
deleted file mode 100644
index 3c4c2e4583..0000000000
--- a/src/secp256k1/doc/CHANGELOG.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Changelog
-
-This file is currently only a template for future use.
-
-Each change falls into one of the following categories: Added, Changed, Deprecated, Removed, Fixed or Security.
-
-## [Unreleased]
-
-## [MAJOR.MINOR.PATCH] - YYYY-MM-DD
-
-### Added/Changed/Deprecated/Removed/Fixed/Security
-- [Title with link to Pull Request](https://link-to-pr)
diff --git a/src/secp256k1/doc/release-process.md b/src/secp256k1/doc/release-process.md
index a35b8a9db3..91e3616915 100644
--- a/src/secp256k1/doc/release-process.md
+++ b/src/secp256k1/doc/release-process.md
@@ -1,14 +1,52 @@
# Release Process
-1. Open PR to master that
- 1. adds release notes to `doc/CHANGELOG.md` and
- 2. if this is **not** a patch release, updates `_PKG_VERSION_{MAJOR,MINOR}` and `_LIB_VERSIONS_*` in `configure.ac`
-2. After the PR is merged,
- * if this is **not** a patch release, create a release branch with name `MAJOR.MINOR`.
- Make sure that the branch contains the right commits.
- Create commit on the release branch that sets `_PKG_VERSION_IS_RELEASE` in `configure.ac` to `true`.
- * if this **is** a patch release, open a pull request with the bugfixes to the `MAJOR.MINOR` branch.
- Also include the release note commit bump `_PKG_VERSION_BUILD` and `_LIB_VERSIONS_*` in `configure.ac`.
-4. Tag the commit with `git tag -s vMAJOR.MINOR.PATCH`.
-5. Push branch and tag with `git push origin --tags`.
-6. Create a new GitHub release with a link to the corresponding entry in `doc/CHANGELOG.md`.
+This document outlines the process for releasing versions of the form `$MAJOR.$MINOR.$PATCH`.
+
+We distinguish between two types of releases: *regular* and *maintenance* releases.
+Regular releases are releases of a new major or minor version as well as patches of the most recent release.
+Maintenance releases, on the other hand, are required for patches of older releases.
+
+You should coordinate with the other maintainers on the release date, if possible.
+This date will be part of the release entry in [CHANGELOG.md](../CHANGELOG.md) and it should match the dates of the remaining steps in the release process (including the date of the tag and the GitHub release).
+It is best if the maintainers are present during the release, so they can help ensure that the process is followed correctly and, in the case of a regular release, they are aware that they should not modify the master branch between merging the PR in step 1 and the PR in step 3.
+
+This process also assumes that there will be no minor releases for old major releases.
+
+## Regular release
+
+1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
+ * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`) and
+ * updates `_PKG_VERSION_*`, `_LIB_VERSION_*`, and sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`.
+2. After the PR is merged, tag the commit and push it:
+ ```
+ RELEASE_COMMIT=<merge commit of step 1>
+ git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" $RELEASE_COMMIT
+ git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH
+ ```
+3. Open a PR to the master branch with a commit (using message `"release: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that sets `_PKG_VERSION_IS_RELEASE` to `false` and `_PKG_VERSION_PATCH` to `$PATCH + 1` and increases `_LIB_VERSION_REVISION`. If other maintainers are not present to approve the PR, it can be merged without ACKs.
+4. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
+
+## Maintenance release
+
+Note that bugfixes only need to be backported to releases for which no compatible release without the bug exists.
+
+1. If `$PATCH = 1`, create maintenance branch `$MAJOR.$MINOR`:
+ ```
+ git checkout -b $MAJOR.$MINOR v$MAJOR.$MINOR.0
+ git push git@github.com:bitcoin-core/secp256k1.git $MAJOR.$MINOR
+ ```
+2. Open a pull request to the `$MAJOR.$MINOR` branch that
+ * includes the bugfixes,
+ * finalizes the release notes,
+ * bumps `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac` (with commit message `"release: update PKG_ and LIB_VERSION for $MAJOR.$MINOR.$PATCH"`, for example).
+3. After the PRs are merged, update the release branch and tag the commit:
+ ```
+ git checkout $MAJOR.$MINOR && git pull
+ git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH"
+ ```
+4. Push tag:
+ ```
+ git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH
+ ```
+5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
+6. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md).
diff --git a/src/secp256k1/examples/ecdh.c b/src/secp256k1/examples/ecdh.c
index d7e8add361..027d52fd5f 100644
--- a/src/secp256k1/examples/ecdh.c
+++ b/src/secp256k1/examples/ecdh.c
@@ -30,12 +30,8 @@ int main(void) {
secp256k1_pubkey pubkey1;
secp256k1_pubkey pubkey2;
- /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create`
- * needs a context object initialized for signing, which is why we create
- * a context with the SECP256K1_CONTEXT_SIGN flag.
- * (The docs for `secp256k1_ecdh` don't require any special context, just
- * some initialized context) */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/examples/ecdsa.c b/src/secp256k1/examples/ecdsa.c
index 434c856ba0..7e4f1b13ac 100644
--- a/src/secp256k1/examples/ecdsa.c
+++ b/src/secp256k1/examples/ecdsa.c
@@ -38,12 +38,8 @@ int main(void) {
int return_val;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
- /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` needs
- * a context object initialized for signing and `secp256k1_ecdsa_verify` needs
- * a context initialized for verification, which is why we create a context
- * for both signing and verification with the SECP256K1_CONTEXT_SIGN and
- * SECP256K1_CONTEXT_VERIFY flags. */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/examples/schnorr.c b/src/secp256k1/examples/schnorr.c
index 82eb07d5d7..207c45c422 100644
--- a/src/secp256k1/examples/schnorr.c
+++ b/src/secp256k1/examples/schnorr.c
@@ -30,12 +30,8 @@ int main(void) {
int return_val;
secp256k1_xonly_pubkey pubkey;
secp256k1_keypair keypair;
- /* The specification in secp256k1_extrakeys.h states that `secp256k1_keypair_create`
- * needs a context object initialized for signing. And in secp256k1_schnorrsig.h
- * they state that `secp256k1_schnorrsig_verify` needs a context initialized for
- * verification, which is why we create a context for both signing and verification
- * with the SECP256K1_CONTEXT_SIGN and SECP256K1_CONTEXT_VERIFY flags. */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index dddab346ae..826ab75850 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -7,7 +7,7 @@ extern "C" {
#include <stddef.h>
-/* Unless explicitly stated all pointer arguments must not be NULL.
+/** Unless explicitly stated all pointer arguments must not be NULL.
*
* The following rules specify the order of arguments in API calls:
*
@@ -24,15 +24,19 @@ extern "C" {
* 5. Opaque data pointers follow the function pointer they are to be passed to.
*/
-/** Opaque data structure that holds context information (precomputed tables etc.).
+/** Opaque data structure that holds context information
*
- * The purpose of context structures is to cache large precomputed data tables
- * that are expensive to construct, and also to maintain the randomization data
- * for blinding.
+ * The primary purpose of context objects is to store randomization data for
+ * enhanced protection against side-channel leakage. This protection is only
+ * effective if the context is randomized after its creation. See
+ * secp256k1_context_create for creation of contexts and
+ * secp256k1_context_randomize for randomization.
*
- * Do not create a new context object for each operation, as construction is
- * far slower than all other API calls (~100 times slower than an ECDSA
- * verification).
+ * A secondary purpose of context objects is to store pointers to callback
+ * functions that the library will call when certain error states arise. See
+ * secp256k1_context_set_error_callback as well as
+ * secp256k1_context_set_illegal_callback for details. Future library versions
+ * may use context objects for additional purposes.
*
* A constructed context can safely be used from multiple threads
* simultaneously, but API calls that take a non-const pointer to a context
@@ -45,7 +49,7 @@ extern "C" {
*/
typedef struct secp256k1_context_struct secp256k1_context;
-/** Opaque data structure that holds rewriteable "scratch space"
+/** Opaque data structure that holds rewritable "scratch space"
*
* The purpose of this structure is to replace dynamic memory allocations,
* because we target architectures where this may not be available. It is
@@ -130,7 +134,7 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_INLINE inline
# endif
-/** When this header is used at build-time the SECP256K1_BUILD define needs to be set
+/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
* to correctly setup export attributes and nullness checks. This is normally done
* by secp256k1.c but to guard against this header being included before secp256k1.c
* has had a chance to set the define (e.g. via test harnesses that just includes
@@ -159,9 +163,9 @@ typedef int (*secp256k1_nonce_function)(
# endif
#endif
-/**Warning attributes
- * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
- * some paranoid null checks. */
+/* Warning attributes
+ * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
+ * some paranoid null checks. */
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
@@ -173,7 +177,7 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_ARG_NONNULL(_x)
# endif
-/** Attribute for marking functions, types, and variables as deprecated */
+/* Attribute for marking functions, types, and variables as deprecated */
#if !defined(SECP256K1_BUILD) && defined(__has_attribute)
# if __has_attribute(__deprecated__)
# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg)))
@@ -184,22 +188,26 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_DEPRECATED(_msg)
#endif
-/** All flags' lower 8 bits indicate what they're for. Do not use directly. */
+/* All flags' lower 8 bits indicate what they're for. Do not use directly. */
#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)
#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)
#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)
-/** The higher bits contain the actual data. Do not use directly. */
+/* The higher bits contain the actual data. Do not use directly. */
#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10)
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
-/** Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
+/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
* secp256k1_context_preallocated_create. */
+#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
+
+/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
+
+/* Testing flag. Do not use. */
#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY)
-#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
/** Flag to pass to secp256k1_ec_pubkey_serialize. */
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
@@ -212,23 +220,66 @@ typedef int (*secp256k1_nonce_function)(
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
-/** A simple secp256k1 context object with no precomputed tables. These are useful for
- * type serialization/parsing functions which require a context object to maintain
- * API consistency, but currently do not require expensive precomputations or dynamic
- * allocations.
+/** A built-in constant secp256k1 context object with static storage duration, to be
+ * used in conjunction with secp256k1_selftest.
+ *
+ * This context object offers *only limited functionality* , i.e., it cannot be used
+ * for API functions that perform computations involving secret keys, e.g., signing
+ * and public key generation. If this restriction applies to a specific API function,
+ * it is mentioned in its documentation. See secp256k1_context_create if you need a
+ * full context object that supports all functionality offered by the library.
+ *
+ * It is highly recommended to call secp256k1_selftest before using this context.
+ */
+SECP256K1_API extern const secp256k1_context *secp256k1_context_static;
+
+/** Deprecated alias for secp256k1_context_static. */
+SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp
+SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
+
+/** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
+ *
+ * This function performs self tests that detect some serious usage errors and
+ * similar conditions, e.g., when the library is compiled for the wrong endianness.
+ * This is a last resort measure to be used in production. The performed tests are
+ * very rudimentary and are not intended as a replacement for running the test
+ * binaries.
+ *
+ * It is highly recommended to call this before using secp256k1_context_static.
+ * It is not necessary to call this function before using a context created with
+ * secp256k1_context_create (or secp256k1_context_preallocated_create), which will
+ * take care of performing the self tests.
+ *
+ * If the tests fail, this function will call the default error handler to abort the
+ * program (see secp256k1_context_set_error_callback).
*/
-SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp;
+SECP256K1_API void secp256k1_selftest(void);
+
/** Create a secp256k1 context object (in dynamically allocated memory).
*
* This function uses malloc to allocate memory. It is guaranteed that malloc is
* called at most once for every call of this function. If you need to avoid dynamic
- * memory allocation entirely, see the functions in secp256k1_preallocated.h.
+ * memory allocation entirely, see secp256k1_context_static and the functions in
+ * secp256k1_preallocated.h.
*
* Returns: a newly created context object.
- * In: flags: which parts of the context to initialize.
+ * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below).
+ *
+ * The only valid non-deprecated flag in recent library versions is
+ * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality
+ * offered by the library. All other (deprecated) flags will be treated as equivalent
+ * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for
+ * historical reasons, future versions of the library may introduce new flags.
*
- * See also secp256k1_context_randomize.
+ * If the context is intended to be used for API functions that perform computations
+ * involving secret keys, e.g., signing and public key generation, then it is highly
+ * recommended to call secp256k1_context_randomize on the context before calling
+ * those API functions. This will provide enhanced protection against side-channel
+ * leakage, see secp256k1_context_randomize for details.
+ *
+ * Do not create a new context object for each operation, as construction and
+ * randomization can take non-negligible time.
*/
SECP256K1_API secp256k1_context* secp256k1_context_create(
unsigned int flags
@@ -308,7 +359,10 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
) SECP256K1_ARG_NONNULL(1);
/** Set a callback function to be called when an internal consistency check
- * fails. The default is crashing.
+ * fails.
+ *
+ * The default callback writes an error message to stderr and calls abort
+ * to abort the program.
*
* This can only trigger in case of a hardware failure, miscompilation,
* memory corruption, serious bug in the library, or other error would can
@@ -426,8 +480,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp(
* encoding is invalid. R and S with value 0 are allowed in the encoding.
*
* After the call, sig will always be initialized. If parsing failed or R or
- * S are zero, the resulting sig value is guaranteed to fail validation for any
- * message and public key.
+ * S are zero, the resulting sig value is guaranteed to fail verification for
+ * any message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
const secp256k1_context* ctx,
@@ -447,7 +501,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
* encoded numbers are out of range.
*
* After the call, sig will always be initialized. If parsing failed or the
- * encoded numbers are out of range, signature validation with it is
+ * encoded numbers are out of range, signature verification with it is
* guaranteed to fail for every message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
@@ -494,7 +548,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
*
* Returns: 1: correct signature
* 0: incorrect or unparseable signature
- * Args: ctx: a secp256k1 context object, initialized for verification.
+ * Args: ctx: a secp256k1 context object.
* In: sig: the signature being verified.
* msghash32: the 32-byte message hash being verified.
* The verifier must make sure to apply a cryptographic
@@ -511,7 +565,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
*
* If you need to accept ECDSA signatures from sources that do not obey this
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
- * validation, but be aware that doing so results in malleable signatures.
+ * verification, but be aware that doing so results in malleable signatures.
*
* For details, see the comments for that function.
*/
@@ -582,7 +636,7 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
@@ -626,7 +680,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
*
* Returns: 1: secret was valid, public key stores.
* 0: secret was invalid, try again.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: pubkey: pointer to the created public key.
* In: seckey: pointer to a 32-byte secret key.
*/
@@ -705,7 +759,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
- * Args: ctx: pointer to a context object initialized for validation.
+ * Args: ctx: pointer to a context object.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
@@ -750,7 +804,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
/** Tweak a public key by multiplying it by a tweak value.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
- * Args: ctx: pointer to a context object initialized for validation.
+ * Args: ctx: pointer to a context object.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
@@ -764,30 +818,41 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
-/** Updates the context randomization to protect against side-channel leakage.
- * Returns: 1: randomization successfully updated or nothing to randomize
+/** Randomizes the context to provide enhanced protection against side-channel leakage.
+ *
+ * Returns: 1: randomization successful (or called on copy of secp256k1_context_static)
* 0: error
* Args: ctx: pointer to a context object.
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
*
- * While secp256k1 code is written to be constant-time no matter what secret
- * values are, it's possible that a future compiler may output code which isn't,
+ * While secp256k1 code is written and tested to be constant-time no matter what
+ * secret values are, it is possible that a compiler may output code which is not,
* and also that the CPU may not emit the same radio frequencies or draw the same
- * amount power for all values.
- *
- * This function provides a seed which is combined into the blinding value: that
- * blinding value is added before each multiplication (and removed afterwards) so
- * that it does not affect function results, but shields against attacks which
- * rely on any input-dependent behaviour.
- *
- * This function has currently an effect only on contexts initialized for signing
- * because randomization is currently used only for signing. However, this is not
- * guaranteed and may change in the future. It is safe to call this function on
- * contexts not initialized for signing; then it will have no effect and return 1.
- *
- * You should call this after secp256k1_context_create or
- * secp256k1_context_clone (and secp256k1_context_preallocated_create or
- * secp256k1_context_clone, resp.), and you may call this repeatedly afterwards.
+ * amount of power for all values. Randomization of the context shields against
+ * side-channel observations which aim to exploit secret-dependent behaviour in
+ * certain computations which involve secret keys.
+ *
+ * It is highly recommended to call this function on contexts returned from
+ * secp256k1_context_create or secp256k1_context_clone (or from the corresponding
+ * functions in secp256k1_preallocated.h) before using these contexts to call API
+ * functions that perform computations involving secret keys, e.g., signing and
+ * public key generation. It is possible to call this function more than once on
+ * the same context, and doing so before every few computations involving secret
+ * keys is recommended as a defense-in-depth measure.
+ *
+ * Currently, the random seed is mainly used for blinding multiplications of a
+ * secret scalar with the elliptic curve base point. Multiplications of this
+ * kind are performed by exactly those API functions which are documented to
+ * require a context that is not the secp256k1_context_static. As a rule of thumb,
+ * these are all functions which take a secret key (or a keypair) as an input.
+ * A notable exception to that rule is the ECDH module, which relies on a different
+ * kind of elliptic curve point multiplication and thus does not benefit from
+ * enhanced protection against side-channel leakage currently.
+ *
+ * It is safe call this function on a copy of secp256k1_context_static in writable
+ * memory (e.g., obtained via secp256k1_context_clone). In that case, this
+ * function is guaranteed to return 1, but the call will have no effect because
+ * the static context (or a copy thereof) is not meant to be randomized.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
secp256k1_context* ctx,
diff --git a/src/secp256k1/include/secp256k1_extrakeys.h b/src/secp256k1/include/secp256k1_extrakeys.h
index 09cbeaaa80..3591bc0012 100644
--- a/src/secp256k1/include/secp256k1_extrakeys.h
+++ b/src/secp256k1/include/secp256k1_extrakeys.h
@@ -108,7 +108,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
*
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0.
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
@@ -137,7 +137,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
*
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
* is passed in as tweaked_pubkey32). This must match the
@@ -159,7 +159,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_
*
* Returns: 1: secret was valid, keypair is ready to use
* 0: secret was invalid, try again with a different secret
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: keypair: pointer to the created keypair.
* In: seckey: pointer to a 32-byte secret key.
*/
@@ -228,7 +228,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
* invalid (only when the tweak is the negation of the keypair's
* secret key). 1 otherwise.
*
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* an invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
diff --git a/src/secp256k1/include/secp256k1_preallocated.h b/src/secp256k1/include/secp256k1_preallocated.h
index d2d9014f02..ed846f75f9 100644
--- a/src/secp256k1/include/secp256k1_preallocated.h
+++ b/src/secp256k1/include/secp256k1_preallocated.h
@@ -58,6 +58,8 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
* bytes, as detailed above.
* flags: which parts of the context to initialize.
*
+ * See secp256k1_context_create (in secp256k1.h) for further details.
+ *
* See also secp256k1_context_randomize (in secp256k1.h)
* and secp256k1_context_preallocated_destroy.
*/
diff --git a/src/secp256k1/include/secp256k1_recovery.h b/src/secp256k1/include/secp256k1_recovery.h
index 0e2847db96..824c604025 100644
--- a/src/secp256k1/include/secp256k1_recovery.h
+++ b/src/secp256k1/include/secp256k1_recovery.h
@@ -72,7 +72,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
@@ -94,7 +94,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
*
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
- * Args: ctx: pointer to a context object, initialized for verification.
+ * Args: ctx: pointer to a context object.
* Out: pubkey: pointer to the recovered public key.
* In: sig: pointer to initialized signature that supports pubkey recovery.
* msghash32: the 32-byte message hash assumed to be signed.
diff --git a/src/secp256k1/include/secp256k1_schnorrsig.h b/src/secp256k1/include/secp256k1_schnorrsig.h
index 5fedcb07b0..e579e1b1d8 100644
--- a/src/secp256k1/include/secp256k1_schnorrsig.h
+++ b/src/secp256k1/include/secp256k1_schnorrsig.h
@@ -106,7 +106,7 @@ typedef struct {
* signatures from being valid in multiple contexts by accident.
*
* Returns 1 on success, 0 on failure.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg32: the 32-byte message being signed.
* keypair: pointer to an initialized keypair.
@@ -161,7 +161,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
*
* Returns: 1: correct signature
* 0: incorrect signature
- * Args: ctx: a secp256k1 context object, initialized for verification.
+ * Args: ctx: a secp256k1 context object.
* In: sig64: pointer to the 64-byte signature to verify.
* msg: the message being verified. Can only be NULL if msglen is 0.
* msglen: length of the message
diff --git a/src/secp256k1/src/assumptions.h b/src/secp256k1/src/assumptions.h
index 6dc527b288..8ed04209e9 100644
--- a/src/secp256k1/src/assumptions.h
+++ b/src/secp256k1/src/assumptions.h
@@ -10,6 +10,9 @@
#include <limits.h>
#include "util.h"
+#if defined(SECP256K1_INT128_NATIVE)
+#include "int128_native.h"
+#endif
/* This library, like most software, relies on a number of compiler implementation defined (but not undefined)
behaviours. Although the behaviours we require are essentially universal we test them specifically here to
@@ -55,7 +58,7 @@ struct secp256k1_assumption_checker {
/* To int64_t. */
((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) &&
-#if defined(SECP256K1_WIDEMUL_INT128)
+#if defined(SECP256K1_INT128_NATIVE)
((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL) &&
(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL) &&
(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL) &&
@@ -71,7 +74,7 @@ struct secp256k1_assumption_checker {
((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A) &&
((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48) &&
((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL) &&
-#if defined(SECP256K1_WIDEMUL_INT128)
+#if defined(SECP256K1_INT128_NATIVE)
((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) &&
#endif
1) * 2 - 1];
diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h
deleted file mode 100644
index 6f7693cb8f..0000000000
--- a/src/secp256k1/src/basic-config.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/***********************************************************************
- * Copyright (c) 2013, 2014 Pieter Wuille *
- * Distributed under the MIT software license, see the accompanying *
- * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
- ***********************************************************************/
-
-#ifndef SECP256K1_BASIC_CONFIG_H
-#define SECP256K1_BASIC_CONFIG_H
-
-#ifdef USE_BASIC_CONFIG
-
-#define ECMULT_WINDOW_SIZE 15
-#define ECMULT_GEN_PREC_BITS 4
-
-#endif /* USE_BASIC_CONFIG */
-
-#endif /* SECP256K1_BASIC_CONFIG_H */
diff --git a/src/secp256k1/src/bench.c b/src/secp256k1/src/bench.c
index d5937b763f..e68021aa28 100644
--- a/src/secp256k1/src/bench.c
+++ b/src/secp256k1/src/bench.c
@@ -164,7 +164,7 @@ int main(int argc, char** argv) {
/* Check if the user tries to benchmark optional module without building it */
#ifndef ENABLE_MODULE_ECDH
- if (have_flag(argc, argv, "ecdh")) {
+ if (have_flag(argc, argv, "ecdh")) {
fprintf(stderr, "./bench: ECDH module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
return 1;
@@ -172,7 +172,7 @@ int main(int argc, char** argv) {
#endif
#ifndef ENABLE_MODULE_RECOVERY
- if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
+ 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");
return 1;
@@ -180,15 +180,15 @@ int main(int argc, char** argv) {
#endif
#ifndef ENABLE_MODULE_SCHNORRSIG
- if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
+ 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");
return 1;
}
#endif
- /* ECDSA verification benchmark */
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* ECDSA benchmark */
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
for (i = 0; i < 32; i++) {
data.msg[i] = 1 + i;
@@ -206,11 +206,6 @@ int main(int argc, char** argv) {
print_output_table_header_row();
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters);
- secp256k1_context_destroy(data.ctx);
-
- /* ECDSA signing benchmark */
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
-
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters);
secp256k1_context_destroy(data.ctx);
diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h
index aa275fe919..611ba11f04 100644
--- a/src/secp256k1/src/bench.h
+++ b/src/secp256k1/src/bench.h
@@ -7,15 +7,31 @@
#ifndef SECP256K1_BENCH_H
#define SECP256K1_BENCH_H
+#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include "sys/time.h"
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1900)
+# include <time.h>
+#else
+# include "sys/time.h"
+#endif
static int64_t gettime_i64(void) {
+#if (defined(_MSC_VER) && _MSC_VER >= 1900)
+ /* C11 way to get wallclock time */
+ struct timespec tv;
+ if (!timespec_get(&tv, TIME_UTC)) {
+ fputs("timespec_get failed!", stderr);
+ exit(1);
+ }
+ return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
+#endif
}
#define FP_EXP (6)
diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c
index 4030e0263f..9d0db340e1 100644
--- a/src/secp256k1/src/bench_ecmult.c
+++ b/src/secp256k1/src/bench_ecmult.c
@@ -84,9 +84,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset
}
}
secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars);
- secp256k1_gej_neg(&tmp, &tmp);
- secp256k1_gej_add_var(&tmp, &tmp, &sum_output, NULL);
- CHECK(secp256k1_gej_is_infinity(&tmp));
+ CHECK(secp256k1_gej_eq_var(&tmp, &sum_output));
}
static void bench_ecmult_setup(void* arg) {
@@ -308,7 +306,7 @@ int main(int argc, char **argv) {
}
}
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16;
if (!have_flag(argc, argv, "simple")) {
data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size);
diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c
index 7eb3af28d7..2224058f64 100644
--- a/src/secp256k1/src/bench_internal.c
+++ b/src/secp256k1/src/bench_internal.c
@@ -343,19 +343,11 @@ void bench_rfc6979_hmac_sha256(void* arg, int iters) {
}
}
-void bench_context_verify(void* arg, int iters) {
+void bench_context(void* arg, int iters) {
int i;
(void)arg;
for (i = 0; i < iters; i++) {
- secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY));
- }
-}
-
-void bench_context_sign(void* arg, int iters) {
- int i;
- (void)arg;
- for (i = 0; i < iters; i++) {
- secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN));
+ secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_NONE));
}
}
@@ -395,8 +387,7 @@ int main(int argc, char **argv) {
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters);
- if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000);
- if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100);
+ if (d || have_flag(argc, argv, "context")) run_benchmark("context_create", bench_context, bench_setup, NULL, &data, 10, iters);
return 0;
}
diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h
index b47d8f494a..e28c602506 100644
--- a/src/secp256k1/src/ecmult.h
+++ b/src/secp256k1/src/ecmult.h
@@ -11,6 +11,17 @@
#include "scalar.h"
#include "scratch.h"
+#ifndef ECMULT_WINDOW_SIZE
+# define ECMULT_WINDOW_SIZE 15
+# ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_MSG("ECMULT_WINDOW_SIZE undefined, assuming default value")
+# endif
+#endif
+
+#ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE)
+#endif
+
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* tested.
diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h
index f48f266461..a430e8d5d9 100644
--- a/src/secp256k1/src/ecmult_gen.h
+++ b/src/secp256k1/src/ecmult_gen.h
@@ -10,9 +10,21 @@
#include "scalar.h"
#include "group.h"
+#ifndef ECMULT_GEN_PREC_BITS
+# define ECMULT_GEN_PREC_BITS 4
+# ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_MSG("ECMULT_GEN_PREC_BITS undefined, assuming default value")
+# endif
+#endif
+
+#ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_DEF(ECMULT_GEN_PREC_BITS)
+#endif
+
#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8
# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8."
#endif
+
#define ECMULT_GEN_PREC_G(bits) (1 << bits)
#define ECMULT_GEN_PREC_N(bits) (256 / bits)
diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h
index 2c8a503acc..4f5ea9f3c0 100644
--- a/src/secp256k1/src/ecmult_gen_impl.h
+++ b/src/secp256k1/src/ecmult_gen_impl.h
@@ -88,31 +88,31 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256 rng;
int overflow;
- unsigned char keydata[64] = {0};
+ unsigned char keydata[64];
if (seed32 == NULL) {
/* When seed is NULL, reset the initial point and blinding value. */
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
secp256k1_gej_neg(&ctx->initial, &ctx->initial);
secp256k1_scalar_set_int(&ctx->blind, 1);
+ return;
}
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
- secp256k1_scalar_get_b32(nonce32, &ctx->blind);
+ secp256k1_scalar_get_b32(keydata, &ctx->blind);
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
* asking the caller for blinding values directly and expecting them to retry on failure.
*/
- memcpy(keydata, nonce32, 32);
- if (seed32 != NULL) {
- memcpy(keydata + 32, seed32, 32);
- }
- secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
+ VERIFY_CHECK(seed32 != NULL);
+ memcpy(keydata + 32, seed32, 32);
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64);
memset(keydata, 0, sizeof(keydata));
/* Accept unobservably small non-uniformity. */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
overflow = !secp256k1_fe_set_b32(&s, nonce32);
overflow |= secp256k1_fe_is_zero(&s);
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
- /* Randomize the projection to defend against multiplier sidechannels. */
+ /* Randomize the projection to defend against multiplier sidechannels.
+ Do this before our own call to secp256k1_ecmult_gen below. */
secp256k1_gej_rescale(&ctx->initial, &s);
secp256k1_fe_clear(&s);
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
@@ -121,6 +121,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b));
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
memset(nonce32, 0, 32);
+ /* The random projection in ctx->initial ensures that gb will have a random projection. */
secp256k1_ecmult_gen(ctx, &gb, &b);
secp256k1_scalar_negate(&b, &b);
ctx->blind = b;
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index bbc820c77c..3776fe73fc 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -200,9 +200,15 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
bit += now;
}
#ifdef VERIFY
- CHECK(carry == 0);
- while (bit < 256) {
- CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
+ {
+ int verify_bit = bit;
+
+ VERIFY_CHECK(carry == 0);
+
+ while (verify_bit < 256) {
+ VERIFY_CHECK(secp256k1_scalar_get_bits(&s, verify_bit, 1) == 0);
+ verify_bit++;
+ }
}
#endif
return last_set_bit + 1;
diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h
index 0ed6118cc9..18567b95f3 100644
--- a/src/secp256k1/src/field_5x52_int128_impl.h
+++ b/src/secp256k1/src/field_5x52_int128_impl.h
@@ -9,14 +9,18 @@
#include <stdint.h>
+#include "int128.h"
+
#ifdef VERIFY
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
+#define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n)))
#else
#define VERIFY_BITS(x, n) do { } while(0)
+#define VERIFY_BITS_128(x, n) do { } while(0)
#endif
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
- uint128_t c, d;
+ secp256k1_uint128 c, d;
uint64_t t3, t4, tx, u0;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
@@ -40,121 +44,119 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
* Note that [x 0 0 0 0 0] = [x*R].
*/
- d = (uint128_t)a0 * b[3]
- + (uint128_t)a1 * b[2]
- + (uint128_t)a2 * b[1]
- + (uint128_t)a3 * b[0];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_mul(&d, a0, b[3]);
+ secp256k1_u128_accum_mul(&d, a1, b[2]);
+ secp256k1_u128_accum_mul(&d, a2, b[1]);
+ secp256k1_u128_accum_mul(&d, a3, b[0]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (uint128_t)a4 * b[4];
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a4, b[4]);
+ VERIFY_BITS_128(&c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)R * (uint64_t)c; c >>= 64;
- VERIFY_BITS(d, 115);
- VERIFY_BITS(c, 48);
+ secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64);
+ VERIFY_BITS_128(&d, 115);
+ VERIFY_BITS_128(&c, 48);
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- t3 = d & M; d >>= 52;
+ t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t3, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)a0 * b[4]
- + (uint128_t)a1 * b[3]
- + (uint128_t)a2 * b[2]
- + (uint128_t)a3 * b[1]
- + (uint128_t)a4 * b[0];
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a0, b[4]);
+ secp256k1_u128_accum_mul(&d, a1, b[3]);
+ secp256k1_u128_accum_mul(&d, a2, b[2]);
+ secp256k1_u128_accum_mul(&d, a3, b[1]);
+ secp256k1_u128_accum_mul(&d, a4, b[0]);
+ VERIFY_BITS_128(&d, 115);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- d += (uint128_t)(R << 12) * (uint64_t)c;
- VERIFY_BITS(d, 116);
+ secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
+ VERIFY_BITS_128(&d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- t4 = d & M; d >>= 52;
+ t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t4, 52);
- VERIFY_BITS(d, 64);
+ VERIFY_BITS_128(&d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (uint128_t)a0 * b[0];
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a0, b[0]);
+ VERIFY_BITS_128(&c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (uint128_t)a1 * b[4]
- + (uint128_t)a2 * b[3]
- + (uint128_t)a3 * b[2]
- + (uint128_t)a4 * b[1];
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a1, b[4]);
+ secp256k1_u128_accum_mul(&d, a2, b[3]);
+ secp256k1_u128_accum_mul(&d, a3, b[2]);
+ secp256k1_u128_accum_mul(&d, a4, b[1]);
+ VERIFY_BITS_128(&d, 115);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- u0 = d & M; d >>= 52;
+ u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(u0, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)u0 * (R >> 4);
- VERIFY_BITS(c, 115);
+ secp256k1_u128_accum_mul(&c, u0, R >> 4);
+ VERIFY_BITS_128(&c, 115);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- r[0] = c & M; c >>= 52;
+ r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[0], 52);
- VERIFY_BITS(c, 61);
+ VERIFY_BITS_128(&c, 61);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)a0 * b[1]
- + (uint128_t)a1 * b[0];
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, b[1]);
+ secp256k1_u128_accum_mul(&c, a1, b[0]);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (uint128_t)a2 * b[4]
- + (uint128_t)a3 * b[3]
- + (uint128_t)a4 * b[2];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a2, b[4]);
+ secp256k1_u128_accum_mul(&d, a3, b[3]);
+ secp256k1_u128_accum_mul(&d, a4, b[2]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (d & M) * R; d >>= 52;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 62);
+ secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 62);
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- r[1] = c & M; c >>= 52;
+ r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[1], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (uint128_t)a0 * b[2]
- + (uint128_t)a1 * b[1]
- + (uint128_t)a2 * b[0];
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, b[2]);
+ secp256k1_u128_accum_mul(&c, a1, b[1]);
+ secp256k1_u128_accum_mul(&c, a2, b[0]);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (uint128_t)a3 * b[4]
- + (uint128_t)a4 * b[3];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a3, b[4]);
+ secp256k1_u128_accum_mul(&d, a4, b[3]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)R * (uint64_t)d; d >>= 64;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 50);
+ secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 50);
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[2] = c & M; c >>= 52;
+ r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[2], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)(R << 12) * (uint64_t)d + t3;
- VERIFY_BITS(c, 100);
+ secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
+ secp256k1_u128_accum_u64(&c, t3);
+ VERIFY_BITS_128(&c, 100);
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[3] = c & M; c >>= 52;
+ r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[3], 52);
- VERIFY_BITS(c, 48);
+ VERIFY_BITS_128(&c, 48);
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += t4;
- VERIFY_BITS(c, 49);
- /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[4] = c;
+ r[4] = secp256k1_u128_to_u64(&c) + t4;
VERIFY_BITS(r[4], 49);
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
- uint128_t c, d;
+ secp256k1_uint128 c, d;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
int64_t t3, t4, tx, u0;
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
@@ -170,107 +172,105 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
* Note that [x 0 0 0 0 0] = [x*R].
*/
- d = (uint128_t)(a0*2) * a3
- + (uint128_t)(a1*2) * a2;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_mul(&d, a0*2, a3);
+ secp256k1_u128_accum_mul(&d, a1*2, a2);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (uint128_t)a4 * a4;
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a4, a4);
+ VERIFY_BITS_128(&c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)R * (uint64_t)c; c >>= 64;
- VERIFY_BITS(d, 115);
- VERIFY_BITS(c, 48);
+ secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64);
+ VERIFY_BITS_128(&d, 115);
+ VERIFY_BITS_128(&c, 48);
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- t3 = d & M; d >>= 52;
+ t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t3, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
a4 *= 2;
- d += (uint128_t)a0 * a4
- + (uint128_t)(a1*2) * a3
- + (uint128_t)a2 * a2;
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a0, a4);
+ secp256k1_u128_accum_mul(&d, a1*2, a3);
+ secp256k1_u128_accum_mul(&d, a2, a2);
+ VERIFY_BITS_128(&d, 115);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- d += (uint128_t)(R << 12) * (uint64_t)c;
- VERIFY_BITS(d, 116);
+ secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
+ VERIFY_BITS_128(&d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- t4 = d & M; d >>= 52;
+ t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t4, 52);
- VERIFY_BITS(d, 64);
+ VERIFY_BITS_128(&d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (uint128_t)a0 * a0;
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a0, a0);
+ VERIFY_BITS_128(&c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (uint128_t)a1 * a4
- + (uint128_t)(a2*2) * a3;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a1, a4);
+ secp256k1_u128_accum_mul(&d, a2*2, a3);
+ VERIFY_BITS_128(&d, 114);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- u0 = d & M; d >>= 52;
+ u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(u0, 52);
- VERIFY_BITS(d, 62);
+ VERIFY_BITS_128(&d, 62);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)u0 * (R >> 4);
- VERIFY_BITS(c, 113);
+ secp256k1_u128_accum_mul(&c, u0, R >> 4);
+ VERIFY_BITS_128(&c, 113);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- r[0] = c & M; c >>= 52;
+ r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[0], 52);
- VERIFY_BITS(c, 61);
+ VERIFY_BITS_128(&c, 61);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
a0 *= 2;
- c += (uint128_t)a0 * a1;
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, a1);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (uint128_t)a2 * a4
- + (uint128_t)a3 * a3;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a2, a4);
+ secp256k1_u128_accum_mul(&d, a3, a3);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (d & M) * R; d >>= 52;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 62);
+ secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 62);
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- r[1] = c & M; c >>= 52;
+ r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[1], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (uint128_t)a0 * a2
- + (uint128_t)a1 * a1;
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, a2);
+ secp256k1_u128_accum_mul(&c, a1, a1);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (uint128_t)a3 * a4;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a3, a4);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)R * (uint64_t)d; d >>= 64;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 50);
+ secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 50);
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[2] = c & M; c >>= 52;
+ r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[2], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)(R << 12) * (uint64_t)d + t3;
- VERIFY_BITS(c, 100);
+ secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
+ secp256k1_u128_accum_u64(&c, t3);
+ VERIFY_BITS_128(&c, 100);
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[3] = c & M; c >>= 52;
+ r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[3], 52);
- VERIFY_BITS(c, 48);
+ VERIFY_BITS_128(&c, 48);
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += t4;
- VERIFY_BITS(c, 49);
- /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[4] = c;
+ r[4] = secp256k1_u128_to_u64(&c) + t4;
VERIFY_BITS(r[4], 49);
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index bb7dae1cf7..b79ba597db 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -23,7 +23,7 @@ typedef struct {
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
/** A group element of the secp256k1 curve, in jacobian coordinates.
- * Note: For exhastive test mode, sepc256k1 is replaced by a small subgroup of a different curve.
+ * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve.
*/
typedef struct {
secp256k1_fe x; /* actual X: x/z^2 */
@@ -97,6 +97,9 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r);
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a);
+/** Check two group elements (jacobian) for equality in variable time. */
+static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b);
+
/** Compare the X coordinate of a group element (jacobian). */
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index 63735ab682..dfe6e32c7f 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -236,6 +236,13 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
secp256k1_fe_set_int(&r->z, 1);
}
+static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
+ secp256k1_gej tmp;
+ secp256k1_gej_neg(&tmp, a);
+ secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
+ return secp256k1_gej_is_infinity(&tmp);
+}
+
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
secp256k1_fe r, r2;
VERIFY_CHECK(!a->infinity);
diff --git a/src/secp256k1/src/int128.h b/src/secp256k1/src/int128.h
new file mode 100644
index 0000000000..84d969a236
--- /dev/null
+++ b/src/secp256k1/src/int128.h
@@ -0,0 +1,85 @@
+#ifndef SECP256K1_INT128_H
+#define SECP256K1_INT128_H
+
+#include "util.h"
+
+#if defined(SECP256K1_WIDEMUL_INT128)
+# if defined(SECP256K1_INT128_NATIVE)
+# include "int128_native.h"
+# elif defined(SECP256K1_INT128_STRUCT)
+# include "int128_struct.h"
+# else
+# error "Please select int128 implementation"
+# endif
+
+/* Construct an unsigned 128-bit value from a high and a low 64-bit value. */
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo);
+
+/* Multiply two unsigned 64-bit values a and b and write the result to r. */
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b);
+
+/* Multiply two unsigned 64-bit values a and b and add the result to r.
+ * The final result is taken modulo 2^128.
+ */
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b);
+
+/* Add an unsigned 64-bit value a to r.
+ * The final result is taken modulo 2^128.
+ */
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a);
+
+/* Unsigned (logical) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n);
+
+/* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a);
+
+/* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a);
+
+/* Write an unsigned 64-bit value to r. */
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a);
+
+/* Tests if r is strictly less than to 2^n.
+ * n must be strictly less than 128.
+ */
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n);
+
+/* Construct an signed 128-bit value from a high and a low 64-bit value. */
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo);
+
+/* Multiply two signed 64-bit values a and b and write the result to r. */
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b);
+
+/* Multiply two signed 64-bit values a and b and add the result to r.
+ * Overflow or underflow from the addition is undefined behaviour.
+ */
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b);
+
+/* Compute a*d - b*c from signed 64-bit values and write the result to r. */
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d);
+
+/* Signed (arithmetic) right shift.
+ * Non-constant time in b.
+ */
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b);
+
+/* Return the low 64-bits of a 128-bit value interpreted as an signed 64-bit value. */
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a);
+
+/* Write a signed 64-bit value to r. */
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a);
+
+/* Compare two 128-bit values for equality. */
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b);
+
+/* Tests if r is equal to 2^n.
+ * n must be strictly less than 127.
+ */
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n);
+
+#endif
+
+#endif
diff --git a/src/secp256k1/src/int128_impl.h b/src/secp256k1/src/int128_impl.h
new file mode 100644
index 0000000000..cfc573408a
--- /dev/null
+++ b/src/secp256k1/src/int128_impl.h
@@ -0,0 +1,18 @@
+#ifndef SECP256K1_INT128_IMPL_H
+#define SECP256K1_INT128_IMPL_H
+
+#include "util.h"
+
+#include "int128.h"
+
+#if defined(SECP256K1_WIDEMUL_INT128)
+# if defined(SECP256K1_INT128_NATIVE)
+# include "int128_native_impl.h"
+# elif defined(SECP256K1_INT128_STRUCT)
+# include "int128_struct_impl.h"
+# else
+# error "Please select int128 implementation"
+# endif
+#endif
+
+#endif
diff --git a/src/secp256k1/src/int128_native.h b/src/secp256k1/src/int128_native.h
new file mode 100644
index 0000000000..7c97aafc74
--- /dev/null
+++ b/src/secp256k1/src/int128_native.h
@@ -0,0 +1,19 @@
+#ifndef SECP256K1_INT128_NATIVE_H
+#define SECP256K1_INT128_NATIVE_H
+
+#include <stdint.h>
+#include "util.h"
+
+#if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__)
+SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
+SECP256K1_GNUC_EXT typedef __int128 int128_t;
+# define UINT128_MAX ((uint128_t)(-1))
+# define INT128_MAX ((int128_t)(UINT128_MAX >> 1))
+# define INT128_MIN (-INT128_MAX - 1)
+/* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */
+#endif
+
+typedef uint128_t secp256k1_uint128;
+typedef int128_t secp256k1_int128;
+
+#endif
diff --git a/src/secp256k1/src/int128_native_impl.h b/src/secp256k1/src/int128_native_impl.h
new file mode 100644
index 0000000000..e4b7f4106c
--- /dev/null
+++ b/src/secp256k1/src/int128_native_impl.h
@@ -0,0 +1,87 @@
+#ifndef SECP256K1_INT128_NATIVE_IMPL_H
+#define SECP256K1_INT128_NATIVE_IMPL_H
+
+#include "int128.h"
+
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
+ *r = (((uint128_t)hi) << 64) + lo;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ *r = (uint128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ *r += (uint128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) {
+ *r += a;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ *r >>= n;
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) {
+ return (uint64_t)(*a);
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) {
+ return (uint64_t)(*a >> 64);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) {
+ *r = a;
+}
+
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ return (*r >> n == 0);
+}
+
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) {
+ *r = (((uint128_t)(uint64_t)hi) << 64) + lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ *r = (int128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int128_t ab = (int128_t)a * b;
+ VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r);
+ *r += ab;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) {
+ int128_t ad = (int128_t)a * d;
+ int128_t bc = (int128_t)b * c;
+ VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc);
+ *r = ad - bc;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ *r >>= n;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) {
+ return *a;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) {
+ *r = a;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) {
+ return *a == *b;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 127);
+ return (*r == (int128_t)1 << n);
+}
+
+#endif
diff --git a/src/secp256k1/src/int128_struct.h b/src/secp256k1/src/int128_struct.h
new file mode 100644
index 0000000000..6156f82cc2
--- /dev/null
+++ b/src/secp256k1/src/int128_struct.h
@@ -0,0 +1,14 @@
+#ifndef SECP256K1_INT128_STRUCT_H
+#define SECP256K1_INT128_STRUCT_H
+
+#include <stdint.h>
+#include "util.h"
+
+typedef struct {
+ uint64_t lo;
+ uint64_t hi;
+} secp256k1_uint128;
+
+typedef secp256k1_uint128 secp256k1_int128;
+
+#endif
diff --git a/src/secp256k1/src/int128_struct_impl.h b/src/secp256k1/src/int128_struct_impl.h
new file mode 100644
index 0000000000..b5f8fb7b65
--- /dev/null
+++ b/src/secp256k1/src/int128_struct_impl.h
@@ -0,0 +1,192 @@
+#ifndef SECP256K1_INT128_STRUCT_IMPL_H
+#define SECP256K1_INT128_STRUCT_IMPL_H
+
+#include "int128.h"
+
+#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
+# include <intrin.h>
+# if defined(_M_ARM64) || defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
+/* On ARM64 MSVC, use __(u)mulh for the upper half of 64x64 multiplications.
+ (Define SECP256K1_MSVC_MULH_TEST_OVERRIDE to test this code path on X64,
+ which supports both __(u)mulh and _umul128.) */
+# if defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
+# pragma message(__FILE__ ": SECP256K1_MSVC_MULH_TEST_OVERRIDE is defined, forcing use of __(u)mulh.")
+# endif
+static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) {
+ *hi = __umulh(a, b);
+ return a * b;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) {
+ *hi = __mulh(a, b);
+ return (uint64_t)a * (uint64_t)b;
+}
+# else
+/* On x84_64 MSVC, use native _(u)mul128 for 64x64->128 multiplications. */
+# define secp256k1_umul128 _umul128
+# define secp256k1_mul128 _mul128
+# endif
+#else
+/* On other systems, emulate 64x64->128 multiplications using 32x32->64 multiplications. */
+static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) {
+ uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b;
+ uint64_t lh = (uint32_t)a * (b >> 32);
+ uint64_t hl = (a >> 32) * (uint32_t)b;
+ uint64_t hh = (a >> 32) * (b >> 32);
+ uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl;
+ *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
+ return (mid34 << 32) + (uint32_t)ll;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) {
+ uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b;
+ int64_t lh = (uint32_t)a * (b >> 32);
+ int64_t hl = (a >> 32) * (uint32_t)b;
+ int64_t hh = (a >> 32) * (b >> 32);
+ uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl;
+ *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
+ return (mid34 << 32) + (uint32_t)ll;
+}
+#endif
+
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
+ r->hi = hi;
+ r->lo = lo;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ r->lo = secp256k1_umul128(a, b, &r->hi);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ uint64_t lo, hi;
+ lo = secp256k1_umul128(a, b, &hi);
+ r->lo += lo;
+ r->hi += hi + (r->lo < lo);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) {
+ r->lo += a;
+ r->hi += r->lo < a;
+}
+
+/* Unsigned (logical) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ if (n >= 64) {
+ r->lo = r->hi >> (n-64);
+ r->hi = 0;
+ } else if (n > 0) {
+ r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
+ r->hi >>= n;
+ }
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) {
+ return a->lo;
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) {
+ return a->hi;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) {
+ r->hi = 0;
+ r->lo = a;
+}
+
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ return n >= 64 ? r->hi >> (n - 64) == 0
+ : r->hi == 0 && r->lo >> n == 0;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) {
+ r->hi = hi;
+ r->lo = lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ r->lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ r->hi = (uint64_t)hi;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ r->lo += lo;
+ hi += r->lo < lo;
+ /* Verify no overflow.
+ * If r represents a positive value (the sign bit is not set) and the value we are adding is a positive value (the sign bit is not set),
+ * then we require that the resulting value also be positive (the sign bit is not set).
+ * Note that (X <= Y) means (X implies Y) when X and Y are boolean values (i.e. 0 or 1).
+ */
+ VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi <= 0x7fffffffffffffffu));
+ /* Verify no underflow.
+ * If r represents a negative value (the sign bit is set) and the value we are adding is a negative value (the sign bit is set),
+ * then we require that the resulting value also be negative (the sign bit is set).
+ */
+ VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi > 0x7fffffffffffffffu));
+ r->hi += hi;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_dissip_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ hi += r->lo < lo;
+ /* Verify no overflow.
+ * If r represents a positive value (the sign bit is not set) and the value we are subtracting is a negative value (the sign bit is set),
+ * then we require that the resulting value also be positive (the sign bit is not set).
+ */
+ VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi <= 0x7fffffffffffffffu));
+ /* Verify no underflow.
+ * If r represents a negative value (the sign bit is set) and the value we are subtracting is a positive value (the sign sign bit is not set),
+ * then we require that the resulting value also be negative (the sign bit is set).
+ */
+ VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi > 0x7fffffffffffffffu));
+ r->hi -= hi;
+ r->lo -= lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) {
+ secp256k1_i128_mul(r, a, d);
+ secp256k1_i128_dissip_mul(r, b, c);
+}
+
+/* Signed (arithmetic) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ if (n >= 64) {
+ r->lo = (uint64_t)((int64_t)(r->hi) >> (n-64));
+ r->hi = (uint64_t)((int64_t)(r->hi) >> 63);
+ } else if (n > 0) {
+ r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
+ r->hi = (uint64_t)((int64_t)(r->hi) >> n);
+ }
+}
+
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) {
+ return (int64_t)a->lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) {
+ r->hi = (uint64_t)(a >> 63);
+ r->lo = (uint64_t)a;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) {
+ return a->hi == b->hi && a->lo == b->lo;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 127);
+ return n >= 64 ? r->hi == (uint64_t)1 << (n - 64) && r->lo == 0
+ : r->hi == 0 && r->lo == (uint64_t)1 << n;
+}
+
+#endif
diff --git a/src/secp256k1/src/modinv64_impl.h b/src/secp256k1/src/modinv64_impl.h
index 0743a9c821..50be2e5e78 100644
--- a/src/secp256k1/src/modinv64_impl.h
+++ b/src/secp256k1/src/modinv64_impl.h
@@ -7,10 +7,9 @@
#ifndef SECP256K1_MODINV64_IMPL_H
#define SECP256K1_MODINV64_IMPL_H
+#include "int128.h"
#include "modinv64.h"
-#include "util.h"
-
/* This file implements modular inversion based on the paper "Fast constant-time gcd computation and
* modular inversion" by Daniel J. Bernstein and Bo-Yin Yang.
*
@@ -18,6 +17,15 @@
* implementation for N=62, using 62-bit signed limbs represented as int64_t.
*/
+/* Data type for transition matrices (see section 3 of explanation).
+ *
+ * t = [ u v ]
+ * [ q r ]
+ */
+typedef struct {
+ int64_t u, v, q, r;
+} secp256k1_modinv64_trans2x2;
+
#ifdef VERIFY
/* Helper function to compute the absolute value of an int64_t.
* (we don't use abs/labs/llabs as it depends on the int sizes). */
@@ -32,15 +40,17 @@ static const secp256k1_modinv64_signed62 SECP256K1_SIGNED62_ONE = {{1}};
/* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^62). */
static void secp256k1_modinv64_mul_62(secp256k1_modinv64_signed62 *r, const secp256k1_modinv64_signed62 *a, int alen, int64_t factor) {
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
- int128_t c = 0;
+ secp256k1_int128 c, d;
int i;
+ secp256k1_i128_from_i64(&c, 0);
for (i = 0; i < 4; ++i) {
- if (i < alen) c += (int128_t)a->v[i] * factor;
- r->v[i] = (int64_t)c & M62; c >>= 62;
+ if (i < alen) secp256k1_i128_accum_mul(&c, a->v[i], factor);
+ r->v[i] = secp256k1_i128_to_i64(&c) & M62; secp256k1_i128_rshift(&c, 62);
}
- if (4 < alen) c += (int128_t)a->v[4] * factor;
- VERIFY_CHECK(c == (int64_t)c);
- r->v[4] = (int64_t)c;
+ if (4 < alen) secp256k1_i128_accum_mul(&c, a->v[4], factor);
+ secp256k1_i128_from_i64(&d, secp256k1_i128_to_i64(&c));
+ VERIFY_CHECK(secp256k1_i128_eq_var(&c, &d));
+ r->v[4] = secp256k1_i128_to_i64(&c);
}
/* Return -1 for a<b*factor, 0 for a==b*factor, 1 for a>b*factor. A has alen limbs; b has 5. */
@@ -60,6 +70,13 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
}
return 0;
}
+
+/* Check if the determinant of t is equal to 1 << n. */
+static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n) {
+ secp256k1_int128 a;
+ secp256k1_i128_det(&a, t->u, t->v, t->q, t->r);
+ return secp256k1_i128_check_pow2(&a, n);
+}
#endif
/* Take as input a signed62 number in range (-2*modulus,modulus), and add a multiple of the modulus
@@ -136,15 +153,6 @@ static void secp256k1_modinv64_normalize_62(secp256k1_modinv64_signed62 *r, int6
#endif
}
-/* Data type for transition matrices (see section 3 of explanation).
- *
- * t = [ u v ]
- * [ q r ]
- */
-typedef struct {
- int64_t u, v, q, r;
-} secp256k1_modinv64_trans2x2;
-
/* Compute the transition matrix and eta for 59 divsteps (where zeta=-(delta+1/2)).
* Note that the transformation matrix is scaled by 2^62 and not 2^59.
*
@@ -203,13 +211,15 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
t->v = (int64_t)v;
t->q = (int64_t)q;
t->r = (int64_t)r;
+#ifdef VERIFY
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2, the
* aggregate of 59 of them will have determinant 2^59. Multiplying with the initial
* 8*identity (which has determinant 2^6) means the overall outputs has determinant
* 2^65. */
- VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 65);
+ VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 65));
+#endif
return zeta;
}
@@ -286,11 +296,13 @@ static int64_t secp256k1_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint
t->v = (int64_t)v;
t->q = (int64_t)q;
t->r = (int64_t)r;
+#ifdef VERIFY
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2, the
* aggregate of 62 of them will have determinant 2^62. */
- VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 62);
+ VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62));
+#endif
return eta;
}
@@ -307,7 +319,7 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
const int64_t e0 = e->v[0], e1 = e->v[1], e2 = e->v[2], e3 = e->v[3], e4 = e->v[4];
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
int64_t md, me, sd, se;
- int128_t cd, ce;
+ secp256k1_int128 cd, ce;
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */
@@ -324,54 +336,64 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
md = (u & sd) + (v & se);
me = (q & sd) + (r & se);
/* Begin computing t*[d,e]. */
- cd = (int128_t)u * d0 + (int128_t)v * e0;
- ce = (int128_t)q * d0 + (int128_t)r * e0;
+ secp256k1_i128_mul(&cd, u, d0);
+ secp256k1_i128_accum_mul(&cd, v, e0);
+ secp256k1_i128_mul(&ce, q, d0);
+ secp256k1_i128_accum_mul(&ce, r, e0);
/* Correct md,me so that t*[d,e]+modulus*[md,me] has 62 zero bottom bits. */
- md -= (modinfo->modulus_inv62 * (uint64_t)cd + md) & M62;
- me -= (modinfo->modulus_inv62 * (uint64_t)ce + me) & M62;
+ md -= (modinfo->modulus_inv62 * (uint64_t)secp256k1_i128_to_i64(&cd) + md) & M62;
+ me -= (modinfo->modulus_inv62 * (uint64_t)secp256k1_i128_to_i64(&ce) + me) & M62;
/* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */
- cd += (int128_t)modinfo->modulus.v[0] * md;
- ce += (int128_t)modinfo->modulus.v[0] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[0], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[0], me);
/* Verify that the low 62 bits of the computation are indeed zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cd & M62) == 0); cd >>= 62;
- VERIFY_CHECK(((int64_t)ce & M62) == 0); ce >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cd) & M62) == 0); secp256k1_i128_rshift(&cd, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&ce) & M62) == 0); secp256k1_i128_rshift(&ce, 62);
/* Compute limb 1 of t*[d,e]+modulus*[md,me], and store it as output limb 0 (= down shift). */
- cd += (int128_t)u * d1 + (int128_t)v * e1;
- ce += (int128_t)q * d1 + (int128_t)r * e1;
+ secp256k1_i128_accum_mul(&cd, u, d1);
+ secp256k1_i128_accum_mul(&cd, v, e1);
+ secp256k1_i128_accum_mul(&ce, q, d1);
+ secp256k1_i128_accum_mul(&ce, r, e1);
if (modinfo->modulus.v[1]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[1] * md;
- ce += (int128_t)modinfo->modulus.v[1] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[1], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[1], me);
}
- d->v[0] = (int64_t)cd & M62; cd >>= 62;
- e->v[0] = (int64_t)ce & M62; ce >>= 62;
+ d->v[0] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[0] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 2 of t*[d,e]+modulus*[md,me], and store it as output limb 1. */
- cd += (int128_t)u * d2 + (int128_t)v * e2;
- ce += (int128_t)q * d2 + (int128_t)r * e2;
+ secp256k1_i128_accum_mul(&cd, u, d2);
+ secp256k1_i128_accum_mul(&cd, v, e2);
+ secp256k1_i128_accum_mul(&ce, q, d2);
+ secp256k1_i128_accum_mul(&ce, r, e2);
if (modinfo->modulus.v[2]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[2] * md;
- ce += (int128_t)modinfo->modulus.v[2] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[2], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[2], me);
}
- d->v[1] = (int64_t)cd & M62; cd >>= 62;
- e->v[1] = (int64_t)ce & M62; ce >>= 62;
+ d->v[1] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[1] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 3 of t*[d,e]+modulus*[md,me], and store it as output limb 2. */
- cd += (int128_t)u * d3 + (int128_t)v * e3;
- ce += (int128_t)q * d3 + (int128_t)r * e3;
+ secp256k1_i128_accum_mul(&cd, u, d3);
+ secp256k1_i128_accum_mul(&cd, v, e3);
+ secp256k1_i128_accum_mul(&ce, q, d3);
+ secp256k1_i128_accum_mul(&ce, r, e3);
if (modinfo->modulus.v[3]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[3] * md;
- ce += (int128_t)modinfo->modulus.v[3] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[3], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[3], me);
}
- d->v[2] = (int64_t)cd & M62; cd >>= 62;
- e->v[2] = (int64_t)ce & M62; ce >>= 62;
+ d->v[2] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[2] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 4 of t*[d,e]+modulus*[md,me], and store it as output limb 3. */
- cd += (int128_t)u * d4 + (int128_t)v * e4;
- ce += (int128_t)q * d4 + (int128_t)r * e4;
- cd += (int128_t)modinfo->modulus.v[4] * md;
- ce += (int128_t)modinfo->modulus.v[4] * me;
- d->v[3] = (int64_t)cd & M62; cd >>= 62;
- e->v[3] = (int64_t)ce & M62; ce >>= 62;
+ secp256k1_i128_accum_mul(&cd, u, d4);
+ secp256k1_i128_accum_mul(&cd, v, e4);
+ secp256k1_i128_accum_mul(&ce, q, d4);
+ secp256k1_i128_accum_mul(&ce, r, e4);
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[4], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[4], me);
+ d->v[3] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[3] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* What remains is limb 5 of t*[d,e]+modulus*[md,me]; store it as output limb 4. */
- d->v[4] = (int64_t)cd;
- e->v[4] = (int64_t)ce;
+ d->v[4] = secp256k1_i128_to_i64(&cd);
+ e->v[4] = secp256k1_i128_to_i64(&ce);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */
@@ -389,36 +411,46 @@ static void secp256k1_modinv64_update_fg_62(secp256k1_modinv64_signed62 *f, secp
const int64_t f0 = f->v[0], f1 = f->v[1], f2 = f->v[2], f3 = f->v[3], f4 = f->v[4];
const int64_t g0 = g->v[0], g1 = g->v[1], g2 = g->v[2], g3 = g->v[3], g4 = g->v[4];
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
- int128_t cf, cg;
+ secp256k1_int128 cf, cg;
/* Start computing t*[f,g]. */
- cf = (int128_t)u * f0 + (int128_t)v * g0;
- cg = (int128_t)q * f0 + (int128_t)r * g0;
+ secp256k1_i128_mul(&cf, u, f0);
+ secp256k1_i128_accum_mul(&cf, v, g0);
+ secp256k1_i128_mul(&cg, q, f0);
+ secp256k1_i128_accum_mul(&cg, r, g0);
/* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
- VERIFY_CHECK(((int64_t)cg & M62) == 0); cg >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62);
/* Compute limb 1 of t*[f,g], and store it as output limb 0 (= down shift). */
- cf += (int128_t)u * f1 + (int128_t)v * g1;
- cg += (int128_t)q * f1 + (int128_t)r * g1;
- f->v[0] = (int64_t)cf & M62; cf >>= 62;
- g->v[0] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f1);
+ secp256k1_i128_accum_mul(&cf, v, g1);
+ secp256k1_i128_accum_mul(&cg, q, f1);
+ secp256k1_i128_accum_mul(&cg, r, g1);
+ f->v[0] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[0] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 2 of t*[f,g], and store it as output limb 1. */
- cf += (int128_t)u * f2 + (int128_t)v * g2;
- cg += (int128_t)q * f2 + (int128_t)r * g2;
- f->v[1] = (int64_t)cf & M62; cf >>= 62;
- g->v[1] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f2);
+ secp256k1_i128_accum_mul(&cf, v, g2);
+ secp256k1_i128_accum_mul(&cg, q, f2);
+ secp256k1_i128_accum_mul(&cg, r, g2);
+ f->v[1] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[1] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 3 of t*[f,g], and store it as output limb 2. */
- cf += (int128_t)u * f3 + (int128_t)v * g3;
- cg += (int128_t)q * f3 + (int128_t)r * g3;
- f->v[2] = (int64_t)cf & M62; cf >>= 62;
- g->v[2] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f3);
+ secp256k1_i128_accum_mul(&cf, v, g3);
+ secp256k1_i128_accum_mul(&cg, q, f3);
+ secp256k1_i128_accum_mul(&cg, r, g3);
+ f->v[2] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[2] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 4 of t*[f,g], and store it as output limb 3. */
- cf += (int128_t)u * f4 + (int128_t)v * g4;
- cg += (int128_t)q * f4 + (int128_t)r * g4;
- f->v[3] = (int64_t)cf & M62; cf >>= 62;
- g->v[3] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f4);
+ secp256k1_i128_accum_mul(&cf, v, g4);
+ secp256k1_i128_accum_mul(&cg, q, f4);
+ secp256k1_i128_accum_mul(&cg, r, g4);
+ f->v[3] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[3] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* What remains is limb 5 of t*[f,g]; store it as output limb 4. */
- f->v[4] = (int64_t)cf;
- g->v[4] = (int64_t)cg;
+ f->v[4] = secp256k1_i128_to_i64(&cf);
+ g->v[4] = secp256k1_i128_to_i64(&cg);
}
/* Compute (t/2^62) * [f, g], where t is a transition matrix for 62 divsteps.
@@ -431,30 +463,34 @@ static void secp256k1_modinv64_update_fg_62_var(int len, secp256k1_modinv64_sign
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
int64_t fi, gi;
- int128_t cf, cg;
+ secp256k1_int128 cf, cg;
int i;
VERIFY_CHECK(len > 0);
/* Start computing t*[f,g]. */
fi = f->v[0];
gi = g->v[0];
- cf = (int128_t)u * fi + (int128_t)v * gi;
- cg = (int128_t)q * fi + (int128_t)r * gi;
+ secp256k1_i128_mul(&cf, u, fi);
+ secp256k1_i128_accum_mul(&cf, v, gi);
+ secp256k1_i128_mul(&cg, q, fi);
+ secp256k1_i128_accum_mul(&cg, r, gi);
/* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
- VERIFY_CHECK(((int64_t)cg & M62) == 0); cg >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62);
/* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting
* down by 62 bits). */
for (i = 1; i < len; ++i) {
fi = f->v[i];
gi = g->v[i];
- cf += (int128_t)u * fi + (int128_t)v * gi;
- cg += (int128_t)q * fi + (int128_t)r * gi;
- f->v[i - 1] = (int64_t)cf & M62; cf >>= 62;
- g->v[i - 1] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, fi);
+ secp256k1_i128_accum_mul(&cf, v, gi);
+ secp256k1_i128_accum_mul(&cg, q, fi);
+ secp256k1_i128_accum_mul(&cg, r, gi);
+ f->v[i - 1] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[i - 1] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
}
/* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */
- f->v[len - 1] = (int64_t)cf;
- g->v[len - 1] = (int64_t)cg;
+ f->v[len - 1] = secp256k1_i128_to_i64(&cf);
+ g->v[len - 1] = secp256k1_i128_to_i64(&cg);
}
/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */
diff --git a/src/secp256k1/src/modules/ecdh/bench_impl.h b/src/secp256k1/src/modules/ecdh/bench_impl.h
index 94d833462f..8df15bcf43 100644
--- a/src/secp256k1/src/modules/ecdh/bench_impl.h
+++ b/src/secp256k1/src/modules/ecdh/bench_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_ECDH_BENCH_H
#define SECP256K1_MODULE_ECDH_BENCH_H
-#include "../include/secp256k1_ecdh.h"
+#include "../../../include/secp256k1_ecdh.h"
typedef struct {
secp256k1_context *ctx;
diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h
index 10b7075c38..ce644d572a 100644
--- a/src/secp256k1/src/modules/ecdh/tests_impl.h
+++ b/src/secp256k1/src/modules/ecdh/tests_impl.h
@@ -26,7 +26,7 @@ int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, con
void test_ecdh_api(void) {
/* Setup context that just counts errors */
- secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_pubkey point;
unsigned char res[32];
unsigned char s_one[32] = { 0 };
diff --git a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
index d4a2f5bdf4..5ecc90d50f 100644
--- a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
@@ -7,8 +7,8 @@
#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H
#define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H
-#include "src/modules/extrakeys/main_impl.h"
#include "../../../include/secp256k1_extrakeys.h"
+#include "main_impl.h"
static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) {
secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1];
diff --git a/src/secp256k1/src/modules/extrakeys/tests_impl.h b/src/secp256k1/src/modules/extrakeys/tests_impl.h
index c8a99f4466..8030aedad6 100644
--- a/src/secp256k1/src/modules/extrakeys/tests_impl.h
+++ b/src/secp256k1/src/modules/extrakeys/tests_impl.h
@@ -9,11 +9,9 @@
#include "../../../include/secp256k1_extrakeys.h"
-static secp256k1_context* api_test_context(int flags, int *ecount) {
- secp256k1_context *ctx0 = secp256k1_context_create(flags);
+static void set_counting_callbacks(secp256k1_context *ctx0, int *ecount) {
secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount);
secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount);
- return ctx0;
}
void test_xonly_pubkey(void) {
@@ -31,28 +29,25 @@ void test_xonly_pubkey(void) {
int i;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
secp256k1_testrand256(sk);
memset(ones32, 0xFF, 32);
secp256k1_testrand256(xy_sk);
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
/* Test xonly_pubkey_from_pubkey */
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, NULL, &pk_parity, &pk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, NULL) == 0);
CHECK(ecount == 2);
memset(&pk, 0, sizeof(pk));
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 0);
CHECK(ecount == 3);
/* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */
@@ -78,9 +73,9 @@ void test_xonly_pubkey(void) {
/* Test xonly_pubkey_serialize and xonly_pubkey_parse */
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, NULL, &xonly_pk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, NULL) == 0);
CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0);
CHECK(ecount == 2);
{
@@ -88,20 +83,20 @@ void test_xonly_pubkey(void) {
* special casing. */
secp256k1_xonly_pubkey pk_tmp;
memset(&pk_tmp, 0, sizeof(pk_tmp));
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &pk_tmp) == 0);
}
/* pubkey_load called illegal callback */
CHECK(ecount == 3);
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, NULL, buf32) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, NULL) == 0);
CHECK(ecount == 2);
/* Serialization and parse roundtrip */
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1);
CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0);
@@ -109,11 +104,11 @@ void test_xonly_pubkey(void) {
/* Test parsing invalid field elements */
memset(&xonly_pk, 1, sizeof(xonly_pk));
/* Overflowing field element */
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, ones32) == 0);
CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
memset(&xonly_pk, 1, sizeof(xonly_pk));
/* There's no point with x-coordinate 0 on secp256k1 */
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, zeros64) == 0);
CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
/* If a random 32-byte string can not be parsed with ec_pubkey_parse
* (because interpreted as X coordinate it does not correspond to a point on
@@ -131,10 +126,6 @@ void test_xonly_pubkey(void) {
}
}
CHECK(ecount == 2);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void test_xonly_pubkey_comparison(void) {
@@ -149,29 +140,28 @@ void test_xonly_pubkey_comparison(void) {
secp256k1_xonly_pubkey pk1;
secp256k1_xonly_pubkey pk2;
int ecount = 0;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- CHECK(secp256k1_xonly_pubkey_parse(none, &pk1, pk1_ser) == 1);
- CHECK(secp256k1_xonly_pubkey_parse(none, &pk2, pk2_ser) == 1);
+ set_counting_callbacks(ctx, &ecount);
- CHECK(secp256k1_xonly_pubkey_cmp(none, NULL, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk1, pk1_ser) == 1);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk2, pk2_ser) == 1);
+
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, NULL, &pk2) < 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, NULL) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, NULL) > 0);
CHECK(ecount == 2);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk2) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk1) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk1) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk2) == 0);
CHECK(ecount == 2);
memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk2) < 0);
CHECK(ecount == 3);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk1) == 0);
CHECK(ecount == 5);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk1) > 0);
CHECK(ecount == 6);
-
- secp256k1_context_destroy(none);
}
void test_xonly_pubkey_tweak(void) {
@@ -186,39 +176,38 @@ void test_xonly_pubkey_tweak(void) {
int i;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
memset(overflows, 0xff, sizeof(overflows));
secp256k1_testrand256(tweak);
secp256k1_testrand256(sk);
CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, NULL, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, NULL, tweak) == 0);
CHECK(ecount == 2);
/* NULL internal_xonly_pk zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 3);
/* NULL tweak zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* Invalid tweak zeroes the output_pk */
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* A zero tweak is fine */
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, zeros64) == 1);
/* Fails if the resulting key was infinity */
for (i = 0; i < count; i++) {
@@ -228,8 +217,8 @@ void test_xonly_pubkey_tweak(void) {
secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL);
secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak);
secp256k1_scalar_get_b32(tweak, &scalar_tweak);
- CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0)
- || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0));
+ CHECK((secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, sk) == 0)
+ || (secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 0));
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
}
@@ -237,13 +226,9 @@ void test_xonly_pubkey_tweak(void) {
memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk));
secp256k1_testrand256(tweak);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void test_xonly_pubkey_tweak_check(void) {
@@ -260,33 +245,32 @@ void test_xonly_pubkey_tweak_check(void) {
unsigned char tweak[32];
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
memset(overflows, 0xff, sizeof(overflows));
secp256k1_testrand256(tweak);
secp256k1_testrand256(sk);
CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
/* invalid pk_parity value */
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, 2, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, NULL, tweak) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 3);
memset(tweak, 1, sizeof(tweak));
@@ -307,10 +291,6 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(ecount == 3);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
/* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1
@@ -356,12 +336,10 @@ void test_keypair(void) {
secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
int pk_parity, pk_parity_tmp;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
- secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
+
+ set_counting_callbacks(ctx, &ecount);
+ set_counting_callbacks(sttc, &ecount);
CHECK(sizeof(zeros96) == sizeof(keypair));
memset(overflows, 0xFF, sizeof(overflows));
@@ -369,75 +347,75 @@ void test_keypair(void) {
/* Test keypair_create */
ecount = 0;
secp256k1_testrand256(sk);
- CHECK(secp256k1_keypair_create(none, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
+ CHECK(secp256k1_keypair_create(ctx, NULL, sk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, NULL) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_keypair_create(sttc, &keypair, sk) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 3);
/* Invalid secret key */
- CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, zeros96) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
- CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, overflows) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
/* Test keypair_pub */
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
- CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, NULL, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* Using an invalid keypair is fine for keypair_pub */
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* keypair holds the same pubkey as pubkey_create */
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, &pk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0);
/** Test keypair_xonly_pub **/
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, NULL, &pk_parity, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, NULL, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
/* Using an invalid keypair will set the xonly_pk to 0 (first reset
* xonly_pk). */
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
CHECK(ecount == 3);
/** keypair holds the same xonly pubkey as pubkey_create **/
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0);
CHECK(pk_parity == pk_parity_tmp);
@@ -445,27 +423,23 @@ void test_keypair(void) {
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
- CHECK(secp256k1_keypair_sec(none, NULL, &keypair) == 0);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, NULL, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, NULL) == 0);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0);
/* keypair returns the same seckey it got */
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0);
/* Using an invalid keypair is fine for keypair_seckey */
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
secp256k1_context_destroy(sttc);
}
@@ -477,9 +451,8 @@ void test_keypair_add(void) {
unsigned char tweak[32];
int i;
int ecount = 0;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
CHECK(sizeof(zeros96) == sizeof(keypair));
secp256k1_testrand256(sk);
@@ -487,14 +460,14 @@ void test_keypair_add(void) {
memset(overflows, 0xFF, 32);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, NULL, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, NULL) == 0);
CHECK(ecount == 2);
/* This does not set the keypair to zeroes */
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);
@@ -530,18 +503,18 @@ void test_keypair_add(void) {
memset(&keypair, 0, sizeof(keypair));
secp256k1_testrand256(tweak);
ecount = 0;
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0);
/* Only seckey part of keypair invalid */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
memset(&keypair, 0, 32);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 2);
/* Only pubkey part of keypair invalid */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
memset(&keypair.data[32], 0, 64);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 3);
/* Check that the keypair_tweak_add implementation is correct */
@@ -570,13 +543,10 @@ void test_keypair_add(void) {
CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
/* Check that the secret key in the keypair is tweaked correctly */
- CHECK(secp256k1_keypair_sec(none, sk32, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk32, &keypair) == 1);
CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, sk32) == 1);
CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
}
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void run_extrakeys_tests(void) {
diff --git a/src/secp256k1/src/modules/recovery/bench_impl.h b/src/secp256k1/src/modules/recovery/bench_impl.h
index 4a9e886910..ffa00df479 100644
--- a/src/secp256k1/src/modules/recovery/bench_impl.h
+++ b/src/secp256k1/src/modules/recovery/bench_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_RECOVERY_BENCH_H
#define SECP256K1_MODULE_RECOVERY_BENCH_H
-#include "../include/secp256k1_recovery.h"
+#include "../../../include/secp256k1_recovery.h"
typedef struct {
secp256k1_context *ctx;
@@ -52,7 +52,7 @@ void run_recovery_bench(int iters, int argc, char** argv) {
bench_recover_data data;
int d = argc == 1;
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters);
diff --git a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
index 590a972ed3..ed9386b6f8 100644
--- a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H
#define SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H
-#include "src/modules/recovery/main_impl.h"
+#include "main_impl.h"
#include "../../../include/secp256k1_recovery.h"
void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) {
diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h
index abf62f7f3a..0ff9294e38 100644
--- a/src/secp256k1/src/modules/recovery/tests_impl.h
+++ b/src/secp256k1/src/modules/recovery/tests_impl.h
@@ -30,11 +30,7 @@ static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned c
void test_ecdsa_recovery_api(void) {
/* Setup contexts that just count errors */
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
secp256k1_pubkey pubkey;
secp256k1_pubkey recpubkey;
secp256k1_ecdsa_signature normal_sig;
@@ -50,15 +46,9 @@ void test_ecdsa_recovery_api(void) {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
/* Construct and verify corresponding public key. */
@@ -67,89 +57,73 @@ void test_ecdsa_recovery_api(void) {
/* Check bad contexts and NULLs for signing */
ecount = 0;
- CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, NULL, message, privkey, NULL, NULL) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, NULL, privkey, NULL, NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, NULL, NULL, NULL) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_ecdsa_sign_recoverable(sttc, &recsig, message, privkey, NULL, NULL) == 0);
CHECK(ecount == 4);
/* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
- secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL);
+ secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, recovery_test_nonce_function, NULL);
CHECK(ecount == 4);
/* These will all fail, but not in ARG_CHECK way */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, zero_privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, over_privkey, NULL, NULL) == 0);
/* This one will succeed. */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
CHECK(ecount == 4);
/* Check signing with a goofy nonce function */
/* Check bad contexts and NULLs for recovery */
ecount = 0;
- CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, NULL, &recsig, message) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, NULL, message) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &recsig, NULL) == 0);
CHECK(ecount == 3);
/* Check NULLs for conversion */
- CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(ctx, &normal_sig, message, privkey, NULL, NULL) == 1);
ecount = 0;
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, NULL, &recsig) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, &recsig) == 1);
/* Check NULLs for de/serialization */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
ecount = 0;
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, NULL, &recid, &recsig) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, NULL, &recsig) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recsig) == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, NULL, sig, recid) == 0);
CHECK(ecount == 4);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, NULL, recid) == 0);
CHECK(ecount == 5);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, -1) == 0);
CHECK(ecount == 6);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, 5) == 0);
CHECK(ecount == 7);
/* overflow in signature will fail but not affect ecount */
memcpy(sig, over_privkey, 32);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, recid) == 0);
CHECK(ecount == 7);
/* cleanup */
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
secp256k1_context_destroy(sttc);
}
diff --git a/src/secp256k1/src/modules/schnorrsig/bench_impl.h b/src/secp256k1/src/modules/schnorrsig/bench_impl.h
index 41f393c84d..f0b0d3de75 100644
--- a/src/secp256k1/src/modules/schnorrsig/bench_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/bench_impl.h
@@ -50,7 +50,7 @@ void run_schnorrsig_bench(int iters, int argc, char** argv) {
bench_schnorrsig_data data;
int d = argc == 1;
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
@@ -91,10 +91,12 @@ void run_schnorrsig_bench(int iters, int argc, char** argv) {
free((void *)data.msgs[i]);
free((void *)data.sigs[i]);
}
- free(data.keypairs);
- free(data.pk);
- free(data.msgs);
- free(data.sigs);
+
+ /* Casting to (void *) avoids a stupid warning in MSVC. */
+ free((void *)data.keypairs);
+ free((void *)data.pk);
+ free((void *)data.msgs);
+ free((void *)data.sigs);
secp256k1_context_destroy(data.ctx);
}
diff --git a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
index d8df9dd2df..55f9028a63 100644
--- a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
@@ -8,7 +8,7 @@
#define SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H
#include "../../../include/secp256k1_schnorrsig.h"
-#include "src/modules/schnorrsig/main_impl.h"
+#include "main_impl.h"
static const unsigned char invalid_pubkey_bytes[][32] = {
/* 0 */
diff --git a/src/secp256k1/src/modules/schnorrsig/tests_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
index 25840b8fa7..06cc097cc1 100644
--- a/src/secp256k1/src/modules/schnorrsig/tests_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
@@ -128,22 +128,12 @@ void test_schnorrsig_api(void) {
secp256k1_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL};
/** setup **/
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
int ecount;
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
secp256k1_testrand256(sk1);
@@ -160,70 +150,54 @@ void test_schnorrsig_api(void) {
/** main test body **/
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign32(none, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypairs[0], NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(vrfy, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(sign, NULL, msg, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, NULL, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, NULL, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, NULL, &keypairs[0], NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, NULL, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, NULL, NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &invalid_keypair, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &invalid_keypair, NULL) == 0);
CHECK(ecount == 4);
CHECK(secp256k1_schnorrsig_sign32(sttc, sig, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 5);
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
CHECK(ecount == 4);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
CHECK(ecount == 4);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
CHECK(ecount == 5);
CHECK(secp256k1_schnorrsig_sign_custom(sttc, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 6);
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, NULL, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, 0, &pk[0]) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &zero_pk) == 0);
CHECK(ecount == 4);
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
secp256k1_context_destroy(sttc);
}
diff --git a/src/secp256k1/src/precompute_ecmult.c b/src/secp256k1/src/precompute_ecmult.c
index 5ccbcb3c57..2aa37b8fe3 100644
--- a/src/secp256k1/src/precompute_ecmult.c
+++ b/src/secp256k1/src/precompute_ecmult.c
@@ -14,10 +14,13 @@
#endif
#include "../include/secp256k1.h"
+
#include "assumptions.h"
#include "util.h"
+
#include "field_impl.h"
#include "group_impl.h"
+#include "int128_impl.h"
#include "ecmult.h"
#include "ecmult_compute_table_impl.h"
diff --git a/src/secp256k1/src/precompute_ecmult_gen.c b/src/secp256k1/src/precompute_ecmult_gen.c
index 7c6359c402..a4ec8e0dc6 100644
--- a/src/secp256k1/src/precompute_ecmult_gen.c
+++ b/src/secp256k1/src/precompute_ecmult_gen.c
@@ -8,9 +8,12 @@
#include <stdio.h>
#include "../include/secp256k1.h"
+
#include "assumptions.h"
#include "util.h"
+
#include "group.h"
+#include "int128_impl.h"
#include "ecmult_gen.h"
#include "ecmult_gen_compute_table_impl.h"
diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h
index a1def26fca..4588219d3a 100644
--- a/src/secp256k1/src/scalar_4x64_impl.h
+++ b/src/secp256k1/src/scalar_4x64_impl.h
@@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
+#include "int128.h"
#include "modinv64_impl.h"
/* Limbs of the secp256k1 order. */
@@ -69,50 +70,61 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal
}
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) {
- uint128_t t;
+ secp256k1_uint128 t;
VERIFY_CHECK(overflow <= 1);
- t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0;
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1;
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2;
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint64_t)r->d[3];
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
+ secp256k1_u128_from_u64(&t, r->d[0]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_0);
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_1);
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_2);
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3]);
+ r->d[3] = secp256k1_u128_to_u64(&t);
return overflow;
}
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
int overflow;
- uint128_t t = (uint128_t)a->d[0] + b->d[0];
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[1] + b->d[1];
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[2] + b->d[2];
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[3] + b->d[3];
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- overflow = t + secp256k1_scalar_check_overflow(r);
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, a->d[0]);
+ secp256k1_u128_accum_u64(&t, b->d[0]);
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[1]);
+ secp256k1_u128_accum_u64(&t, b->d[1]);
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[2]);
+ secp256k1_u128_accum_u64(&t, b->d[2]);
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[3]);
+ secp256k1_u128_accum_u64(&t, b->d[3]);
+ r->d[3] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ overflow = secp256k1_u128_to_u64(&t) + secp256k1_scalar_check_overflow(r);
VERIFY_CHECK(overflow == 0 || overflow == 1);
secp256k1_scalar_reduce(r, overflow);
return overflow;
}
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
- uint128_t t;
+ secp256k1_uint128 t;
VERIFY_CHECK(bit < 256);
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
- t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
+ secp256k1_u128_from_u64(&t, r->d[0]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
+ r->d[3] = secp256k1_u128_to_u64(&t);
#ifdef VERIFY
- VERIFY_CHECK((t >> 64) == 0);
- VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
+ VERIFY_CHECK(secp256k1_u128_hi_u64(&t) == 0);
#endif
}
@@ -141,14 +153,19 @@ SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a)
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0);
- uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1;
- r->d[0] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[1]) + SECP256K1_N_1;
- r->d[1] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[2]) + SECP256K1_N_2;
- r->d[2] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[3]) + SECP256K1_N_3;
- r->d[3] = t & nonzero;
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, ~a->d[0]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_0 + 1);
+ r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[1]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_1);
+ r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[2]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_2);
+ r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[3]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_3);
+ r->d[3] = secp256k1_u128_to_u64(&t) & nonzero;
}
SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
@@ -172,14 +189,19 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
uint64_t mask = !flag - 1;
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
- uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
- r->d[0] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask);
- r->d[1] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask);
- r->d[2] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask);
- r->d[3] = t & nonzero;
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, r->d[0] ^ mask);
+ secp256k1_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask);
+ r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_1 & mask);
+ r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_2 & mask);
+ r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_3 & mask);
+ r->d[3] = secp256k1_u128_to_u64(&t) & nonzero;
return 2 * (mask == 0) - 1;
}
@@ -189,9 +211,10 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define muladd(a,b) { \
uint64_t tl, th; \
{ \
- uint128_t t = (uint128_t)a * b; \
- th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
- tl = t; \
+ secp256k1_uint128 t; \
+ secp256k1_u128_mul(&t, a, b); \
+ th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \
+ tl = secp256k1_u128_to_u64(&t); \
} \
c0 += tl; /* overflow is handled on the next line */ \
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -204,9 +227,10 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define muladd_fast(a,b) { \
uint64_t tl, th; \
{ \
- uint128_t t = (uint128_t)a * b; \
- th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
- tl = t; \
+ secp256k1_uint128 t; \
+ secp256k1_u128_mul(&t, a, b); \
+ th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \
+ tl = secp256k1_u128_to_u64(&t); \
} \
c0 += tl; /* overflow is handled on the next line */ \
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -484,8 +508,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
: "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1)
: "rax", "rdx", "r8", "r9", "r10", "cc", "memory");
#else
- uint128_t c;
- uint64_t c0, c1, c2;
+ secp256k1_uint128 c128;
+ uint64_t c, c0, c1, c2;
uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
uint64_t m0, m1, m2, m3, m4, m5;
uint32_t m6;
@@ -542,14 +566,18 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
/* Reduce 258 bits into 256. */
/* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
- c = p0 + (uint128_t)SECP256K1_N_C_0 * p4;
- r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p1 + (uint128_t)SECP256K1_N_C_1 * p4;
- r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p2 + (uint128_t)p4;
- r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p3;
- r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
+ secp256k1_u128_from_u64(&c128, p0);
+ secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_0, p4);
+ r->d[0] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p1);
+ secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_1, p4);
+ r->d[1] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p2);
+ secp256k1_u128_accum_u64(&c128, p4);
+ r->d[2] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p3);
+ r->d[3] = secp256k1_u128_to_u64(&c128);
+ c = secp256k1_u128_hi_u64(&c128);
#endif
/* Final reduction of r. */
diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h
index 688e18eb66..f71a20b963 100644
--- a/src/secp256k1/src/scratch_impl.h
+++ b/src/secp256k1/src/scratch_impl.h
@@ -25,11 +25,11 @@ static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* err
static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) {
if (scratch != NULL) {
- VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space");
return;
}
+ VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
memset(scratch->magic, 0, sizeof(scratch->magic));
free(scratch);
}
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index 8f34c35283..5ed3824161 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -4,6 +4,17 @@
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
+/* This is a C project. It should not be compiled with a C++ compiler,
+ * and we error out if we detect one.
+ *
+ * We still want to be able to test the project with a C++ compiler
+ * because it is still good to know if this will lead to real trouble, so
+ * there is a possibility to override the check. But be warned that
+ * compiling with a C++ compiler is not supported. */
+#if defined(__cplusplus) && !defined(SECP256K1_CPLUSPLUS_TEST_OVERRIDE)
+#error Trying to compile a C project with a C++ compiler.
+#endif
+
#define SECP256K1_BUILD
#include "../include/secp256k1.h"
@@ -11,6 +22,7 @@
#include "assumptions.h"
#include "util.h"
+
#include "field_impl.h"
#include "scalar_impl.h"
#include "group_impl.h"
@@ -20,6 +32,7 @@
#include "ecdsa_impl.h"
#include "eckey_impl.h"
#include "hash_impl.h"
+#include "int128_impl.h"
#include "scratch_impl.h"
#include "selftest.h"
@@ -44,6 +57,8 @@
} \
} while(0)
+/* Note that whenever you change the context struct, you must also change the
+ * context_eq function. */
struct secp256k1_context_struct {
secp256k1_ecmult_gen_context ecmult_gen_ctx;
secp256k1_callback illegal_callback;
@@ -51,13 +66,20 @@ struct secp256k1_context_struct {
int declassify;
};
-static const secp256k1_context secp256k1_context_no_precomp_ = {
+static const secp256k1_context secp256k1_context_static_ = {
{ 0 },
{ secp256k1_default_illegal_callback_fn, 0 },
{ secp256k1_default_error_callback_fn, 0 },
0
};
-const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
+const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_;
+const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_;
+
+void secp256k1_selftest(void) {
+ if (!secp256k1_selftest_passes()) {
+ secp256k1_callback_call(&default_error_callback, "self test failed");
+ }
+}
size_t secp256k1_context_preallocated_size(unsigned int flags) {
size_t ret = sizeof(secp256k1_context);
@@ -83,9 +105,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
size_t prealloc_size;
secp256k1_context* ret;
- if (!secp256k1_selftest()) {
- secp256k1_callback_call(&default_error_callback, "self test failed");
- }
+ secp256k1_selftest();
prealloc_size = secp256k1_context_preallocated_size(flags);
if (prealloc_size == 0) {
@@ -137,7 +157,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
}
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (ctx != NULL) {
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
}
@@ -151,7 +171,7 @@ void secp256k1_context_destroy(secp256k1_context* ctx) {
}
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (fun == NULL) {
fun = secp256k1_default_illegal_callback_fn;
}
@@ -160,7 +180,7 @@ void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(
}
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (fun == NULL) {
fun = secp256k1_default_error_callback_fn;
}
diff --git a/src/secp256k1/src/selftest.h b/src/secp256k1/src/selftest.h
index 52f1b8442e..d083ac9524 100644
--- a/src/secp256k1/src/selftest.h
+++ b/src/secp256k1/src/selftest.h
@@ -25,7 +25,7 @@ static int secp256k1_selftest_sha256(void) {
return secp256k1_memcmp_var(out, output32, 32) == 0;
}
-static int secp256k1_selftest(void) {
+static int secp256k1_selftest_passes(void) {
return secp256k1_selftest_sha256();
}
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index dd53173930..53613f420a 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -26,6 +26,7 @@
#include "modinv32_impl.h"
#ifdef SECP256K1_WIDEMUL_INT128
#include "modinv64_impl.h"
+#include "int128_impl.h"
#endif
#define CONDITIONAL_TEST(cnt, nam) if (count < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else
@@ -140,6 +141,43 @@ void random_scalar_order_b32(unsigned char *b32) {
secp256k1_scalar_get_b32(b32, &num);
}
+void run_selftest_tests(void) {
+ /* Test public API */
+ secp256k1_selftest();
+}
+
+int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const secp256k1_ecmult_gen_context *b) {
+ return a->built == b->built
+ && secp256k1_scalar_eq(&a->blind, &b->blind)
+ && secp256k1_gej_eq_var(&a->initial, &b->initial);
+}
+
+int context_eq(const secp256k1_context *a, const secp256k1_context *b) {
+ return a->declassify == b->declassify
+ && ecmult_gen_context_eq(&a->ecmult_gen_ctx, &b->ecmult_gen_ctx)
+ && a->illegal_callback.fn == b->illegal_callback.fn
+ && a->illegal_callback.data == b->illegal_callback.
+data
+ && a->error_callback.fn == b->error_callback.fn
+ && a->error_callback.data == b->error_callback.data;
+}
+
+void test_deprecated_flags(void) {
+ unsigned int flags[] = { SECP256K1_CONTEXT_SIGN,
+ SECP256K1_CONTEXT_VERIFY,
+ SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY };
+ int i;
+ /* Check that a context created with any of the flags in the flags array is
+ * identical to the NONE context. */
+ for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) {
+ secp256k1_context *tmp_ctx;
+ CHECK(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE) == secp256k1_context_preallocated_size(flags[i]));
+ tmp_ctx = secp256k1_context_create(flags[i]);
+ CHECK(context_eq(ctx, tmp_ctx));
+ secp256k1_context_destroy(tmp_ctx);
+ }
+}
+
void run_context_tests(int use_prealloc) {
secp256k1_pubkey pubkey;
secp256k1_pubkey zero_pubkey;
@@ -147,15 +185,8 @@ void run_context_tests(int use_prealloc) {
unsigned char ctmp[32];
int32_t ecount;
int32_t ecount2;
- secp256k1_context *none;
- secp256k1_context *sign;
- secp256k1_context *vrfy;
- secp256k1_context *both;
secp256k1_context *sttc;
- void *none_prealloc = NULL;
- void *sign_prealloc = NULL;
- void *vrfy_prealloc = NULL;
- void *both_prealloc = NULL;
+ void *ctx_prealloc = NULL;
void *sttc_prealloc = NULL;
secp256k1_gej pubj;
@@ -163,46 +194,36 @@ void run_context_tests(int use_prealloc) {
secp256k1_scalar msg, key, nonce;
secp256k1_scalar sigr, sigs;
+ /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
+ CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
+
if (use_prealloc) {
- none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
- sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
- vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
- both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
- sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp));
- CHECK(none_prealloc != NULL);
- CHECK(sign_prealloc != NULL);
- CHECK(vrfy_prealloc != NULL);
- CHECK(both_prealloc != NULL);
+ ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
+ CHECK(ctx_prealloc != NULL);
+ ctx = secp256k1_context_preallocated_create(ctx_prealloc, SECP256K1_CONTEXT_NONE);
+ sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_static));
CHECK(sttc_prealloc != NULL);
- none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE);
- sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
- vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
- both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc);
+ sttc = secp256k1_context_preallocated_clone(secp256k1_context_static, sttc_prealloc);
} else {
- none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ sttc = secp256k1_context_clone(secp256k1_context_static);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
}
+ test_deprecated_flags();
+
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
ecount = 0;
ecount2 = 10;
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount2);
/* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
- secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL);
- CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
- CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
+ secp256k1_context_set_error_callback(ctx, secp256k1_default_illegal_callback_fn, NULL);
+ CHECK(ctx->error_callback.fn != sttc->error_callback.fn);
+ CHECK(ctx->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* check if sizes for cloning are consistent */
- CHECK(secp256k1_context_preallocated_clone_size(none) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
- CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
- CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
- CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
+ CHECK(secp256k1_context_preallocated_clone_size(ctx) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
CHECK(secp256k1_context_preallocated_clone_size(sttc) >= sizeof(secp256k1_context));
/*** clone and destroy all of them to make sure cloning was complete ***/
@@ -211,58 +232,31 @@ void run_context_tests(int use_prealloc) {
if (use_prealloc) {
/* clone into a non-preallocated context and then again into a new preallocated one. */
- ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(none_prealloc); none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(none_prealloc != NULL);
- ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, none_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(sign_prealloc); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(sign_prealloc != NULL);
- ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, sign_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(vrfy_prealloc); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(vrfy_prealloc != NULL);
- ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, vrfy_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(both_prealloc); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(both_prealloc != NULL);
- ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, both_prealloc); secp256k1_context_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_clone(ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
+ free(ctx_prealloc); ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(ctx_prealloc != NULL);
+ ctx_tmp = ctx; ctx = secp256k1_context_preallocated_clone(ctx, ctx_prealloc); secp256k1_context_destroy(ctx_tmp);
} else {
/* clone into a preallocated context and then again into a new non-preallocated one. */
void *prealloc_tmp;
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_preallocated_clone(ctx, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_clone(ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
free(prealloc_tmp);
}
}
/* Verify that the error callback makes it across the clone. */
- CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
- CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
+ CHECK(ctx->error_callback.fn != sttc->error_callback.fn);
+ CHECK(ctx->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* And that it resets back to default. */
- secp256k1_context_set_error_callback(sign, NULL, NULL);
- CHECK(vrfy->error_callback.fn == sign->error_callback.fn);
+ secp256k1_context_set_error_callback(ctx, NULL, NULL);
+ CHECK(ctx->error_callback.fn == sttc->error_callback.fn);
/*** attempt to use them ***/
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
- secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
+ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);
/* Verify context-type checking illegal-argument errors. */
@@ -270,29 +264,29 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ec_pubkey_create(sttc, &pubkey, ctmp) == 0);
CHECK(ecount == 1);
VG_UNDEF(&pubkey, sizeof(pubkey));
- CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ecdsa_sign(sttc, &sig, ctmp, ctmp, NULL, NULL) == 0);
CHECK(ecount == 2);
VG_UNDEF(&sig, sizeof(sig));
- CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(ctx, &sig, ctmp, ctmp, NULL, NULL) == 1);
VG_CHECK(&sig, sizeof(sig));
CHECK(ecount2 == 10);
- CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
+ CHECK(secp256k1_ecdsa_verify(ctx, &sig, ctmp, &pubkey) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(sttc, &sig, ctmp, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_tweak_add(sttc, &pubkey, ctmp) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_negate(sttc, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
+ CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
+ CHECK(secp256k1_ec_pubkey_negate(ctx, NULL) == 0);
CHECK(ecount2 == 11);
CHECK(secp256k1_ec_pubkey_negate(sttc, &zero_pubkey) == 0);
CHECK(ecount == 3);
@@ -302,49 +296,37 @@ void run_context_tests(int use_prealloc) {
CHECK(ecount == 3);
CHECK(secp256k1_context_randomize(sttc, NULL) == 1);
CHECK(ecount == 3);
- CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
+ CHECK(secp256k1_context_randomize(ctx, ctmp) == 1);
CHECK(ecount2 == 11);
- CHECK(secp256k1_context_randomize(sign, NULL) == 1);
+ CHECK(secp256k1_context_randomize(ctx, NULL) == 1);
CHECK(ecount2 == 11);
secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
- secp256k1_context_set_illegal_callback(sign, NULL, NULL);
+ secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
/* obtain a working nonce */
do {
random_scalar_order_test(&nonce);
- } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+ } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try signing */
- CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
- CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+ CHECK(secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try verifying */
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
- CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
/* cleanup */
if (use_prealloc) {
- secp256k1_context_preallocated_destroy(none);
- secp256k1_context_preallocated_destroy(sign);
- secp256k1_context_preallocated_destroy(vrfy);
- secp256k1_context_preallocated_destroy(both);
+ secp256k1_context_preallocated_destroy(ctx);
secp256k1_context_preallocated_destroy(sttc);
- free(none_prealloc);
- free(sign_prealloc);
- free(vrfy_prealloc);
- free(both_prealloc);
+ free(ctx_prealloc);
free(sttc_prealloc);
} else {
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
+ secp256k1_context_destroy(ctx);
secp256k1_context_destroy(sttc);
}
/* Defined as no-op. */
secp256k1_context_destroy(NULL);
secp256k1_context_preallocated_destroy(NULL);
-
}
void run_scratch_tests(void) {
@@ -353,83 +335,85 @@ void run_scratch_tests(void) {
int32_t ecount = 0;
size_t checkpoint;
size_t checkpoint_2;
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_scratch_space *scratch;
secp256k1_scratch_space local_scratch;
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+
/* Test public API */
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
- scratch = secp256k1_scratch_space_create(none, 1000);
+ scratch = secp256k1_scratch_space_create(ctx, 1000);
CHECK(scratch != NULL);
CHECK(ecount == 0);
/* Test internal API */
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1));
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1));
CHECK(scratch->alloc_size == 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* Allocating 500 bytes succeeds */
- checkpoint = secp256k1_scratch_checkpoint(&none->error_callback, scratch);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
+ checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) != NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000 - adj_alloc);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
CHECK(scratch->alloc_size != 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* Allocating another 501 bytes fails */
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 501) == NULL);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 501) == NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000 - adj_alloc);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
CHECK(scratch->alloc_size != 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* ...but it succeeds once we apply the checkpoint to undo it */
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint);
CHECK(scratch->alloc_size == 0);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) != NULL);
CHECK(scratch->alloc_size != 0);
/* try to apply a bad checkpoint */
- checkpoint_2 = secp256k1_scratch_checkpoint(&none->error_callback, scratch);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
+ checkpoint_2 = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint);
CHECK(ecount == 0);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
CHECK(ecount == 1);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */
CHECK(ecount == 2);
/* try to use badly initialized scratch space */
- secp256k1_scratch_space_destroy(none, scratch);
+ secp256k1_scratch_space_destroy(ctx, scratch);
memset(&local_scratch, 0, sizeof(local_scratch));
scratch = &local_scratch;
- CHECK(!secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0));
+ CHECK(!secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0));
CHECK(ecount == 3);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) == NULL);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) == NULL);
CHECK(ecount == 4);
- secp256k1_scratch_space_destroy(none, scratch);
+ secp256k1_scratch_space_destroy(ctx, scratch);
CHECK(ecount == 5);
/* Test that large integers do not wrap around in a bad way */
- scratch = secp256k1_scratch_space_create(none, 1000);
+ scratch = secp256k1_scratch_space_create(ctx, 1000);
/* Try max allocation with a large number of objects. Only makes sense if
* ALIGNMENT is greater than 1 because otherwise the objects take no extra
* space. */
- CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&none->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
+ CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
/* Try allocating SIZE_MAX to test wrap around which only happens if
* ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch
* space is too small. */
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, SIZE_MAX) == NULL);
- secp256k1_scratch_space_destroy(none, scratch);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, SIZE_MAX) == NULL);
+ secp256k1_scratch_space_destroy(ctx, scratch);
/* cleanup */
- secp256k1_scratch_space_destroy(none, NULL); /* no-op */
- secp256k1_context_destroy(none);
+ secp256k1_scratch_space_destroy(ctx, NULL); /* no-op */
+ secp256k1_context_destroy(ctx);
}
+
void run_ctz_tests(void) {
static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129};
static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef};
@@ -697,7 +681,6 @@ void run_rfc6979_hmac_sha256_tests(void) {
void run_tagged_sha256_tests(void) {
int ecount = 0;
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
unsigned char tag[32] = { 0 };
unsigned char msg[32] = { 0 };
unsigned char hash32[32];
@@ -708,23 +691,22 @@ void run_tagged_sha256_tests(void) {
0xE2, 0x76, 0x55, 0x9A, 0x3B, 0xDE, 0x55, 0xB3
};
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
/* API test */
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1);
- CHECK(secp256k1_tagged_sha256(none, NULL, tag, sizeof(tag), msg, sizeof(msg)) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1);
+ CHECK(secp256k1_tagged_sha256(ctx, NULL, tag, sizeof(tag), msg, sizeof(msg)) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_tagged_sha256(none, hash32, NULL, 0, msg, sizeof(msg)) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, NULL, 0, msg, sizeof(msg)) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), NULL, 0) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, sizeof(tag), NULL, 0) == 0);
CHECK(ecount == 3);
/* Static test vector */
memcpy(tag, "tag", 3);
memcpy(msg, "msg", 3);
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, 3, msg, 3) == 1);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, 3, msg, 3) == 1);
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
- secp256k1_context_destroy(none);
}
/***** RANDOM TESTS *****/
@@ -814,7 +796,8 @@ uint64_t modinv2p64(uint64_t x) {
return w;
}
-/* compute out = (a*b) mod m; if b=NULL, treat b=1.
+
+/* compute out = (a*b) mod m; if b=NULL, treat b=1; if m=NULL, treat m=infinity.
*
* Out is a 512-bit number (represented as 32 uint16_t's in LE order). The other
* arguments are 256-bit numbers (represented as 16 uint16_t's in LE order). */
@@ -856,46 +839,48 @@ void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint16
}
}
- /* Compute the highest set bit in m. */
- for (i = 255; i >= 0; --i) {
- if ((m[i >> 4] >> (i & 15)) & 1) {
- m_bitlen = i;
- break;
+ if (m) {
+ /* Compute the highest set bit in m. */
+ for (i = 255; i >= 0; --i) {
+ if ((m[i >> 4] >> (i & 15)) & 1) {
+ m_bitlen = i;
+ break;
+ }
}
- }
- /* Try do mul -= m<<i, for i going down to 0, whenever the result is not negative */
- for (i = mul_bitlen - m_bitlen; i >= 0; --i) {
- uint16_t mul2[32];
- int64_t cs;
-
- /* Compute mul2 = mul - m<<i. */
- cs = 0; /* accumulator */
- for (j = 0; j < 32; ++j) { /* j loops over the output limbs in mul2. */
- /* Compute sub: the 16 bits in m that will be subtracted from mul2[j]. */
- uint16_t sub = 0;
- int p;
- for (p = 0; p < 16; ++p) { /* p loops over the bit positions in mul2[j]. */
- int bitpos = j * 16 - i + p; /* bitpos is the correspond bit position in m. */
- if (bitpos >= 0 && bitpos < 256) {
- sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p;
+ /* Try do mul -= m<<i, for i going down to 0, whenever the result is not negative */
+ for (i = mul_bitlen - m_bitlen; i >= 0; --i) {
+ uint16_t mul2[32];
+ int64_t cs;
+
+ /* Compute mul2 = mul - m<<i. */
+ cs = 0; /* accumulator */
+ for (j = 0; j < 32; ++j) { /* j loops over the output limbs in mul2. */
+ /* Compute sub: the 16 bits in m that will be subtracted from mul2[j]. */
+ uint16_t sub = 0;
+ int p;
+ for (p = 0; p < 16; ++p) { /* p loops over the bit positions in mul2[j]. */
+ int bitpos = j * 16 - i + p; /* bitpos is the correspond bit position in m. */
+ if (bitpos >= 0 && bitpos < 256) {
+ sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p;
+ }
}
+ /* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */
+ cs += mul[j];
+ cs -= sub;
+ mul2[j] = (cs & 0xFFFF);
+ cs >>= 16;
+ }
+ /* If remainder of subtraction is 0, set mul = mul2. */
+ if (cs == 0) {
+ memcpy(mul, mul2, sizeof(mul));
}
- /* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */
- cs += mul[j];
- cs -= sub;
- mul2[j] = (cs & 0xFFFF);
- cs >>= 16;
}
- /* If remainder of subtraction is 0, set mul = mul2. */
- if (cs == 0) {
- memcpy(mul, mul2, sizeof(mul));
+ /* Sanity check: test that all limbs higher than m's highest are zero */
+ for (i = (m_bitlen >> 4) + 1; i < 32; ++i) {
+ CHECK(mul[i] == 0);
}
}
- /* Sanity check: test that all limbs higher than m's highest are zero */
- for (i = (m_bitlen >> 4) + 1; i < 32; ++i) {
- CHECK(mul[i] == 0);
- }
memcpy(out, mul, 32);
}
@@ -1710,8 +1695,305 @@ void run_modinv_tests(void) {
}
}
-/***** SCALAR TESTS *****/
+/***** INT128 TESTS *****/
+
+#ifdef SECP256K1_WIDEMUL_INT128
+/* Add two 256-bit numbers (represented as 16 uint16_t's in LE order) together mod 2^256. */
+void add256(uint16_t* out, const uint16_t* a, const uint16_t* b) {
+ int i;
+ uint32_t carry = 0;
+ for (i = 0; i < 16; ++i) {
+ carry += a[i];
+ carry += b[i];
+ out[i] = carry;
+ carry >>= 16;
+ }
+}
+
+/* Negate a 256-bit number (represented as 16 uint16_t's in LE order) mod 2^256. */
+void neg256(uint16_t* out, const uint16_t* a) {
+ int i;
+ uint32_t carry = 1;
+ for (i = 0; i < 16; ++i) {
+ carry += (uint16_t)~a[i];
+ out[i] = carry;
+ carry >>= 16;
+ }
+}
+
+/* Right-shift a 256-bit number (represented as 16 uint16_t's in LE order). */
+void rshift256(uint16_t* out, const uint16_t* a, int n, int sign_extend) {
+ uint16_t sign = sign_extend && (a[15] >> 15);
+ int i, j;
+ for (i = 15; i >= 0; --i) {
+ uint16_t v = 0;
+ for (j = 0; j < 16; ++j) {
+ int frompos = i*16 + j + n;
+ if (frompos >= 256) {
+ v |= sign << j;
+ } else {
+ v |= ((uint16_t)((a[frompos >> 4] >> (frompos & 15)) & 1)) << j;
+ }
+ }
+ out[i] = v;
+ }
+}
+
+/* Load a 64-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */
+void load256u64(uint16_t* out, uint64_t v, int is_signed) {
+ int i;
+ uint64_t sign = is_signed && (v >> 63) ? UINT64_MAX : 0;
+ for (i = 0; i < 4; ++i) {
+ out[i] = v >> (16 * i);
+ }
+ for (i = 4; i < 16; ++i) {
+ out[i] = sign;
+ }
+}
+
+/* Load a 128-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */
+void load256two64(uint16_t* out, uint64_t hi, uint64_t lo, int is_signed) {
+ int i;
+ uint64_t sign = is_signed && (hi >> 63) ? UINT64_MAX : 0;
+ for (i = 0; i < 4; ++i) {
+ out[i] = lo >> (16 * i);
+ }
+ for (i = 4; i < 8; ++i) {
+ out[i] = hi >> (16 * (i - 4));
+ }
+ for (i = 8; i < 16; ++i) {
+ out[i] = sign;
+ }
+}
+
+/* Check whether the 256-bit value represented by array of 16-bit values is in range -2^127 < v < 2^127. */
+int int256is127(const uint16_t* v) {
+ int all_0 = ((v[7] & 0x8000) == 0), all_1 = ((v[7] & 0x8000) == 0x8000);
+ int i;
+ for (i = 8; i < 16; ++i) {
+ if (v[i] != 0) all_0 = 0;
+ if (v[i] != 0xffff) all_1 = 0;
+ }
+ return all_0 || all_1;
+}
+void load256u128(uint16_t* out, const secp256k1_uint128* v) {
+ uint64_t lo = secp256k1_u128_to_u64(v), hi = secp256k1_u128_hi_u64(v);
+ load256two64(out, hi, lo, 0);
+}
+
+void load256i128(uint16_t* out, const secp256k1_int128* v) {
+ uint64_t lo;
+ int64_t hi;
+ secp256k1_int128 c = *v;
+ lo = secp256k1_i128_to_i64(&c);
+ secp256k1_i128_rshift(&c, 64);
+ hi = secp256k1_i128_to_i64(&c);
+ load256two64(out, hi, lo, 1);
+}
+
+void run_int128_test_case(void) {
+ unsigned char buf[32];
+ uint64_t v[4];
+ secp256k1_int128 swa, swz;
+ secp256k1_uint128 uwa, uwz;
+ uint64_t ub, uc;
+ int64_t sb, sc;
+ uint16_t rswa[16], rswz[32], rswr[32], ruwa[16], ruwz[32], ruwr[32];
+ uint16_t rub[16], ruc[16], rsb[16], rsc[16];
+ int i;
+
+ /* Generate 32-byte random value. */
+ secp256k1_testrand256_test(buf);
+ /* Convert into 4 64-bit integers. */
+ for (i = 0; i < 4; ++i) {
+ uint64_t vi = 0;
+ int j;
+ for (j = 0; j < 8; ++j) vi = (vi << 8) + buf[8*i + j];
+ v[i] = vi;
+ }
+ /* Convert those into a 128-bit value and two 64-bit values (signed and unsigned). */
+ secp256k1_u128_load(&uwa, v[1], v[0]);
+ secp256k1_i128_load(&swa, v[1], v[0]);
+ ub = v[2];
+ sb = v[2];
+ uc = v[3];
+ sc = v[3];
+ /* Load those also into 16-bit array representations. */
+ load256u128(ruwa, &uwa);
+ load256i128(rswa, &swa);
+ load256u64(rub, ub, 0);
+ load256u64(rsb, sb, 1);
+ load256u64(ruc, uc, 0);
+ load256u64(rsc, sc, 1);
+ /* test secp256k1_u128_mul */
+ mulmod256(ruwr, rub, ruc, NULL);
+ secp256k1_u128_mul(&uwz, ub, uc);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_accum_mul */
+ mulmod256(ruwr, rub, ruc, NULL);
+ add256(ruwr, ruwr, ruwa);
+ uwz = uwa;
+ secp256k1_u128_accum_mul(&uwz, ub, uc);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_accum_u64 */
+ add256(ruwr, rub, ruwa);
+ uwz = uwa;
+ secp256k1_u128_accum_u64(&uwz, ub);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_rshift */
+ rshift256(ruwr, ruwa, uc % 128, 0);
+ uwz = uwa;
+ secp256k1_u128_rshift(&uwz, uc % 128);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_to_u64 */
+ CHECK(secp256k1_u128_to_u64(&uwa) == v[0]);
+ /* test secp256k1_u128_hi_u64 */
+ CHECK(secp256k1_u128_hi_u64(&uwa) == v[1]);
+ /* test secp256k1_u128_from_u64 */
+ secp256k1_u128_from_u64(&uwz, ub);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(rub, ruwz, 16) == 0);
+ /* test secp256k1_u128_check_bits */
+ {
+ int uwa_bits = 0;
+ int j;
+ for (j = 0; j < 128; ++j) {
+ if (ruwa[j / 16] >> (j % 16)) uwa_bits = 1 + j;
+ }
+ for (j = 0; j < 128; ++j) {
+ CHECK(secp256k1_u128_check_bits(&uwa, j) == (uwa_bits <= j));
+ }
+ }
+ /* test secp256k1_i128_mul */
+ mulmod256(rswr, rsb, rsc, NULL);
+ secp256k1_i128_mul(&swz, sb, sc);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ /* test secp256k1_i128_accum_mul */
+ mulmod256(rswr, rsb, rsc, NULL);
+ add256(rswr, rswr, rswa);
+ if (int256is127(rswr)) {
+ swz = swa;
+ secp256k1_i128_accum_mul(&swz, sb, sc);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ }
+ /* test secp256k1_i128_det */
+ {
+ uint16_t rsd[16], rse[16], rst[32];
+ int64_t sd = v[0], se = v[1];
+ load256u64(rsd, sd, 1);
+ load256u64(rse, se, 1);
+ mulmod256(rst, rsc, rsd, NULL);
+ neg256(rst, rst);
+ mulmod256(rswr, rsb, rse, NULL);
+ add256(rswr, rswr, rst);
+ secp256k1_i128_det(&swz, sb, sc, sd, se);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ }
+ /* test secp256k1_i128_rshift */
+ rshift256(rswr, rswa, uc % 127, 1);
+ swz = swa;
+ secp256k1_i128_rshift(&swz, uc % 127);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ /* test secp256k1_i128_to_i64 */
+ CHECK((uint64_t)secp256k1_i128_to_i64(&swa) == v[0]);
+ /* test secp256k1_i128_from_i64 */
+ secp256k1_i128_from_i64(&swz, sb);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rsb, rswz, 16) == 0);
+ /* test secp256k1_i128_eq_var */
+ {
+ int expect = (uc & 1);
+ swz = swa;
+ if (!expect) {
+ /* Make sure swz != swa */
+ uint64_t v0c = v[0], v1c = v[1];
+ if (ub & 64) {
+ v1c ^= (((uint64_t)1) << (ub & 63));
+ } else {
+ v0c ^= (((uint64_t)1) << (ub & 63));
+ }
+ secp256k1_i128_load(&swz, v1c, v0c);
+ }
+ CHECK(secp256k1_i128_eq_var(&swa, &swz) == expect);
+ }
+ /* test secp256k1_i128_check_pow2 */
+ {
+ int expect = (uc & 1);
+ int pos = ub % 127;
+ if (expect) {
+ /* If expect==1, set swz to exactly (2 << pos). */
+ uint64_t hi = 0;
+ uint64_t lo = 0;
+ if (pos & 64) {
+ hi = (((uint64_t)1) << (pos & 63));
+ } else {
+ lo = (((uint64_t)1) << (pos & 63));
+ }
+ secp256k1_i128_load(&swz, hi, lo);
+ } else {
+ /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal (2 << pos). */
+ if (pos & 64) {
+ if ((v[1] == (((uint64_t)1) << (pos & 63))) && v[0] == 0) expect = 1;
+ } else {
+ if ((v[0] == (((uint64_t)1) << (pos & 63))) && v[1] == 0) expect = 1;
+ }
+ swz = swa;
+ }
+ CHECK(secp256k1_i128_check_pow2(&swz, pos) == expect);
+ }
+}
+
+void run_int128_tests(void) {
+ { /* secp256k1_u128_accum_mul */
+ secp256k1_uint128 res;
+
+ /* Check secp256k1_u128_accum_mul overflow */
+ secp256k1_u128_mul(&res, UINT64_MAX, UINT64_MAX);
+ secp256k1_u128_accum_mul(&res, UINT64_MAX, UINT64_MAX);
+ CHECK(secp256k1_u128_to_u64(&res) == 2);
+ CHECK(secp256k1_u128_hi_u64(&res) == 18446744073709551612U);
+ }
+ { /* secp256k1_u128_accum_mul */
+ secp256k1_int128 res;
+
+ /* Compute INT128_MAX = 2^127 - 1 with secp256k1_i128_accum_mul */
+ secp256k1_i128_mul(&res, INT64_MAX, INT64_MAX);
+ secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MAX);
+ CHECK(secp256k1_i128_to_i64(&res) == 2);
+ secp256k1_i128_accum_mul(&res, 4, 9223372036854775807);
+ secp256k1_i128_accum_mul(&res, 1, 1);
+ CHECK((uint64_t)secp256k1_i128_to_i64(&res) == UINT64_MAX);
+ secp256k1_i128_rshift(&res, 64);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MAX);
+
+ /* Compute INT128_MIN = - 2^127 with secp256k1_i128_accum_mul */
+ secp256k1_i128_mul(&res, INT64_MAX, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MIN);
+ secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == 0);
+ secp256k1_i128_accum_mul(&res, 2, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == 0);
+ secp256k1_i128_rshift(&res, 64);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MIN);
+ }
+ {
+ /* Randomized tests. */
+ int i;
+ for (i = 0; i < 256 * count; ++i) run_int128_test_case();
+ }
+}
+#endif
+
+/***** SCALAR TESTS *****/
void scalar_test(void) {
secp256k1_scalar s;
@@ -3562,6 +3844,22 @@ void run_gej(void) {
test_gej_cmov(&a, &b);
test_gej_cmov(&b, &a);
}
+
+ /* Tests for secp256k1_gej_eq_var */
+ for (i = 0; i < count; i++) {
+ secp256k1_fe fe;
+ random_gej_test(&a);
+ random_gej_test(&b);
+ CHECK(!secp256k1_gej_eq_var(&a, &b));
+
+ b = a;
+ random_field_element_test(&fe);
+ if (secp256k1_fe_is_zero(&fe)) {
+ continue;
+ }
+ secp256k1_gej_rescale(&a, &fe);
+ CHECK(secp256k1_gej_eq_var(&a, &b));
+ }
}
void test_ec_combine(void) {
@@ -3767,17 +4065,12 @@ void run_ecmult_chain(void) {
0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D,
0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88
);
-
- secp256k1_gej_neg(&rp, &rp);
- secp256k1_gej_add_var(&rp, &rp, &x, NULL);
- CHECK(secp256k1_gej_is_infinity(&rp));
+ CHECK(secp256k1_gej_eq_var(&rp, &x));
}
}
/* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_ecmult(&x2, &a, &ae, &ge);
- secp256k1_gej_neg(&x2, &x2);
- secp256k1_gej_add_var(&x2, &x2, &x, NULL);
- CHECK(secp256k1_gej_is_infinity(&x2));
+ CHECK(secp256k1_gej_eq_var(&x, &x2));
}
void test_point_times_order(const secp256k1_gej *point) {
@@ -4070,16 +4363,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
/* only G scalar */
secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* 1-point */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* Try to multiply 1 point, but callback returns false */
CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
@@ -4087,16 +4376,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
/* 2-point */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* 2-point with G scalar */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Check infinite outputs of various forms */
@@ -4181,9 +4466,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ecmult(&r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Check random scalars, constant point */
@@ -4204,9 +4487,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Sanity check that zero scalars don't cause problems */
@@ -4268,9 +4549,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
- secp256k1_gej_neg(&expected, &expected);
- secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
- CHECK(secp256k1_gej_is_infinity(&actual));
+ CHECK(secp256k1_gej_eq_var(&actual, &expected));
}
}
}
@@ -4440,9 +4719,7 @@ int test_ecmult_multi_random(secp256k1_scratch *scratch) {
CHECK(ecmult_multi(&ctx->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled));
mults += num_nonzero + g_nonzero;
/* Compare with expected result. */
- secp256k1_gej_neg(&computed, &computed);
- secp256k1_gej_add_var(&computed, &computed, &expected, NULL);
- CHECK(secp256k1_gej_is_infinity(&computed));
+ CHECK(secp256k1_gej_eq_var(&computed, &expected));
return mults;
}
@@ -5497,7 +5774,7 @@ void run_ec_pubkey_parse_test(void) {
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1);
- CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &pubkey, pubkeyc, 65) == 1);
+ CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
VG_UNDEF(&ge, sizeof(ge));
@@ -7083,19 +7360,27 @@ int main(int argc, char **argv) {
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
/* initialize */
+ run_selftest_tests();
run_context_tests(0);
run_context_tests(1);
run_scratch_tests();
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- if (secp256k1_testrand_bits(1)) {
+
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ /* Randomize the context only with probability 15/16
+ to make sure we test without context randomization from time to time.
+ TODO Reconsider this when recalibrating the tests. */
+ if (secp256k1_testrand_bits(4)) {
unsigned char rand32[32];
secp256k1_testrand256(rand32);
- CHECK(secp256k1_context_randomize(ctx, secp256k1_testrand_bits(1) ? rand32 : NULL));
+ CHECK(secp256k1_context_randomize(ctx, rand32));
}
run_rand_bits();
run_rand_int();
+#ifdef SECP256K1_WIDEMUL_INT128
+ run_int128_tests();
+#endif
run_ctz_tests();
run_modinv_tests();
run_inverse_tests();
diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c
index 6a4e2340f2..c001dcb80b 100644
--- a/src/secp256k1/src/tests_exhaustive.c
+++ b/src/secp256k1/src/tests_exhaustive.c
@@ -342,15 +342,15 @@ void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *grou
}
#ifdef ENABLE_MODULE_RECOVERY
-#include "src/modules/recovery/tests_exhaustive_impl.h"
+#include "modules/recovery/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_EXTRAKEYS
-#include "src/modules/extrakeys/tests_exhaustive_impl.h"
+#include "modules/extrakeys/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_SCHNORRSIG
-#include "src/modules/schnorrsig/tests_exhaustive_impl.h"
+#include "modules/schnorrsig/tests_exhaustive_impl.h"
#endif
int main(int argc, char** argv) {
@@ -396,7 +396,7 @@ int main(int argc, char** argv) {
while (count--) {
/* Build context */
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_testrand256(rand32);
CHECK(secp256k1_context_randomize(ctx, rand32));
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index dac86bd77f..864baaee4d 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -16,6 +16,11 @@
#include <stdio.h>
#include <limits.h>
+#define STR_(x) #x
+#define STR(x) STR_(x)
+#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
+#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
+
typedef struct {
void (*fn)(const char *text, void* data);
const void* data;
@@ -225,28 +230,36 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag)
*r = (int)(r_masked | a_masked);
}
-/* If USE_FORCE_WIDEMUL_{INT128,INT64} is set, use that wide multiplication implementation.
- * Otherwise use the presence of __SIZEOF_INT128__ to decide.
- */
-#if defined(USE_FORCE_WIDEMUL_INT128)
+#if defined(USE_FORCE_WIDEMUL_INT128_STRUCT)
+/* If USE_FORCE_WIDEMUL_INT128_STRUCT is set, use int128_struct. */
# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
+#elif defined(USE_FORCE_WIDEMUL_INT128)
+/* If USE_FORCE_WIDEMUL_INT128 is set, use int128. */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_NATIVE 1
#elif defined(USE_FORCE_WIDEMUL_INT64)
+/* If USE_FORCE_WIDEMUL_INT64 is set, use int64. */
# define SECP256K1_WIDEMUL_INT64 1
#elif defined(UINT128_MAX) || defined(__SIZEOF_INT128__)
+/* If a native 128-bit integer type exists, use int128. */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_NATIVE 1
+#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
+/* On 64-bit MSVC targets (x86_64 and arm64), use int128_struct
+ * (which has special logic to implement using intrinsics on those systems). */
# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
+#elif SIZE_MAX > 0xffffffff
+/* Systems with 64-bit pointers (and thus registers) very likely benefit from
+ * using 64-bit based arithmetic (even if we need to fall back to 32x32->64 based
+ * multiplication logic). */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
#else
+/* Lastly, fall back to int64 based arithmetic. */
# define SECP256K1_WIDEMUL_INT64 1
#endif
-#if defined(SECP256K1_WIDEMUL_INT128)
-# if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__)
-SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
-SECP256K1_GNUC_EXT typedef __int128 int128_t;
-#define UINT128_MAX ((uint128_t)(-1))
-#define INT128_MAX ((int128_t)(UINT128_MAX >> 1))
-#define INT128_MIN (-INT128_MAX - 1)
-/* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */
-# endif
-#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
diff --git a/src/secp256k1/src/valgrind_ctime_test.c b/src/secp256k1/src/valgrind_ctime_test.c
index 6ff0085d34..a0f888b00f 100644
--- a/src/secp256k1/src/valgrind_ctime_test.c
+++ b/src/secp256k1/src/valgrind_ctime_test.c
@@ -39,9 +39,7 @@ int main(void) {
fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n");
return 1;
}
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN
- | SECP256K1_CONTEXT_VERIFY
- | SECP256K1_CONTEXT_DECLASSIFY);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY);
/** In theory, testing with a single secret input should be sufficient:
* If control flow depended on secrets the tool would generate an error.
*/